aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ahci.c3
-rw-r--r--drivers/scsi/libata-bmdma.c11
-rw-r--r--drivers/scsi/libata-core.c85
-rw-r--r--drivers/scsi/libata-eh.c60
-rw-r--r--drivers/scsi/sata_sil24.c3
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
1032static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) 1033static 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 */
713void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset, 714void 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
2528static 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 */
2569int 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);
5840EXPORT_SYMBOL_GPL(__sata_phy_reset); 5924EXPORT_SYMBOL_GPL(__sata_phy_reset);
5841EXPORT_SYMBOL_GPL(ata_bus_reset); 5925EXPORT_SYMBOL_GPL(ata_bus_reset);
5842EXPORT_SYMBOL_GPL(ata_std_probeinit); 5926EXPORT_SYMBOL_GPL(ata_std_probeinit);
5927EXPORT_SYMBOL_GPL(ata_std_prereset);
5843EXPORT_SYMBOL_GPL(ata_std_softreset); 5928EXPORT_SYMBOL_GPL(ata_std_softreset);
5844EXPORT_SYMBOL_GPL(sata_std_hardreset); 5929EXPORT_SYMBOL_GPL(sata_std_hardreset);
5845EXPORT_SYMBOL_GPL(ata_std_postreset); 5930EXPORT_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
1321static int ata_eh_reset(struct ata_port *ap, ata_reset_fn_t softreset, 1321static 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 */
1443static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset, 1482static 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 */
1598void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset, 1639void 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
918static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) 919static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)