Commit 3e706399b03bd237d087d731d4b1b029e546b33d
1 parent
ccf68c3405
Exists in
master
and in
7 other branches
[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>
Showing 2 changed files with 52 additions and 24 deletions Side-by-side Diff
drivers/scsi/libata-core.c
... | ... | @@ -5419,7 +5419,7 @@ |
5419 | 5419 | |
5420 | 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 | 5423 | !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { |
5424 | 5424 | printk(KERN_ERR "ata%u: no reset mechanism available\n", |
5425 | 5425 | port_no); |
... | ... | @@ -5465,7 +5465,6 @@ |
5465 | 5465 | * RETURNS: |
5466 | 5466 | * Number of ports registered. Zero on error (no ports registered). |
5467 | 5467 | */ |
5468 | - | |
5469 | 5468 | int ata_device_add(const struct ata_probe_ent *ent) |
5470 | 5469 | { |
5471 | 5470 | unsigned int count = 0, i; |
... | ... | @@ -5542,19 +5541,6 @@ |
5542 | 5541 | } |
5543 | 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 | 5544 | rc = scsi_add_host(ap->host, dev); |
5559 | 5545 | if (rc) { |
5560 | 5546 | ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n"); |
... | ... | @@ -5563,6 +5549,39 @@ |
5563 | 5549 | * scsi_scan_host and ata_host_remove, below, |
5564 | 5550 | * at the very least |
5565 | 5551 | */ |
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 | + } | |
5566 | 5585 | } |
5567 | 5586 | } |
5568 | 5587 |
drivers/scsi/libata-eh.c
... | ... | @@ -287,12 +287,15 @@ |
287 | 287 | /* clean up */ |
288 | 288 | spin_lock_irqsave(hs_lock, flags); |
289 | 289 | |
290 | - if (ap->flags & ATA_FLAG_SCSI_HOTPLUG) | |
291 | - queue_work(ata_aux_wq, &ap->hotplug_task); | |
290 | + if (ap->flags & ATA_FLAG_LOADING) { | |
291 | + ap->flags &= ~ATA_FLAG_LOADING; | |
292 | + } else { | |
293 | + if (ap->flags & ATA_FLAG_SCSI_HOTPLUG) | |
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 | + } | |
292 | 298 | |
293 | - if (ap->flags & ATA_FLAG_RECOVERED) | |
294 | - ata_port_printk(ap, KERN_INFO, "EH complete\n"); | |
295 | - | |
296 | 299 | ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED); |
297 | 300 | |
298 | 301 | /* tell wait_eh that we're done */ |
... | ... | @@ -1367,6 +1370,7 @@ |
1367 | 1370 | struct ata_eh_context *ehc = &ap->eh_context; |
1368 | 1371 | unsigned int *classes = ehc->classes; |
1369 | 1372 | int tries = ATA_EH_RESET_TRIES; |
1373 | + int verbose = !(ap->flags & ATA_FLAG_LOADING); | |
1370 | 1374 | unsigned int action; |
1371 | 1375 | ata_reset_fn_t reset; |
1372 | 1376 | int i, did_followup_srst, rc; |
... | ... | @@ -1414,8 +1418,10 @@ |
1414 | 1418 | } |
1415 | 1419 | |
1416 | 1420 | retry: |
1417 | - ata_port_printk(ap, KERN_INFO, "%s resetting port\n", | |
1418 | - reset == softreset ? "soft" : "hard"); | |
1421 | + /* shut up during boot probing */ | |
1422 | + if (verbose) | |
1423 | + ata_port_printk(ap, KERN_INFO, "%s resetting port\n", | |
1424 | + reset == softreset ? "soft" : "hard"); | |
1419 | 1425 | |
1420 | 1426 | /* reset */ |
1421 | 1427 | ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); |
... | ... | @@ -1799,8 +1805,11 @@ |
1799 | 1805 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, |
1800 | 1806 | ata_postreset_fn_t postreset) |
1801 | 1807 | { |
1802 | - ata_eh_autopsy(ap); | |
1803 | - ata_eh_report(ap); | |
1808 | + if (!(ap->flags & ATA_FLAG_LOADING)) { | |
1809 | + ata_eh_autopsy(ap); | |
1810 | + ata_eh_report(ap); | |
1811 | + } | |
1812 | + | |
1804 | 1813 | ata_eh_recover(ap, prereset, softreset, hardreset, postreset); |
1805 | 1814 | ata_eh_finish(ap); |
1806 | 1815 | } |