* [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once"
@ 2012-07-10 2:33 Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 1/5] async: introduce 'async_domain' type Dan Williams
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Dan Williams @ 2012-07-10 2:33 UTC (permalink / raw)
To: jgarzik, JBottomley; +Cc: linux-ide, linux-scsi
Hi Jeff,
Let me know if any of these need reworking, otherwise I believe James is
waiting on your ack to take them (well, all except patch1) through scsi.git.
--
Dan
Original description:
Set4 of 5 patchsets to update scsi, libsas, and libata in
support of the isci driver.
Let libsas hook into the generic suspend resume infrastructure in
libata, and provide a common suspend/resume implementation for lldds to
reuse.
"Reset once" is not part of the suspend/resume work. But it is relevant
to libsas users who need to wait for domain-wide ata error recovery and
want to limit the effort for known well-behaved devices.
These have been in -next for the past couple kernel cycles.
---
Artur Wojcik (1):
isci: implement suspend/resume support
Dan Williams (4):
libata: reset once
libata: export ata_port suspend/resume infrastructure for sas
libsas: suspend / resume support
libsas, ipr: cleanup ata_host flags initialization via ata_host_init
Documentation/kernel-parameters.txt | 3 +
drivers/ata/libata-core.c | 69 +++++++++++++++++++--------
drivers/ata/libata-eh.c | 2 +
drivers/scsi/ipr.c | 3 -
drivers/scsi/isci/host.c | 2 -
drivers/scsi/isci/host.h | 2 -
drivers/scsi/isci/init.c | 58 ++++++++++++++++++++++
drivers/scsi/libsas/sas_ata.c | 91 +++++++++++++++++++++++++++++++++--
drivers/scsi/libsas/sas_discover.c | 69 +++++++++++++++++++++++----
drivers/scsi/libsas/sas_dump.c | 1
drivers/scsi/libsas/sas_event.c | 4 +-
drivers/scsi/libsas/sas_init.c | 90 ++++++++++++++++++++++++++++++++++-
drivers/scsi/libsas/sas_internal.h | 1
drivers/scsi/libsas/sas_phy.c | 21 ++++++++
drivers/scsi/libsas/sas_port.c | 52 ++++++++++++++++++++
include/linux/libata.h | 15 +++++-
include/scsi/libsas.h | 20 ++++++--
include/scsi/sas_ata.h | 10 ++++
18 files changed, 463 insertions(+), 50 deletions(-)
^ permalink raw reply [flat|nested] 7+ messages in thread
* [set4 resend PATCH 1/5] async: introduce 'async_domain' type
2012-07-10 2:33 [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
@ 2012-07-10 2:33 ` Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 2/5] async: make async_synchronize_full() flush all work regardless of domain Dan Williams
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2012-07-10 2:33 UTC (permalink / raw)
To: jgarzik, JBottomley
Cc: linux-scsi, Eldad Zack, Mark Brown, linux-ide, Arjan van de Ven,
Liam Girdwood
This is in preparation for teaching async_synchronize_full() to sync all
pending async work, and not just on the async_running domain. This
conversion is functionally equivalent, just embedding the existing list
in a new async_domain type.
The .registered attribute is used in a later patch to distinguish
between domains that want to be flushed by async_synchronize_full()
versus those that only expect async_synchronize_{full|cookie}_domain to
be used for flushing.
Cc: Liam Girdwood <lrg@ti.com>
Cc: James Bottomley <JBottomley@parallels.com>
Acked-by: Arjan van de Ven <arjan@linux.intel.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Tested-by: Eldad Zack <eldad@fogrefinery.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/regulator/core.c | 2 +-
drivers/scsi/libsas/sas_ata.c | 2 +-
drivers/scsi/scsi.c | 3 ++-
drivers/scsi/scsi_priv.h | 2 +-
include/linux/async.h | 35 +++++++++++++++++++++++++++++++----
kernel/async.c | 35 +++++++++++++++++------------------
sound/soc/soc-dapm.c | 2 +-
7 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 09a737c..4293aae 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2744,7 +2744,7 @@ static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
int regulator_bulk_enable(int num_consumers,
struct regulator_bulk_data *consumers)
{
- LIST_HEAD(async_domain);
+ ASYNC_DOMAIN_EXCLUSIVE(async_domain);
int i;
int ret = 0;
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index bec3bc8..a59fcdc 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -742,7 +742,7 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie)
void sas_ata_strategy_handler(struct Scsi_Host *shost)
{
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
- LIST_HEAD(async);
+ ASYNC_DOMAIN_EXCLUSIVE(async);
int i;
/* it's ok to defer revalidation events during ata eh, these
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index bbbc9c9..4cade88 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -54,6 +54,7 @@
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/mutex.h>
+#include <linux/async.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -91,7 +92,7 @@ EXPORT_SYMBOL(scsi_logging_level);
#endif
/* sd, scsi core and power management need to coordinate flushing async actions */
-LIST_HEAD(scsi_sd_probe_domain);
+ASYNC_DOMAIN(scsi_sd_probe_domain);
EXPORT_SYMBOL(scsi_sd_probe_domain);
/* NB: These are exposed through /proc/scsi/scsi and form part of the ABI.
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 13d74da..4bd25ec 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -163,7 +163,7 @@ static inline int scsi_autopm_get_host(struct Scsi_Host *h) { return 0; }
static inline void scsi_autopm_put_host(struct Scsi_Host *h) {}
#endif /* CONFIG_PM_RUNTIME */
-extern struct list_head scsi_sd_probe_domain;
+extern struct async_domain scsi_sd_probe_domain;
/*
* internal scsi timeout functions: for use by mid-layer and transport
diff --git a/include/linux/async.h b/include/linux/async.h
index 68a9530..364e7ff 100644
--- a/include/linux/async.h
+++ b/include/linux/async.h
@@ -9,19 +9,46 @@
* as published by the Free Software Foundation; version 2
* of the License.
*/
+#ifndef __ASYNC_H__
+#define __ASYNC_H__
#include <linux/types.h>
#include <linux/list.h>
typedef u64 async_cookie_t;
typedef void (async_func_ptr) (void *data, async_cookie_t cookie);
+struct async_domain {
+ struct list_head node;
+ struct list_head domain;
+ int count;
+ unsigned registered:1;
+};
+
+/*
+ * domain participates in global async_synchronize_full
+ */
+#define ASYNC_DOMAIN(_name) \
+ struct async_domain _name = { .node = LIST_HEAD_INIT(_name.node), \
+ .domain = LIST_HEAD_INIT(_name.domain), \
+ .count = 0, \
+ .registered = 1 }
+
+/*
+ * domain is free to go out of scope as soon as all pending work is
+ * complete, this domain does not participate in async_synchronize_full
+ */
+#define ASYNC_DOMAIN_EXCLUSIVE(_name) \
+ struct async_domain _name = { .node = LIST_HEAD_INIT(_name.node), \
+ .domain = LIST_HEAD_INIT(_name.domain), \
+ .count = 0, \
+ .registered = 0 }
extern async_cookie_t async_schedule(async_func_ptr *ptr, void *data);
extern async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data,
- struct list_head *list);
+ struct async_domain *domain);
extern void async_synchronize_full(void);
-extern void async_synchronize_full_domain(struct list_head *list);
+extern void async_synchronize_full_domain(struct async_domain *domain);
extern void async_synchronize_cookie(async_cookie_t cookie);
extern void async_synchronize_cookie_domain(async_cookie_t cookie,
- struct list_head *list);
-
+ struct async_domain *domain);
+#endif
diff --git a/kernel/async.c b/kernel/async.c
index bd0c168..ba5491d 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -62,7 +62,7 @@ static async_cookie_t next_cookie = 1;
#define MAX_WORK 32768
static LIST_HEAD(async_pending);
-static LIST_HEAD(async_running);
+static ASYNC_DOMAIN(async_running);
static DEFINE_SPINLOCK(async_lock);
struct async_entry {
@@ -71,7 +71,7 @@ struct async_entry {
async_cookie_t cookie;
async_func_ptr *func;
void *data;
- struct list_head *running;
+ struct async_domain *running;
};
static DECLARE_WAIT_QUEUE_HEAD(async_done);
@@ -82,13 +82,12 @@ static atomic_t entry_count;
/*
* MUST be called with the lock held!
*/
-static async_cookie_t __lowest_in_progress(struct list_head *running)
+static async_cookie_t __lowest_in_progress(struct async_domain *running)
{
struct async_entry *entry;
- if (!list_empty(running)) {
- entry = list_first_entry(running,
- struct async_entry, list);
+ if (!list_empty(&running->domain)) {
+ entry = list_first_entry(&running->domain, typeof(*entry), list);
return entry->cookie;
}
@@ -99,7 +98,7 @@ static async_cookie_t __lowest_in_progress(struct list_head *running)
return next_cookie; /* "infinity" value */
}
-static async_cookie_t lowest_in_progress(struct list_head *running)
+static async_cookie_t lowest_in_progress(struct async_domain *running)
{
unsigned long flags;
async_cookie_t ret;
@@ -119,10 +118,11 @@ static void async_run_entry_fn(struct work_struct *work)
container_of(work, struct async_entry, work);
unsigned long flags;
ktime_t uninitialized_var(calltime), delta, rettime;
+ struct async_domain *running = entry->running;
/* 1) move self to the running queue */
spin_lock_irqsave(&async_lock, flags);
- list_move_tail(&entry->list, entry->running);
+ list_move_tail(&entry->list, &running->domain);
spin_unlock_irqrestore(&async_lock, flags);
/* 2) run (and print duration) */
@@ -156,7 +156,7 @@ static void async_run_entry_fn(struct work_struct *work)
wake_up(&async_done);
}
-static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct list_head *running)
+static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct async_domain *running)
{
struct async_entry *entry;
unsigned long flags;
@@ -223,7 +223,7 @@ EXPORT_SYMBOL_GPL(async_schedule);
* Note: This function may be called from atomic or non-atomic contexts.
*/
async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data,
- struct list_head *running)
+ struct async_domain *running)
{
return __async_schedule(ptr, data, running);
}
@@ -238,20 +238,20 @@ void async_synchronize_full(void)
{
do {
async_synchronize_cookie(next_cookie);
- } while (!list_empty(&async_running) || !list_empty(&async_pending));
+ } while (!list_empty(&async_running.domain) || !list_empty(&async_pending));
}
EXPORT_SYMBOL_GPL(async_synchronize_full);
/**
* async_synchronize_full_domain - synchronize all asynchronous function within a certain domain
- * @list: running list to synchronize on
+ * @domain: running list to synchronize on
*
* This function waits until all asynchronous function calls for the
- * synchronization domain specified by the running list @list have been done.
+ * synchronization domain specified by the running list @domain have been done.
*/
-void async_synchronize_full_domain(struct list_head *list)
+void async_synchronize_full_domain(struct async_domain *domain)
{
- async_synchronize_cookie_domain(next_cookie, list);
+ async_synchronize_cookie_domain(next_cookie, domain);
}
EXPORT_SYMBOL_GPL(async_synchronize_full_domain);
@@ -261,11 +261,10 @@ EXPORT_SYMBOL_GPL(async_synchronize_full_domain);
* @running: running list to synchronize on
*
* This function waits until all asynchronous function calls for the
- * synchronization domain specified by the running list @list submitted
+ * synchronization domain specified by running list @running submitted
* prior to @cookie have been done.
*/
-void async_synchronize_cookie_domain(async_cookie_t cookie,
- struct list_head *running)
+void async_synchronize_cookie_domain(async_cookie_t cookie, struct async_domain *running)
{
ktime_t uninitialized_var(starttime), delta, endtime;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 89eae93..fa1e312 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1545,7 +1545,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
struct snd_soc_dapm_context *d;
LIST_HEAD(up_list);
LIST_HEAD(down_list);
- LIST_HEAD(async_domain);
+ ASYNC_DOMAIN_EXCLUSIVE(async_domain);
enum snd_soc_bias_level bias;
trace_snd_soc_dapm_start(card);
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [set4 resend PATCH 2/5] async: make async_synchronize_full() flush all work regardless of domain
2012-07-10 2:33 [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 1/5] async: introduce 'async_domain' type Dan Williams
@ 2012-07-10 2:33 ` Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 3/5] scsi: queue async scan work to an async_schedule domain Dan Williams
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2012-07-10 2:33 UTC (permalink / raw)
To: jgarzik, JBottomley
Cc: Len Brown, linux-scsi, Meelis Roos, Eldad Zack, Rafael J. Wysocki,
linux-ide, Arjan van de Ven, Eldad Zack
In response to an async related regression James noted:
"My theory is that this is an init problem: The assumption in a lot of
our code is that async_synchronize_full() waits for everything ... even
the domain specific async schedules, which isn't true."
...so make this assumption true.
Each domain, including the default one, registers itself on a global domain
list when work is scheduled. Once all entries complete it exits that
list. Waiting for the list to be empty syncs all in-flight work across
all domains.
Domains can opt-out of global syncing if they are declared as exclusive
ASYNC_DOMAIN_EXCLUSIVE(). All stack-based domains have been declared
exclusive since the domain may go out of scope as soon as the last work
item completes.
Statically declared domains are mostly ok, but async_unregister_domain()
is there to close any theoretical races with pending
async_synchronize_full waiters at module removal time.
Cc: Len Brown <len.brown@intel.com>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: James Bottomley <JBottomley@parallels.com>
Acked-by: Arjan van de Ven <arjan@linux.intel.com>
Reported-by: Meelis Roos <mroos@linux.ee>
Reported-by: Eldad Zack <eldadzack@gmail.com>
Tested-by: Eldad Zack <eldad@fogrefinery.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/scsi.c | 1 +
include/linux/async.h | 1 +
kernel/async.c | 43 +++++++++++++++++++++++++++++++++++++++++--
3 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 4cade88..2936b44 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1355,6 +1355,7 @@ static void __exit exit_scsi(void)
scsi_exit_devinfo();
scsi_exit_procfs();
scsi_exit_queue();
+ async_unregister_domain(&scsi_sd_probe_domain);
}
subsys_initcall(init_scsi);
diff --git a/include/linux/async.h b/include/linux/async.h
index 364e7ff..7a24fe9 100644
--- a/include/linux/async.h
+++ b/include/linux/async.h
@@ -46,6 +46,7 @@ struct async_domain {
extern async_cookie_t async_schedule(async_func_ptr *ptr, void *data);
extern async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data,
struct async_domain *domain);
+void async_unregister_domain(struct async_domain *domain);
extern void async_synchronize_full(void);
extern void async_synchronize_full_domain(struct async_domain *domain);
extern void async_synchronize_cookie(async_cookie_t cookie);
diff --git a/kernel/async.c b/kernel/async.c
index ba5491d..9d31183 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -63,7 +63,9 @@ static async_cookie_t next_cookie = 1;
static LIST_HEAD(async_pending);
static ASYNC_DOMAIN(async_running);
+static LIST_HEAD(async_domains);
static DEFINE_SPINLOCK(async_lock);
+static DEFINE_MUTEX(async_register_mutex);
struct async_entry {
struct list_head list;
@@ -145,6 +147,8 @@ static void async_run_entry_fn(struct work_struct *work)
/* 3) remove self from the running queue */
spin_lock_irqsave(&async_lock, flags);
list_del(&entry->list);
+ if (running->registered && --running->count == 0)
+ list_del_init(&running->node);
/* 4) free the entry */
kfree(entry);
@@ -187,6 +191,8 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct a
spin_lock_irqsave(&async_lock, flags);
newcookie = entry->cookie = next_cookie++;
list_add_tail(&entry->list, &async_pending);
+ if (running->registered && running->count++ == 0)
+ list_add_tail(&running->node, &async_domains);
atomic_inc(&entry_count);
spin_unlock_irqrestore(&async_lock, flags);
@@ -236,13 +242,43 @@ EXPORT_SYMBOL_GPL(async_schedule_domain);
*/
void async_synchronize_full(void)
{
+ mutex_lock(&async_register_mutex);
do {
- async_synchronize_cookie(next_cookie);
- } while (!list_empty(&async_running.domain) || !list_empty(&async_pending));
+ struct async_domain *domain = NULL;
+
+ spin_lock_irq(&async_lock);
+ if (!list_empty(&async_domains))
+ domain = list_first_entry(&async_domains, typeof(*domain), node);
+ spin_unlock_irq(&async_lock);
+
+ async_synchronize_cookie_domain(next_cookie, domain);
+ } while (!list_empty(&async_domains));
+ mutex_unlock(&async_register_mutex);
}
EXPORT_SYMBOL_GPL(async_synchronize_full);
/**
+ * async_unregister_domain - ensure no more anonymous waiters on this domain
+ * @domain: idle domain to flush out of any async_synchronize_full instances
+ *
+ * async_synchronize_{cookie|full}_domain() are not flushed since callers
+ * of these routines should know the lifetime of @domain
+ *
+ * Prefer ASYNC_DOMAIN_EXCLUSIVE() declarations over flushing
+ */
+void async_unregister_domain(struct async_domain *domain)
+{
+ mutex_lock(&async_register_mutex);
+ spin_lock_irq(&async_lock);
+ WARN_ON(!domain->registered || !list_empty(&domain->node) ||
+ !list_empty(&domain->domain));
+ domain->registered = 0;
+ spin_unlock_irq(&async_lock);
+ mutex_unlock(&async_register_mutex);
+}
+EXPORT_SYMBOL_GPL(async_unregister_domain);
+
+/**
* async_synchronize_full_domain - synchronize all asynchronous function within a certain domain
* @domain: running list to synchronize on
*
@@ -268,6 +304,9 @@ void async_synchronize_cookie_domain(async_cookie_t cookie, struct async_domain
{
ktime_t uninitialized_var(starttime), delta, endtime;
+ if (!running)
+ return;
+
if (initcall_debug && system_state == SYSTEM_BOOTING) {
printk(KERN_DEBUG "async_waiting @ %i\n", task_pid_nr(current));
starttime = ktime_get();
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [set4 resend PATCH 3/5] scsi: queue async scan work to an async_schedule domain
2012-07-10 2:33 [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 1/5] async: introduce 'async_domain' type Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 2/5] async: make async_synchronize_full() flush all work regardless of domain Dan Williams
@ 2012-07-10 2:33 ` Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 4/5] scsi: cleanup usages of scsi_complete_async_scans Dan Williams
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2012-07-10 2:33 UTC (permalink / raw)
To: jgarzik, JBottomley
Cc: Len Brown, linux-scsi, Eldad Zack, Rafael J. Wysocki, linux-ide,
Arjan van de Ven
This is preparation to enable async_synchronize_full() to be used as a
replacement for scsi_complete_async_scans(), i.e. to stop leaking scsi
internal details where they are not needed.
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Len Brown <len.brown@intel.com>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: James Bottomley <JBottomley@parallels.com>
Tested-by: Eldad Zack <eldad@fogrefinery.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/scsi_scan.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f55e5f1..dff17c1 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1845,14 +1845,13 @@ static void do_scsi_scan_host(struct Scsi_Host *shost)
}
}
-static int do_scan_async(void *_data)
+static void do_scan_async(void *_data, async_cookie_t c)
{
struct async_scan_data *data = _data;
struct Scsi_Host *shost = data->shost;
do_scsi_scan_host(shost);
scsi_finish_async_scan(data);
- return 0;
}
/**
@@ -1861,7 +1860,6 @@ static int do_scan_async(void *_data)
**/
void scsi_scan_host(struct Scsi_Host *shost)
{
- struct task_struct *p;
struct async_scan_data *data;
if (strncmp(scsi_scan_type, "none", 4) == 0)
@@ -1876,9 +1874,11 @@ void scsi_scan_host(struct Scsi_Host *shost)
return;
}
- p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
- if (IS_ERR(p))
- do_scan_async(data);
+ /* register with the async subsystem so wait_for_device_probe()
+ * will flush this work
+ */
+ async_schedule(do_scan_async, data);
+
/* scsi_autopm_put_host(shost) is called in scsi_finish_async_scan() */
}
EXPORT_SYMBOL(scsi_scan_host);
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [set4 resend PATCH 4/5] scsi: cleanup usages of scsi_complete_async_scans
2012-07-10 2:33 [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
` (2 preceding siblings ...)
2012-07-10 2:33 ` [set4 resend PATCH 3/5] scsi: queue async scan work to an async_schedule domain Dan Williams
@ 2012-07-10 2:33 ` Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 5/5] Revert "[SCSI] fix async probe regression" Dan Williams
2012-07-10 3:34 ` [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2012-07-10 2:33 UTC (permalink / raw)
To: jgarzik, JBottomley
Cc: Len Brown, linux-scsi, Eldad Zack, Rafael J. Wysocki, linux-ide,
Arjan van de Ven
Now that scsi registers its async scan work with the async subsystem,
wait_for_device_probe() is sufficient for ensuring all scanning is
complete.
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Len Brown <len.brown@intel.com>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: James Bottomley <JBottomley@parallels.com>
Tested-by: Eldad Zack <eldad@fogrefinery.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/scsi_scan.c | 12 ------------
include/scsi/scsi_scan.h | 11 -----------
kernel/power/hibernate.c | 8 --------
kernel/power/user.c | 2 --
4 files changed, 33 deletions(-)
delete mode 100644 include/scsi/scsi_scan.h
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index dff17c1..a0bc663 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -187,18 +187,6 @@ int scsi_complete_async_scans(void)
return 0;
}
-/* Only exported for the benefit of scsi_wait_scan */
-EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
-
-#ifndef MODULE
-/*
- * For async scanning we need to wait for all the scans to complete before
- * trying to mount the root fs. Otherwise non-modular drivers may not be ready
- * yet.
- */
-late_initcall(scsi_complete_async_scans);
-#endif
-
/**
* scsi_unlock_floptical - unlock device via a special MODE SENSE command
* @sdev: scsi device to send command to
diff --git a/include/scsi/scsi_scan.h b/include/scsi/scsi_scan.h
deleted file mode 100644
index 7889888..0000000
--- a/include/scsi/scsi_scan.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _SCSI_SCSI_SCAN_H
-#define _SCSI_SCSI_SCAN_H
-
-#ifdef CONFIG_SCSI
-/* drivers/scsi/scsi_scan.c */
-extern int scsi_complete_async_scans(void);
-#else
-static inline int scsi_complete_async_scans(void) { return 0; }
-#endif
-
-#endif /* _SCSI_SCSI_SCAN_H */
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 8b53db3..238025f 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -27,7 +27,6 @@
#include <linux/syscore_ops.h>
#include <linux/ctype.h>
#include <linux/genhd.h>
-#include <scsi/scsi_scan.h>
#include "power.h"
@@ -748,13 +747,6 @@ static int software_resume(void)
async_synchronize_full();
}
- /*
- * We can't depend on SCSI devices being available after loading
- * one of their modules until scsi_complete_async_scans() is
- * called and the resume device usually is a SCSI one.
- */
- scsi_complete_async_scans();
-
swsusp_resume_device = name_to_dev_t(resume_file);
if (!swsusp_resume_device) {
error = -ENODEV;
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 91b0fd0..4ed81e7 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -24,7 +24,6 @@
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/freezer.h>
-#include <scsi/scsi_scan.h>
#include <asm/uaccess.h>
@@ -84,7 +83,6 @@ static int snapshot_open(struct inode *inode, struct file *filp)
* appear.
*/
wait_for_device_probe();
- scsi_complete_async_scans();
data->swap = -1;
data->mode = O_WRONLY;
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [set4 resend PATCH 5/5] Revert "[SCSI] fix async probe regression"
2012-07-10 2:33 [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
` (3 preceding siblings ...)
2012-07-10 2:33 ` [set4 resend PATCH 4/5] scsi: cleanup usages of scsi_complete_async_scans Dan Williams
@ 2012-07-10 2:33 ` Dan Williams
2012-07-10 3:34 ` [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2012-07-10 2:33 UTC (permalink / raw)
To: jgarzik, JBottomley; +Cc: linux-ide, Meelis Roos, Eldad Zack, linux-scsi
This reverts commit 43a8d39d0137612c336aa8bbb2cb886a79772ffb.
Commit 43a8d39d fixed the fact that wait_for_device_probe() was unable
to flush sd probe work. Now that sd probe work is once again flushable
via wait_for_device_probe() this workaround is no longer needed.
Cc: Meelis Roos <mroos@linux.ee>
Tested-by: Eldad Zack <eldad@fogrefinery.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/scsi/scsi_scan.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index a0bc663..56a9379 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -147,7 +147,7 @@ int scsi_complete_async_scans(void)
do {
if (list_empty(&scanning_hosts))
- goto out;
+ return 0;
/* If we can't get memory immediately, that's OK. Just
* sleep a little. Even if we never get memory, the async
* scans will finish eventually.
@@ -179,11 +179,8 @@ int scsi_complete_async_scans(void)
}
done:
spin_unlock(&async_scan_lock);
- kfree(data);
-
- out:
- async_synchronize_full_domain(&scsi_sd_probe_domain);
+ kfree(data);
return 0;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once"
2012-07-10 2:33 [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
` (4 preceding siblings ...)
2012-07-10 2:33 ` [set4 resend PATCH 5/5] Revert "[SCSI] fix async probe regression" Dan Williams
@ 2012-07-10 3:34 ` Dan Williams
5 siblings, 0 replies; 7+ messages in thread
From: Dan Williams @ 2012-07-10 3:34 UTC (permalink / raw)
To: jgarzik, JBottomley; +Cc: linux-ide, linux-scsi
Sorry. Sent the wrong cover letter with this patch set.
Should be:
Subject: [set5 PATCH v2 0/5] scsi, async: asynchronous probing rework
Changes since v1: http://marc.info/?l=linux-scsi&m=134034693629294&w=2
1/ rebased on scsi/for-next to pick up the scsi_wait_scan module deletion
2/ added Arjan's ack (spoke with Arjan offline)
3/ added Eldad's tested-by
4/ dropped the scsi async scan fix that was merged to scsi/misc
Original description:
Set5 of 5 patchsets to update scsi, libsas, and libata in
support of the isci driver.
Commit 43a8d39d "[SCSI] fix async probe regression" found that
async_synchronize_full() was missing async work that was scheduled to
its own domain. This led James to note:
"My theory is that this is an init problem: The assumption in a lot of
our code is that async_synchronize_full() waits for everything ... even
the domain specific async schedules, which isn't true."
...and this set aims to make that assumption true, but also with the
ability to opt-out for "private" async work.
---
Dan Williams (5):
async: introduce 'async_domain' type
async: make async_synchronize_full() flush all work regardless of domain
scsi: queue async scan work to an async_schedule domain
scsi: cleanup usages of scsi_complete_async_scans
Revert "[SCSI] fix async probe regression"
drivers/regulator/core.c | 2 +
drivers/scsi/libsas/sas_ata.c | 2 +
drivers/scsi/scsi.c | 4 ++
drivers/scsi/scsi_priv.h | 2 +
drivers/scsi/scsi_scan.c | 31 ++++-------------
include/linux/async.h | 36 +++++++++++++++++--
include/scsi/scsi_scan.h | 11 ------
kernel/async.c | 76 +++++++++++++++++++++++++++++++----------
kernel/power/hibernate.c | 8 ----
kernel/power/user.c | 2 -
sound/soc/soc-dapm.c | 2 +
11 files changed, 104 insertions(+), 72 deletions(-)
delete mode 100644 include/scsi/scsi_scan.h
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-07-10 3:34 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-10 2:33 [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 1/5] async: introduce 'async_domain' type Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 2/5] async: make async_synchronize_full() flush all work regardless of domain Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 3/5] scsi: queue async scan work to an async_schedule domain Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 4/5] scsi: cleanup usages of scsi_complete_async_scans Dan Williams
2012-07-10 2:33 ` [set4 resend PATCH 5/5] Revert "[SCSI] fix async probe regression" Dan Williams
2012-07-10 3:34 ` [set4 resend PATCH 0/5] libsas, libata: suspend / resume and "reset once" Dan Williams
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).