===================================================================
@@ -87,6 +87,44 @@ extern int initcall_debug;
/*
* MUST be called with the lock held!
*/
+static int __cookie_is_done(struct list_head *running, async_cookie_t cookie)
+{
+ struct async_entry *entry;
+
+ if (!list_empty(running)) {
+ list_for_each_entry(entry, running, list) {
+ if (entry->cookie > cookie)
+ break;
+ if (entry->cookie == cookie)
+ return 0;
+ }
+ }
+
+ if (!list_empty(&async_pending)) {
+ list_for_each_entry(entry, &async_pending, list) {
+ if (entry->cookie > cookie)
+ break;
+ if (entry->cookie == cookie)
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int cookie_is_done(struct list_head *running, async_cookie_t cookie)
+{
+ unsigned long flags;
+ async_cookie_t ret;
+
+ spin_lock_irqsave(&async_lock, flags);
+ ret = __cookie_is_done(running, cookie);
+ spin_unlock_irqrestore(&async_lock, flags);
+ return ret;
+}
+
+/*
+ * MUST be called with the lock held!
+ */
static async_cookie_t __lowest_in_progress(struct list_head *running)
{
struct async_entry *entry;
@@ -220,18 +258,19 @@ EXPORT_SYMBOL_GPL(async_schedule_special
void async_synchronize_full(void)
{
do {
- async_synchronize_cookie(next_cookie);
+ async_synchronize_cookies(next_cookie);
} while (!list_empty(&async_running) || !list_empty(&async_pending));
}
EXPORT_SYMBOL_GPL(async_synchronize_full);
void async_synchronize_full_special(struct list_head *list)
{
- async_synchronize_cookie_special(next_cookie, list);
+ async_synchronize_cookies_special(next_cookie, list);
}
EXPORT_SYMBOL_GPL(async_synchronize_full_special);
-void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *running)
+static void __async_synchronize_cookie_special(async_cookie_t cookie,
+ struct list_head *running, int type)
{
ktime_t starttime, delta, endtime;
@@ -240,7 +279,10 @@ void async_synchronize_cookie_special(as
starttime = ktime_get();
}
- wait_event(async_done, lowest_in_progress(running) >= cookie);
+ if (type)
+ wait_event(async_done, lowest_in_progress(running) >= cookie);
+ else
+ wait_event(async_done, cookie_is_done(running, cookie));
if (initcall_debug && system_state == SYSTEM_BOOTING) {
endtime = ktime_get();
@@ -250,13 +292,37 @@ void async_synchronize_cookie_special(as
task_pid_nr(current), ktime_to_ns(delta) >> 10);
}
}
-EXPORT_SYMBOL_GPL(async_synchronize_cookie_special);
-void async_synchronize_cookie(async_cookie_t cookie)
+void async_synchronize_cookies_special(async_cookie_t cookie, struct list_head *running)
+{
+ __async_synchronize_cookie_special(cookie, running, 1);
+}
+EXPORT_SYMBOL_GPL(async_synchronize_cookies_special);
+
+void async_synchronize_cookies(async_cookie_t cookie)
+{
+ __async_synchronize_cookie_special(cookie, &async_running, 1);
+}
+EXPORT_SYMBOL_GPL(async_synchronize_cookies);
+
+
+/*
+ * sychronize a specific cookie
+ * block until the entry with a speicific cookie is done.
+ * Note that waiting for a cookie while holding it is not allowed.
+ * because it may cause a deadlock issue.
+ */
+void async_synchronize_one_cookie_special(async_cookie_t cookie, struct list_head *running)
+{
+ __async_synchronize_cookie_special(cookie, running, 0);
+}
+EXPORT_SYMBOL_GPL(async_synchronize_one_cookie_special);
+
+void async_synchronize_one_cookie(async_cookie_t cookie)
{
- async_synchronize_cookie_special(cookie, &async_running);
+ __async_synchronize_cookie_special(cookie, &async_running, 0);
}
-EXPORT_SYMBOL_GPL(async_synchronize_cookie);
+EXPORT_SYMBOL_GPL(async_synchronize_one_cookie);
static int async_thread(void *unused)
===================================================================
@@ -20,6 +20,8 @@ extern async_cookie_t async_schedule(asy
extern async_cookie_t async_schedule_special(async_func_ptr *ptr, void *data, struct list_head *list);
extern void async_synchronize_full(void);
extern void async_synchronize_full_special(struct list_head *list);
-extern void async_synchronize_cookie(async_cookie_t cookie);
-extern void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *list);
+extern void async_synchronize_cookies(async_cookie_t cookie);
+extern void async_synchronize_cookies_special(async_cookie_t cookie, struct list_head *list);
+extern void async_synchronize_one_cookie(async_cookie_t cookie);
+extern void async_synchronize_one_cookie_special(async_cookie_t cookie, struct list_head *list);
===================================================================
@@ -5929,7 +5929,7 @@ static void async_port_probe(void *data,
* don't need to wait for port 0, only for later ports.
*/
if (!(ap->host->flags & ATA_HOST_PARALLEL_SCAN) && ap->port_no != 0)
- async_synchronize_cookie(cookie);
+ async_synchronize_cookies(cookie);
/* probe */
if (ap->ops->error_handler) {
@@ -5969,7 +5969,7 @@ static void async_port_probe(void *data,
}
/* in order to keep device order, we need to synchronize at this point */
- async_synchronize_cookie(cookie);
+ async_synchronize_cookies(cookie);
ata_scsi_scan_host(ap, 1);