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>
This commit is contained in:
@@ -56,6 +56,7 @@
|
|||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/scatterlist.h>
|
#include <linux/scatterlist.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/async.h>
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
#include <scsi/scsi_cmnd.h>
|
#include <scsi/scsi_cmnd.h>
|
||||||
#include <scsi/scsi_host.h>
|
#include <scsi/scsi_host.h>
|
||||||
@@ -5909,6 +5910,48 @@ void ata_host_init(struct ata_host *host, struct device *dev,
|
|||||||
host->ops = ops;
|
host->ops = ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void async_port_probe(void *data, async_cookie_t cookie)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct ata_port *ap = data;
|
||||||
|
/* probe */
|
||||||
|
if (ap->ops->error_handler) {
|
||||||
|
struct ata_eh_info *ehi = &ap->link.eh_info;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
ata_port_probe(ap);
|
||||||
|
|
||||||
|
/* kick EH for boot probing */
|
||||||
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
|
|
||||||
|
ehi->probe_mask |= ATA_ALL_DEVICES;
|
||||||
|
ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
|
||||||
|
ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
|
||||||
|
|
||||||
|
ap->pflags &= ~ATA_PFLAG_INITIALIZING;
|
||||||
|
ap->pflags |= ATA_PFLAG_LOADING;
|
||||||
|
ata_port_schedule_eh(ap);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(ap->lock, flags);
|
||||||
|
|
||||||
|
/* wait for EH to finish */
|
||||||
|
ata_port_wait_eh(ap);
|
||||||
|
} else {
|
||||||
|
DPRINTK("ata%u: bus probe begin\n", ap->print_id);
|
||||||
|
rc = ata_bus_probe(ap);
|
||||||
|
DPRINTK("ata%u: bus probe end\n", ap->print_id);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
/* FIXME: do something useful here?
|
||||||
|
* Current libata behavior will
|
||||||
|
* tear down everything when
|
||||||
|
* the module is removed
|
||||||
|
* or the h/w is unplugged.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* ata_host_register - register initialized ATA host
|
* ata_host_register - register initialized ATA host
|
||||||
* @host: ATA host to register
|
* @host: ATA host to register
|
||||||
@@ -5988,45 +6031,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
|
|||||||
DPRINTK("probe begin\n");
|
DPRINTK("probe begin\n");
|
||||||
for (i = 0; i < host->n_ports; i++) {
|
for (i = 0; i < host->n_ports; i++) {
|
||||||
struct ata_port *ap = host->ports[i];
|
struct ata_port *ap = host->ports[i];
|
||||||
|
async_schedule(async_port_probe, ap);
|
||||||
/* probe */
|
|
||||||
if (ap->ops->error_handler) {
|
|
||||||
struct ata_eh_info *ehi = &ap->link.eh_info;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
ata_port_probe(ap);
|
|
||||||
|
|
||||||
/* kick EH for boot probing */
|
|
||||||
spin_lock_irqsave(ap->lock, flags);
|
|
||||||
|
|
||||||
ehi->probe_mask |= ATA_ALL_DEVICES;
|
|
||||||
ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
|
|
||||||
ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
|
|
||||||
|
|
||||||
ap->pflags &= ~ATA_PFLAG_INITIALIZING;
|
|
||||||
ap->pflags |= ATA_PFLAG_LOADING;
|
|
||||||
ata_port_schedule_eh(ap);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(ap->lock, flags);
|
|
||||||
|
|
||||||
/* wait for EH to finish */
|
|
||||||
ata_port_wait_eh(ap);
|
|
||||||
} else {
|
|
||||||
DPRINTK("ata%u: bus probe begin\n", ap->print_id);
|
|
||||||
rc = ata_bus_probe(ap);
|
|
||||||
DPRINTK("ata%u: bus probe end\n", ap->print_id);
|
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
/* FIXME: do something useful here?
|
|
||||||
* Current libata behavior will
|
|
||||||
* tear down everything when
|
|
||||||
* the module is removed
|
|
||||||
* or the h/w is unplugged.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
async_synchronize_full();
|
||||||
/* probes are done, now scan each port's disk(s) */
|
/* probes are done, now scan each port's disk(s) */
|
||||||
DPRINTK("host probe begin\n");
|
DPRINTK("host probe begin\n");
|
||||||
for (i = 0; i < host->n_ports; i++) {
|
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)
|
|||||||
|
|
||||||
ata_scsi_scan_host(ap, 1);
|
ata_scsi_scan_host(ap, 1);
|
||||||
}
|
}
|
||||||
|
DPRINTK("host probe end\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user