aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-eh.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libata-eh.c')
-rw-r--r--drivers/scsi/libata-eh.c60
1 files changed, 51 insertions, 9 deletions
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}