diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/ahci.c | 3 | ||||
-rw-r--r-- | drivers/scsi/libata-bmdma.c | 11 | ||||
-rw-r--r-- | drivers/scsi/libata-core.c | 85 | ||||
-rw-r--r-- | drivers/scsi/libata-eh.c | 60 | ||||
-rw-r--r-- | drivers/scsi/sata_sil24.c | 3 |
5 files changed, 147 insertions, 15 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 45fd71d80128..8493b021cc07 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c | |||
@@ -1026,7 +1026,8 @@ static void ahci_error_handler(struct ata_port *ap) | |||
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | /* perform recovery */ | 1028 | /* perform recovery */ |
1029 | ata_do_eh(ap, ahci_softreset, ahci_hardreset, ahci_postreset); | 1029 | ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, |
1030 | ahci_postreset); | ||
1030 | } | 1031 | } |
1031 | 1032 | ||
1032 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) | 1033 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) |
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 6d30d2c52960..4bc05371737c 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c | |||
@@ -695,6 +695,7 @@ void ata_bmdma_thaw(struct ata_port *ap) | |||
695 | /** | 695 | /** |
696 | * ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller | 696 | * ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller |
697 | * @ap: port to handle error for | 697 | * @ap: port to handle error for |
698 | * @prereset: prereset method (can be NULL) | ||
698 | * @softreset: softreset method (can be NULL) | 699 | * @softreset: softreset method (can be NULL) |
699 | * @hardreset: hardreset method (can be NULL) | 700 | * @hardreset: hardreset method (can be NULL) |
700 | * @postreset: postreset method (can be NULL) | 701 | * @postreset: postreset method (can be NULL) |
@@ -710,8 +711,9 @@ void ata_bmdma_thaw(struct ata_port *ap) | |||
710 | * LOCKING: | 711 | * LOCKING: |
711 | * Kernel thread context (may sleep) | 712 | * Kernel thread context (may sleep) |
712 | */ | 713 | */ |
713 | void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, | 714 | void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, |
714 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) | 715 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, |
716 | ata_postreset_fn_t postreset) | ||
715 | { | 717 | { |
716 | struct ata_host_set *host_set = ap->host_set; | 718 | struct ata_host_set *host_set = ap->host_set; |
717 | struct ata_eh_context *ehc = &ap->eh_context; | 719 | struct ata_eh_context *ehc = &ap->eh_context; |
@@ -759,7 +761,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, | |||
759 | ata_eh_thaw_port(ap); | 761 | ata_eh_thaw_port(ap); |
760 | 762 | ||
761 | /* PIO and DMA engines have been stopped, perform recovery */ | 763 | /* PIO and DMA engines have been stopped, perform recovery */ |
762 | ata_do_eh(ap, softreset, hardreset, postreset); | 764 | ata_do_eh(ap, prereset, softreset, hardreset, postreset); |
763 | } | 765 | } |
764 | 766 | ||
765 | /** | 767 | /** |
@@ -779,7 +781,8 @@ void ata_bmdma_error_handler(struct ata_port *ap) | |||
779 | if (sata_scr_valid(ap)) | 781 | if (sata_scr_valid(ap)) |
780 | hardreset = sata_std_hardreset; | 782 | hardreset = sata_std_hardreset; |
781 | 783 | ||
782 | ata_bmdma_drive_eh(ap, ata_std_softreset, hardreset, ata_std_postreset); | 784 | ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset, |
785 | ata_std_postreset); | ||
783 | } | 786 | } |
784 | 787 | ||
785 | /** | 788 | /** |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 4823ecefb8a1..2531a701d6e9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -2525,6 +2525,90 @@ int sata_phy_resume(struct ata_port *ap, const unsigned long *params) | |||
2525 | return sata_phy_debounce(ap, params); | 2525 | return sata_phy_debounce(ap, params); |
2526 | } | 2526 | } |
2527 | 2527 | ||
2528 | static void ata_wait_spinup(struct ata_port *ap) | ||
2529 | { | ||
2530 | struct ata_eh_context *ehc = &ap->eh_context; | ||
2531 | unsigned long end, secs; | ||
2532 | int rc; | ||
2533 | |||
2534 | /* first, debounce phy if SATA */ | ||
2535 | if (ap->cbl == ATA_CBL_SATA) { | ||
2536 | rc = sata_phy_debounce(ap, sata_deb_timing_eh); | ||
2537 | |||
2538 | /* if debounced successfully and offline, no need to wait */ | ||
2539 | if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap)) | ||
2540 | return; | ||
2541 | } | ||
2542 | |||
2543 | /* okay, let's give the drive time to spin up */ | ||
2544 | end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000; | ||
2545 | secs = ((end - jiffies) + HZ - 1) / HZ; | ||
2546 | |||
2547 | if (time_after(jiffies, end)) | ||
2548 | return; | ||
2549 | |||
2550 | if (secs > 5) | ||
2551 | ata_port_printk(ap, KERN_INFO, "waiting for device to spin up " | ||
2552 | "(%lu secs)\n", secs); | ||
2553 | |||
2554 | schedule_timeout_uninterruptible(end - jiffies); | ||
2555 | } | ||
2556 | |||
2557 | /** | ||
2558 | * ata_std_prereset - prepare for reset | ||
2559 | * @ap: ATA port to be reset | ||
2560 | * | ||
2561 | * @ap is about to be reset. Initialize it. | ||
2562 | * | ||
2563 | * LOCKING: | ||
2564 | * Kernel thread context (may sleep) | ||
2565 | * | ||
2566 | * RETURNS: | ||
2567 | * 0 on success, -errno otherwise. | ||
2568 | */ | ||
2569 | int ata_std_prereset(struct ata_port *ap) | ||
2570 | { | ||
2571 | struct ata_eh_context *ehc = &ap->eh_context; | ||
2572 | const unsigned long *timing; | ||
2573 | int rc; | ||
2574 | |||
2575 | /* hotplug? */ | ||
2576 | if (ehc->i.flags & ATA_EHI_HOTPLUGGED) { | ||
2577 | if (ap->flags & ATA_FLAG_HRST_TO_RESUME) | ||
2578 | ehc->i.action |= ATA_EH_HARDRESET; | ||
2579 | if (ap->flags & ATA_FLAG_SKIP_D2H_BSY) | ||
2580 | ata_wait_spinup(ap); | ||
2581 | } | ||
2582 | |||
2583 | /* if we're about to do hardreset, nothing more to do */ | ||
2584 | if (ehc->i.action & ATA_EH_HARDRESET) | ||
2585 | return 0; | ||
2586 | |||
2587 | /* if SATA, resume phy */ | ||
2588 | if (ap->cbl == ATA_CBL_SATA) { | ||
2589 | if (ap->flags & ATA_FLAG_LOADING) | ||
2590 | timing = sata_deb_timing_boot; | ||
2591 | else | ||
2592 | timing = sata_deb_timing_eh; | ||
2593 | |||
2594 | rc = sata_phy_resume(ap, timing); | ||
2595 | if (rc && rc != -EOPNOTSUPP) { | ||
2596 | /* phy resume failed */ | ||
2597 | ata_port_printk(ap, KERN_WARNING, "failed to resume " | ||
2598 | "link for reset (errno=%d)\n", rc); | ||
2599 | return rc; | ||
2600 | } | ||
2601 | } | ||
2602 | |||
2603 | /* Wait for !BSY if the controller can wait for the first D2H | ||
2604 | * Reg FIS and we don't know that no device is attached. | ||
2605 | */ | ||
2606 | if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap)) | ||
2607 | ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); | ||
2608 | |||
2609 | return 0; | ||
2610 | } | ||
2611 | |||
2528 | /** | 2612 | /** |
2529 | * ata_std_probeinit - initialize probing | 2613 | * ata_std_probeinit - initialize probing |
2530 | * @ap: port to be probed | 2614 | * @ap: port to be probed |
@@ -5840,6 +5924,7 @@ EXPORT_SYMBOL_GPL(sata_phy_reset); | |||
5840 | EXPORT_SYMBOL_GPL(__sata_phy_reset); | 5924 | EXPORT_SYMBOL_GPL(__sata_phy_reset); |
5841 | EXPORT_SYMBOL_GPL(ata_bus_reset); | 5925 | EXPORT_SYMBOL_GPL(ata_bus_reset); |
5842 | EXPORT_SYMBOL_GPL(ata_std_probeinit); | 5926 | EXPORT_SYMBOL_GPL(ata_std_probeinit); |
5927 | EXPORT_SYMBOL_GPL(ata_std_prereset); | ||
5843 | EXPORT_SYMBOL_GPL(ata_std_softreset); | 5928 | EXPORT_SYMBOL_GPL(ata_std_softreset); |
5844 | EXPORT_SYMBOL_GPL(sata_std_hardreset); | 5929 | EXPORT_SYMBOL_GPL(sata_std_hardreset); |
5845 | EXPORT_SYMBOL_GPL(ata_std_postreset); | 5930 | EXPORT_SYMBOL_GPL(ata_std_postreset); |
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 9173d8f2ce5d..0e66f140e53b 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c | |||
@@ -1318,20 +1318,58 @@ static void ata_eh_report(struct ata_port *ap) | |||
1318 | } | 1318 | } |
1319 | } | 1319 | } |
1320 | 1320 | ||
1321 | static int ata_eh_reset(struct ata_port *ap, ata_reset_fn_t softreset, | 1321 | static int ata_eh_reset(struct ata_port *ap, |
1322 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, | ||
1322 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) | 1323 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) |
1323 | { | 1324 | { |
1324 | struct ata_eh_context *ehc = &ap->eh_context; | 1325 | struct ata_eh_context *ehc = &ap->eh_context; |
1325 | unsigned int classes[ATA_MAX_DEVICES]; | 1326 | unsigned int classes[ATA_MAX_DEVICES]; |
1326 | int tries = ATA_EH_RESET_TRIES; | 1327 | int tries = ATA_EH_RESET_TRIES; |
1328 | unsigned int action; | ||
1327 | ata_reset_fn_t reset; | 1329 | ata_reset_fn_t reset; |
1328 | int i, rc; | 1330 | int i, rc; |
1329 | 1331 | ||
1332 | /* Determine which reset to use and record in ehc->i.action. | ||
1333 | * prereset() may examine and modify it. | ||
1334 | */ | ||
1335 | action = ehc->i.action; | ||
1336 | ehc->i.action &= ~ATA_EH_RESET_MASK; | ||
1330 | if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && | 1337 | if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && |
1331 | !(ehc->i.action & ATA_EH_HARDRESET)))) | 1338 | !(action & ATA_EH_HARDRESET)))) |
1332 | reset = softreset; | 1339 | ehc->i.action |= ATA_EH_SOFTRESET; |
1333 | else | 1340 | else |
1341 | ehc->i.action |= ATA_EH_HARDRESET; | ||
1342 | |||
1343 | if (prereset) { | ||
1344 | rc = prereset(ap); | ||
1345 | if (rc) { | ||
1346 | ata_port_printk(ap, KERN_ERR, | ||
1347 | "prereset failed (errno=%d)\n", rc); | ||
1348 | return rc; | ||
1349 | } | ||
1350 | } | ||
1351 | |||
1352 | /* prereset() might have modified ehc->i.action */ | ||
1353 | if (ehc->i.action & ATA_EH_HARDRESET) | ||
1334 | reset = hardreset; | 1354 | reset = hardreset; |
1355 | else if (ehc->i.action & ATA_EH_SOFTRESET) | ||
1356 | reset = softreset; | ||
1357 | else { | ||
1358 | /* prereset told us not to reset, bang classes and return */ | ||
1359 | for (i = 0; i < ATA_MAX_DEVICES; i++) | ||
1360 | classes[i] = ATA_DEV_NONE; | ||
1361 | return 0; | ||
1362 | } | ||
1363 | |||
1364 | /* did prereset() screw up? if so, fix up to avoid oopsing */ | ||
1365 | if (!reset) { | ||
1366 | ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested " | ||
1367 | "invalid reset type\n"); | ||
1368 | if (softreset) | ||
1369 | reset = softreset; | ||
1370 | else | ||
1371 | reset = hardreset; | ||
1372 | } | ||
1335 | 1373 | ||
1336 | retry: | 1374 | retry: |
1337 | ata_port_printk(ap, KERN_INFO, "%s resetting port\n", | 1375 | ata_port_printk(ap, KERN_INFO, "%s resetting port\n", |
@@ -1424,6 +1462,7 @@ static int ata_port_nr_enabled(struct ata_port *ap) | |||
1424 | /** | 1462 | /** |
1425 | * ata_eh_recover - recover host port after error | 1463 | * ata_eh_recover - recover host port after error |
1426 | * @ap: host port to recover | 1464 | * @ap: host port to recover |
1465 | * @prereset: prereset method (can be NULL) | ||
1427 | * @softreset: softreset method (can be NULL) | 1466 | * @softreset: softreset method (can be NULL) |
1428 | * @hardreset: hardreset method (can be NULL) | 1467 | * @hardreset: hardreset method (can be NULL) |
1429 | * @postreset: postreset method (can be NULL) | 1468 | * @postreset: postreset method (can be NULL) |
@@ -1440,8 +1479,8 @@ static int ata_port_nr_enabled(struct ata_port *ap) | |||
1440 | * RETURNS: | 1479 | * RETURNS: |
1441 | * 0 on success, -errno on failure. | 1480 | * 0 on success, -errno on failure. |
1442 | */ | 1481 | */ |
1443 | static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset, | 1482 | static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, |
1444 | ata_reset_fn_t hardreset, | 1483 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, |
1445 | ata_postreset_fn_t postreset) | 1484 | ata_postreset_fn_t postreset) |
1446 | { | 1485 | { |
1447 | struct ata_eh_context *ehc = &ap->eh_context; | 1486 | struct ata_eh_context *ehc = &ap->eh_context; |
@@ -1469,7 +1508,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset, | |||
1469 | if (ehc->i.action & ATA_EH_RESET_MASK) { | 1508 | if (ehc->i.action & ATA_EH_RESET_MASK) { |
1470 | ata_eh_freeze_port(ap); | 1509 | ata_eh_freeze_port(ap); |
1471 | 1510 | ||
1472 | rc = ata_eh_reset(ap, softreset, hardreset, postreset); | 1511 | rc = ata_eh_reset(ap, prereset, softreset, hardreset, |
1512 | postreset); | ||
1473 | if (rc) { | 1513 | if (rc) { |
1474 | ata_port_printk(ap, KERN_ERR, | 1514 | ata_port_printk(ap, KERN_ERR, |
1475 | "reset failed, giving up\n"); | 1515 | "reset failed, giving up\n"); |
@@ -1586,6 +1626,7 @@ static void ata_eh_finish(struct ata_port *ap) | |||
1586 | /** | 1626 | /** |
1587 | * ata_do_eh - do standard error handling | 1627 | * ata_do_eh - do standard error handling |
1588 | * @ap: host port to handle error for | 1628 | * @ap: host port to handle error for |
1629 | * @prereset: prereset method (can be NULL) | ||
1589 | * @softreset: softreset method (can be NULL) | 1630 | * @softreset: softreset method (can be NULL) |
1590 | * @hardreset: hardreset method (can be NULL) | 1631 | * @hardreset: hardreset method (can be NULL) |
1591 | * @postreset: postreset method (can be NULL) | 1632 | * @postreset: postreset method (can be NULL) |
@@ -1595,11 +1636,12 @@ static void ata_eh_finish(struct ata_port *ap) | |||
1595 | * LOCKING: | 1636 | * LOCKING: |
1596 | * Kernel thread context (may sleep). | 1637 | * Kernel thread context (may sleep). |
1597 | */ | 1638 | */ |
1598 | void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset, | 1639 | void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, |
1599 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) | 1640 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, |
1641 | ata_postreset_fn_t postreset) | ||
1600 | { | 1642 | { |
1601 | ata_eh_autopsy(ap); | 1643 | ata_eh_autopsy(ap); |
1602 | ata_eh_report(ap); | 1644 | ata_eh_report(ap); |
1603 | ata_eh_recover(ap, softreset, hardreset, postreset); | 1645 | ata_eh_recover(ap, prereset, softreset, hardreset, postreset); |
1604 | ata_eh_finish(ap); | 1646 | ata_eh_finish(ap); |
1605 | } | 1647 | } |
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 4c76f05d9b65..26d7c54c175e 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c | |||
@@ -912,7 +912,8 @@ static void sil24_error_handler(struct ata_port *ap) | |||
912 | } | 912 | } |
913 | 913 | ||
914 | /* perform recovery */ | 914 | /* perform recovery */ |
915 | ata_do_eh(ap, sil24_softreset, sil24_hardreset, ata_std_postreset); | 915 | ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, |
916 | ata_std_postreset); | ||
916 | } | 917 | } |
917 | 918 | ||
918 | static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) | 919 | static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) |