diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_bsg.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 358 |
1 files changed, 272 insertions, 86 deletions
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index c13e54760cb1..56a86baece5b 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -916,9 +916,11 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
916 | } else { | 916 | } else { |
917 | switch (cmd) { | 917 | switch (cmd) { |
918 | case ELX_LOOPBACK_DATA: | 918 | case ELX_LOOPBACK_DATA: |
919 | diag_cmd_data_free(phba, | 919 | if (phba->sli_rev < |
920 | (struct lpfc_dmabufext *) | 920 | LPFC_SLI_REV4) |
921 | dmabuf); | 921 | diag_cmd_data_free(phba, |
922 | (struct lpfc_dmabufext | ||
923 | *)dmabuf); | ||
922 | break; | 924 | break; |
923 | case ELX_LOOPBACK_XRI_SETUP: | 925 | case ELX_LOOPBACK_XRI_SETUP: |
924 | if ((phba->sli_rev == | 926 | if ((phba->sli_rev == |
@@ -1000,7 +1002,8 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
1000 | error_ct_unsol_exit: | 1002 | error_ct_unsol_exit: |
1001 | if (!list_empty(&head)) | 1003 | if (!list_empty(&head)) |
1002 | list_del(&head); | 1004 | list_del(&head); |
1003 | if (evt_req_id == SLI_CT_ELX_LOOPBACK) | 1005 | if ((phba->sli_rev < LPFC_SLI_REV4) && |
1006 | (evt_req_id == SLI_CT_ELX_LOOPBACK)) | ||
1004 | return 0; | 1007 | return 0; |
1005 | return 1; | 1008 | return 1; |
1006 | } | 1009 | } |
@@ -1566,7 +1569,7 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | |||
1566 | struct diag_mode_set *loopback_mode; | 1569 | struct diag_mode_set *loopback_mode; |
1567 | uint32_t link_flags; | 1570 | uint32_t link_flags; |
1568 | uint32_t timeout; | 1571 | uint32_t timeout; |
1569 | LPFC_MBOXQ_t *pmboxq; | 1572 | LPFC_MBOXQ_t *pmboxq = NULL; |
1570 | int mbxstatus = MBX_SUCCESS; | 1573 | int mbxstatus = MBX_SUCCESS; |
1571 | int i = 0; | 1574 | int i = 0; |
1572 | int rc = 0; | 1575 | int rc = 0; |
@@ -1615,7 +1618,6 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | |||
1615 | rc = -ETIMEDOUT; | 1618 | rc = -ETIMEDOUT; |
1616 | goto loopback_mode_exit; | 1619 | goto loopback_mode_exit; |
1617 | } | 1620 | } |
1618 | |||
1619 | msleep(10); | 1621 | msleep(10); |
1620 | } | 1622 | } |
1621 | 1623 | ||
@@ -1635,7 +1637,9 @@ lpfc_sli3_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | |||
1635 | if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) | 1637 | if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) |
1636 | rc = -ENODEV; | 1638 | rc = -ENODEV; |
1637 | else { | 1639 | else { |
1640 | spin_lock_irq(&phba->hbalock); | ||
1638 | phba->link_flag |= LS_LOOPBACK_MODE; | 1641 | phba->link_flag |= LS_LOOPBACK_MODE; |
1642 | spin_unlock_irq(&phba->hbalock); | ||
1639 | /* wait for the link attention interrupt */ | 1643 | /* wait for the link attention interrupt */ |
1640 | msleep(100); | 1644 | msleep(100); |
1641 | 1645 | ||
@@ -1659,7 +1663,7 @@ loopback_mode_exit: | |||
1659 | /* | 1663 | /* |
1660 | * Let SLI layer release mboxq if mbox command completed after timeout. | 1664 | * Let SLI layer release mboxq if mbox command completed after timeout. |
1661 | */ | 1665 | */ |
1662 | if (mbxstatus != MBX_TIMEOUT) | 1666 | if (pmboxq && mbxstatus != MBX_TIMEOUT) |
1663 | mempool_free(pmboxq, phba->mbox_mem_pool); | 1667 | mempool_free(pmboxq, phba->mbox_mem_pool); |
1664 | 1668 | ||
1665 | job_error: | 1669 | job_error: |
@@ -1700,11 +1704,16 @@ lpfc_sli4_bsg_set_link_diag_state(struct lpfc_hba *phba, uint32_t diag) | |||
1700 | rc = -ENOMEM; | 1704 | rc = -ENOMEM; |
1701 | goto link_diag_state_set_out; | 1705 | goto link_diag_state_set_out; |
1702 | } | 1706 | } |
1707 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
1708 | "3128 Set link to diagnostic state:x%x (x%x/x%x)\n", | ||
1709 | diag, phba->sli4_hba.lnk_info.lnk_tp, | ||
1710 | phba->sli4_hba.lnk_info.lnk_no); | ||
1711 | |||
1703 | link_diag_state = &pmboxq->u.mqe.un.link_diag_state; | 1712 | link_diag_state = &pmboxq->u.mqe.un.link_diag_state; |
1704 | bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req, | 1713 | bf_set(lpfc_mbx_set_diag_state_link_num, &link_diag_state->u.req, |
1705 | phba->sli4_hba.link_state.number); | 1714 | phba->sli4_hba.lnk_info.lnk_no); |
1706 | bf_set(lpfc_mbx_set_diag_state_link_type, &link_diag_state->u.req, | 1715 | bf_set(lpfc_mbx_set_diag_state_link_type, &link_diag_state->u.req, |
1707 | phba->sli4_hba.link_state.type); | 1716 | phba->sli4_hba.lnk_info.lnk_tp); |
1708 | if (diag) | 1717 | if (diag) |
1709 | bf_set(lpfc_mbx_set_diag_state_diag, | 1718 | bf_set(lpfc_mbx_set_diag_state_diag, |
1710 | &link_diag_state->u.req, 1); | 1719 | &link_diag_state->u.req, 1); |
@@ -1727,6 +1736,79 @@ link_diag_state_set_out: | |||
1727 | } | 1736 | } |
1728 | 1737 | ||
1729 | /** | 1738 | /** |
1739 | * lpfc_sli4_bsg_set_internal_loopback - set sli4 internal loopback diagnostic | ||
1740 | * @phba: Pointer to HBA context object. | ||
1741 | * | ||
1742 | * This function is responsible for issuing a sli4 mailbox command for setting | ||
1743 | * up internal loopback diagnostic. | ||
1744 | */ | ||
1745 | static int | ||
1746 | lpfc_sli4_bsg_set_internal_loopback(struct lpfc_hba *phba) | ||
1747 | { | ||
1748 | LPFC_MBOXQ_t *pmboxq; | ||
1749 | uint32_t req_len, alloc_len; | ||
1750 | struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback; | ||
1751 | int mbxstatus = MBX_SUCCESS, rc = 0; | ||
1752 | |||
1753 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
1754 | if (!pmboxq) | ||
1755 | return -ENOMEM; | ||
1756 | req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) - | ||
1757 | sizeof(struct lpfc_sli4_cfg_mhdr)); | ||
1758 | alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
1759 | LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK, | ||
1760 | req_len, LPFC_SLI4_MBX_EMBED); | ||
1761 | if (alloc_len != req_len) { | ||
1762 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
1763 | return -ENOMEM; | ||
1764 | } | ||
1765 | link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback; | ||
1766 | bf_set(lpfc_mbx_set_diag_state_link_num, | ||
1767 | &link_diag_loopback->u.req, phba->sli4_hba.lnk_info.lnk_no); | ||
1768 | bf_set(lpfc_mbx_set_diag_state_link_type, | ||
1769 | &link_diag_loopback->u.req, phba->sli4_hba.lnk_info.lnk_tp); | ||
1770 | bf_set(lpfc_mbx_set_diag_lpbk_type, &link_diag_loopback->u.req, | ||
1771 | LPFC_DIAG_LOOPBACK_TYPE_SERDES); | ||
1772 | |||
1773 | mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO); | ||
1774 | if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) { | ||
1775 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
1776 | "3127 Failed setup loopback mode mailbox " | ||
1777 | "command, rc:x%x, status:x%x\n", mbxstatus, | ||
1778 | pmboxq->u.mb.mbxStatus); | ||
1779 | rc = -ENODEV; | ||
1780 | } | ||
1781 | if (pmboxq && (mbxstatus != MBX_TIMEOUT)) | ||
1782 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
1783 | return rc; | ||
1784 | } | ||
1785 | |||
1786 | /** | ||
1787 | * lpfc_sli4_diag_fcport_reg_setup - setup port registrations for diagnostic | ||
1788 | * @phba: Pointer to HBA context object. | ||
1789 | * | ||
1790 | * This function set up SLI4 FC port registrations for diagnostic run, which | ||
1791 | * includes all the rpis, vfi, and also vpi. | ||
1792 | */ | ||
1793 | static int | ||
1794 | lpfc_sli4_diag_fcport_reg_setup(struct lpfc_hba *phba) | ||
1795 | { | ||
1796 | int rc; | ||
1797 | |||
1798 | if (phba->pport->fc_flag & FC_VFI_REGISTERED) { | ||
1799 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
1800 | "3136 Port still had vfi registered: " | ||
1801 | "mydid:x%x, fcfi:%d, vfi:%d, vpi:%d\n", | ||
1802 | phba->pport->fc_myDID, phba->fcf.fcfi, | ||
1803 | phba->sli4_hba.vfi_ids[phba->pport->vfi], | ||
1804 | phba->vpi_ids[phba->pport->vpi]); | ||
1805 | return -EINVAL; | ||
1806 | } | ||
1807 | rc = lpfc_issue_reg_vfi(phba->pport); | ||
1808 | return rc; | ||
1809 | } | ||
1810 | |||
1811 | /** | ||
1730 | * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command | 1812 | * lpfc_sli4_bsg_diag_loopback_mode - process an sli4 bsg vendor command |
1731 | * @phba: Pointer to HBA context object. | 1813 | * @phba: Pointer to HBA context object. |
1732 | * @job: LPFC_BSG_VENDOR_DIAG_MODE | 1814 | * @job: LPFC_BSG_VENDOR_DIAG_MODE |
@@ -1738,10 +1820,8 @@ static int | |||
1738 | lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | 1820 | lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) |
1739 | { | 1821 | { |
1740 | struct diag_mode_set *loopback_mode; | 1822 | struct diag_mode_set *loopback_mode; |
1741 | uint32_t link_flags, timeout, req_len, alloc_len; | 1823 | uint32_t link_flags, timeout; |
1742 | struct lpfc_mbx_set_link_diag_loopback *link_diag_loopback; | 1824 | int i, rc = 0; |
1743 | LPFC_MBOXQ_t *pmboxq = NULL; | ||
1744 | int mbxstatus = MBX_SUCCESS, i, rc = 0; | ||
1745 | 1825 | ||
1746 | /* no data to return just the return code */ | 1826 | /* no data to return just the return code */ |
1747 | job->reply->reply_payload_rcv_len = 0; | 1827 | job->reply->reply_payload_rcv_len = 0; |
@@ -1762,65 +1842,100 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | |||
1762 | if (rc) | 1842 | if (rc) |
1763 | goto job_error; | 1843 | goto job_error; |
1764 | 1844 | ||
1845 | /* indicate we are in loobpack diagnostic mode */ | ||
1846 | spin_lock_irq(&phba->hbalock); | ||
1847 | phba->link_flag |= LS_LOOPBACK_MODE; | ||
1848 | spin_unlock_irq(&phba->hbalock); | ||
1849 | |||
1850 | /* reset port to start frome scratch */ | ||
1851 | rc = lpfc_selective_reset(phba); | ||
1852 | if (rc) | ||
1853 | goto job_error; | ||
1854 | |||
1765 | /* bring the link to diagnostic mode */ | 1855 | /* bring the link to diagnostic mode */ |
1856 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
1857 | "3129 Bring link to diagnostic state.\n"); | ||
1766 | loopback_mode = (struct diag_mode_set *) | 1858 | loopback_mode = (struct diag_mode_set *) |
1767 | job->request->rqst_data.h_vendor.vendor_cmd; | 1859 | job->request->rqst_data.h_vendor.vendor_cmd; |
1768 | link_flags = loopback_mode->type; | 1860 | link_flags = loopback_mode->type; |
1769 | timeout = loopback_mode->timeout * 100; | 1861 | timeout = loopback_mode->timeout * 100; |
1770 | 1862 | ||
1771 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1); | 1863 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 1); |
1772 | if (rc) | 1864 | if (rc) { |
1865 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
1866 | "3130 Failed to bring link to diagnostic " | ||
1867 | "state, rc:x%x\n", rc); | ||
1773 | goto loopback_mode_exit; | 1868 | goto loopback_mode_exit; |
1869 | } | ||
1774 | 1870 | ||
1775 | /* wait for link down before proceeding */ | 1871 | /* wait for link down before proceeding */ |
1776 | i = 0; | 1872 | i = 0; |
1777 | while (phba->link_state != LPFC_LINK_DOWN) { | 1873 | while (phba->link_state != LPFC_LINK_DOWN) { |
1778 | if (i++ > timeout) { | 1874 | if (i++ > timeout) { |
1779 | rc = -ETIMEDOUT; | 1875 | rc = -ETIMEDOUT; |
1876 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
1877 | "3131 Timeout waiting for link to " | ||
1878 | "diagnostic mode, timeout:%d ms\n", | ||
1879 | timeout * 10); | ||
1780 | goto loopback_mode_exit; | 1880 | goto loopback_mode_exit; |
1781 | } | 1881 | } |
1782 | msleep(10); | 1882 | msleep(10); |
1783 | } | 1883 | } |
1884 | |||
1784 | /* set up loopback mode */ | 1885 | /* set up loopback mode */ |
1785 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 1886 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, |
1786 | if (!pmboxq) { | 1887 | "3132 Set up loopback mode:x%x\n", link_flags); |
1787 | rc = -ENOMEM; | 1888 | |
1788 | goto loopback_mode_exit; | 1889 | if (link_flags == INTERNAL_LOOP_BACK) |
1789 | } | 1890 | rc = lpfc_sli4_bsg_set_internal_loopback(phba); |
1790 | req_len = (sizeof(struct lpfc_mbx_set_link_diag_loopback) - | 1891 | else if (link_flags == EXTERNAL_LOOP_BACK) |
1791 | sizeof(struct lpfc_sli4_cfg_mhdr)); | 1892 | rc = lpfc_hba_init_link_fc_topology(phba, |
1792 | alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | 1893 | FLAGS_TOPOLOGY_MODE_PT_PT, |
1793 | LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_LOOPBACK, | 1894 | MBX_NOWAIT); |
1794 | req_len, LPFC_SLI4_MBX_EMBED); | 1895 | else { |
1795 | if (alloc_len != req_len) { | 1896 | rc = -EINVAL; |
1796 | rc = -ENOMEM; | 1897 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, |
1898 | "3141 Loopback mode:x%x not supported\n", | ||
1899 | link_flags); | ||
1797 | goto loopback_mode_exit; | 1900 | goto loopback_mode_exit; |
1798 | } | 1901 | } |
1799 | link_diag_loopback = &pmboxq->u.mqe.un.link_diag_loopback; | ||
1800 | bf_set(lpfc_mbx_set_diag_state_link_num, | ||
1801 | &link_diag_loopback->u.req, phba->sli4_hba.link_state.number); | ||
1802 | bf_set(lpfc_mbx_set_diag_state_link_type, | ||
1803 | &link_diag_loopback->u.req, phba->sli4_hba.link_state.type); | ||
1804 | if (link_flags == INTERNAL_LOOP_BACK) | ||
1805 | bf_set(lpfc_mbx_set_diag_lpbk_type, | ||
1806 | &link_diag_loopback->u.req, | ||
1807 | LPFC_DIAG_LOOPBACK_TYPE_INTERNAL); | ||
1808 | else | ||
1809 | bf_set(lpfc_mbx_set_diag_lpbk_type, | ||
1810 | &link_diag_loopback->u.req, | ||
1811 | LPFC_DIAG_LOOPBACK_TYPE_EXTERNAL); | ||
1812 | 1902 | ||
1813 | mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO); | 1903 | if (!rc) { |
1814 | if ((mbxstatus != MBX_SUCCESS) || (pmboxq->u.mb.mbxStatus)) | ||
1815 | rc = -ENODEV; | ||
1816 | else { | ||
1817 | phba->link_flag |= LS_LOOPBACK_MODE; | ||
1818 | /* wait for the link attention interrupt */ | 1904 | /* wait for the link attention interrupt */ |
1819 | msleep(100); | 1905 | msleep(100); |
1820 | i = 0; | 1906 | i = 0; |
1907 | while (phba->link_state < LPFC_LINK_UP) { | ||
1908 | if (i++ > timeout) { | ||
1909 | rc = -ETIMEDOUT; | ||
1910 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
1911 | "3137 Timeout waiting for link up " | ||
1912 | "in loopback mode, timeout:%d ms\n", | ||
1913 | timeout * 10); | ||
1914 | break; | ||
1915 | } | ||
1916 | msleep(10); | ||
1917 | } | ||
1918 | } | ||
1919 | |||
1920 | /* port resource registration setup for loopback diagnostic */ | ||
1921 | if (!rc) { | ||
1922 | /* set up a none zero myDID for loopback test */ | ||
1923 | phba->pport->fc_myDID = 1; | ||
1924 | rc = lpfc_sli4_diag_fcport_reg_setup(phba); | ||
1925 | } else | ||
1926 | goto loopback_mode_exit; | ||
1927 | |||
1928 | if (!rc) { | ||
1929 | /* wait for the port ready */ | ||
1930 | msleep(100); | ||
1931 | i = 0; | ||
1821 | while (phba->link_state != LPFC_HBA_READY) { | 1932 | while (phba->link_state != LPFC_HBA_READY) { |
1822 | if (i++ > timeout) { | 1933 | if (i++ > timeout) { |
1823 | rc = -ETIMEDOUT; | 1934 | rc = -ETIMEDOUT; |
1935 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
1936 | "3133 Timeout waiting for port " | ||
1937 | "loopback mode ready, timeout:%d ms\n", | ||
1938 | timeout * 10); | ||
1824 | break; | 1939 | break; |
1825 | } | 1940 | } |
1826 | msleep(10); | 1941 | msleep(10); |
@@ -1828,14 +1943,14 @@ lpfc_sli4_bsg_diag_loopback_mode(struct lpfc_hba *phba, struct fc_bsg_job *job) | |||
1828 | } | 1943 | } |
1829 | 1944 | ||
1830 | loopback_mode_exit: | 1945 | loopback_mode_exit: |
1946 | /* clear loopback diagnostic mode */ | ||
1947 | if (rc) { | ||
1948 | spin_lock_irq(&phba->hbalock); | ||
1949 | phba->link_flag &= ~LS_LOOPBACK_MODE; | ||
1950 | spin_unlock_irq(&phba->hbalock); | ||
1951 | } | ||
1831 | lpfc_bsg_diag_mode_exit(phba); | 1952 | lpfc_bsg_diag_mode_exit(phba); |
1832 | 1953 | ||
1833 | /* | ||
1834 | * Let SLI layer release mboxq if mbox command completed after timeout. | ||
1835 | */ | ||
1836 | if (pmboxq && (mbxstatus != MBX_TIMEOUT)) | ||
1837 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
1838 | |||
1839 | job_error: | 1954 | job_error: |
1840 | /* make error code available to userspace */ | 1955 | /* make error code available to userspace */ |
1841 | job->reply->result = rc; | 1956 | job->reply->result = rc; |
@@ -1879,7 +1994,6 @@ lpfc_bsg_diag_loopback_mode(struct fc_bsg_job *job) | |||
1879 | rc = -ENODEV; | 1994 | rc = -ENODEV; |
1880 | 1995 | ||
1881 | return rc; | 1996 | return rc; |
1882 | |||
1883 | } | 1997 | } |
1884 | 1998 | ||
1885 | /** | 1999 | /** |
@@ -1895,7 +2009,9 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) | |||
1895 | struct Scsi_Host *shost; | 2009 | struct Scsi_Host *shost; |
1896 | struct lpfc_vport *vport; | 2010 | struct lpfc_vport *vport; |
1897 | struct lpfc_hba *phba; | 2011 | struct lpfc_hba *phba; |
1898 | int rc; | 2012 | struct diag_mode_set *loopback_mode_end_cmd; |
2013 | uint32_t timeout; | ||
2014 | int rc, i; | ||
1899 | 2015 | ||
1900 | shost = job->shost; | 2016 | shost = job->shost; |
1901 | if (!shost) | 2017 | if (!shost) |
@@ -1913,11 +2029,47 @@ lpfc_sli4_bsg_diag_mode_end(struct fc_bsg_job *job) | |||
1913 | LPFC_SLI_INTF_IF_TYPE_2) | 2029 | LPFC_SLI_INTF_IF_TYPE_2) |
1914 | return -ENODEV; | 2030 | return -ENODEV; |
1915 | 2031 | ||
2032 | /* clear loopback diagnostic mode */ | ||
2033 | spin_lock_irq(&phba->hbalock); | ||
2034 | phba->link_flag &= ~LS_LOOPBACK_MODE; | ||
2035 | spin_unlock_irq(&phba->hbalock); | ||
2036 | loopback_mode_end_cmd = (struct diag_mode_set *) | ||
2037 | job->request->rqst_data.h_vendor.vendor_cmd; | ||
2038 | timeout = loopback_mode_end_cmd->timeout * 100; | ||
2039 | |||
1916 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); | 2040 | rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0); |
2041 | if (rc) { | ||
2042 | lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC, | ||
2043 | "3139 Failed to bring link to diagnostic " | ||
2044 | "state, rc:x%x\n", rc); | ||
2045 | goto loopback_mode_end_exit; | ||
2046 | } | ||
2047 | |||
2048 | /* wait for link down before proceeding */ | ||
2049 | i = 0; | ||
2050 | while (phba->link_state != LPFC_LINK_DOWN) { | ||
2051 | if (i++ > timeout) { | ||
2052 | rc = -ETIMEDOUT; | ||
2053 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | ||
2054 | "3140 Timeout waiting for link to " | ||
2055 | "diagnostic mode_end, timeout:%d ms\n", | ||
2056 | timeout * 10); | ||
2057 | /* there is nothing much we can do here */ | ||
2058 | break; | ||
2059 | } | ||
2060 | msleep(10); | ||
2061 | } | ||
1917 | 2062 | ||
1918 | if (!rc) | 2063 | /* reset port resource registrations */ |
1919 | rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); | 2064 | rc = lpfc_selective_reset(phba); |
2065 | phba->pport->fc_myDID = 0; | ||
1920 | 2066 | ||
2067 | loopback_mode_end_exit: | ||
2068 | /* make return code available to userspace */ | ||
2069 | job->reply->result = rc; | ||
2070 | /* complete the job back to userspace if no error */ | ||
2071 | if (rc == 0) | ||
2072 | job->job_done(job); | ||
1921 | return rc; | 2073 | return rc; |
1922 | } | 2074 | } |
1923 | 2075 | ||
@@ -2012,9 +2164,9 @@ lpfc_sli4_bsg_link_diag_test(struct fc_bsg_job *job) | |||
2012 | } | 2164 | } |
2013 | run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test; | 2165 | run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test; |
2014 | bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req, | 2166 | bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req, |
2015 | phba->sli4_hba.link_state.number); | 2167 | phba->sli4_hba.lnk_info.lnk_no); |
2016 | bf_set(lpfc_mbx_run_diag_test_link_type, &run_link_diag_test->u.req, | 2168 | bf_set(lpfc_mbx_run_diag_test_link_type, &run_link_diag_test->u.req, |
2017 | phba->sli4_hba.link_state.type); | 2169 | phba->sli4_hba.lnk_info.lnk_tp); |
2018 | bf_set(lpfc_mbx_run_diag_test_test_id, &run_link_diag_test->u.req, | 2170 | bf_set(lpfc_mbx_run_diag_test_test_id, &run_link_diag_test->u.req, |
2019 | link_diag_test_cmd->test_id); | 2171 | link_diag_test_cmd->test_id); |
2020 | bf_set(lpfc_mbx_run_diag_test_loops, &run_link_diag_test->u.req, | 2172 | bf_set(lpfc_mbx_run_diag_test_loops, &run_link_diag_test->u.req, |
@@ -2091,10 +2243,18 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi) | |||
2091 | if (!mbox) | 2243 | if (!mbox) |
2092 | return -ENOMEM; | 2244 | return -ENOMEM; |
2093 | 2245 | ||
2094 | if (phba->sli_rev == LPFC_SLI_REV4) | 2246 | if (phba->sli_rev < LPFC_SLI_REV4) |
2247 | status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID, | ||
2248 | (uint8_t *)&phba->pport->fc_sparam, | ||
2249 | mbox, *rpi); | ||
2250 | else { | ||
2095 | *rpi = lpfc_sli4_alloc_rpi(phba); | 2251 | *rpi = lpfc_sli4_alloc_rpi(phba); |
2096 | status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID, | 2252 | status = lpfc_reg_rpi(phba, phba->pport->vpi, |
2097 | (uint8_t *)&phba->pport->fc_sparam, mbox, *rpi); | 2253 | phba->pport->fc_myDID, |
2254 | (uint8_t *)&phba->pport->fc_sparam, | ||
2255 | mbox, *rpi); | ||
2256 | } | ||
2257 | |||
2098 | if (status) { | 2258 | if (status) { |
2099 | mempool_free(mbox, phba->mbox_mem_pool); | 2259 | mempool_free(mbox, phba->mbox_mem_pool); |
2100 | if (phba->sli_rev == LPFC_SLI_REV4) | 2260 | if (phba->sli_rev == LPFC_SLI_REV4) |
@@ -2117,7 +2277,8 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi) | |||
2117 | return -ENODEV; | 2277 | return -ENODEV; |
2118 | } | 2278 | } |
2119 | 2279 | ||
2120 | *rpi = mbox->u.mb.un.varWords[0]; | 2280 | if (phba->sli_rev < LPFC_SLI_REV4) |
2281 | *rpi = mbox->u.mb.un.varWords[0]; | ||
2121 | 2282 | ||
2122 | lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys); | 2283 | lpfc_mbuf_free(phba, dmabuff->virt, dmabuff->phys); |
2123 | kfree(dmabuff); | 2284 | kfree(dmabuff); |
@@ -2142,7 +2303,12 @@ static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi) | |||
2142 | if (mbox == NULL) | 2303 | if (mbox == NULL) |
2143 | return -ENOMEM; | 2304 | return -ENOMEM; |
2144 | 2305 | ||
2145 | lpfc_unreg_login(phba, 0, rpi, mbox); | 2306 | if (phba->sli_rev < LPFC_SLI_REV4) |
2307 | lpfc_unreg_login(phba, 0, rpi, mbox); | ||
2308 | else | ||
2309 | lpfc_unreg_login(phba, phba->pport->vpi, | ||
2310 | phba->sli4_hba.rpi_ids[rpi], mbox); | ||
2311 | |||
2146 | status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); | 2312 | status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); |
2147 | 2313 | ||
2148 | if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) { | 2314 | if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) { |
@@ -2630,15 +2796,15 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
2630 | uint32_t full_size; | 2796 | uint32_t full_size; |
2631 | size_t segment_len = 0, segment_offset = 0, current_offset = 0; | 2797 | size_t segment_len = 0, segment_offset = 0, current_offset = 0; |
2632 | uint16_t rpi = 0; | 2798 | uint16_t rpi = 0; |
2633 | struct lpfc_iocbq *cmdiocbq, *rspiocbq; | 2799 | struct lpfc_iocbq *cmdiocbq, *rspiocbq = NULL; |
2634 | IOCB_t *cmd, *rsp; | 2800 | IOCB_t *cmd, *rsp = NULL; |
2635 | struct lpfc_sli_ct_request *ctreq; | 2801 | struct lpfc_sli_ct_request *ctreq; |
2636 | struct lpfc_dmabuf *txbmp; | 2802 | struct lpfc_dmabuf *txbmp; |
2637 | struct ulp_bde64 *txbpl = NULL; | 2803 | struct ulp_bde64 *txbpl = NULL; |
2638 | struct lpfc_dmabufext *txbuffer = NULL; | 2804 | struct lpfc_dmabufext *txbuffer = NULL; |
2639 | struct list_head head; | 2805 | struct list_head head; |
2640 | struct lpfc_dmabuf *curr; | 2806 | struct lpfc_dmabuf *curr; |
2641 | uint16_t txxri, rxxri; | 2807 | uint16_t txxri = 0, rxxri; |
2642 | uint32_t num_bde; | 2808 | uint32_t num_bde; |
2643 | uint8_t *ptr = NULL, *rx_databuf = NULL; | 2809 | uint8_t *ptr = NULL, *rx_databuf = NULL; |
2644 | int rc = 0; | 2810 | int rc = 0; |
@@ -2665,7 +2831,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
2665 | rc = -EINVAL; | 2831 | rc = -EINVAL; |
2666 | goto loopback_test_exit; | 2832 | goto loopback_test_exit; |
2667 | } | 2833 | } |
2668 | |||
2669 | diag_mode = (struct diag_mode_test *) | 2834 | diag_mode = (struct diag_mode_test *) |
2670 | job->request->rqst_data.h_vendor.vendor_cmd; | 2835 | job->request->rqst_data.h_vendor.vendor_cmd; |
2671 | 2836 | ||
@@ -2720,18 +2885,19 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
2720 | if (rc) | 2885 | if (rc) |
2721 | goto loopback_test_exit; | 2886 | goto loopback_test_exit; |
2722 | 2887 | ||
2723 | rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri); | 2888 | if (phba->sli_rev < LPFC_SLI_REV4) { |
2724 | if (rc) { | 2889 | rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri); |
2725 | lpfcdiag_loop_self_unreg(phba, rpi); | 2890 | if (rc) { |
2726 | goto loopback_test_exit; | 2891 | lpfcdiag_loop_self_unreg(phba, rpi); |
2727 | } | 2892 | goto loopback_test_exit; |
2893 | } | ||
2728 | 2894 | ||
2729 | rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size); | 2895 | rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size); |
2730 | if (rc) { | 2896 | if (rc) { |
2731 | lpfcdiag_loop_self_unreg(phba, rpi); | 2897 | lpfcdiag_loop_self_unreg(phba, rpi); |
2732 | goto loopback_test_exit; | 2898 | goto loopback_test_exit; |
2899 | } | ||
2733 | } | 2900 | } |
2734 | |||
2735 | evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid, | 2901 | evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid, |
2736 | SLI_CT_ELX_LOOPBACK); | 2902 | SLI_CT_ELX_LOOPBACK); |
2737 | if (!evt) { | 2903 | if (!evt) { |
@@ -2746,7 +2912,8 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
2746 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 2912 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
2747 | 2913 | ||
2748 | cmdiocbq = lpfc_sli_get_iocbq(phba); | 2914 | cmdiocbq = lpfc_sli_get_iocbq(phba); |
2749 | rspiocbq = lpfc_sli_get_iocbq(phba); | 2915 | if (phba->sli_rev < LPFC_SLI_REV4) |
2916 | rspiocbq = lpfc_sli_get_iocbq(phba); | ||
2750 | txbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | 2917 | txbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
2751 | 2918 | ||
2752 | if (txbmp) { | 2919 | if (txbmp) { |
@@ -2759,14 +2926,18 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
2759 | } | 2926 | } |
2760 | } | 2927 | } |
2761 | 2928 | ||
2762 | if (!cmdiocbq || !rspiocbq || !txbmp || !txbpl || !txbuffer || | 2929 | if (!cmdiocbq || !txbmp || !txbpl || !txbuffer || !txbmp->virt) { |
2763 | !txbmp->virt) { | 2930 | rc = -ENOMEM; |
2931 | goto err_loopback_test_exit; | ||
2932 | } | ||
2933 | if ((phba->sli_rev < LPFC_SLI_REV4) && !rspiocbq) { | ||
2764 | rc = -ENOMEM; | 2934 | rc = -ENOMEM; |
2765 | goto err_loopback_test_exit; | 2935 | goto err_loopback_test_exit; |
2766 | } | 2936 | } |
2767 | 2937 | ||
2768 | cmd = &cmdiocbq->iocb; | 2938 | cmd = &cmdiocbq->iocb; |
2769 | rsp = &rspiocbq->iocb; | 2939 | if (phba->sli_rev < LPFC_SLI_REV4) |
2940 | rsp = &rspiocbq->iocb; | ||
2770 | 2941 | ||
2771 | INIT_LIST_HEAD(&head); | 2942 | INIT_LIST_HEAD(&head); |
2772 | list_add_tail(&head, &txbuffer->dma.list); | 2943 | list_add_tail(&head, &txbuffer->dma.list); |
@@ -2796,7 +2967,6 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
2796 | list_del(&head); | 2967 | list_del(&head); |
2797 | 2968 | ||
2798 | /* Build the XMIT_SEQUENCE iocb */ | 2969 | /* Build the XMIT_SEQUENCE iocb */ |
2799 | |||
2800 | num_bde = (uint32_t)txbuffer->flag; | 2970 | num_bde = (uint32_t)txbuffer->flag; |
2801 | 2971 | ||
2802 | cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(txbmp->phys); | 2972 | cmd->un.xseq64.bdl.addrHigh = putPaddrHigh(txbmp->phys); |
@@ -2813,16 +2983,27 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
2813 | cmd->ulpBdeCount = 1; | 2983 | cmd->ulpBdeCount = 1; |
2814 | cmd->ulpLe = 1; | 2984 | cmd->ulpLe = 1; |
2815 | cmd->ulpClass = CLASS3; | 2985 | cmd->ulpClass = CLASS3; |
2816 | cmd->ulpContext = txxri; | ||
2817 | 2986 | ||
2987 | if (phba->sli_rev < LPFC_SLI_REV4) { | ||
2988 | cmd->ulpContext = txxri; | ||
2989 | } else { | ||
2990 | cmd->un.xseq64.bdl.ulpIoTag32 = 0; | ||
2991 | cmd->un.ulpWord[3] = phba->sli4_hba.rpi_ids[rpi]; | ||
2992 | cmdiocbq->context3 = txbmp; | ||
2993 | cmdiocbq->sli4_xritag = NO_XRI; | ||
2994 | cmd->unsli3.rcvsli3.ox_id = 0xffff; | ||
2995 | } | ||
2818 | cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; | 2996 | cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; |
2819 | cmdiocbq->vport = phba->pport; | 2997 | cmdiocbq->vport = phba->pport; |
2820 | |||
2821 | iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, | 2998 | iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, |
2822 | rspiocbq, (phba->fc_ratov * 2) + | 2999 | rspiocbq, (phba->fc_ratov * 2) + |
2823 | LPFC_DRVR_TIMEOUT); | 3000 | LPFC_DRVR_TIMEOUT); |
2824 | 3001 | ||
2825 | if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) { | 3002 | if ((iocb_stat != IOCB_SUCCESS) || ((phba->sli_rev < LPFC_SLI_REV4) && |
3003 | (rsp->ulpStatus != IOCB_SUCCESS))) { | ||
3004 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, | ||
3005 | "3126 Failed loopback test issue iocb: " | ||
3006 | "iocb_stat:x%x\n", iocb_stat); | ||
2826 | rc = -EIO; | 3007 | rc = -EIO; |
2827 | goto err_loopback_test_exit; | 3008 | goto err_loopback_test_exit; |
2828 | } | 3009 | } |
@@ -2832,9 +3013,12 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
2832 | evt->wq, !list_empty(&evt->events_to_see), | 3013 | evt->wq, !list_empty(&evt->events_to_see), |
2833 | ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ); | 3014 | ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ); |
2834 | evt->waiting = 0; | 3015 | evt->waiting = 0; |
2835 | if (list_empty(&evt->events_to_see)) | 3016 | if (list_empty(&evt->events_to_see)) { |
2836 | rc = (time_left) ? -EINTR : -ETIMEDOUT; | 3017 | rc = (time_left) ? -EINTR : -ETIMEDOUT; |
2837 | else { | 3018 | lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, |
3019 | "3125 Not receiving unsolicited event, " | ||
3020 | "rc:x%x\n", rc); | ||
3021 | } else { | ||
2838 | spin_lock_irqsave(&phba->ct_ev_lock, flags); | 3022 | spin_lock_irqsave(&phba->ct_ev_lock, flags); |
2839 | list_move(evt->events_to_see.prev, &evt->events_to_get); | 3023 | list_move(evt->events_to_see.prev, &evt->events_to_get); |
2840 | evdat = list_entry(evt->events_to_get.prev, | 3024 | evdat = list_entry(evt->events_to_get.prev, |
@@ -2891,7 +3075,7 @@ loopback_test_exit: | |||
2891 | job->reply->result = rc; | 3075 | job->reply->result = rc; |
2892 | job->dd_data = NULL; | 3076 | job->dd_data = NULL; |
2893 | /* complete the job back to userspace if no error */ | 3077 | /* complete the job back to userspace if no error */ |
2894 | if (rc == 0) | 3078 | if (rc == IOCB_SUCCESS) |
2895 | job->job_done(job); | 3079 | job->job_done(job); |
2896 | return rc; | 3080 | return rc; |
2897 | } | 3081 | } |
@@ -3078,7 +3262,9 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, | |||
3078 | && (mb->un.varWords[1] == 1)) { | 3262 | && (mb->un.varWords[1] == 1)) { |
3079 | phba->wait_4_mlo_maint_flg = 1; | 3263 | phba->wait_4_mlo_maint_flg = 1; |
3080 | } else if (mb->un.varWords[0] == SETVAR_MLORST) { | 3264 | } else if (mb->un.varWords[0] == SETVAR_MLORST) { |
3265 | spin_lock_irq(&phba->hbalock); | ||
3081 | phba->link_flag &= ~LS_LOOPBACK_MODE; | 3266 | phba->link_flag &= ~LS_LOOPBACK_MODE; |
3267 | spin_unlock_irq(&phba->hbalock); | ||
3082 | phba->fc_topology = LPFC_TOPOLOGY_PT_PT; | 3268 | phba->fc_topology = LPFC_TOPOLOGY_PT_PT; |
3083 | } | 3269 | } |
3084 | break; | 3270 | break; |