diff options
author | Arjan van de Ven <arjan@linux.intel.com> | 2009-01-04 08:32:28 -0500 |
---|---|---|
committer | Arjan van de Ven <arjan@linux.intel.com> | 2009-01-07 11:46:57 -0500 |
commit | 793180570ff2530d133343ceea85648de5f01b02 (patch) | |
tree | de75df600287442c4eb527a2e0bd607517b14a59 /drivers/ata | |
parent | 4ace92fc112c6069b4fcb95a31d3142d4a43ff2a (diff) |
fastboot: make the libata port scan asynchronous
This patch makes the libata port scanning asynchronous (per device).
There is a synchronization point before doing the actual disk scan
so that device ordering is not affected.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-core.c | 84 |
1 files changed, 46 insertions, 38 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index fecca4223f8e..7d3ae6a6fce7 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/workqueue.h> | 56 | #include <linux/workqueue.h> |
57 | #include <linux/scatterlist.h> | 57 | #include <linux/scatterlist.h> |
58 | #include <linux/io.h> | 58 | #include <linux/io.h> |
59 | #include <linux/async.h> | ||
59 | #include <scsi/scsi.h> | 60 | #include <scsi/scsi.h> |
60 | #include <scsi/scsi_cmnd.h> | 61 | #include <scsi/scsi_cmnd.h> |
61 | #include <scsi/scsi_host.h> | 62 | #include <scsi/scsi_host.h> |
@@ -5909,6 +5910,48 @@ void ata_host_init(struct ata_host *host, struct device *dev, | |||
5909 | host->ops = ops; | 5910 | host->ops = ops; |
5910 | } | 5911 | } |
5911 | 5912 | ||
5913 | |||
5914 | static void async_port_probe(void *data, async_cookie_t cookie) | ||
5915 | { | ||
5916 | int rc; | ||
5917 | struct ata_port *ap = data; | ||
5918 | /* probe */ | ||
5919 | if (ap->ops->error_handler) { | ||
5920 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
5921 | unsigned long flags; | ||
5922 | |||
5923 | ata_port_probe(ap); | ||
5924 | |||
5925 | /* kick EH for boot probing */ | ||
5926 | spin_lock_irqsave(ap->lock, flags); | ||
5927 | |||
5928 | ehi->probe_mask |= ATA_ALL_DEVICES; | ||
5929 | ehi->action |= ATA_EH_RESET | ATA_EH_LPM; | ||
5930 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; | ||
5931 | |||
5932 | ap->pflags &= ~ATA_PFLAG_INITIALIZING; | ||
5933 | ap->pflags |= ATA_PFLAG_LOADING; | ||
5934 | ata_port_schedule_eh(ap); | ||
5935 | |||
5936 | spin_unlock_irqrestore(ap->lock, flags); | ||
5937 | |||
5938 | /* wait for EH to finish */ | ||
5939 | ata_port_wait_eh(ap); | ||
5940 | } else { | ||
5941 | DPRINTK("ata%u: bus probe begin\n", ap->print_id); | ||
5942 | rc = ata_bus_probe(ap); | ||
5943 | DPRINTK("ata%u: bus probe end\n", ap->print_id); | ||
5944 | |||
5945 | if (rc) { | ||
5946 | /* FIXME: do something useful here? | ||
5947 | * Current libata behavior will | ||
5948 | * tear down everything when | ||
5949 | * the module is removed | ||
5950 | * or the h/w is unplugged. | ||
5951 | */ | ||
5952 | } | ||
5953 | } | ||
5954 | } | ||
5912 | /** | 5955 | /** |
5913 | * ata_host_register - register initialized ATA host | 5956 | * ata_host_register - register initialized ATA host |
5914 | * @host: ATA host to register | 5957 | * @host: ATA host to register |
@@ -5988,45 +6031,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) | |||
5988 | DPRINTK("probe begin\n"); | 6031 | DPRINTK("probe begin\n"); |
5989 | for (i = 0; i < host->n_ports; i++) { | 6032 | for (i = 0; i < host->n_ports; i++) { |
5990 | struct ata_port *ap = host->ports[i]; | 6033 | struct ata_port *ap = host->ports[i]; |
5991 | 6034 | async_schedule(async_port_probe, ap); | |
5992 | /* probe */ | ||
5993 | if (ap->ops->error_handler) { | ||
5994 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
5995 | unsigned long flags; | ||
5996 | |||
5997 | ata_port_probe(ap); | ||
5998 | |||
5999 | /* kick EH for boot probing */ | ||
6000 | spin_lock_irqsave(ap->lock, flags); | ||
6001 | |||
6002 | ehi->probe_mask |= ATA_ALL_DEVICES; | ||
6003 | ehi->action |= ATA_EH_RESET | ATA_EH_LPM; | ||
6004 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; | ||
6005 | |||
6006 | ap->pflags &= ~ATA_PFLAG_INITIALIZING; | ||
6007 | ap->pflags |= ATA_PFLAG_LOADING; | ||
6008 | ata_port_schedule_eh(ap); | ||
6009 | |||
6010 | spin_unlock_irqrestore(ap->lock, flags); | ||
6011 | |||
6012 | /* wait for EH to finish */ | ||
6013 | ata_port_wait_eh(ap); | ||
6014 | } else { | ||
6015 | DPRINTK("ata%u: bus probe begin\n", ap->print_id); | ||
6016 | rc = ata_bus_probe(ap); | ||
6017 | DPRINTK("ata%u: bus probe end\n", ap->print_id); | ||
6018 | |||
6019 | if (rc) { | ||
6020 | /* FIXME: do something useful here? | ||
6021 | * Current libata behavior will | ||
6022 | * tear down everything when | ||
6023 | * the module is removed | ||
6024 | * or the h/w is unplugged. | ||
6025 | */ | ||
6026 | } | ||
6027 | } | ||
6028 | } | 6035 | } |
6029 | 6036 | async_synchronize_full(); | |
6030 | /* probes are done, now scan each port's disk(s) */ | 6037 | /* probes are done, now scan each port's disk(s) */ |
6031 | DPRINTK("host probe begin\n"); | 6038 | DPRINTK("host probe begin\n"); |
6032 | for (i = 0; i < host->n_ports; i++) { | 6039 | for (i = 0; i < host->n_ports; i++) { |
@@ -6034,6 +6041,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) | |||
6034 | 6041 | ||
6035 | ata_scsi_scan_host(ap, 1); | 6042 | ata_scsi_scan_host(ap, 1); |
6036 | } | 6043 | } |
6044 | DPRINTK("host probe end\n"); | ||
6037 | 6045 | ||
6038 | return 0; | 6046 | return 0; |
6039 | } | 6047 | } |