aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libata-eh.c123
-rw-r--r--include/linux/libata.h13
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
1490static int ata_eh_revalidate(struct ata_port *ap, 1488static 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
1552static 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
1562static 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
827static 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 */