aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2009-01-04 08:32:28 -0500
committerArjan van de Ven <arjan@linux.intel.com>2009-01-07 11:46:57 -0500
commit793180570ff2530d133343ceea85648de5f01b02 (patch)
treede75df600287442c4eb527a2e0bd607517b14a59 /drivers/ata
parent4ace92fc112c6069b4fcb95a31d3142d4a43ff2a (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.c84
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
5914static 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}