diff options
-rw-r--r-- | drivers/scsi/libata-eh.c | 123 | ||||
-rw-r--r-- | include/linux/libata.h | 13 |
2 files changed, 115 insertions, 21 deletions
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index a049bffdf770..b53e2e7db498 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c | |||
@@ -932,10 +932,8 @@ static void ata_eh_analyze_serror(struct ata_port *ap) | |||
932 | err_mask |= AC_ERR_SYSTEM; | 932 | err_mask |= AC_ERR_SYSTEM; |
933 | action |= ATA_EH_SOFTRESET; | 933 | action |= ATA_EH_SOFTRESET; |
934 | } | 934 | } |
935 | if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) { | 935 | if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) |
936 | err_mask |= AC_ERR_ATA_BUS; | 936 | ata_ehi_hotplugged(&ehc->i); |
937 | action |= ATA_EH_HARDRESET; | ||
938 | } | ||
939 | 937 | ||
940 | ehc->i.err_mask |= err_mask; | 938 | ehc->i.err_mask |= err_mask; |
941 | ehc->i.action |= action; | 939 | ehc->i.action |= action; |
@@ -1487,11 +1485,12 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1487 | return rc; | 1485 | return rc; |
1488 | } | 1486 | } |
1489 | 1487 | ||
1490 | static int ata_eh_revalidate(struct ata_port *ap, | 1488 | static int ata_eh_revalidate_and_attach(struct ata_port *ap, |
1491 | struct ata_device **r_failed_dev) | 1489 | struct ata_device **r_failed_dev) |
1492 | { | 1490 | { |
1493 | struct ata_eh_context *ehc = &ap->eh_context; | 1491 | struct ata_eh_context *ehc = &ap->eh_context; |
1494 | struct ata_device *dev; | 1492 | struct ata_device *dev; |
1493 | unsigned long flags; | ||
1495 | int i, rc = 0; | 1494 | int i, rc = 0; |
1496 | 1495 | ||
1497 | DPRINTK("ENTER\n"); | 1496 | DPRINTK("ENTER\n"); |
@@ -1513,6 +1512,23 @@ static int ata_eh_revalidate(struct ata_port *ap, | |||
1513 | break; | 1512 | break; |
1514 | 1513 | ||
1515 | ehc->i.action &= ~ATA_EH_REVALIDATE; | 1514 | ehc->i.action &= ~ATA_EH_REVALIDATE; |
1515 | } else if (dev->class == ATA_DEV_UNKNOWN && | ||
1516 | ehc->tries[dev->devno] && | ||
1517 | ata_class_enabled(ehc->classes[dev->devno])) { | ||
1518 | dev->class = ehc->classes[dev->devno]; | ||
1519 | |||
1520 | rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); | ||
1521 | if (rc == 0) | ||
1522 | rc = ata_dev_configure(dev, 1); | ||
1523 | |||
1524 | if (rc) { | ||
1525 | dev->class = ATA_DEV_UNKNOWN; | ||
1526 | break; | ||
1527 | } | ||
1528 | |||
1529 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
1530 | ap->flags |= ATA_FLAG_SCSI_HOTPLUG; | ||
1531 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
1516 | } | 1532 | } |
1517 | } | 1533 | } |
1518 | 1534 | ||
@@ -1533,6 +1549,36 @@ static int ata_port_nr_enabled(struct ata_port *ap) | |||
1533 | return cnt; | 1549 | return cnt; |
1534 | } | 1550 | } |
1535 | 1551 | ||
1552 | static int ata_port_nr_vacant(struct ata_port *ap) | ||
1553 | { | ||
1554 | int i, cnt = 0; | ||
1555 | |||
1556 | for (i = 0; i < ATA_MAX_DEVICES; i++) | ||
1557 | if (ap->device[i].class == ATA_DEV_UNKNOWN) | ||
1558 | cnt++; | ||
1559 | return cnt; | ||
1560 | } | ||
1561 | |||
1562 | static int ata_eh_skip_recovery(struct ata_port *ap) | ||
1563 | { | ||
1564 | struct ata_eh_context *ehc = &ap->eh_context; | ||
1565 | int i; | ||
1566 | |||
1567 | if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap)) | ||
1568 | return 0; | ||
1569 | |||
1570 | /* skip if class codes for all vacant slots are ATA_DEV_NONE */ | ||
1571 | for (i = 0; i < ATA_MAX_DEVICES; i++) { | ||
1572 | struct ata_device *dev = &ap->device[i]; | ||
1573 | |||
1574 | if (dev->class == ATA_DEV_UNKNOWN && | ||
1575 | ehc->classes[dev->devno] != ATA_DEV_NONE) | ||
1576 | return 0; | ||
1577 | } | ||
1578 | |||
1579 | return 1; | ||
1580 | } | ||
1581 | |||
1536 | /** | 1582 | /** |
1537 | * ata_eh_recover - recover host port after error | 1583 | * ata_eh_recover - recover host port after error |
1538 | * @ap: host port to recover | 1584 | * @ap: host port to recover |
@@ -1543,9 +1589,10 @@ static int ata_port_nr_enabled(struct ata_port *ap) | |||
1543 | * | 1589 | * |
1544 | * This is the alpha and omega, eum and yang, heart and soul of | 1590 | * This is the alpha and omega, eum and yang, heart and soul of |
1545 | * libata exception handling. On entry, actions required to | 1591 | * libata exception handling. On entry, actions required to |
1546 | * recover each devices are recorded in eh_context. This | 1592 | * recover the port and hotplug requests are recorded in |
1547 | * function executes all the operations with appropriate retrials | 1593 | * eh_context. This function executes all the operations with |
1548 | * and fallbacks to resurrect failed devices. | 1594 | * appropriate retrials and fallbacks to resurrect failed |
1595 | * devices, detach goners and greet newcomers. | ||
1549 | * | 1596 | * |
1550 | * LOCKING: | 1597 | * LOCKING: |
1551 | * Kernel thread context (may sleep). | 1598 | * Kernel thread context (may sleep). |
@@ -1568,6 +1615,19 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1568 | dev = &ap->device[i]; | 1615 | dev = &ap->device[i]; |
1569 | 1616 | ||
1570 | ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; | 1617 | ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; |
1618 | |||
1619 | /* process hotplug request */ | ||
1620 | if (dev->flags & ATA_DFLAG_DETACH) | ||
1621 | ata_eh_detach_dev(dev); | ||
1622 | |||
1623 | if (!ata_dev_enabled(dev) && | ||
1624 | ((ehc->i.probe_mask & (1 << dev->devno)) && | ||
1625 | !(ehc->did_probe_mask & (1 << dev->devno)))) { | ||
1626 | ata_eh_detach_dev(dev); | ||
1627 | ata_dev_init(dev); | ||
1628 | ehc->did_probe_mask |= (1 << dev->devno); | ||
1629 | ehc->i.action |= ATA_EH_SOFTRESET; | ||
1630 | } | ||
1571 | } | 1631 | } |
1572 | 1632 | ||
1573 | retry: | 1633 | retry: |
@@ -1575,15 +1635,18 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1575 | rc = 0; | 1635 | rc = 0; |
1576 | 1636 | ||
1577 | /* skip EH if possible. */ | 1637 | /* skip EH if possible. */ |
1578 | if (!ata_port_nr_enabled(ap) && !(ap->flags & ATA_FLAG_FROZEN)) | 1638 | if (ata_eh_skip_recovery(ap)) |
1579 | ehc->i.action = 0; | 1639 | ehc->i.action = 0; |
1580 | 1640 | ||
1641 | for (i = 0; i < ATA_MAX_DEVICES; i++) | ||
1642 | ehc->classes[i] = ATA_DEV_UNKNOWN; | ||
1643 | |||
1581 | /* reset */ | 1644 | /* reset */ |
1582 | if (ehc->i.action & ATA_EH_RESET_MASK) { | 1645 | if (ehc->i.action & ATA_EH_RESET_MASK) { |
1583 | ata_eh_freeze_port(ap); | 1646 | ata_eh_freeze_port(ap); |
1584 | 1647 | ||
1585 | rc = ata_eh_reset(ap, 0, prereset, softreset, hardreset, | 1648 | rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset, |
1586 | postreset); | 1649 | softreset, hardreset, postreset); |
1587 | if (rc) { | 1650 | if (rc) { |
1588 | ata_port_printk(ap, KERN_ERR, | 1651 | ata_port_printk(ap, KERN_ERR, |
1589 | "reset failed, giving up\n"); | 1652 | "reset failed, giving up\n"); |
@@ -1593,8 +1656,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1593 | ata_eh_thaw_port(ap); | 1656 | ata_eh_thaw_port(ap); |
1594 | } | 1657 | } |
1595 | 1658 | ||
1596 | /* revalidate existing devices */ | 1659 | /* revalidate existing devices and attach new ones */ |
1597 | rc = ata_eh_revalidate(ap, &dev); | 1660 | rc = ata_eh_revalidate_and_attach(ap, &dev); |
1598 | if (rc) | 1661 | if (rc) |
1599 | goto dev_fail; | 1662 | goto dev_fail; |
1600 | 1663 | ||
@@ -1612,6 +1675,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1612 | dev_fail: | 1675 | dev_fail: |
1613 | switch (rc) { | 1676 | switch (rc) { |
1614 | case -ENODEV: | 1677 | case -ENODEV: |
1678 | /* device missing, schedule probing */ | ||
1679 | ehc->i.probe_mask |= (1 << dev->devno); | ||
1615 | case -EINVAL: | 1680 | case -EINVAL: |
1616 | ehc->tries[dev->devno] = 0; | 1681 | ehc->tries[dev->devno] = 0; |
1617 | break; | 1682 | break; |
@@ -1624,15 +1689,31 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1624 | ehc->tries[dev->devno] = 0; | 1689 | ehc->tries[dev->devno] = 0; |
1625 | } | 1690 | } |
1626 | 1691 | ||
1627 | /* disable device if it has used up all its chances */ | 1692 | if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) { |
1628 | if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) | 1693 | /* disable device if it has used up all its chances */ |
1629 | ata_dev_disable(dev); | 1694 | ata_dev_disable(dev); |
1630 | 1695 | ||
1631 | /* soft didn't work? be haaaaard */ | 1696 | /* detach if offline */ |
1632 | if (ehc->i.flags & ATA_EHI_DID_RESET) | 1697 | if (ata_port_offline(ap)) |
1633 | ehc->i.action |= ATA_EH_HARDRESET; | 1698 | ata_eh_detach_dev(dev); |
1634 | else | 1699 | |
1635 | ehc->i.action |= ATA_EH_SOFTRESET; | 1700 | /* probe if requested */ |
1701 | if ((ehc->i.probe_mask & (1 << dev->devno)) && | ||
1702 | !(ehc->did_probe_mask & (1 << dev->devno))) { | ||
1703 | ata_eh_detach_dev(dev); | ||
1704 | ata_dev_init(dev); | ||
1705 | |||
1706 | ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; | ||
1707 | ehc->did_probe_mask |= (1 << dev->devno); | ||
1708 | ehc->i.action |= ATA_EH_SOFTRESET; | ||
1709 | } | ||
1710 | } else { | ||
1711 | /* soft didn't work? be haaaaard */ | ||
1712 | if (ehc->i.flags & ATA_EHI_DID_RESET) | ||
1713 | ehc->i.action |= ATA_EH_HARDRESET; | ||
1714 | else | ||
1715 | ehc->i.action |= ATA_EH_SOFTRESET; | ||
1716 | } | ||
1636 | 1717 | ||
1637 | if (ata_port_nr_enabled(ap)) { | 1718 | if (ata_port_nr_enabled(ap)) { |
1638 | ata_port_printk(ap, KERN_WARNING, "failed to recover some " | 1719 | ata_port_printk(ap, KERN_WARNING, "failed to recover some " |
diff --git a/include/linux/libata.h b/include/linux/libata.h index a1ceb5b67b97..56971943d261 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -824,6 +824,19 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
824 | (ehi)->desc_len = 0; \ | 824 | (ehi)->desc_len = 0; \ |
825 | } while (0) | 825 | } while (0) |
826 | 826 | ||
827 | static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi) | ||
828 | { | ||
829 | if (ehi->flags & ATA_EHI_HOTPLUGGED) | ||
830 | return; | ||
831 | |||
832 | ehi->flags |= ATA_EHI_HOTPLUGGED; | ||
833 | ehi->hotplug_timestamp = jiffies; | ||
834 | |||
835 | ehi->err_mask |= AC_ERR_ATA_BUS; | ||
836 | ehi->action |= ATA_EH_SOFTRESET; | ||
837 | ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1; | ||
838 | } | ||
839 | |||
827 | /* | 840 | /* |
828 | * qc helpers | 841 | * qc helpers |
829 | */ | 842 | */ |