diff options
author | Tejun Heo <htejun@gmail.com> | 2006-05-31 05:28:11 -0400 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-05-31 05:28:11 -0400 |
commit | 3e706399b03bd237d087d731d4b1b029e546b33d (patch) | |
tree | 51a5de83f8493d1b78cc16b0fa0abcac2b37cebc | |
parent | ccf68c3405fca11386004674377d951b9b18e756 (diff) |
[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>
-rw-r--r-- | drivers/scsi/libata-core.c | 49 | ||||
-rw-r--r-- | drivers/scsi/libata-eh.c | 27 |
2 files changed, 52 insertions, 24 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, | |||
5419 | 5419 | ||
5420 | DPRINTK("ENTER\n"); | 5420 | DPRINTK("ENTER\n"); |
5421 | 5421 | ||
5422 | if (!ent->port_ops->probe_reset && | 5422 | if (!ent->port_ops->probe_reset && !ent->port_ops->error_handler && |
5423 | !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { | 5423 | !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { |
5424 | printk(KERN_ERR "ata%u: no reset mechanism available\n", | 5424 | printk(KERN_ERR "ata%u: no reset mechanism available\n", |
5425 | port_no); | 5425 | port_no); |
@@ -5465,7 +5465,6 @@ err_out: | |||
5465 | * RETURNS: | 5465 | * RETURNS: |
5466 | * Number of ports registered. Zero on error (no ports registered). | 5466 | * Number of ports registered. Zero on error (no ports registered). |
5467 | */ | 5467 | */ |
5468 | |||
5469 | int ata_device_add(const struct ata_probe_ent *ent) | 5468 | int ata_device_add(const struct ata_probe_ent *ent) |
5470 | { | 5469 | { |
5471 | unsigned int count = 0, i; | 5470 | unsigned int count = 0, i; |
@@ -5542,19 +5541,6 @@ int ata_device_add(const struct ata_probe_ent *ent) | |||
5542 | } | 5541 | } |
5543 | ap->sata_spd_limit = ap->hw_sata_spd_limit; | 5542 | ap->sata_spd_limit = ap->hw_sata_spd_limit; |
5544 | 5543 | ||
5545 | DPRINTK("ata%u: bus probe begin\n", ap->id); | ||
5546 | rc = ata_bus_probe(ap); | ||
5547 | DPRINTK("ata%u: bus probe end\n", ap->id); | ||
5548 | |||
5549 | if (rc) { | ||
5550 | /* FIXME: do something useful here? | ||
5551 | * Current libata behavior will | ||
5552 | * tear down everything when | ||
5553 | * the module is removed | ||
5554 | * or the h/w is unplugged. | ||
5555 | */ | ||
5556 | } | ||
5557 | |||
5558 | rc = scsi_add_host(ap->host, dev); | 5544 | rc = scsi_add_host(ap->host, dev); |
5559 | if (rc) { | 5545 | if (rc) { |
5560 | ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n"); | 5546 | 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) | |||
5564 | * at the very least | 5550 | * at the very least |
5565 | */ | 5551 | */ |
5566 | } | 5552 | } |
5553 | |||
5554 | if (!ap->ops->probe_reset) { | ||
5555 | unsigned long flags; | ||
5556 | |||
5557 | ata_port_probe(ap); | ||
5558 | |||
5559 | /* kick EH for boot probing */ | ||
5560 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
5561 | |||
5562 | ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1; | ||
5563 | ap->eh_info.action |= ATA_EH_SOFTRESET; | ||
5564 | |||
5565 | ap->flags |= ATA_FLAG_LOADING; | ||
5566 | ata_port_schedule_eh(ap); | ||
5567 | |||
5568 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
5569 | |||
5570 | /* wait for EH to finish */ | ||
5571 | ata_port_wait_eh(ap); | ||
5572 | } else { | ||
5573 | DPRINTK("ata%u: bus probe begin\n", ap->id); | ||
5574 | rc = ata_bus_probe(ap); | ||
5575 | DPRINTK("ata%u: bus probe end\n", ap->id); | ||
5576 | |||
5577 | if (rc) { | ||
5578 | /* FIXME: do something useful here? | ||
5579 | * Current libata behavior will | ||
5580 | * tear down everything when | ||
5581 | * the module is removed | ||
5582 | * or the h/w is unplugged. | ||
5583 | */ | ||
5584 | } | ||
5585 | } | ||
5567 | } | 5586 | } |
5568 | 5587 | ||
5569 | /* probes are done, now scan each port's disk(s) */ | 5588 | /* probes are done, now scan each port's disk(s) */ |
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 733dfa532977..70c132bef68e 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c | |||
@@ -287,11 +287,14 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
287 | /* clean up */ | 287 | /* clean up */ |
288 | spin_lock_irqsave(hs_lock, flags); | 288 | spin_lock_irqsave(hs_lock, flags); |
289 | 289 | ||
290 | if (ap->flags & ATA_FLAG_SCSI_HOTPLUG) | 290 | if (ap->flags & ATA_FLAG_LOADING) { |
291 | queue_work(ata_aux_wq, &ap->hotplug_task); | 291 | ap->flags &= ~ATA_FLAG_LOADING; |
292 | 292 | } else { | |
293 | if (ap->flags & ATA_FLAG_RECOVERED) | 293 | if (ap->flags & ATA_FLAG_SCSI_HOTPLUG) |
294 | ata_port_printk(ap, KERN_INFO, "EH complete\n"); | 294 | queue_work(ata_aux_wq, &ap->hotplug_task); |
295 | if (ap->flags & ATA_FLAG_RECOVERED) | ||
296 | ata_port_printk(ap, KERN_INFO, "EH complete\n"); | ||
297 | } | ||
295 | 298 | ||
296 | ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED); | 299 | ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED); |
297 | 300 | ||
@@ -1367,6 +1370,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1367 | struct ata_eh_context *ehc = &ap->eh_context; | 1370 | struct ata_eh_context *ehc = &ap->eh_context; |
1368 | unsigned int *classes = ehc->classes; | 1371 | unsigned int *classes = ehc->classes; |
1369 | int tries = ATA_EH_RESET_TRIES; | 1372 | int tries = ATA_EH_RESET_TRIES; |
1373 | int verbose = !(ap->flags & ATA_FLAG_LOADING); | ||
1370 | unsigned int action; | 1374 | unsigned int action; |
1371 | ata_reset_fn_t reset; | 1375 | ata_reset_fn_t reset; |
1372 | int i, did_followup_srst, rc; | 1376 | int i, did_followup_srst, rc; |
@@ -1414,8 +1418,10 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1414 | } | 1418 | } |
1415 | 1419 | ||
1416 | retry: | 1420 | retry: |
1417 | ata_port_printk(ap, KERN_INFO, "%s resetting port\n", | 1421 | /* shut up during boot probing */ |
1418 | reset == softreset ? "soft" : "hard"); | 1422 | if (verbose) |
1423 | ata_port_printk(ap, KERN_INFO, "%s resetting port\n", | ||
1424 | reset == softreset ? "soft" : "hard"); | ||
1419 | 1425 | ||
1420 | /* reset */ | 1426 | /* reset */ |
1421 | ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); | 1427 | ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); |
@@ -1799,8 +1805,11 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1799 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, | 1805 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, |
1800 | ata_postreset_fn_t postreset) | 1806 | ata_postreset_fn_t postreset) |
1801 | { | 1807 | { |
1802 | ata_eh_autopsy(ap); | 1808 | if (!(ap->flags & ATA_FLAG_LOADING)) { |
1803 | ata_eh_report(ap); | 1809 | ata_eh_autopsy(ap); |
1810 | ata_eh_report(ap); | ||
1811 | } | ||
1812 | |||
1804 | ata_eh_recover(ap, prereset, softreset, hardreset, postreset); | 1813 | ata_eh_recover(ap, prereset, softreset, hardreset, postreset); |
1805 | ata_eh_finish(ap); | 1814 | ata_eh_finish(ap); |
1806 | } | 1815 | } |