diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 23 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 4 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 147 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_port.c | 19 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 98 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.h | 6 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_config.c | 91 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 124 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_dbg.c | 15 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 9 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 7 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_iocb.c | 133 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 145 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 10 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 40 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_version.h | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 4 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 20 |
18 files changed, 553 insertions, 344 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 2bc22be5f849..145ab9ba55ea 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c | |||
@@ -415,9 +415,9 @@ static void fc_exch_timeout(struct work_struct *work) | |||
415 | e_stat = ep->esb_stat; | 415 | e_stat = ep->esb_stat; |
416 | if (e_stat & ESB_ST_COMPLETE) { | 416 | if (e_stat & ESB_ST_COMPLETE) { |
417 | ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL; | 417 | ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL; |
418 | spin_unlock_bh(&ep->ex_lock); | ||
418 | if (e_stat & ESB_ST_REC_QUAL) | 419 | if (e_stat & ESB_ST_REC_QUAL) |
419 | fc_exch_rrq(ep); | 420 | fc_exch_rrq(ep); |
420 | spin_unlock_bh(&ep->ex_lock); | ||
421 | goto done; | 421 | goto done; |
422 | } else { | 422 | } else { |
423 | resp = ep->resp; | 423 | resp = ep->resp; |
@@ -1624,14 +1624,14 @@ static void fc_exch_rrq(struct fc_exch *ep) | |||
1624 | struct fc_lport *lp; | 1624 | struct fc_lport *lp; |
1625 | struct fc_els_rrq *rrq; | 1625 | struct fc_els_rrq *rrq; |
1626 | struct fc_frame *fp; | 1626 | struct fc_frame *fp; |
1627 | struct fc_seq *rrq_sp; | ||
1628 | u32 did; | 1627 | u32 did; |
1629 | 1628 | ||
1630 | lp = ep->lp; | 1629 | lp = ep->lp; |
1631 | 1630 | ||
1632 | fp = fc_frame_alloc(lp, sizeof(*rrq)); | 1631 | fp = fc_frame_alloc(lp, sizeof(*rrq)); |
1633 | if (!fp) | 1632 | if (!fp) |
1634 | return; | 1633 | goto retry; |
1634 | |||
1635 | rrq = fc_frame_payload_get(fp, sizeof(*rrq)); | 1635 | rrq = fc_frame_payload_get(fp, sizeof(*rrq)); |
1636 | memset(rrq, 0, sizeof(*rrq)); | 1636 | memset(rrq, 0, sizeof(*rrq)); |
1637 | rrq->rrq_cmd = ELS_RRQ; | 1637 | rrq->rrq_cmd = ELS_RRQ; |
@@ -1647,13 +1647,20 @@ static void fc_exch_rrq(struct fc_exch *ep) | |||
1647 | fc_host_port_id(lp->host), FC_TYPE_ELS, | 1647 | fc_host_port_id(lp->host), FC_TYPE_ELS, |
1648 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | 1648 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); |
1649 | 1649 | ||
1650 | rrq_sp = fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep, | 1650 | if (fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep, lp->e_d_tov)) |
1651 | lp->e_d_tov); | 1651 | return; |
1652 | if (!rrq_sp) { | 1652 | |
1653 | ep->esb_stat |= ESB_ST_REC_QUAL; | 1653 | retry: |
1654 | fc_exch_timer_set_locked(ep, ep->r_a_tov); | 1654 | spin_lock_bh(&ep->ex_lock); |
1655 | if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) { | ||
1656 | spin_unlock_bh(&ep->ex_lock); | ||
1657 | /* drop hold for rec qual */ | ||
1658 | fc_exch_release(ep); | ||
1655 | return; | 1659 | return; |
1656 | } | 1660 | } |
1661 | ep->esb_stat |= ESB_ST_REC_QUAL; | ||
1662 | fc_exch_timer_set_locked(ep, ep->r_a_tov); | ||
1663 | spin_unlock_bh(&ep->ex_lock); | ||
1657 | } | 1664 | } |
1658 | 1665 | ||
1659 | 1666 | ||
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 716cc344c5df..a751f6230c22 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1974,10 +1974,10 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1974 | * good and have never sent us a successful tmf response | 1974 | * good and have never sent us a successful tmf response |
1975 | * then sent more data for the cmd. | 1975 | * then sent more data for the cmd. |
1976 | */ | 1976 | */ |
1977 | spin_lock(&session->lock); | 1977 | spin_lock_bh(&session->lock); |
1978 | fail_scsi_task(task, DID_ABORT); | 1978 | fail_scsi_task(task, DID_ABORT); |
1979 | conn->tmf_state = TMF_INITIAL; | 1979 | conn->tmf_state = TMF_INITIAL; |
1980 | spin_unlock(&session->lock); | 1980 | spin_unlock_bh(&session->lock); |
1981 | iscsi_start_tx(conn); | 1981 | iscsi_start_tx(conn); |
1982 | goto success_unlocked; | 1982 | goto success_unlocked; |
1983 | case TMF_TIMEDOUT: | 1983 | case TMF_TIMEDOUT: |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 54fa1e42dc4d..b3381959acce 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
@@ -766,6 +766,7 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) | |||
766 | if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr, | 766 | if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr, |
767 | SAS_ADDR_SIZE) && ephy->port) { | 767 | SAS_ADDR_SIZE) && ephy->port) { |
768 | sas_port_add_phy(ephy->port, phy->phy); | 768 | sas_port_add_phy(ephy->port, phy->phy); |
769 | phy->port = ephy->port; | ||
769 | phy->phy_state = PHY_DEVICE_DISCOVERED; | 770 | phy->phy_state = PHY_DEVICE_DISCOVERED; |
770 | return 0; | 771 | return 0; |
771 | } | 772 | } |
@@ -945,11 +946,21 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) | |||
945 | if (ex->ex_phy[i].phy_state == PHY_VACANT || | 946 | if (ex->ex_phy[i].phy_state == PHY_VACANT || |
946 | ex->ex_phy[i].phy_state == PHY_NOT_PRESENT) | 947 | ex->ex_phy[i].phy_state == PHY_NOT_PRESENT) |
947 | continue; | 948 | continue; |
948 | 949 | /* | |
950 | * Due to races, the phy might not get added to the | ||
951 | * wide port, so we add the phy to the wide port here. | ||
952 | */ | ||
949 | if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == | 953 | if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == |
950 | SAS_ADDR(child->sas_addr)) | 954 | SAS_ADDR(child->sas_addr)) { |
951 | ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; | 955 | ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; |
956 | res = sas_ex_join_wide_port(dev, i); | ||
957 | if (!res) | ||
958 | SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", | ||
959 | i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); | ||
960 | |||
961 | } | ||
952 | } | 962 | } |
963 | res = 0; | ||
953 | } | 964 | } |
954 | 965 | ||
955 | return res; | 966 | return res; |
@@ -1598,7 +1609,7 @@ static int sas_get_phy_attached_sas_addr(struct domain_device *dev, | |||
1598 | } | 1609 | } |
1599 | 1610 | ||
1600 | static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id, | 1611 | static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id, |
1601 | int from_phy) | 1612 | int from_phy, bool update) |
1602 | { | 1613 | { |
1603 | struct expander_device *ex = &dev->ex_dev; | 1614 | struct expander_device *ex = &dev->ex_dev; |
1604 | int res = 0; | 1615 | int res = 0; |
@@ -1611,7 +1622,9 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id, | |||
1611 | if (res) | 1622 | if (res) |
1612 | goto out; | 1623 | goto out; |
1613 | else if (phy_change_count != ex->ex_phy[i].phy_change_count) { | 1624 | else if (phy_change_count != ex->ex_phy[i].phy_change_count) { |
1614 | ex->ex_phy[i].phy_change_count = phy_change_count; | 1625 | if (update) |
1626 | ex->ex_phy[i].phy_change_count = | ||
1627 | phy_change_count; | ||
1615 | *phy_id = i; | 1628 | *phy_id = i; |
1616 | return 0; | 1629 | return 0; |
1617 | } | 1630 | } |
@@ -1653,31 +1666,52 @@ out: | |||
1653 | kfree(rg_req); | 1666 | kfree(rg_req); |
1654 | return res; | 1667 | return res; |
1655 | } | 1668 | } |
1669 | /** | ||
1670 | * sas_find_bcast_dev - find the device issue BROADCAST(CHANGE). | ||
1671 | * @dev:domain device to be detect. | ||
1672 | * @src_dev: the device which originated BROADCAST(CHANGE). | ||
1673 | * | ||
1674 | * Add self-configuration expander suport. Suppose two expander cascading, | ||
1675 | * when the first level expander is self-configuring, hotplug the disks in | ||
1676 | * second level expander, BROADCAST(CHANGE) will not only be originated | ||
1677 | * in the second level expander, but also be originated in the first level | ||
1678 | * expander (see SAS protocol SAS 2r-14, 7.11 for detail), it is to say, | ||
1679 | * expander changed count in two level expanders will all increment at least | ||
1680 | * once, but the phy which chang count has changed is the source device which | ||
1681 | * we concerned. | ||
1682 | */ | ||
1656 | 1683 | ||
1657 | static int sas_find_bcast_dev(struct domain_device *dev, | 1684 | static int sas_find_bcast_dev(struct domain_device *dev, |
1658 | struct domain_device **src_dev) | 1685 | struct domain_device **src_dev) |
1659 | { | 1686 | { |
1660 | struct expander_device *ex = &dev->ex_dev; | 1687 | struct expander_device *ex = &dev->ex_dev; |
1661 | int ex_change_count = -1; | 1688 | int ex_change_count = -1; |
1689 | int phy_id = -1; | ||
1662 | int res; | 1690 | int res; |
1691 | struct domain_device *ch; | ||
1663 | 1692 | ||
1664 | res = sas_get_ex_change_count(dev, &ex_change_count); | 1693 | res = sas_get_ex_change_count(dev, &ex_change_count); |
1665 | if (res) | 1694 | if (res) |
1666 | goto out; | 1695 | goto out; |
1667 | if (ex_change_count != -1 && | 1696 | if (ex_change_count != -1 && ex_change_count != ex->ex_change_count) { |
1668 | ex_change_count != ex->ex_change_count) { | 1697 | /* Just detect if this expander phys phy change count changed, |
1669 | *src_dev = dev; | 1698 | * in order to determine if this expander originate BROADCAST, |
1670 | ex->ex_change_count = ex_change_count; | 1699 | * and do not update phy change count field in our structure. |
1671 | } else { | 1700 | */ |
1672 | struct domain_device *ch; | 1701 | res = sas_find_bcast_phy(dev, &phy_id, 0, false); |
1673 | 1702 | if (phy_id != -1) { | |
1674 | list_for_each_entry(ch, &ex->children, siblings) { | 1703 | *src_dev = dev; |
1675 | if (ch->dev_type == EDGE_DEV || | 1704 | ex->ex_change_count = ex_change_count; |
1676 | ch->dev_type == FANOUT_DEV) { | 1705 | SAS_DPRINTK("Expander phy change count has changed\n"); |
1677 | res = sas_find_bcast_dev(ch, src_dev); | 1706 | return res; |
1678 | if (src_dev) | 1707 | } else |
1679 | return res; | 1708 | SAS_DPRINTK("Expander phys DID NOT change\n"); |
1680 | } | 1709 | } |
1710 | list_for_each_entry(ch, &ex->children, siblings) { | ||
1711 | if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV) { | ||
1712 | res = sas_find_bcast_dev(ch, src_dev); | ||
1713 | if (src_dev) | ||
1714 | return res; | ||
1681 | } | 1715 | } |
1682 | } | 1716 | } |
1683 | out: | 1717 | out: |
@@ -1700,24 +1734,26 @@ static void sas_unregister_ex_tree(struct domain_device *dev) | |||
1700 | } | 1734 | } |
1701 | 1735 | ||
1702 | static void sas_unregister_devs_sas_addr(struct domain_device *parent, | 1736 | static void sas_unregister_devs_sas_addr(struct domain_device *parent, |
1703 | int phy_id) | 1737 | int phy_id, bool last) |
1704 | { | 1738 | { |
1705 | struct expander_device *ex_dev = &parent->ex_dev; | 1739 | struct expander_device *ex_dev = &parent->ex_dev; |
1706 | struct ex_phy *phy = &ex_dev->ex_phy[phy_id]; | 1740 | struct ex_phy *phy = &ex_dev->ex_phy[phy_id]; |
1707 | struct domain_device *child, *n; | 1741 | struct domain_device *child, *n; |
1708 | 1742 | if (last) { | |
1709 | list_for_each_entry_safe(child, n, &ex_dev->children, siblings) { | 1743 | list_for_each_entry_safe(child, n, |
1710 | if (SAS_ADDR(child->sas_addr) == | 1744 | &ex_dev->children, siblings) { |
1711 | SAS_ADDR(phy->attached_sas_addr)) { | 1745 | if (SAS_ADDR(child->sas_addr) == |
1712 | if (child->dev_type == EDGE_DEV || | 1746 | SAS_ADDR(phy->attached_sas_addr)) { |
1713 | child->dev_type == FANOUT_DEV) | 1747 | if (child->dev_type == EDGE_DEV || |
1714 | sas_unregister_ex_tree(child); | 1748 | child->dev_type == FANOUT_DEV) |
1715 | else | 1749 | sas_unregister_ex_tree(child); |
1716 | sas_unregister_dev(child); | 1750 | else |
1717 | break; | 1751 | sas_unregister_dev(child); |
1752 | break; | ||
1753 | } | ||
1718 | } | 1754 | } |
1755 | sas_disable_routing(parent, phy->attached_sas_addr); | ||
1719 | } | 1756 | } |
1720 | sas_disable_routing(parent, phy->attached_sas_addr); | ||
1721 | memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); | 1757 | memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); |
1722 | sas_port_delete_phy(phy->port, phy->phy); | 1758 | sas_port_delete_phy(phy->port, phy->phy); |
1723 | if (phy->port->num_phys == 0) | 1759 | if (phy->port->num_phys == 0) |
@@ -1770,15 +1806,31 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) | |||
1770 | { | 1806 | { |
1771 | struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; | 1807 | struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; |
1772 | struct domain_device *child; | 1808 | struct domain_device *child; |
1773 | int res; | 1809 | bool found = false; |
1810 | int res, i; | ||
1774 | 1811 | ||
1775 | SAS_DPRINTK("ex %016llx phy%d new device attached\n", | 1812 | SAS_DPRINTK("ex %016llx phy%d new device attached\n", |
1776 | SAS_ADDR(dev->sas_addr), phy_id); | 1813 | SAS_ADDR(dev->sas_addr), phy_id); |
1777 | res = sas_ex_phy_discover(dev, phy_id); | 1814 | res = sas_ex_phy_discover(dev, phy_id); |
1778 | if (res) | 1815 | if (res) |
1779 | goto out; | 1816 | goto out; |
1817 | /* to support the wide port inserted */ | ||
1818 | for (i = 0; i < dev->ex_dev.num_phys; i++) { | ||
1819 | struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i]; | ||
1820 | if (i == phy_id) | ||
1821 | continue; | ||
1822 | if (SAS_ADDR(ex_phy_temp->attached_sas_addr) == | ||
1823 | SAS_ADDR(ex_phy->attached_sas_addr)) { | ||
1824 | found = true; | ||
1825 | break; | ||
1826 | } | ||
1827 | } | ||
1828 | if (found) { | ||
1829 | sas_ex_join_wide_port(dev, phy_id); | ||
1830 | return 0; | ||
1831 | } | ||
1780 | res = sas_ex_discover_devices(dev, phy_id); | 1832 | res = sas_ex_discover_devices(dev, phy_id); |
1781 | if (res) | 1833 | if (!res) |
1782 | goto out; | 1834 | goto out; |
1783 | list_for_each_entry(child, &dev->ex_dev.children, siblings) { | 1835 | list_for_each_entry(child, &dev->ex_dev.children, siblings) { |
1784 | if (SAS_ADDR(child->sas_addr) == | 1836 | if (SAS_ADDR(child->sas_addr) == |
@@ -1793,7 +1845,7 @@ out: | |||
1793 | return res; | 1845 | return res; |
1794 | } | 1846 | } |
1795 | 1847 | ||
1796 | static int sas_rediscover_dev(struct domain_device *dev, int phy_id) | 1848 | static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) |
1797 | { | 1849 | { |
1798 | struct expander_device *ex = &dev->ex_dev; | 1850 | struct expander_device *ex = &dev->ex_dev; |
1799 | struct ex_phy *phy = &ex->ex_phy[phy_id]; | 1851 | struct ex_phy *phy = &ex->ex_phy[phy_id]; |
@@ -1804,11 +1856,11 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id) | |||
1804 | switch (res) { | 1856 | switch (res) { |
1805 | case SMP_RESP_NO_PHY: | 1857 | case SMP_RESP_NO_PHY: |
1806 | phy->phy_state = PHY_NOT_PRESENT; | 1858 | phy->phy_state = PHY_NOT_PRESENT; |
1807 | sas_unregister_devs_sas_addr(dev, phy_id); | 1859 | sas_unregister_devs_sas_addr(dev, phy_id, last); |
1808 | goto out; break; | 1860 | goto out; break; |
1809 | case SMP_RESP_PHY_VACANT: | 1861 | case SMP_RESP_PHY_VACANT: |
1810 | phy->phy_state = PHY_VACANT; | 1862 | phy->phy_state = PHY_VACANT; |
1811 | sas_unregister_devs_sas_addr(dev, phy_id); | 1863 | sas_unregister_devs_sas_addr(dev, phy_id, last); |
1812 | goto out; break; | 1864 | goto out; break; |
1813 | case SMP_RESP_FUNC_ACC: | 1865 | case SMP_RESP_FUNC_ACC: |
1814 | break; | 1866 | break; |
@@ -1816,7 +1868,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id) | |||
1816 | 1868 | ||
1817 | if (SAS_ADDR(attached_sas_addr) == 0) { | 1869 | if (SAS_ADDR(attached_sas_addr) == 0) { |
1818 | phy->phy_state = PHY_EMPTY; | 1870 | phy->phy_state = PHY_EMPTY; |
1819 | sas_unregister_devs_sas_addr(dev, phy_id); | 1871 | sas_unregister_devs_sas_addr(dev, phy_id, last); |
1820 | } else if (SAS_ADDR(attached_sas_addr) == | 1872 | } else if (SAS_ADDR(attached_sas_addr) == |
1821 | SAS_ADDR(phy->attached_sas_addr)) { | 1873 | SAS_ADDR(phy->attached_sas_addr)) { |
1822 | SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n", | 1874 | SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n", |
@@ -1828,12 +1880,27 @@ out: | |||
1828 | return res; | 1880 | return res; |
1829 | } | 1881 | } |
1830 | 1882 | ||
1883 | /** | ||
1884 | * sas_rediscover - revalidate the domain. | ||
1885 | * @dev:domain device to be detect. | ||
1886 | * @phy_id: the phy id will be detected. | ||
1887 | * | ||
1888 | * NOTE: this process _must_ quit (return) as soon as any connection | ||
1889 | * errors are encountered. Connection recovery is done elsewhere. | ||
1890 | * Discover process only interrogates devices in order to discover the | ||
1891 | * domain.For plugging out, we un-register the device only when it is | ||
1892 | * the last phy in the port, for other phys in this port, we just delete it | ||
1893 | * from the port.For inserting, we do discovery when it is the | ||
1894 | * first phy,for other phys in this port, we add it to the port to | ||
1895 | * forming the wide-port. | ||
1896 | */ | ||
1831 | static int sas_rediscover(struct domain_device *dev, const int phy_id) | 1897 | static int sas_rediscover(struct domain_device *dev, const int phy_id) |
1832 | { | 1898 | { |
1833 | struct expander_device *ex = &dev->ex_dev; | 1899 | struct expander_device *ex = &dev->ex_dev; |
1834 | struct ex_phy *changed_phy = &ex->ex_phy[phy_id]; | 1900 | struct ex_phy *changed_phy = &ex->ex_phy[phy_id]; |
1835 | int res = 0; | 1901 | int res = 0; |
1836 | int i; | 1902 | int i; |
1903 | bool last = true; /* is this the last phy of the port */ | ||
1837 | 1904 | ||
1838 | SAS_DPRINTK("ex %016llx phy%d originated BROADCAST(CHANGE)\n", | 1905 | SAS_DPRINTK("ex %016llx phy%d originated BROADCAST(CHANGE)\n", |
1839 | SAS_ADDR(dev->sas_addr), phy_id); | 1906 | SAS_ADDR(dev->sas_addr), phy_id); |
@@ -1848,13 +1915,13 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id) | |||
1848 | SAS_ADDR(changed_phy->attached_sas_addr)) { | 1915 | SAS_ADDR(changed_phy->attached_sas_addr)) { |
1849 | SAS_DPRINTK("phy%d part of wide port with " | 1916 | SAS_DPRINTK("phy%d part of wide port with " |
1850 | "phy%d\n", phy_id, i); | 1917 | "phy%d\n", phy_id, i); |
1851 | goto out; | 1918 | last = false; |
1919 | break; | ||
1852 | } | 1920 | } |
1853 | } | 1921 | } |
1854 | res = sas_rediscover_dev(dev, phy_id); | 1922 | res = sas_rediscover_dev(dev, phy_id, last); |
1855 | } else | 1923 | } else |
1856 | res = sas_discover_new(dev, phy_id); | 1924 | res = sas_discover_new(dev, phy_id); |
1857 | out: | ||
1858 | return res; | 1925 | return res; |
1859 | } | 1926 | } |
1860 | 1927 | ||
@@ -1881,7 +1948,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) | |||
1881 | 1948 | ||
1882 | do { | 1949 | do { |
1883 | phy_id = -1; | 1950 | phy_id = -1; |
1884 | res = sas_find_bcast_phy(dev, &phy_id, i); | 1951 | res = sas_find_bcast_phy(dev, &phy_id, i, true); |
1885 | if (phy_id == -1) | 1952 | if (phy_id == -1) |
1886 | break; | 1953 | break; |
1887 | res = sas_rediscover(dev, phy_id); | 1954 | res = sas_rediscover(dev, phy_id); |
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index e6ac59c023f1..fe8b74c706d2 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
@@ -56,7 +56,7 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | /* find a port */ | 59 | /* see if the phy should be part of a wide port */ |
60 | spin_lock_irqsave(&sas_ha->phy_port_lock, flags); | 60 | spin_lock_irqsave(&sas_ha->phy_port_lock, flags); |
61 | for (i = 0; i < sas_ha->num_phys; i++) { | 61 | for (i = 0; i < sas_ha->num_phys; i++) { |
62 | port = sas_ha->sas_port[i]; | 62 | port = sas_ha->sas_port[i]; |
@@ -69,12 +69,23 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
69 | SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, | 69 | SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, |
70 | port->id); | 70 | port->id); |
71 | break; | 71 | break; |
72 | } else if (*(u64 *) port->sas_addr == 0 && port->num_phys==0) { | ||
73 | memcpy(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE); | ||
74 | break; | ||
75 | } | 72 | } |
76 | spin_unlock(&port->phy_list_lock); | 73 | spin_unlock(&port->phy_list_lock); |
77 | } | 74 | } |
75 | /* The phy does not match any existing port, create a new one */ | ||
76 | if (i == sas_ha->num_phys) { | ||
77 | for (i = 0; i < sas_ha->num_phys; i++) { | ||
78 | port = sas_ha->sas_port[i]; | ||
79 | spin_lock(&port->phy_list_lock); | ||
80 | if (*(u64 *)port->sas_addr == 0 | ||
81 | && port->num_phys == 0) { | ||
82 | memcpy(port->sas_addr, phy->sas_addr, | ||
83 | SAS_ADDR_SIZE); | ||
84 | break; | ||
85 | } | ||
86 | spin_unlock(&port->phy_list_lock); | ||
87 | } | ||
88 | } | ||
78 | 89 | ||
79 | if (i >= sas_ha->num_phys) { | 90 | if (i >= sas_ha->num_phys) { |
80 | printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n", | 91 | printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n", |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index f3da592f7bcc..35a13867495e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -119,6 +119,64 @@ _base_fault_reset_work(struct work_struct *work) | |||
119 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | 119 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); |
120 | } | 120 | } |
121 | 121 | ||
122 | /** | ||
123 | * mpt2sas_base_start_watchdog - start the fault_reset_work_q | ||
124 | * @ioc: pointer to scsi command object | ||
125 | * Context: sleep. | ||
126 | * | ||
127 | * Return nothing. | ||
128 | */ | ||
129 | void | ||
130 | mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc) | ||
131 | { | ||
132 | unsigned long flags; | ||
133 | |||
134 | if (ioc->fault_reset_work_q) | ||
135 | return; | ||
136 | |||
137 | /* initialize fault polling */ | ||
138 | INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); | ||
139 | snprintf(ioc->fault_reset_work_q_name, | ||
140 | sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); | ||
141 | ioc->fault_reset_work_q = | ||
142 | create_singlethread_workqueue(ioc->fault_reset_work_q_name); | ||
143 | if (!ioc->fault_reset_work_q) { | ||
144 | printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", | ||
145 | ioc->name, __func__, __LINE__); | ||
146 | return; | ||
147 | } | ||
148 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
149 | if (ioc->fault_reset_work_q) | ||
150 | queue_delayed_work(ioc->fault_reset_work_q, | ||
151 | &ioc->fault_reset_work, | ||
152 | msecs_to_jiffies(FAULT_POLLING_INTERVAL)); | ||
153 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q | ||
158 | * @ioc: pointer to scsi command object | ||
159 | * Context: sleep. | ||
160 | * | ||
161 | * Return nothing. | ||
162 | */ | ||
163 | void | ||
164 | mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc) | ||
165 | { | ||
166 | unsigned long flags; | ||
167 | struct workqueue_struct *wq; | ||
168 | |||
169 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
170 | wq = ioc->fault_reset_work_q; | ||
171 | ioc->fault_reset_work_q = NULL; | ||
172 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
173 | if (wq) { | ||
174 | if (!cancel_delayed_work(&ioc->fault_reset_work)) | ||
175 | flush_workqueue(wq); | ||
176 | destroy_workqueue(wq); | ||
177 | } | ||
178 | } | ||
179 | |||
122 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 180 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
123 | /** | 181 | /** |
124 | * _base_sas_ioc_info - verbose translation of the ioc status | 182 | * _base_sas_ioc_info - verbose translation of the ioc status |
@@ -440,6 +498,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info) | |||
440 | if (sas_loginfo.dw.bus_type != 3 /*SAS*/) | 498 | if (sas_loginfo.dw.bus_type != 3 /*SAS*/) |
441 | return; | 499 | return; |
442 | 500 | ||
501 | /* each nexus loss loginfo */ | ||
502 | if (log_info == 0x31170000) | ||
503 | return; | ||
504 | |||
443 | /* eat the loginfos associated with task aborts */ | 505 | /* eat the loginfos associated with task aborts */ |
444 | if (ioc->ignore_loginfos && (log_info == 30050000 || log_info == | 506 | if (ioc->ignore_loginfos && (log_info == 30050000 || log_info == |
445 | 0x31140000 || log_info == 0x31130000)) | 507 | 0x31140000 || log_info == 0x31130000)) |
@@ -1109,7 +1171,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1109 | } | 1171 | } |
1110 | } | 1172 | } |
1111 | 1173 | ||
1112 | pci_set_drvdata(pdev, ioc->shost); | ||
1113 | _base_mask_interrupts(ioc); | 1174 | _base_mask_interrupts(ioc); |
1114 | r = _base_enable_msix(ioc); | 1175 | r = _base_enable_msix(ioc); |
1115 | if (r) | 1176 | if (r) |
@@ -1132,7 +1193,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1132 | ioc->pci_irq = -1; | 1193 | ioc->pci_irq = -1; |
1133 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 1194 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
1134 | pci_disable_device(pdev); | 1195 | pci_disable_device(pdev); |
1135 | pci_set_drvdata(pdev, NULL); | ||
1136 | return r; | 1196 | return r; |
1137 | } | 1197 | } |
1138 | 1198 | ||
@@ -3191,7 +3251,6 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
3191 | ioc->chip_phys = 0; | 3251 | ioc->chip_phys = 0; |
3192 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 3252 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
3193 | pci_disable_device(pdev); | 3253 | pci_disable_device(pdev); |
3194 | pci_set_drvdata(pdev, NULL); | ||
3195 | return; | 3254 | return; |
3196 | } | 3255 | } |
3197 | 3256 | ||
@@ -3205,7 +3264,6 @@ int | |||
3205 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | 3264 | mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) |
3206 | { | 3265 | { |
3207 | int r, i; | 3266 | int r, i; |
3208 | unsigned long flags; | ||
3209 | 3267 | ||
3210 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3268 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3211 | __func__)); | 3269 | __func__)); |
@@ -3214,6 +3272,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3214 | if (r) | 3272 | if (r) |
3215 | return r; | 3273 | return r; |
3216 | 3274 | ||
3275 | pci_set_drvdata(ioc->pdev, ioc->shost); | ||
3217 | r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 3276 | r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); |
3218 | if (r) | 3277 | if (r) |
3219 | goto out_free_resources; | 3278 | goto out_free_resources; |
@@ -3288,23 +3347,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3288 | if (r) | 3347 | if (r) |
3289 | goto out_free_resources; | 3348 | goto out_free_resources; |
3290 | 3349 | ||
3291 | /* initialize fault polling */ | 3350 | mpt2sas_base_start_watchdog(ioc); |
3292 | INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); | ||
3293 | snprintf(ioc->fault_reset_work_q_name, | ||
3294 | sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); | ||
3295 | ioc->fault_reset_work_q = | ||
3296 | create_singlethread_workqueue(ioc->fault_reset_work_q_name); | ||
3297 | if (!ioc->fault_reset_work_q) { | ||
3298 | printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n", | ||
3299 | ioc->name, __func__, __LINE__); | ||
3300 | goto out_free_resources; | ||
3301 | } | ||
3302 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | ||
3303 | if (ioc->fault_reset_work_q) | ||
3304 | queue_delayed_work(ioc->fault_reset_work_q, | ||
3305 | &ioc->fault_reset_work, | ||
3306 | msecs_to_jiffies(FAULT_POLLING_INTERVAL)); | ||
3307 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
3308 | return 0; | 3351 | return 0; |
3309 | 3352 | ||
3310 | out_free_resources: | 3353 | out_free_resources: |
@@ -3312,6 +3355,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3312 | ioc->remove_host = 1; | 3355 | ioc->remove_host = 1; |
3313 | mpt2sas_base_free_resources(ioc); | 3356 | mpt2sas_base_free_resources(ioc); |
3314 | _base_release_memory_pools(ioc); | 3357 | _base_release_memory_pools(ioc); |
3358 | pci_set_drvdata(ioc->pdev, NULL); | ||
3315 | kfree(ioc->tm_cmds.reply); | 3359 | kfree(ioc->tm_cmds.reply); |
3316 | kfree(ioc->transport_cmds.reply); | 3360 | kfree(ioc->transport_cmds.reply); |
3317 | kfree(ioc->config_cmds.reply); | 3361 | kfree(ioc->config_cmds.reply); |
@@ -3337,22 +3381,14 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3337 | void | 3381 | void |
3338 | mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) | 3382 | mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) |
3339 | { | 3383 | { |
3340 | unsigned long flags; | ||
3341 | struct workqueue_struct *wq; | ||
3342 | 3384 | ||
3343 | dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3385 | dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3344 | __func__)); | 3386 | __func__)); |
3345 | 3387 | ||
3346 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 3388 | mpt2sas_base_stop_watchdog(ioc); |
3347 | wq = ioc->fault_reset_work_q; | ||
3348 | ioc->fault_reset_work_q = NULL; | ||
3349 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); | ||
3350 | if (!cancel_delayed_work(&ioc->fault_reset_work)) | ||
3351 | flush_workqueue(wq); | ||
3352 | destroy_workqueue(wq); | ||
3353 | |||
3354 | mpt2sas_base_free_resources(ioc); | 3389 | mpt2sas_base_free_resources(ioc); |
3355 | _base_release_memory_pools(ioc); | 3390 | _base_release_memory_pools(ioc); |
3391 | pci_set_drvdata(ioc->pdev, NULL); | ||
3356 | kfree(ioc->pfacts); | 3392 | kfree(ioc->pfacts); |
3357 | kfree(ioc->ctl_cmds.reply); | 3393 | kfree(ioc->ctl_cmds.reply); |
3358 | kfree(ioc->base_cmds.reply); | 3394 | kfree(ioc->base_cmds.reply); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 286c185fa9e4..acdcff150a35 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
@@ -69,10 +69,10 @@ | |||
69 | #define MPT2SAS_DRIVER_NAME "mpt2sas" | 69 | #define MPT2SAS_DRIVER_NAME "mpt2sas" |
70 | #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" | 70 | #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" |
71 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" | 71 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" |
72 | #define MPT2SAS_DRIVER_VERSION "01.100.03.00" | 72 | #define MPT2SAS_DRIVER_VERSION "01.100.04.00" |
73 | #define MPT2SAS_MAJOR_VERSION 01 | 73 | #define MPT2SAS_MAJOR_VERSION 01 |
74 | #define MPT2SAS_MINOR_VERSION 100 | 74 | #define MPT2SAS_MINOR_VERSION 100 |
75 | #define MPT2SAS_BUILD_VERSION 03 | 75 | #define MPT2SAS_BUILD_VERSION 04 |
76 | #define MPT2SAS_RELEASE_VERSION 00 | 76 | #define MPT2SAS_RELEASE_VERSION 00 |
77 | 77 | ||
78 | /* | 78 | /* |
@@ -673,6 +673,8 @@ typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | |||
673 | 673 | ||
674 | /* base shared API */ | 674 | /* base shared API */ |
675 | extern struct list_head mpt2sas_ioc_list; | 675 | extern struct list_head mpt2sas_ioc_list; |
676 | void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); | ||
677 | void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); | ||
676 | 678 | ||
677 | int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); | 679 | int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc); |
678 | void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); | 680 | void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c index 58cfb97846f7..6ddee161beb3 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c | |||
@@ -236,17 +236,25 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |||
236 | Mpi2ConfigRequest_t *config_request; | 236 | Mpi2ConfigRequest_t *config_request; |
237 | int r; | 237 | int r; |
238 | u8 retry_count; | 238 | u8 retry_count; |
239 | u8 issue_reset; | 239 | u8 issue_host_reset = 0; |
240 | u16 wait_state_count; | 240 | u16 wait_state_count; |
241 | 241 | ||
242 | mutex_lock(&ioc->config_cmds.mutex); | ||
242 | if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) { | 243 | if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) { |
243 | printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n", | 244 | printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n", |
244 | ioc->name, __func__); | 245 | ioc->name, __func__); |
246 | mutex_unlock(&ioc->config_cmds.mutex); | ||
245 | return -EAGAIN; | 247 | return -EAGAIN; |
246 | } | 248 | } |
247 | retry_count = 0; | 249 | retry_count = 0; |
248 | 250 | ||
249 | retry_config: | 251 | retry_config: |
252 | if (retry_count) { | ||
253 | if (retry_count > 2) /* attempt only 2 retries */ | ||
254 | return -EFAULT; | ||
255 | printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n", | ||
256 | ioc->name, __func__, retry_count); | ||
257 | } | ||
250 | wait_state_count = 0; | 258 | wait_state_count = 0; |
251 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | 259 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); |
252 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | 260 | while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { |
@@ -254,8 +262,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |||
254 | printk(MPT2SAS_ERR_FMT | 262 | printk(MPT2SAS_ERR_FMT |
255 | "%s: failed due to ioc not operational\n", | 263 | "%s: failed due to ioc not operational\n", |
256 | ioc->name, __func__); | 264 | ioc->name, __func__); |
257 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | 265 | r = -EFAULT; |
258 | return -EFAULT; | 266 | goto out; |
259 | } | 267 | } |
260 | ssleep(1); | 268 | ssleep(1); |
261 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | 269 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); |
@@ -271,8 +279,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |||
271 | if (!smid) { | 279 | if (!smid) { |
272 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 280 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", |
273 | ioc->name, __func__); | 281 | ioc->name, __func__); |
274 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | 282 | r = -EAGAIN; |
275 | return -EAGAIN; | 283 | goto out; |
276 | } | 284 | } |
277 | 285 | ||
278 | r = 0; | 286 | r = 0; |
@@ -292,9 +300,15 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |||
292 | ioc->name, __func__); | 300 | ioc->name, __func__); |
293 | _debug_dump_mf(mpi_request, | 301 | _debug_dump_mf(mpi_request, |
294 | sizeof(Mpi2ConfigRequest_t)/4); | 302 | sizeof(Mpi2ConfigRequest_t)/4); |
295 | if (!(ioc->config_cmds.status & MPT2_CMD_RESET)) | 303 | retry_count++; |
296 | issue_reset = 1; | 304 | if (ioc->config_cmds.smid == smid) |
297 | goto issue_host_reset; | 305 | mpt2sas_base_free_smid(ioc, smid); |
306 | if ((ioc->shost_recovery) || | ||
307 | (ioc->config_cmds.status & MPT2_CMD_RESET)) | ||
308 | goto retry_config; | ||
309 | issue_host_reset = 1; | ||
310 | r = -EFAULT; | ||
311 | goto out; | ||
298 | } | 312 | } |
299 | if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) | 313 | if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID) |
300 | memcpy(mpi_reply, ioc->config_cmds.reply, | 314 | memcpy(mpi_reply, ioc->config_cmds.reply, |
@@ -302,21 +316,13 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |||
302 | if (retry_count) | 316 | if (retry_count) |
303 | printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n", | 317 | printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n", |
304 | ioc->name, __func__); | 318 | ioc->name, __func__); |
319 | out: | ||
305 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | 320 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; |
306 | return r; | 321 | mutex_unlock(&ioc->config_cmds.mutex); |
307 | 322 | if (issue_host_reset) | |
308 | issue_host_reset: | ||
309 | if (issue_reset) | ||
310 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 323 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, |
311 | FORCE_BIG_HAMMER); | 324 | FORCE_BIG_HAMMER); |
312 | ioc->config_cmds.status = MPT2_CMD_NOT_USED; | 325 | return r; |
313 | if (!retry_count) { | ||
314 | printk(MPT2SAS_INFO_FMT "%s: attempting retry\n", | ||
315 | ioc->name, __func__); | ||
316 | retry_count++; | ||
317 | goto retry_config; | ||
318 | } | ||
319 | return -EFAULT; | ||
320 | } | 326 | } |
321 | 327 | ||
322 | /** | 328 | /** |
@@ -375,7 +381,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, | |||
375 | int r; | 381 | int r; |
376 | struct config_request mem; | 382 | struct config_request mem; |
377 | 383 | ||
378 | mutex_lock(&ioc->config_cmds.mutex); | ||
379 | memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t)); | 384 | memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t)); |
380 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 385 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
381 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 386 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -417,7 +422,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, | |||
417 | _config_free_config_dma_memory(ioc, &mem); | 422 | _config_free_config_dma_memory(ioc, &mem); |
418 | 423 | ||
419 | out: | 424 | out: |
420 | mutex_unlock(&ioc->config_cmds.mutex); | ||
421 | return r; | 425 | return r; |
422 | } | 426 | } |
423 | 427 | ||
@@ -438,7 +442,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, | |||
438 | int r; | 442 | int r; |
439 | struct config_request mem; | 443 | struct config_request mem; |
440 | 444 | ||
441 | mutex_lock(&ioc->config_cmds.mutex); | ||
442 | memset(config_page, 0, sizeof(Mpi2BiosPage2_t)); | 445 | memset(config_page, 0, sizeof(Mpi2BiosPage2_t)); |
443 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 446 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
444 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 447 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -480,7 +483,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, | |||
480 | _config_free_config_dma_memory(ioc, &mem); | 483 | _config_free_config_dma_memory(ioc, &mem); |
481 | 484 | ||
482 | out: | 485 | out: |
483 | mutex_unlock(&ioc->config_cmds.mutex); | ||
484 | return r; | 486 | return r; |
485 | } | 487 | } |
486 | 488 | ||
@@ -501,7 +503,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
501 | int r; | 503 | int r; |
502 | struct config_request mem; | 504 | struct config_request mem; |
503 | 505 | ||
504 | mutex_lock(&ioc->config_cmds.mutex); | ||
505 | memset(config_page, 0, sizeof(Mpi2BiosPage3_t)); | 506 | memset(config_page, 0, sizeof(Mpi2BiosPage3_t)); |
506 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 507 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
507 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 508 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -543,7 +544,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
543 | _config_free_config_dma_memory(ioc, &mem); | 544 | _config_free_config_dma_memory(ioc, &mem); |
544 | 545 | ||
545 | out: | 546 | out: |
546 | mutex_unlock(&ioc->config_cmds.mutex); | ||
547 | return r; | 547 | return r; |
548 | } | 548 | } |
549 | 549 | ||
@@ -564,7 +564,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, | |||
564 | int r; | 564 | int r; |
565 | struct config_request mem; | 565 | struct config_request mem; |
566 | 566 | ||
567 | mutex_lock(&ioc->config_cmds.mutex); | ||
568 | memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t)); | 567 | memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t)); |
569 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 568 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
570 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 569 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -606,7 +605,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, | |||
606 | _config_free_config_dma_memory(ioc, &mem); | 605 | _config_free_config_dma_memory(ioc, &mem); |
607 | 606 | ||
608 | out: | 607 | out: |
609 | mutex_unlock(&ioc->config_cmds.mutex); | ||
610 | return r; | 608 | return r; |
611 | } | 609 | } |
612 | 610 | ||
@@ -627,7 +625,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | |||
627 | int r; | 625 | int r; |
628 | struct config_request mem; | 626 | struct config_request mem; |
629 | 627 | ||
630 | mutex_lock(&ioc->config_cmds.mutex); | ||
631 | memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t)); | 628 | memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t)); |
632 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 629 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
633 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 630 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -669,7 +666,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | |||
669 | _config_free_config_dma_memory(ioc, &mem); | 666 | _config_free_config_dma_memory(ioc, &mem); |
670 | 667 | ||
671 | out: | 668 | out: |
672 | mutex_unlock(&ioc->config_cmds.mutex); | ||
673 | return r; | 669 | return r; |
674 | } | 670 | } |
675 | 671 | ||
@@ -690,7 +686,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | |||
690 | int r; | 686 | int r; |
691 | struct config_request mem; | 687 | struct config_request mem; |
692 | 688 | ||
693 | mutex_lock(&ioc->config_cmds.mutex); | ||
694 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 689 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
695 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 690 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
696 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | 691 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; |
@@ -732,7 +727,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, | |||
732 | _config_free_config_dma_memory(ioc, &mem); | 727 | _config_free_config_dma_memory(ioc, &mem); |
733 | 728 | ||
734 | out: | 729 | out: |
735 | mutex_unlock(&ioc->config_cmds.mutex); | ||
736 | return r; | 730 | return r; |
737 | } | 731 | } |
738 | 732 | ||
@@ -753,7 +747,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, | |||
753 | int r; | 747 | int r; |
754 | struct config_request mem; | 748 | struct config_request mem; |
755 | 749 | ||
756 | mutex_lock(&ioc->config_cmds.mutex); | ||
757 | memset(config_page, 0, sizeof(Mpi2IOCPage8_t)); | 750 | memset(config_page, 0, sizeof(Mpi2IOCPage8_t)); |
758 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 751 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
759 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 752 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -795,7 +788,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, | |||
795 | _config_free_config_dma_memory(ioc, &mem); | 788 | _config_free_config_dma_memory(ioc, &mem); |
796 | 789 | ||
797 | out: | 790 | out: |
798 | mutex_unlock(&ioc->config_cmds.mutex); | ||
799 | return r; | 791 | return r; |
800 | } | 792 | } |
801 | 793 | ||
@@ -818,7 +810,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
818 | int r; | 810 | int r; |
819 | struct config_request mem; | 811 | struct config_request mem; |
820 | 812 | ||
821 | mutex_lock(&ioc->config_cmds.mutex); | ||
822 | memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t)); | 813 | memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t)); |
823 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 814 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
824 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 815 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -863,7 +854,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
863 | _config_free_config_dma_memory(ioc, &mem); | 854 | _config_free_config_dma_memory(ioc, &mem); |
864 | 855 | ||
865 | out: | 856 | out: |
866 | mutex_unlock(&ioc->config_cmds.mutex); | ||
867 | return r; | 857 | return r; |
868 | } | 858 | } |
869 | 859 | ||
@@ -886,7 +876,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
886 | int r; | 876 | int r; |
887 | struct config_request mem; | 877 | struct config_request mem; |
888 | 878 | ||
889 | mutex_lock(&ioc->config_cmds.mutex); | ||
890 | memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t)); | 879 | memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t)); |
891 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 880 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
892 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 881 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -931,7 +920,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
931 | _config_free_config_dma_memory(ioc, &mem); | 920 | _config_free_config_dma_memory(ioc, &mem); |
932 | 921 | ||
933 | out: | 922 | out: |
934 | mutex_unlock(&ioc->config_cmds.mutex); | ||
935 | return r; | 923 | return r; |
936 | } | 924 | } |
937 | 925 | ||
@@ -953,7 +941,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) | |||
953 | Mpi2ConfigReply_t mpi_reply; | 941 | Mpi2ConfigReply_t mpi_reply; |
954 | Mpi2SasIOUnitPage0_t config_page; | 942 | Mpi2SasIOUnitPage0_t config_page; |
955 | 943 | ||
956 | mutex_lock(&ioc->config_cmds.mutex); | ||
957 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 944 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
958 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 945 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
959 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | 946 | mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; |
@@ -1002,7 +989,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys) | |||
1002 | _config_free_config_dma_memory(ioc, &mem); | 989 | _config_free_config_dma_memory(ioc, &mem); |
1003 | 990 | ||
1004 | out: | 991 | out: |
1005 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1006 | return r; | 992 | return r; |
1007 | } | 993 | } |
1008 | 994 | ||
@@ -1026,8 +1012,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1026 | Mpi2ConfigRequest_t mpi_request; | 1012 | Mpi2ConfigRequest_t mpi_request; |
1027 | int r; | 1013 | int r; |
1028 | struct config_request mem; | 1014 | struct config_request mem; |
1029 | |||
1030 | mutex_lock(&ioc->config_cmds.mutex); | ||
1031 | memset(config_page, 0, sz); | 1015 | memset(config_page, 0, sz); |
1032 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1016 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1033 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1017 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1070,7 +1054,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1070 | _config_free_config_dma_memory(ioc, &mem); | 1054 | _config_free_config_dma_memory(ioc, &mem); |
1071 | 1055 | ||
1072 | out: | 1056 | out: |
1073 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1074 | return r; | 1057 | return r; |
1075 | } | 1058 | } |
1076 | 1059 | ||
@@ -1095,7 +1078,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1095 | int r; | 1078 | int r; |
1096 | struct config_request mem; | 1079 | struct config_request mem; |
1097 | 1080 | ||
1098 | mutex_lock(&ioc->config_cmds.mutex); | ||
1099 | memset(config_page, 0, sz); | 1081 | memset(config_page, 0, sz); |
1100 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1082 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1101 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1083 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1138,7 +1120,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1138 | _config_free_config_dma_memory(ioc, &mem); | 1120 | _config_free_config_dma_memory(ioc, &mem); |
1139 | 1121 | ||
1140 | out: | 1122 | out: |
1141 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1142 | return r; | 1123 | return r; |
1143 | } | 1124 | } |
1144 | 1125 | ||
@@ -1161,7 +1142,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1161 | int r; | 1142 | int r; |
1162 | struct config_request mem; | 1143 | struct config_request mem; |
1163 | 1144 | ||
1164 | mutex_lock(&ioc->config_cmds.mutex); | ||
1165 | memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t)); | 1145 | memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t)); |
1166 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1146 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1167 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1147 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1206,7 +1186,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1206 | _config_free_config_dma_memory(ioc, &mem); | 1186 | _config_free_config_dma_memory(ioc, &mem); |
1207 | 1187 | ||
1208 | out: | 1188 | out: |
1209 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1210 | return r; | 1189 | return r; |
1211 | } | 1190 | } |
1212 | 1191 | ||
@@ -1230,7 +1209,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1230 | int r; | 1209 | int r; |
1231 | struct config_request mem; | 1210 | struct config_request mem; |
1232 | 1211 | ||
1233 | mutex_lock(&ioc->config_cmds.mutex); | ||
1234 | memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t)); | 1212 | memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t)); |
1235 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1213 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1236 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1214 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1277,7 +1255,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1277 | _config_free_config_dma_memory(ioc, &mem); | 1255 | _config_free_config_dma_memory(ioc, &mem); |
1278 | 1256 | ||
1279 | out: | 1257 | out: |
1280 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1281 | return r; | 1258 | return r; |
1282 | } | 1259 | } |
1283 | 1260 | ||
@@ -1300,7 +1277,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1300 | int r; | 1277 | int r; |
1301 | struct config_request mem; | 1278 | struct config_request mem; |
1302 | 1279 | ||
1303 | mutex_lock(&ioc->config_cmds.mutex); | ||
1304 | memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t)); | 1280 | memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t)); |
1305 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1281 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1306 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1282 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1345,7 +1321,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1345 | _config_free_config_dma_memory(ioc, &mem); | 1321 | _config_free_config_dma_memory(ioc, &mem); |
1346 | 1322 | ||
1347 | out: | 1323 | out: |
1348 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1349 | return r; | 1324 | return r; |
1350 | } | 1325 | } |
1351 | 1326 | ||
@@ -1367,7 +1342,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1367 | int r; | 1342 | int r; |
1368 | struct config_request mem; | 1343 | struct config_request mem; |
1369 | 1344 | ||
1370 | mutex_lock(&ioc->config_cmds.mutex); | ||
1371 | memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t)); | 1345 | memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t)); |
1372 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1346 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1373 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1347 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1413,7 +1387,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1413 | _config_free_config_dma_memory(ioc, &mem); | 1387 | _config_free_config_dma_memory(ioc, &mem); |
1414 | 1388 | ||
1415 | out: | 1389 | out: |
1416 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1417 | return r; | 1390 | return r; |
1418 | } | 1391 | } |
1419 | 1392 | ||
@@ -1435,7 +1408,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1435 | int r; | 1408 | int r; |
1436 | struct config_request mem; | 1409 | struct config_request mem; |
1437 | 1410 | ||
1438 | mutex_lock(&ioc->config_cmds.mutex); | ||
1439 | memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t)); | 1411 | memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t)); |
1440 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1412 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1441 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1413 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1481,7 +1453,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1481 | _config_free_config_dma_memory(ioc, &mem); | 1453 | _config_free_config_dma_memory(ioc, &mem); |
1482 | 1454 | ||
1483 | out: | 1455 | out: |
1484 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1485 | return r; | 1456 | return r; |
1486 | } | 1457 | } |
1487 | 1458 | ||
@@ -1505,7 +1476,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, | |||
1505 | int r; | 1476 | int r; |
1506 | struct config_request mem; | 1477 | struct config_request mem; |
1507 | 1478 | ||
1508 | mutex_lock(&ioc->config_cmds.mutex); | ||
1509 | memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t)); | 1479 | memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t)); |
1510 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1480 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1511 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1481 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1548,7 +1518,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, | |||
1548 | _config_free_config_dma_memory(ioc, &mem); | 1518 | _config_free_config_dma_memory(ioc, &mem); |
1549 | 1519 | ||
1550 | out: | 1520 | out: |
1551 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1552 | return r; | 1521 | return r; |
1553 | } | 1522 | } |
1554 | 1523 | ||
@@ -1572,7 +1541,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, | |||
1572 | struct config_request mem; | 1541 | struct config_request mem; |
1573 | u16 ioc_status; | 1542 | u16 ioc_status; |
1574 | 1543 | ||
1575 | mutex_lock(&ioc->config_cmds.mutex); | ||
1576 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1544 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1577 | *num_pds = 0; | 1545 | *num_pds = 0; |
1578 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1546 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1620,7 +1588,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, | |||
1620 | _config_free_config_dma_memory(ioc, &mem); | 1588 | _config_free_config_dma_memory(ioc, &mem); |
1621 | 1589 | ||
1622 | out: | 1590 | out: |
1623 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1624 | return r; | 1591 | return r; |
1625 | } | 1592 | } |
1626 | 1593 | ||
@@ -1645,7 +1612,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, | |||
1645 | int r; | 1612 | int r; |
1646 | struct config_request mem; | 1613 | struct config_request mem; |
1647 | 1614 | ||
1648 | mutex_lock(&ioc->config_cmds.mutex); | ||
1649 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1615 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1650 | memset(config_page, 0, sz); | 1616 | memset(config_page, 0, sz); |
1651 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1617 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1687,7 +1653,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, | |||
1687 | _config_free_config_dma_memory(ioc, &mem); | 1653 | _config_free_config_dma_memory(ioc, &mem); |
1688 | 1654 | ||
1689 | out: | 1655 | out: |
1690 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1691 | return r; | 1656 | return r; |
1692 | } | 1657 | } |
1693 | 1658 | ||
@@ -1711,7 +1676,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1711 | int r; | 1676 | int r; |
1712 | struct config_request mem; | 1677 | struct config_request mem; |
1713 | 1678 | ||
1714 | mutex_lock(&ioc->config_cmds.mutex); | ||
1715 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1679 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1716 | memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t)); | 1680 | memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t)); |
1717 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1681 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1754,7 +1718,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t | |||
1754 | _config_free_config_dma_memory(ioc, &mem); | 1718 | _config_free_config_dma_memory(ioc, &mem); |
1755 | 1719 | ||
1756 | out: | 1720 | out: |
1757 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1758 | return r; | 1721 | return r; |
1759 | } | 1722 | } |
1760 | 1723 | ||
@@ -1778,7 +1741,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, | |||
1778 | struct config_request mem; | 1741 | struct config_request mem; |
1779 | u16 ioc_status; | 1742 | u16 ioc_status; |
1780 | 1743 | ||
1781 | mutex_lock(&ioc->config_cmds.mutex); | ||
1782 | *volume_handle = 0; | 1744 | *volume_handle = 0; |
1783 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); | 1745 | memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); |
1784 | mpi_request.Function = MPI2_FUNCTION_CONFIG; | 1746 | mpi_request.Function = MPI2_FUNCTION_CONFIG; |
@@ -1842,7 +1804,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle, | |||
1842 | _config_free_config_dma_memory(ioc, &mem); | 1804 | _config_free_config_dma_memory(ioc, &mem); |
1843 | 1805 | ||
1844 | out: | 1806 | out: |
1845 | mutex_unlock(&ioc->config_cmds.mutex); | ||
1846 | return r; | 1807 | return r; |
1847 | } | 1808 | } |
1848 | 1809 | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 2a01a5f2a84d..2e9a4445596f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -2767,6 +2767,10 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
2767 | char *desc_ioc_state = NULL; | 2767 | char *desc_ioc_state = NULL; |
2768 | char *desc_scsi_status = NULL; | 2768 | char *desc_scsi_status = NULL; |
2769 | char *desc_scsi_state = ioc->tmp_string; | 2769 | char *desc_scsi_state = ioc->tmp_string; |
2770 | u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); | ||
2771 | |||
2772 | if (log_info == 0x31170000) | ||
2773 | return; | ||
2770 | 2774 | ||
2771 | switch (ioc_status) { | 2775 | switch (ioc_status) { |
2772 | case MPI2_IOCSTATUS_SUCCESS: | 2776 | case MPI2_IOCSTATUS_SUCCESS: |
@@ -3426,7 +3430,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3426 | __le64 sas_address; | 3430 | __le64 sas_address; |
3427 | int i; | 3431 | int i; |
3428 | unsigned long flags; | 3432 | unsigned long flags; |
3429 | struct _sas_port *mpt2sas_port; | 3433 | struct _sas_port *mpt2sas_port = NULL; |
3430 | int rc = 0; | 3434 | int rc = 0; |
3431 | 3435 | ||
3432 | if (!handle) | 3436 | if (!handle) |
@@ -3518,12 +3522,20 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3518 | &expander_pg1, i, handle))) { | 3522 | &expander_pg1, i, handle))) { |
3519 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 3523 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
3520 | ioc->name, __FILE__, __LINE__, __func__); | 3524 | ioc->name, __FILE__, __LINE__, __func__); |
3521 | continue; | 3525 | rc = -1; |
3526 | goto out_fail; | ||
3522 | } | 3527 | } |
3523 | sas_expander->phy[i].handle = handle; | 3528 | sas_expander->phy[i].handle = handle; |
3524 | sas_expander->phy[i].phy_id = i; | 3529 | sas_expander->phy[i].phy_id = i; |
3525 | mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i], | 3530 | |
3526 | expander_pg1, sas_expander->parent_dev); | 3531 | if ((mpt2sas_transport_add_expander_phy(ioc, |
3532 | &sas_expander->phy[i], expander_pg1, | ||
3533 | sas_expander->parent_dev))) { | ||
3534 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
3535 | ioc->name, __FILE__, __LINE__, __func__); | ||
3536 | rc = -1; | ||
3537 | goto out_fail; | ||
3538 | } | ||
3527 | } | 3539 | } |
3528 | 3540 | ||
3529 | if (sas_expander->enclosure_handle) { | 3541 | if (sas_expander->enclosure_handle) { |
@@ -3540,8 +3552,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3540 | 3552 | ||
3541 | out_fail: | 3553 | out_fail: |
3542 | 3554 | ||
3543 | if (sas_expander) | 3555 | if (mpt2sas_port) |
3544 | kfree(sas_expander->phy); | 3556 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, |
3557 | sas_expander->parent_handle); | ||
3545 | kfree(sas_expander); | 3558 | kfree(sas_expander); |
3546 | return rc; | 3559 | return rc; |
3547 | } | 3560 | } |
@@ -3663,12 +3676,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
3663 | sas_device->hidden_raid_component = is_pd; | 3676 | sas_device->hidden_raid_component = is_pd; |
3664 | 3677 | ||
3665 | /* get enclosure_logical_id */ | 3678 | /* get enclosure_logical_id */ |
3666 | if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0, | 3679 | if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0( |
3667 | MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, | 3680 | ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, |
3668 | sas_device->enclosure_handle))) { | 3681 | sas_device->enclosure_handle))) |
3669 | sas_device->enclosure_logical_id = | 3682 | sas_device->enclosure_logical_id = |
3670 | le64_to_cpu(enclosure_pg0.EnclosureLogicalID); | 3683 | le64_to_cpu(enclosure_pg0.EnclosureLogicalID); |
3671 | } | ||
3672 | 3684 | ||
3673 | /* get device name */ | 3685 | /* get device name */ |
3674 | sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); | 3686 | sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); |
@@ -4250,12 +4262,6 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc, | |||
4250 | u16 handle = le16_to_cpu(element->VolDevHandle); | 4262 | u16 handle = le16_to_cpu(element->VolDevHandle); |
4251 | int rc; | 4263 | int rc; |
4252 | 4264 | ||
4253 | #if 0 /* RAID_HACKS */ | ||
4254 | if (le32_to_cpu(event_data->Flags) & | ||
4255 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) | ||
4256 | return; | ||
4257 | #endif | ||
4258 | |||
4259 | mpt2sas_config_get_volume_wwid(ioc, handle, &wwid); | 4265 | mpt2sas_config_get_volume_wwid(ioc, handle, &wwid); |
4260 | if (!wwid) { | 4266 | if (!wwid) { |
4261 | printk(MPT2SAS_ERR_FMT | 4267 | printk(MPT2SAS_ERR_FMT |
@@ -4310,12 +4316,6 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, | |||
4310 | unsigned long flags; | 4316 | unsigned long flags; |
4311 | struct MPT2SAS_TARGET *sas_target_priv_data; | 4317 | struct MPT2SAS_TARGET *sas_target_priv_data; |
4312 | 4318 | ||
4313 | #if 0 /* RAID_HACKS */ | ||
4314 | if (le32_to_cpu(event_data->Flags) & | ||
4315 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) | ||
4316 | return; | ||
4317 | #endif | ||
4318 | |||
4319 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | 4319 | spin_lock_irqsave(&ioc->raid_device_lock, flags); |
4320 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | 4320 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); |
4321 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | 4321 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); |
@@ -4428,14 +4428,38 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
4428 | struct _sas_device *sas_device; | 4428 | struct _sas_device *sas_device; |
4429 | unsigned long flags; | 4429 | unsigned long flags; |
4430 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | 4430 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); |
4431 | Mpi2ConfigReply_t mpi_reply; | ||
4432 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
4433 | u32 ioc_status; | ||
4431 | 4434 | ||
4432 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4435 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
4433 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4436 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); |
4434 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4437 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
4435 | if (sas_device) | 4438 | if (sas_device) { |
4436 | sas_device->hidden_raid_component = 1; | 4439 | sas_device->hidden_raid_component = 1; |
4437 | else | 4440 | return; |
4438 | _scsih_add_device(ioc, handle, 0, 1); | 4441 | } |
4442 | |||
4443 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
4444 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | ||
4445 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
4446 | ioc->name, __FILE__, __LINE__, __func__); | ||
4447 | return; | ||
4448 | } | ||
4449 | |||
4450 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
4451 | MPI2_IOCSTATUS_MASK; | ||
4452 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
4453 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
4454 | ioc->name, __FILE__, __LINE__, __func__); | ||
4455 | return; | ||
4456 | } | ||
4457 | |||
4458 | _scsih_link_change(ioc, | ||
4459 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | ||
4460 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
4461 | |||
4462 | _scsih_add_device(ioc, handle, 0, 1); | ||
4439 | } | 4463 | } |
4440 | 4464 | ||
4441 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4465 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
@@ -4535,12 +4559,15 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4535 | { | 4559 | { |
4536 | Mpi2EventIrConfigElement_t *element; | 4560 | Mpi2EventIrConfigElement_t *element; |
4537 | int i; | 4561 | int i; |
4562 | u8 foreign_config; | ||
4538 | 4563 | ||
4539 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4564 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
4540 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 4565 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
4541 | _scsih_sas_ir_config_change_event_debug(ioc, event_data); | 4566 | _scsih_sas_ir_config_change_event_debug(ioc, event_data); |
4542 | 4567 | ||
4543 | #endif | 4568 | #endif |
4569 | foreign_config = (le32_to_cpu(event_data->Flags) & | ||
4570 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; | ||
4544 | 4571 | ||
4545 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; | 4572 | element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; |
4546 | for (i = 0; i < event_data->NumElements; i++, element++) { | 4573 | for (i = 0; i < event_data->NumElements; i++, element++) { |
@@ -4548,11 +4575,13 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4548 | switch (element->ReasonCode) { | 4575 | switch (element->ReasonCode) { |
4549 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: | 4576 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: |
4550 | case MPI2_EVENT_IR_CHANGE_RC_ADDED: | 4577 | case MPI2_EVENT_IR_CHANGE_RC_ADDED: |
4551 | _scsih_sas_volume_add(ioc, element); | 4578 | if (!foreign_config) |
4579 | _scsih_sas_volume_add(ioc, element); | ||
4552 | break; | 4580 | break; |
4553 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: | 4581 | case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: |
4554 | case MPI2_EVENT_IR_CHANGE_RC_REMOVED: | 4582 | case MPI2_EVENT_IR_CHANGE_RC_REMOVED: |
4555 | _scsih_sas_volume_delete(ioc, element); | 4583 | if (!foreign_config) |
4584 | _scsih_sas_volume_delete(ioc, element); | ||
4556 | break; | 4585 | break; |
4557 | case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: | 4586 | case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: |
4558 | _scsih_sas_pd_hide(ioc, element); | 4587 | _scsih_sas_pd_hide(ioc, element); |
@@ -4671,6 +4700,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4671 | u32 state; | 4700 | u32 state; |
4672 | struct _sas_device *sas_device; | 4701 | struct _sas_device *sas_device; |
4673 | unsigned long flags; | 4702 | unsigned long flags; |
4703 | Mpi2ConfigReply_t mpi_reply; | ||
4704 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
4705 | u32 ioc_status; | ||
4674 | 4706 | ||
4675 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) | 4707 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) |
4676 | return; | 4708 | return; |
@@ -4687,22 +4719,40 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4687 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4719 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
4688 | 4720 | ||
4689 | switch (state) { | 4721 | switch (state) { |
4690 | #if 0 | ||
4691 | case MPI2_RAID_PD_STATE_OFFLINE: | ||
4692 | if (sas_device) | ||
4693 | _scsih_remove_device(ioc, handle); | ||
4694 | break; | ||
4695 | #endif | ||
4696 | case MPI2_RAID_PD_STATE_ONLINE: | 4722 | case MPI2_RAID_PD_STATE_ONLINE: |
4697 | case MPI2_RAID_PD_STATE_DEGRADED: | 4723 | case MPI2_RAID_PD_STATE_DEGRADED: |
4698 | case MPI2_RAID_PD_STATE_REBUILDING: | 4724 | case MPI2_RAID_PD_STATE_REBUILDING: |
4699 | case MPI2_RAID_PD_STATE_OPTIMAL: | 4725 | case MPI2_RAID_PD_STATE_OPTIMAL: |
4700 | if (sas_device) | 4726 | if (sas_device) { |
4701 | sas_device->hidden_raid_component = 1; | 4727 | sas_device->hidden_raid_component = 1; |
4702 | else | 4728 | return; |
4703 | _scsih_add_device(ioc, handle, 0, 1); | 4729 | } |
4730 | |||
4731 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | ||
4732 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | ||
4733 | handle))) { | ||
4734 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
4735 | ioc->name, __FILE__, __LINE__, __func__); | ||
4736 | return; | ||
4737 | } | ||
4738 | |||
4739 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
4740 | MPI2_IOCSTATUS_MASK; | ||
4741 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
4742 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
4743 | ioc->name, __FILE__, __LINE__, __func__); | ||
4744 | return; | ||
4745 | } | ||
4746 | |||
4747 | _scsih_link_change(ioc, | ||
4748 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | ||
4749 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
4750 | |||
4751 | _scsih_add_device(ioc, handle, 0, 1); | ||
4752 | |||
4704 | break; | 4753 | break; |
4705 | 4754 | ||
4755 | case MPI2_RAID_PD_STATE_OFFLINE: | ||
4706 | case MPI2_RAID_PD_STATE_NOT_CONFIGURED: | 4756 | case MPI2_RAID_PD_STATE_NOT_CONFIGURED: |
4707 | case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: | 4757 | case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: |
4708 | case MPI2_RAID_PD_STATE_HOT_SPARE: | 4758 | case MPI2_RAID_PD_STATE_HOT_SPARE: |
@@ -5774,6 +5824,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5774 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | 5824 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); |
5775 | u32 device_state; | 5825 | u32 device_state; |
5776 | 5826 | ||
5827 | mpt2sas_base_stop_watchdog(ioc); | ||
5777 | flush_scheduled_work(); | 5828 | flush_scheduled_work(); |
5778 | scsi_block_requests(shost); | 5829 | scsi_block_requests(shost); |
5779 | device_state = pci_choose_state(pdev, state); | 5830 | device_state = pci_choose_state(pdev, state); |
@@ -5816,6 +5867,7 @@ _scsih_resume(struct pci_dev *pdev) | |||
5816 | 5867 | ||
5817 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); | 5868 | mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); |
5818 | scsi_unblock_requests(shost); | 5869 | scsi_unblock_requests(shost); |
5870 | mpt2sas_base_start_watchdog(ioc); | ||
5819 | return 0; | 5871 | return 0; |
5820 | } | 5872 | } |
5821 | #endif /* CONFIG_PM */ | 5873 | #endif /* CONFIG_PM */ |
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c index fcc184cd066d..cbceb0ebabf7 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c | |||
@@ -15,19 +15,18 @@ void qla4xxx_dump_buffer(void *b, uint32_t size) | |||
15 | uint32_t cnt; | 15 | uint32_t cnt; |
16 | uint8_t *c = b; | 16 | uint8_t *c = b; |
17 | 17 | ||
18 | printk(" 0 1 2 3 4 5 6 7 8 9 Ah Bh Ch Dh Eh " | 18 | printk(" 0 1 2 3 4 5 6 7 8 9 Ah Bh Ch Dh Eh " |
19 | "Fh\n"); | 19 | "Fh\n"); |
20 | printk("------------------------------------------------------------" | 20 | printk("------------------------------------------------------------" |
21 | "--\n"); | 21 | "--\n"); |
22 | for (cnt = 0; cnt < size; cnt++, c++) { | 22 | for (cnt = 0; cnt < size; c++) { |
23 | printk(KERN_DEBUG "%02x", *c); | 23 | printk(KERN_INFO "%02x", *c); |
24 | if (!(cnt % 16)) | 24 | if (!(++cnt % 16)) |
25 | printk(KERN_DEBUG "\n"); | 25 | printk(KERN_INFO "\n"); |
26 | 26 | ||
27 | else | 27 | else |
28 | printk(KERN_DEBUG " "); | 28 | printk(KERN_INFO " "); |
29 | } | 29 | } |
30 | if (cnt % 16) | 30 | printk(KERN_INFO "\n"); |
31 | printk(KERN_DEBUG "\n"); | ||
32 | } | 31 | } |
33 | 32 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index b586f27c3bd4..81b5f29254e2 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -100,7 +100,6 @@ | |||
100 | #define MAX_SRBS MAX_CMDS_TO_RISC | 100 | #define MAX_SRBS MAX_CMDS_TO_RISC |
101 | #define MBOX_AEN_REG_COUNT 5 | 101 | #define MBOX_AEN_REG_COUNT 5 |
102 | #define MAX_INIT_RETRIES 5 | 102 | #define MAX_INIT_RETRIES 5 |
103 | #define IOCB_HIWAT_CUSHION 16 | ||
104 | 103 | ||
105 | /* | 104 | /* |
106 | * Buffer sizes | 105 | * Buffer sizes |
@@ -184,6 +183,11 @@ struct srb { | |||
184 | uint16_t cc_stat; | 183 | uint16_t cc_stat; |
185 | u_long r_start; /* Time we recieve a cmd from OS */ | 184 | u_long r_start; /* Time we recieve a cmd from OS */ |
186 | u_long u_start; /* Time when we handed the cmd to F/W */ | 185 | u_long u_start; /* Time when we handed the cmd to F/W */ |
186 | |||
187 | /* Used for extended sense / status continuation */ | ||
188 | uint8_t *req_sense_ptr; | ||
189 | uint16_t req_sense_len; | ||
190 | uint16_t reserved2; | ||
187 | }; | 191 | }; |
188 | 192 | ||
189 | /* | 193 | /* |
@@ -302,7 +306,6 @@ struct scsi_qla_host { | |||
302 | uint32_t tot_ddbs; | 306 | uint32_t tot_ddbs; |
303 | 307 | ||
304 | uint16_t iocb_cnt; | 308 | uint16_t iocb_cnt; |
305 | uint16_t iocb_hiwat; | ||
306 | 309 | ||
307 | /* SRB cache. */ | 310 | /* SRB cache. */ |
308 | #define SRB_MIN_REQ 128 | 311 | #define SRB_MIN_REQ 128 |
@@ -436,6 +439,8 @@ struct scsi_qla_host { | |||
436 | /* Map ddb_list entry by FW ddb index */ | 439 | /* Map ddb_list entry by FW ddb index */ |
437 | struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES]; | 440 | struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES]; |
438 | 441 | ||
442 | /* Saved srb for status continuation entry processing */ | ||
443 | struct srb *status_srb; | ||
439 | }; | 444 | }; |
440 | 445 | ||
441 | static inline int is_qla4010(struct scsi_qla_host *ha) | 446 | static inline int is_qla4010(struct scsi_qla_host *ha) |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 1b667a70cffa..9cd7a608df38 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -572,6 +572,7 @@ struct conn_event_log_entry { | |||
572 | *************************************************************************/ | 572 | *************************************************************************/ |
573 | #define IOCB_MAX_CDB_LEN 16 /* Bytes in a CBD */ | 573 | #define IOCB_MAX_CDB_LEN 16 /* Bytes in a CBD */ |
574 | #define IOCB_MAX_SENSEDATA_LEN 32 /* Bytes of sense data */ | 574 | #define IOCB_MAX_SENSEDATA_LEN 32 /* Bytes of sense data */ |
575 | #define IOCB_MAX_EXT_SENSEDATA_LEN 60 /* Bytes of extended sense data */ | ||
575 | 576 | ||
576 | /* IOCB header structure */ | 577 | /* IOCB header structure */ |
577 | struct qla4_header { | 578 | struct qla4_header { |
@@ -733,6 +734,12 @@ struct status_entry { | |||
733 | 734 | ||
734 | }; | 735 | }; |
735 | 736 | ||
737 | /* Status Continuation entry */ | ||
738 | struct status_cont_entry { | ||
739 | struct qla4_header hdr; /* 00-03 */ | ||
740 | uint8_t ext_sense_data[IOCB_MAX_EXT_SENSEDATA_LEN]; /* 04-63 */ | ||
741 | }; | ||
742 | |||
736 | struct passthru0 { | 743 | struct passthru0 { |
737 | struct qla4_header hdr; /* 00-03 */ | 744 | struct qla4_header hdr; /* 00-03 */ |
738 | uint32_t handle; /* 04-07 */ | 745 | uint32_t handle; /* 04-07 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index 912a67494adf..e0c32159749c 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c | |||
@@ -10,9 +10,42 @@ | |||
10 | #include "ql4_dbg.h" | 10 | #include "ql4_dbg.h" |
11 | #include "ql4_inline.h" | 11 | #include "ql4_inline.h" |
12 | 12 | ||
13 | |||
14 | #include <scsi/scsi_tcq.h> | 13 | #include <scsi/scsi_tcq.h> |
15 | 14 | ||
15 | static int | ||
16 | qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt) | ||
17 | { | ||
18 | uint16_t cnt; | ||
19 | |||
20 | /* Calculate number of free request entries. */ | ||
21 | if ((req_cnt + 2) >= ha->req_q_count) { | ||
22 | cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); | ||
23 | if (ha->request_in < cnt) | ||
24 | ha->req_q_count = cnt - ha->request_in; | ||
25 | else | ||
26 | ha->req_q_count = REQUEST_QUEUE_DEPTH - | ||
27 | (ha->request_in - cnt); | ||
28 | } | ||
29 | |||
30 | /* Check if room for request in request ring. */ | ||
31 | if ((req_cnt + 2) < ha->req_q_count) | ||
32 | return 1; | ||
33 | else | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static void qla4xxx_advance_req_ring_ptr(struct scsi_qla_host *ha) | ||
38 | { | ||
39 | /* Advance request queue pointer */ | ||
40 | if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { | ||
41 | ha->request_in = 0; | ||
42 | ha->request_ptr = ha->request_ring; | ||
43 | } else { | ||
44 | ha->request_in++; | ||
45 | ha->request_ptr++; | ||
46 | } | ||
47 | } | ||
48 | |||
16 | /** | 49 | /** |
17 | * qla4xxx_get_req_pkt - returns a valid entry in request queue. | 50 | * qla4xxx_get_req_pkt - returns a valid entry in request queue. |
18 | * @ha: Pointer to host adapter structure. | 51 | * @ha: Pointer to host adapter structure. |
@@ -26,35 +59,18 @@ | |||
26 | static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, | 59 | static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, |
27 | struct queue_entry **queue_entry) | 60 | struct queue_entry **queue_entry) |
28 | { | 61 | { |
29 | uint16_t request_in; | 62 | uint16_t req_cnt = 1; |
30 | uint8_t status = QLA_SUCCESS; | ||
31 | |||
32 | *queue_entry = ha->request_ptr; | ||
33 | 63 | ||
34 | /* get the latest request_in and request_out index */ | 64 | if (qla4xxx_space_in_req_ring(ha, req_cnt)) { |
35 | request_in = ha->request_in; | 65 | *queue_entry = ha->request_ptr; |
36 | ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); | ||
37 | |||
38 | /* Advance request queue pointer and check for queue full */ | ||
39 | if (request_in == (REQUEST_QUEUE_DEPTH - 1)) { | ||
40 | request_in = 0; | ||
41 | ha->request_ptr = ha->request_ring; | ||
42 | } else { | ||
43 | request_in++; | ||
44 | ha->request_ptr++; | ||
45 | } | ||
46 | |||
47 | /* request queue is full, try again later */ | ||
48 | if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) { | ||
49 | /* restore request pointer */ | ||
50 | ha->request_ptr = *queue_entry; | ||
51 | status = QLA_ERROR; | ||
52 | } else { | ||
53 | ha->request_in = request_in; | ||
54 | memset(*queue_entry, 0, sizeof(**queue_entry)); | 66 | memset(*queue_entry, 0, sizeof(**queue_entry)); |
67 | |||
68 | qla4xxx_advance_req_ring_ptr(ha); | ||
69 | ha->req_q_count -= req_cnt; | ||
70 | return QLA_SUCCESS; | ||
55 | } | 71 | } |
56 | 72 | ||
57 | return status; | 73 | return QLA_ERROR; |
58 | } | 74 | } |
59 | 75 | ||
60 | /** | 76 | /** |
@@ -100,21 +116,14 @@ exit_send_marker: | |||
100 | return status; | 116 | return status; |
101 | } | 117 | } |
102 | 118 | ||
103 | static struct continuation_t1_entry* qla4xxx_alloc_cont_entry( | 119 | static struct continuation_t1_entry * |
104 | struct scsi_qla_host *ha) | 120 | qla4xxx_alloc_cont_entry(struct scsi_qla_host *ha) |
105 | { | 121 | { |
106 | struct continuation_t1_entry *cont_entry; | 122 | struct continuation_t1_entry *cont_entry; |
107 | 123 | ||
108 | cont_entry = (struct continuation_t1_entry *)ha->request_ptr; | 124 | cont_entry = (struct continuation_t1_entry *)ha->request_ptr; |
109 | 125 | ||
110 | /* Advance request queue pointer */ | 126 | qla4xxx_advance_req_ring_ptr(ha); |
111 | if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { | ||
112 | ha->request_in = 0; | ||
113 | ha->request_ptr = ha->request_ring; | ||
114 | } else { | ||
115 | ha->request_in++; | ||
116 | ha->request_ptr++; | ||
117 | } | ||
118 | 127 | ||
119 | /* Load packet defaults */ | 128 | /* Load packet defaults */ |
120 | cont_entry->hdr.entryType = ET_CONTINUE; | 129 | cont_entry->hdr.entryType = ET_CONTINUE; |
@@ -197,13 +206,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
197 | struct scsi_cmnd *cmd = srb->cmd; | 206 | struct scsi_cmnd *cmd = srb->cmd; |
198 | struct ddb_entry *ddb_entry; | 207 | struct ddb_entry *ddb_entry; |
199 | struct command_t3_entry *cmd_entry; | 208 | struct command_t3_entry *cmd_entry; |
200 | |||
201 | int nseg; | 209 | int nseg; |
202 | uint16_t tot_dsds; | 210 | uint16_t tot_dsds; |
203 | uint16_t req_cnt; | 211 | uint16_t req_cnt; |
204 | |||
205 | unsigned long flags; | 212 | unsigned long flags; |
206 | uint16_t cnt; | ||
207 | uint32_t index; | 213 | uint32_t index; |
208 | char tag[2]; | 214 | char tag[2]; |
209 | 215 | ||
@@ -217,6 +223,19 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
217 | 223 | ||
218 | index = (uint32_t)cmd->request->tag; | 224 | index = (uint32_t)cmd->request->tag; |
219 | 225 | ||
226 | /* | ||
227 | * Check to see if adapter is online before placing request on | ||
228 | * request queue. If a reset occurs and a request is in the queue, | ||
229 | * the firmware will still attempt to process the request, retrieving | ||
230 | * garbage for pointers. | ||
231 | */ | ||
232 | if (!test_bit(AF_ONLINE, &ha->flags)) { | ||
233 | DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " | ||
234 | "Do not issue command.\n", | ||
235 | ha->host_no, __func__)); | ||
236 | goto queuing_error; | ||
237 | } | ||
238 | |||
220 | /* Calculate the number of request entries needed. */ | 239 | /* Calculate the number of request entries needed. */ |
221 | nseg = scsi_dma_map(cmd); | 240 | nseg = scsi_dma_map(cmd); |
222 | if (nseg < 0) | 241 | if (nseg < 0) |
@@ -224,17 +243,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
224 | tot_dsds = nseg; | 243 | tot_dsds = nseg; |
225 | 244 | ||
226 | req_cnt = qla4xxx_calc_request_entries(tot_dsds); | 245 | req_cnt = qla4xxx_calc_request_entries(tot_dsds); |
227 | 246 | if (!qla4xxx_space_in_req_ring(ha, req_cnt)) | |
228 | if (ha->req_q_count < (req_cnt + 2)) { | ||
229 | cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); | ||
230 | if (ha->request_in < cnt) | ||
231 | ha->req_q_count = cnt - ha->request_in; | ||
232 | else | ||
233 | ha->req_q_count = REQUEST_QUEUE_DEPTH - | ||
234 | (ha->request_in - cnt); | ||
235 | } | ||
236 | |||
237 | if (ha->req_q_count < (req_cnt + 2)) | ||
238 | goto queuing_error; | 247 | goto queuing_error; |
239 | 248 | ||
240 | /* total iocbs active */ | 249 | /* total iocbs active */ |
@@ -286,32 +295,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
286 | break; | 295 | break; |
287 | } | 296 | } |
288 | 297 | ||
289 | 298 | qla4xxx_advance_req_ring_ptr(ha); | |
290 | /* Advance request queue pointer */ | ||
291 | ha->request_in++; | ||
292 | if (ha->request_in == REQUEST_QUEUE_DEPTH) { | ||
293 | ha->request_in = 0; | ||
294 | ha->request_ptr = ha->request_ring; | ||
295 | } else | ||
296 | ha->request_ptr++; | ||
297 | |||
298 | |||
299 | qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds); | 299 | qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds); |
300 | wmb(); | 300 | wmb(); |
301 | 301 | ||
302 | /* | ||
303 | * Check to see if adapter is online before placing request on | ||
304 | * request queue. If a reset occurs and a request is in the queue, | ||
305 | * the firmware will still attempt to process the request, retrieving | ||
306 | * garbage for pointers. | ||
307 | */ | ||
308 | if (!test_bit(AF_ONLINE, &ha->flags)) { | ||
309 | DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " | ||
310 | "Do not issue command.\n", | ||
311 | ha->host_no, __func__)); | ||
312 | goto queuing_error; | ||
313 | } | ||
314 | |||
315 | srb->cmd->host_scribble = (unsigned char *)srb; | 302 | srb->cmd->host_scribble = (unsigned char *)srb; |
316 | 303 | ||
317 | /* update counters */ | 304 | /* update counters */ |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 799120fcb9be..8025ee16588e 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -11,6 +11,98 @@ | |||
11 | #include "ql4_inline.h" | 11 | #include "ql4_inline.h" |
12 | 12 | ||
13 | /** | 13 | /** |
14 | * qla4xxx_copy_sense - copy sense data into cmd sense buffer | ||
15 | * @ha: Pointer to host adapter structure. | ||
16 | * @sts_entry: Pointer to status entry structure. | ||
17 | * @srb: Pointer to srb structure. | ||
18 | **/ | ||
19 | static void qla4xxx_copy_sense(struct scsi_qla_host *ha, | ||
20 | struct status_entry *sts_entry, | ||
21 | struct srb *srb) | ||
22 | { | ||
23 | struct scsi_cmnd *cmd = srb->cmd; | ||
24 | uint16_t sense_len; | ||
25 | |||
26 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | ||
27 | sense_len = le16_to_cpu(sts_entry->senseDataByteCnt); | ||
28 | if (sense_len == 0) | ||
29 | return; | ||
30 | |||
31 | /* Save total available sense length, | ||
32 | * not to exceed cmd's sense buffer size */ | ||
33 | sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE); | ||
34 | srb->req_sense_ptr = cmd->sense_buffer; | ||
35 | srb->req_sense_len = sense_len; | ||
36 | |||
37 | /* Copy sense from sts_entry pkt */ | ||
38 | sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN); | ||
39 | memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len); | ||
40 | |||
41 | DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: %s: sense key = %x, " | ||
42 | "ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no, | ||
43 | cmd->device->channel, cmd->device->id, | ||
44 | cmd->device->lun, __func__, | ||
45 | sts_entry->senseData[2] & 0x0f, | ||
46 | sts_entry->senseData[7], | ||
47 | sts_entry->senseData[12], | ||
48 | sts_entry->senseData[13])); | ||
49 | |||
50 | DEBUG5(qla4xxx_dump_buffer(cmd->sense_buffer, sense_len)); | ||
51 | srb->flags |= SRB_GOT_SENSE; | ||
52 | |||
53 | /* Update srb, in case a sts_cont pkt follows */ | ||
54 | srb->req_sense_ptr += sense_len; | ||
55 | srb->req_sense_len -= sense_len; | ||
56 | if (srb->req_sense_len != 0) | ||
57 | ha->status_srb = srb; | ||
58 | else | ||
59 | ha->status_srb = NULL; | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * qla4xxx_status_cont_entry - Process a Status Continuations entry. | ||
64 | * @ha: SCSI driver HA context | ||
65 | * @sts_cont: Entry pointer | ||
66 | * | ||
67 | * Extended sense data. | ||
68 | */ | ||
69 | static void | ||
70 | qla4xxx_status_cont_entry(struct scsi_qla_host *ha, | ||
71 | struct status_cont_entry *sts_cont) | ||
72 | { | ||
73 | struct srb *srb = ha->status_srb; | ||
74 | struct scsi_cmnd *cmd; | ||
75 | uint8_t sense_len; | ||
76 | |||
77 | if (srb == NULL) | ||
78 | return; | ||
79 | |||
80 | cmd = srb->cmd; | ||
81 | if (cmd == NULL) { | ||
82 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: Cmd already returned " | ||
83 | "back to OS srb=%p srb->state:%d\n", ha->host_no, | ||
84 | __func__, srb, srb->state)); | ||
85 | ha->status_srb = NULL; | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | /* Copy sense data. */ | ||
90 | sense_len = min_t(uint16_t, srb->req_sense_len, | ||
91 | IOCB_MAX_EXT_SENSEDATA_LEN); | ||
92 | memcpy(srb->req_sense_ptr, sts_cont->ext_sense_data, sense_len); | ||
93 | DEBUG5(qla4xxx_dump_buffer(srb->req_sense_ptr, sense_len)); | ||
94 | |||
95 | srb->req_sense_ptr += sense_len; | ||
96 | srb->req_sense_len -= sense_len; | ||
97 | |||
98 | /* Place command on done queue. */ | ||
99 | if (srb->req_sense_len == 0) { | ||
100 | qla4xxx_srb_compl(ha, srb); | ||
101 | ha->status_srb = NULL; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /** | ||
14 | * qla4xxx_status_entry - processes status IOCBs | 106 | * qla4xxx_status_entry - processes status IOCBs |
15 | * @ha: Pointer to host adapter structure. | 107 | * @ha: Pointer to host adapter structure. |
16 | * @sts_entry: Pointer to status entry structure. | 108 | * @sts_entry: Pointer to status entry structure. |
@@ -23,7 +115,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
23 | struct srb *srb; | 115 | struct srb *srb; |
24 | struct ddb_entry *ddb_entry; | 116 | struct ddb_entry *ddb_entry; |
25 | uint32_t residual; | 117 | uint32_t residual; |
26 | uint16_t sensebytecnt; | ||
27 | 118 | ||
28 | srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); | 119 | srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); |
29 | if (!srb) { | 120 | if (!srb) { |
@@ -92,24 +183,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
92 | break; | 183 | break; |
93 | 184 | ||
94 | /* Copy Sense Data into sense buffer. */ | 185 | /* Copy Sense Data into sense buffer. */ |
95 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | 186 | qla4xxx_copy_sense(ha, sts_entry, srb); |
96 | |||
97 | sensebytecnt = le16_to_cpu(sts_entry->senseDataByteCnt); | ||
98 | if (sensebytecnt == 0) | ||
99 | break; | ||
100 | |||
101 | memcpy(cmd->sense_buffer, sts_entry->senseData, | ||
102 | min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE)); | ||
103 | |||
104 | DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, " | ||
105 | "ASC/ASCQ = %02x/%02x\n", ha->host_no, | ||
106 | cmd->device->channel, cmd->device->id, | ||
107 | cmd->device->lun, __func__, | ||
108 | sts_entry->senseData[2] & 0x0f, | ||
109 | sts_entry->senseData[12], | ||
110 | sts_entry->senseData[13])); | ||
111 | |||
112 | srb->flags |= SRB_GOT_SENSE; | ||
113 | break; | 187 | break; |
114 | 188 | ||
115 | case SCS_INCOMPLETE: | 189 | case SCS_INCOMPLETE: |
@@ -176,23 +250,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
176 | break; | 250 | break; |
177 | 251 | ||
178 | /* Copy Sense Data into sense buffer. */ | 252 | /* Copy Sense Data into sense buffer. */ |
179 | memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | 253 | qla4xxx_copy_sense(ha, sts_entry, srb); |
180 | |||
181 | sensebytecnt = | ||
182 | le16_to_cpu(sts_entry->senseDataByteCnt); | ||
183 | if (sensebytecnt == 0) | ||
184 | break; | ||
185 | |||
186 | memcpy(cmd->sense_buffer, sts_entry->senseData, | ||
187 | min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE)); | ||
188 | |||
189 | DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, " | ||
190 | "ASC/ASCQ = %02x/%02x\n", ha->host_no, | ||
191 | cmd->device->channel, cmd->device->id, | ||
192 | cmd->device->lun, __func__, | ||
193 | sts_entry->senseData[2] & 0x0f, | ||
194 | sts_entry->senseData[12], | ||
195 | sts_entry->senseData[13])); | ||
196 | } else { | 254 | } else { |
197 | /* | 255 | /* |
198 | * If RISC reports underrun and target does not | 256 | * If RISC reports underrun and target does not |
@@ -268,9 +326,10 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
268 | 326 | ||
269 | status_entry_exit: | 327 | status_entry_exit: |
270 | 328 | ||
271 | /* complete the request */ | 329 | /* complete the request, if not waiting for status_continuation pkt */ |
272 | srb->cc_stat = sts_entry->completionStatus; | 330 | srb->cc_stat = sts_entry->completionStatus; |
273 | qla4xxx_srb_compl(ha, srb); | 331 | if (ha->status_srb == NULL) |
332 | qla4xxx_srb_compl(ha, srb); | ||
274 | } | 333 | } |
275 | 334 | ||
276 | /** | 335 | /** |
@@ -305,10 +364,7 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha) | |||
305 | /* process entry */ | 364 | /* process entry */ |
306 | switch (sts_entry->hdr.entryType) { | 365 | switch (sts_entry->hdr.entryType) { |
307 | case ET_STATUS: | 366 | case ET_STATUS: |
308 | /* | 367 | /* Common status */ |
309 | * Common status - Single completion posted in single | ||
310 | * IOSB. | ||
311 | */ | ||
312 | qla4xxx_status_entry(ha, sts_entry); | 368 | qla4xxx_status_entry(ha, sts_entry); |
313 | break; | 369 | break; |
314 | 370 | ||
@@ -316,9 +372,8 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha) | |||
316 | break; | 372 | break; |
317 | 373 | ||
318 | case ET_STATUS_CONTINUATION: | 374 | case ET_STATUS_CONTINUATION: |
319 | /* Just throw away the status continuation entries */ | 375 | qla4xxx_status_cont_entry(ha, |
320 | DEBUG2(printk("scsi%ld: %s: Status Continuation entry " | 376 | (struct status_cont_entry *) sts_entry); |
321 | "- ignoring\n", ha->host_no, __func__)); | ||
322 | break; | 377 | break; |
323 | 378 | ||
324 | case ET_COMMAND: | 379 | case ET_COMMAND: |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 051b0f5e8c8e..09d6d4b76f39 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -385,16 +385,6 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) | |||
385 | mbox_sts[0])); | 385 | mbox_sts[0])); |
386 | return QLA_ERROR; | 386 | return QLA_ERROR; |
387 | } | 387 | } |
388 | |||
389 | /* High-water mark of IOCBs */ | ||
390 | ha->iocb_hiwat = mbox_sts[2]; | ||
391 | if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION) | ||
392 | ha->iocb_hiwat -= IOCB_HIWAT_CUSHION; | ||
393 | else | ||
394 | dev_info(&ha->pdev->dev, "WARNING!!! You have less than %d " | ||
395 | "firmware IOCBs available (%d).\n", | ||
396 | IOCB_HIWAT_CUSHION, ha->iocb_hiwat); | ||
397 | |||
398 | return QLA_SUCCESS; | 388 | return QLA_SUCCESS; |
399 | } | 389 | } |
400 | 390 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ec9da6ce8489..40e3cafb3a9c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -66,6 +66,7 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess, | |||
66 | static int qla4xxx_host_get_param(struct Scsi_Host *shost, | 66 | static int qla4xxx_host_get_param(struct Scsi_Host *shost, |
67 | enum iscsi_host_param param, char *buf); | 67 | enum iscsi_host_param param, char *buf); |
68 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); | 68 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); |
69 | static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc); | ||
69 | 70 | ||
70 | /* | 71 | /* |
71 | * SCSI host template entry points | 72 | * SCSI host template entry points |
@@ -89,6 +90,7 @@ static struct scsi_host_template qla4xxx_driver_template = { | |||
89 | .eh_device_reset_handler = qla4xxx_eh_device_reset, | 90 | .eh_device_reset_handler = qla4xxx_eh_device_reset, |
90 | .eh_target_reset_handler = qla4xxx_eh_target_reset, | 91 | .eh_target_reset_handler = qla4xxx_eh_target_reset, |
91 | .eh_host_reset_handler = qla4xxx_eh_host_reset, | 92 | .eh_host_reset_handler = qla4xxx_eh_host_reset, |
93 | .eh_timed_out = qla4xxx_eh_cmd_timed_out, | ||
92 | 94 | ||
93 | .slave_configure = qla4xxx_slave_configure, | 95 | .slave_configure = qla4xxx_slave_configure, |
94 | .slave_alloc = qla4xxx_slave_alloc, | 96 | .slave_alloc = qla4xxx_slave_alloc, |
@@ -124,6 +126,21 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
124 | 126 | ||
125 | static struct scsi_transport_template *qla4xxx_scsi_transport; | 127 | static struct scsi_transport_template *qla4xxx_scsi_transport; |
126 | 128 | ||
129 | static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc) | ||
130 | { | ||
131 | struct iscsi_cls_session *session; | ||
132 | struct ddb_entry *ddb_entry; | ||
133 | |||
134 | session = starget_to_session(scsi_target(sc->device)); | ||
135 | ddb_entry = session->dd_data; | ||
136 | |||
137 | /* if we are not logged in then the LLD is going to clean up the cmd */ | ||
138 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) | ||
139 | return BLK_EH_RESET_TIMER; | ||
140 | else | ||
141 | return BLK_EH_NOT_HANDLED; | ||
142 | } | ||
143 | |||
127 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) | 144 | static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) |
128 | { | 145 | { |
129 | struct ddb_entry *ddb_entry = session->dd_data; | 146 | struct ddb_entry *ddb_entry = session->dd_data; |
@@ -904,18 +921,17 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | |||
904 | /* Flush any pending ddb changed AENs */ | 921 | /* Flush any pending ddb changed AENs */ |
905 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 922 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
906 | 923 | ||
924 | qla4xxx_flush_active_srbs(ha); | ||
925 | |||
907 | /* Reset the firmware. If successful, function | 926 | /* Reset the firmware. If successful, function |
908 | * returns with ISP interrupts enabled. | 927 | * returns with ISP interrupts enabled. |
909 | */ | 928 | */ |
910 | if (status == QLA_SUCCESS) { | 929 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", |
911 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", | 930 | ha->host_no, __func__)); |
912 | ha->host_no, __func__)); | 931 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) |
913 | qla4xxx_flush_active_srbs(ha); | 932 | status = qla4xxx_soft_reset(ha); |
914 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) | 933 | else |
915 | status = qla4xxx_soft_reset(ha); | 934 | status = QLA_ERROR; |
916 | else | ||
917 | status = QLA_ERROR; | ||
918 | } | ||
919 | 935 | ||
920 | /* Flush any pending ddb changed AENs */ | 936 | /* Flush any pending ddb changed AENs */ |
921 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 937 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
@@ -1527,11 +1543,9 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
1527 | { | 1543 | { |
1528 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); | 1544 | struct scsi_qla_host *ha = to_qla_host(cmd->device->host); |
1529 | struct ddb_entry *ddb_entry = cmd->device->hostdata; | 1545 | struct ddb_entry *ddb_entry = cmd->device->hostdata; |
1530 | struct srb *sp; | ||
1531 | int ret = FAILED, stat; | 1546 | int ret = FAILED, stat; |
1532 | 1547 | ||
1533 | sp = (struct srb *) cmd->SCp.ptr; | 1548 | if (!ddb_entry) |
1534 | if (!sp || !ddb_entry) | ||
1535 | return ret; | 1549 | return ret; |
1536 | 1550 | ||
1537 | dev_info(&ha->pdev->dev, | 1551 | dev_info(&ha->pdev->dev, |
@@ -1644,7 +1658,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1644 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; | 1658 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; |
1645 | 1659 | ||
1646 | dev_info(&ha->pdev->dev, | 1660 | dev_info(&ha->pdev->dev, |
1647 | "scsi(%ld:%d:%d:%d): ADAPTER RESET ISSUED.\n", ha->host_no, | 1661 | "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, |
1648 | cmd->device->channel, cmd->device->id, cmd->device->lun); | 1662 | cmd->device->channel, cmd->device->id, cmd->device->lun); |
1649 | 1663 | ||
1650 | if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) { | 1664 | if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) { |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index ab984cb89cea..6980cb279c81 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
@@ -5,5 +5,5 @@ | |||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define QLA4XXX_DRIVER_VERSION "5.01.00-k8" | 8 | #define QLA4XXX_DRIVER_VERSION "5.01.00-k9" |
9 | 9 | ||
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 783e33c65eb7..b47240ca4b19 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -990,7 +990,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost, | |||
990 | struct iscsi_uevent *ev; | 990 | struct iscsi_uevent *ev; |
991 | int len = NLMSG_SPACE(sizeof(*ev) + data_size); | 991 | int len = NLMSG_SPACE(sizeof(*ev) + data_size); |
992 | 992 | ||
993 | skb = alloc_skb(len, GFP_NOIO); | 993 | skb = alloc_skb(len, GFP_ATOMIC); |
994 | if (!skb) { | 994 | if (!skb) { |
995 | printk(KERN_ERR "can not deliver iscsi offload message:OOM\n"); | 995 | printk(KERN_ERR "can not deliver iscsi offload message:OOM\n"); |
996 | return -ENOMEM; | 996 | return -ENOMEM; |
@@ -1012,7 +1012,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost, | |||
1012 | 1012 | ||
1013 | memcpy((char *)ev + sizeof(*ev), data, data_size); | 1013 | memcpy((char *)ev + sizeof(*ev), data, data_size); |
1014 | 1014 | ||
1015 | return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_NOIO); | 1015 | return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC); |
1016 | } | 1016 | } |
1017 | EXPORT_SYMBOL_GPL(iscsi_offload_mesg); | 1017 | EXPORT_SYMBOL_GPL(iscsi_offload_mesg); |
1018 | 1018 | ||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 5616cd780ff3..b7b9fec67a98 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1840,6 +1840,18 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) | |||
1840 | kfree(buffer); | 1840 | kfree(buffer); |
1841 | } | 1841 | } |
1842 | 1842 | ||
1843 | static int sd_try_extended_inquiry(struct scsi_device *sdp) | ||
1844 | { | ||
1845 | /* | ||
1846 | * Although VPD inquiries can go to SCSI-2 type devices, | ||
1847 | * some USB ones crash on receiving them, and the pages | ||
1848 | * we currently ask for are for SPC-3 and beyond | ||
1849 | */ | ||
1850 | if (sdp->scsi_level > SCSI_SPC_2) | ||
1851 | return 1; | ||
1852 | return 0; | ||
1853 | } | ||
1854 | |||
1843 | /** | 1855 | /** |
1844 | * sd_revalidate_disk - called the first time a new disk is seen, | 1856 | * sd_revalidate_disk - called the first time a new disk is seen, |
1845 | * performs disk spin up, read_capacity, etc. | 1857 | * performs disk spin up, read_capacity, etc. |
@@ -1877,8 +1889,12 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
1877 | */ | 1889 | */ |
1878 | if (sdkp->media_present) { | 1890 | if (sdkp->media_present) { |
1879 | sd_read_capacity(sdkp, buffer); | 1891 | sd_read_capacity(sdkp, buffer); |
1880 | sd_read_block_limits(sdkp); | 1892 | |
1881 | sd_read_block_characteristics(sdkp); | 1893 | if (sd_try_extended_inquiry(sdp)) { |
1894 | sd_read_block_limits(sdkp); | ||
1895 | sd_read_block_characteristics(sdkp); | ||
1896 | } | ||
1897 | |||
1882 | sd_read_write_protect_flag(sdkp, buffer); | 1898 | sd_read_write_protect_flag(sdkp, buffer); |
1883 | sd_read_cache_type(sdkp, buffer); | 1899 | sd_read_cache_type(sdkp, buffer); |
1884 | sd_read_app_tag_own(sdkp, buffer); | 1900 | sd_read_app_tag_own(sdkp, buffer); |