aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libata-eh.c85
-rw-r--r--include/linux/libata.h2
2 files changed, 71 insertions, 16 deletions
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 531a4e11c078..70b623988a9f 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -706,9 +706,35 @@ static void ata_eh_detach_dev(struct ata_device *dev)
706 spin_unlock_irqrestore(&ap->host_set->lock, flags); 706 spin_unlock_irqrestore(&ap->host_set->lock, flags);
707} 707}
708 708
709static void ata_eh_clear_action(struct ata_device *dev,
710 struct ata_eh_info *ehi, unsigned int action)
711{
712 int i;
713
714 if (!dev) {
715 ehi->action &= ~action;
716 for (i = 0; i < ATA_MAX_DEVICES; i++)
717 ehi->dev_action[i] &= ~action;
718 } else {
719 /* doesn't make sense for port-wide EH actions */
720 WARN_ON(!(action & ATA_EH_PERDEV_MASK));
721
722 /* break ehi->action into ehi->dev_action */
723 if (ehi->action & action) {
724 for (i = 0; i < ATA_MAX_DEVICES; i++)
725 ehi->dev_action[i] |= ehi->action & action;
726 ehi->action &= ~action;
727 }
728
729 /* turn off the specified per-dev action */
730 ehi->dev_action[dev->devno] &= ~action;
731 }
732}
733
709/** 734/**
710 * ata_eh_about_to_do - about to perform eh_action 735 * ata_eh_about_to_do - about to perform eh_action
711 * @ap: target ATA port 736 * @ap: target ATA port
737 * @dev: target ATA dev for per-dev action (can be NULL)
712 * @action: action about to be performed 738 * @action: action about to be performed
713 * 739 *
714 * Called just before performing EH actions to clear related bits 740 * Called just before performing EH actions to clear related bits
@@ -718,17 +744,36 @@ static void ata_eh_detach_dev(struct ata_device *dev)
718 * LOCKING: 744 * LOCKING:
719 * None. 745 * None.
720 */ 746 */
721static void ata_eh_about_to_do(struct ata_port *ap, unsigned int action) 747static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
748 unsigned int action)
722{ 749{
723 unsigned long flags; 750 unsigned long flags;
724 751
725 spin_lock_irqsave(&ap->host_set->lock, flags); 752 spin_lock_irqsave(&ap->host_set->lock, flags);
726 ap->eh_info.action &= ~action; 753 ata_eh_clear_action(dev, &ap->eh_info, action);
727 ap->flags |= ATA_FLAG_RECOVERED; 754 ap->flags |= ATA_FLAG_RECOVERED;
728 spin_unlock_irqrestore(&ap->host_set->lock, flags); 755 spin_unlock_irqrestore(&ap->host_set->lock, flags);
729} 756}
730 757
731/** 758/**
759 * ata_eh_done - EH action complete
760 * @ap: target ATA port
761 * @dev: target ATA dev for per-dev action (can be NULL)
762 * @action: action just completed
763 *
764 * Called right after performing EH actions to clear related bits
765 * in @ap->eh_context.
766 *
767 * LOCKING:
768 * None.
769 */
770static void ata_eh_done(struct ata_port *ap, struct ata_device *dev,
771 unsigned int action)
772{
773 ata_eh_clear_action(dev, &ap->eh_context.i, action);
774}
775
776/**
732 * ata_err_string - convert err_mask to descriptive string 777 * ata_err_string - convert err_mask to descriptive string
733 * @err_mask: error mask to convert to string 778 * @err_mask: error mask to convert to string
734 * 779 *
@@ -1271,10 +1316,6 @@ static void ata_eh_autopsy(struct ata_port *ap)
1271 is_io = 1; 1316 is_io = 1;
1272 } 1317 }
1273 1318
1274 /* speed down iff command was in progress */
1275 if (failed_dev)
1276 action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask);
1277
1278 /* enforce default EH actions */ 1319 /* enforce default EH actions */
1279 if (ap->flags & ATA_FLAG_FROZEN || 1320 if (ap->flags & ATA_FLAG_FROZEN ||
1280 all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) 1321 all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
@@ -1282,6 +1323,17 @@ static void ata_eh_autopsy(struct ata_port *ap)
1282 else if (all_err_mask) 1323 else if (all_err_mask)
1283 action |= ATA_EH_REVALIDATE; 1324 action |= ATA_EH_REVALIDATE;
1284 1325
1326 /* if we have offending qcs and the associated failed device */
1327 if (failed_dev) {
1328 /* speed down */
1329 action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask);
1330
1331 /* perform per-dev EH action only on the offending device */
1332 ehc->i.dev_action[failed_dev->devno] |=
1333 action & ATA_EH_PERDEV_MASK;
1334 action &= ~ATA_EH_PERDEV_MASK;
1335 }
1336
1285 /* record autopsy result */ 1337 /* record autopsy result */
1286 ehc->i.dev = failed_dev; 1338 ehc->i.dev = failed_dev;
1287 ehc->i.action = action; 1339 ehc->i.action = action;
@@ -1457,7 +1509,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1457 reset == softreset ? "soft" : "hard"); 1509 reset == softreset ? "soft" : "hard");
1458 1510
1459 /* reset */ 1511 /* reset */
1460 ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); 1512 ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
1461 ehc->i.flags |= ATA_EHI_DID_RESET; 1513 ehc->i.flags |= ATA_EHI_DID_RESET;
1462 1514
1463 rc = ata_do_reset(ap, reset, classes); 1515 rc = ata_do_reset(ap, reset, classes);
@@ -1476,7 +1528,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1476 return -EINVAL; 1528 return -EINVAL;
1477 } 1529 }
1478 1530
1479 ata_eh_about_to_do(ap, ATA_EH_RESET_MASK); 1531 ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
1480 rc = ata_do_reset(ap, reset, classes); 1532 rc = ata_do_reset(ap, reset, classes);
1481 1533
1482 if (rc == 0 && classify && 1534 if (rc == 0 && classify &&
@@ -1520,8 +1572,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1520 postreset(ap, classes); 1572 postreset(ap, classes);
1521 1573
1522 /* reset successful, schedule revalidation */ 1574 /* reset successful, schedule revalidation */
1523 ehc->i.dev = NULL; 1575 ata_eh_done(ap, NULL, ATA_EH_RESET_MASK);
1524 ehc->i.action &= ~ATA_EH_RESET_MASK;
1525 ehc->i.action |= ATA_EH_REVALIDATE; 1576 ehc->i.action |= ATA_EH_REVALIDATE;
1526 } 1577 }
1527 1578
@@ -1539,21 +1590,25 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
1539 DPRINTK("ENTER\n"); 1590 DPRINTK("ENTER\n");
1540 1591
1541 for (i = 0; i < ATA_MAX_DEVICES; i++) { 1592 for (i = 0; i < ATA_MAX_DEVICES; i++) {
1593 unsigned int action;
1594
1542 dev = &ap->device[i]; 1595 dev = &ap->device[i];
1596 action = ehc->i.action | ehc->i.dev_action[dev->devno];
1543 1597
1544 if (ehc->i.action & ATA_EH_REVALIDATE && ata_dev_enabled(dev) && 1598 if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) {
1545 (!ehc->i.dev || ehc->i.dev == dev)) {
1546 if (ata_port_offline(ap)) { 1599 if (ata_port_offline(ap)) {
1547 rc = -EIO; 1600 rc = -EIO;
1548 break; 1601 break;
1549 } 1602 }
1550 1603
1551 ata_eh_about_to_do(ap, ATA_EH_REVALIDATE); 1604 ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
1552 rc = ata_dev_revalidate(dev, 1605 rc = ata_dev_revalidate(dev,
1553 ehc->i.flags & ATA_EHI_DID_RESET); 1606 ehc->i.flags & ATA_EHI_DID_RESET);
1554 if (rc) 1607 if (rc)
1555 break; 1608 break;
1556 1609
1610 ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
1611
1557 /* schedule the scsi_rescan_device() here */ 1612 /* schedule the scsi_rescan_device() here */
1558 queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); 1613 queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
1559 } else if (dev->class == ATA_DEV_UNKNOWN && 1614 } else if (dev->class == ATA_DEV_UNKNOWN &&
@@ -1576,9 +1631,7 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
1576 } 1631 }
1577 } 1632 }
1578 1633
1579 if (rc == 0) 1634 if (rc)
1580 ehc->i.action &= ~ATA_EH_REVALIDATE;
1581 else
1582 *r_failed_dev = dev; 1635 *r_failed_dev = dev;
1583 1636
1584 DPRINTK("EXIT\n"); 1637 DPRINTK("EXIT\n");
diff --git a/include/linux/libata.h b/include/linux/libata.h
index f03b8664af11..6b3c3af2c75f 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -249,6 +249,7 @@ enum {
249 ATA_EH_HARDRESET = (1 << 2), 249 ATA_EH_HARDRESET = (1 << 2),
250 250
251 ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, 251 ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
252 ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE,
252 253
253 /* ata_eh_info->flags */ 254 /* ata_eh_info->flags */
254 ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ 255 ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
@@ -462,6 +463,7 @@ struct ata_eh_info {
462 u32 serror; /* SError from LLDD */ 463 u32 serror; /* SError from LLDD */
463 unsigned int err_mask; /* port-wide err_mask */ 464 unsigned int err_mask; /* port-wide err_mask */
464 unsigned int action; /* ATA_EH_* action mask */ 465 unsigned int action; /* ATA_EH_* action mask */
466 unsigned int dev_action[ATA_MAX_DEVICES]; /* dev EH action */
465 unsigned int flags; /* ATA_EHI_* flags */ 467 unsigned int flags; /* ATA_EHI_* flags */
466 468
467 unsigned long hotplug_timestamp; 469 unsigned long hotplug_timestamp;