diff options
author | Tejun Heo <htejun@gmail.com> | 2006-05-31 18:28:11 +0900 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-05-31 18:28:11 +0900 |
commit | 3e706399b03bd237d087d731d4b1b029e546b33d (patch) | |
tree | 51a5de83f8493d1b78cc16b0fa0abcac2b37cebc /drivers/scsi/libata-core.c | |
parent | ccf68c3405fca11386004674377d951b9b18e756 (diff) | |
download | linux-3e706399b03bd237d087d731d4b1b029e546b33d.tar.bz2 |
[PATCH] libata-hp: implement bootplug
Implement bootplug - boot probing via hotplug path. While loading,
ata_host_add() simply schedules probing and invokes EH. After EH
completes, ata_host_add() scans and assicates them with SCSI devices.
EH path is slightly modified to handle this (e.g. no autopsy during
bootplug). The SCSI part is left in ata_host_add() because it's
shared with legacy path and to keep probing order as before (ATA scan
all ports in host_set then attach all).
Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r-- | drivers/scsi/libata-core.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index c61cfc742388..a42877e6b865 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -5419,7 +5419,7 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, DPRINTK("ENTER\n"); - if (!ent->port_ops->probe_reset && + if (!ent->port_ops->probe_reset && !ent->port_ops->error_handler && !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { printk(KERN_ERR "ata%u: no reset mechanism available\n", port_no); @@ -5465,7 +5465,6 @@ err_out: * RETURNS: * Number of ports registered. Zero on error (no ports registered). */ - int ata_device_add(const struct ata_probe_ent *ent) { unsigned int count = 0, i; @@ -5542,19 +5541,6 @@ int ata_device_add(const struct ata_probe_ent *ent) } ap->sata_spd_limit = ap->hw_sata_spd_limit; - DPRINTK("ata%u: bus probe begin\n", ap->id); - rc = ata_bus_probe(ap); - DPRINTK("ata%u: bus probe end\n", ap->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. - */ - } - rc = scsi_add_host(ap->host, dev); if (rc) { ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n"); @@ -5564,6 +5550,39 @@ int ata_device_add(const struct ata_probe_ent *ent) * at the very least */ } + + if (!ap->ops->probe_reset) { + unsigned long flags; + + ata_port_probe(ap); + + /* kick EH for boot probing */ + spin_lock_irqsave(&ap->host_set->lock, flags); + + ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1; + ap->eh_info.action |= ATA_EH_SOFTRESET; + + ap->flags |= ATA_FLAG_LOADING; + ata_port_schedule_eh(ap); + + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + /* wait for EH to finish */ + ata_port_wait_eh(ap); + } else { + DPRINTK("ata%u: bus probe begin\n", ap->id); + rc = ata_bus_probe(ap); + DPRINTK("ata%u: bus probe end\n", ap->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. + */ + } + } } /* probes are done, now scan each port's disk(s) */ |