diff options
author | Giridhar Malavali <giridhar.malavali@qlogic.com> | 2010-01-12 16:02:47 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-01-18 17:51:05 -0500 |
commit | 9a069e196767d7b87184fd8d8211d22bb5b9c0b8 (patch) | |
tree | 44bc0f206793a2e9bcf280ea168e468bd62c15bb /drivers/scsi/qla2xxx | |
parent | 90a86fc05ffefe48581c88106d0b9cc37f6e060c (diff) |
[SCSI] qla2xxx: Add BSG support for FC ELS/CT passthrough and vendor commands.
[jejb: fixed printk casting issues]
Signed-off-by: Sarang Radke <sarang.radke@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 746 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 155 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 33 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 5 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 14 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 120 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 105 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 151 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 1 |
9 files changed, 1326 insertions, 4 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 3a9f5b288aee..5a19aea17022 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -11,7 +11,9 @@ | |||
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | 12 | ||
13 | static int qla24xx_vport_disable(struct fc_vport *, bool); | 13 | static int qla24xx_vport_disable(struct fc_vport *, bool); |
14 | 14 | static int qla84xx_reset(scsi_qla_host_t *, struct msg_echo_lb *, struct fc_bsg_job *); | |
15 | int qla84xx_reset_chip(scsi_qla_host_t *, uint16_t, uint16_t *); | ||
16 | static int qla84xx_mgmt_cmd(scsi_qla_host_t *, struct msg_echo_lb *, struct fc_bsg_job *); | ||
15 | /* SYSFS attributes --------------------------------------------------------- */ | 17 | /* SYSFS attributes --------------------------------------------------------- */ |
16 | 18 | ||
17 | static ssize_t | 19 | static ssize_t |
@@ -1168,6 +1170,28 @@ qla2x00_total_isp_aborts_show(struct device *dev, | |||
1168 | } | 1170 | } |
1169 | 1171 | ||
1170 | static ssize_t | 1172 | static ssize_t |
1173 | qla24xx_84xx_fw_version_show(struct device *dev, | ||
1174 | struct device_attribute *attr, char *buf) | ||
1175 | { | ||
1176 | int rval = QLA_SUCCESS; | ||
1177 | uint16_t status[2] = {0, 0}; | ||
1178 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1179 | struct qla_hw_data *ha = vha->hw; | ||
1180 | |||
1181 | if (IS_QLA84XX(ha) && ha->cs84xx) { | ||
1182 | if (ha->cs84xx->op_fw_version == 0) { | ||
1183 | rval = qla84xx_verify_chip(vha, status); | ||
1184 | } | ||
1185 | |||
1186 | if ((rval == QLA_SUCCESS) && (status[0] == 0)) | ||
1187 | return snprintf(buf, PAGE_SIZE, "%u\n", | ||
1188 | (uint32_t)ha->cs84xx->op_fw_version); | ||
1189 | } | ||
1190 | |||
1191 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1192 | } | ||
1193 | |||
1194 | static ssize_t | ||
1171 | qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, | 1195 | qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, |
1172 | char *buf) | 1196 | char *buf) |
1173 | { | 1197 | { |
@@ -1281,6 +1305,8 @@ static DEVICE_ATTR(optrom_fcode_version, S_IRUGO, | |||
1281 | qla2x00_optrom_fcode_version_show, NULL); | 1305 | qla2x00_optrom_fcode_version_show, NULL); |
1282 | static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, | 1306 | static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, |
1283 | NULL); | 1307 | NULL); |
1308 | static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show, | ||
1309 | NULL); | ||
1284 | static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, | 1310 | static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, |
1285 | NULL); | 1311 | NULL); |
1286 | static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); | 1312 | static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); |
@@ -1310,6 +1336,7 @@ struct device_attribute *qla2x00_host_attrs[] = { | |||
1310 | &dev_attr_optrom_efi_version, | 1336 | &dev_attr_optrom_efi_version, |
1311 | &dev_attr_optrom_fcode_version, | 1337 | &dev_attr_optrom_fcode_version, |
1312 | &dev_attr_optrom_fw_version, | 1338 | &dev_attr_optrom_fw_version, |
1339 | &dev_attr_84xx_fw_version, | ||
1313 | &dev_attr_total_isp_aborts, | 1340 | &dev_attr_total_isp_aborts, |
1314 | &dev_attr_mpi_version, | 1341 | &dev_attr_mpi_version, |
1315 | &dev_attr_phy_version, | 1342 | &dev_attr_phy_version, |
@@ -1795,6 +1822,597 @@ qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable) | |||
1795 | return 0; | 1822 | return 0; |
1796 | } | 1823 | } |
1797 | 1824 | ||
1825 | /* BSG support for ELS/CT pass through */ | ||
1826 | inline srb_t * | ||
1827 | qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size) | ||
1828 | { | ||
1829 | srb_t *sp; | ||
1830 | struct qla_hw_data *ha = vha->hw; | ||
1831 | struct srb_bsg_ctx *ctx; | ||
1832 | |||
1833 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | ||
1834 | if (!sp) | ||
1835 | goto done; | ||
1836 | ctx = kzalloc(size, GFP_KERNEL); | ||
1837 | if (!ctx) { | ||
1838 | mempool_free(sp, ha->srb_mempool); | ||
1839 | goto done; | ||
1840 | } | ||
1841 | |||
1842 | memset(sp, 0, sizeof(*sp)); | ||
1843 | sp->fcport = fcport; | ||
1844 | sp->ctx = ctx; | ||
1845 | done: | ||
1846 | return sp; | ||
1847 | } | ||
1848 | |||
1849 | static int | ||
1850 | qla2x00_process_els(struct fc_bsg_job *bsg_job) | ||
1851 | { | ||
1852 | struct fc_rport *rport; | ||
1853 | fc_port_t *fcport; | ||
1854 | struct Scsi_Host *host; | ||
1855 | scsi_qla_host_t *vha; | ||
1856 | struct qla_hw_data *ha; | ||
1857 | srb_t *sp; | ||
1858 | const char *type; | ||
1859 | int req_sg_cnt, rsp_sg_cnt; | ||
1860 | int rval = (DRIVER_ERROR << 16); | ||
1861 | uint16_t nextlid = 0; | ||
1862 | struct srb_bsg *els; | ||
1863 | |||
1864 | /* Multiple SG's are not supported for ELS requests */ | ||
1865 | if (bsg_job->request_payload.sg_cnt > 1 || | ||
1866 | bsg_job->reply_payload.sg_cnt > 1) { | ||
1867 | DEBUG2(printk(KERN_INFO | ||
1868 | "multiple SG's are not supported for ELS requests" | ||
1869 | " [request_sg_cnt: %x reply_sg_cnt: %x]\n", | ||
1870 | bsg_job->request_payload.sg_cnt, | ||
1871 | bsg_job->reply_payload.sg_cnt)); | ||
1872 | rval = -EPERM; | ||
1873 | goto done; | ||
1874 | } | ||
1875 | |||
1876 | /* ELS request for rport */ | ||
1877 | if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { | ||
1878 | rport = bsg_job->rport; | ||
1879 | fcport = *(fc_port_t **) rport->dd_data; | ||
1880 | host = rport_to_shost(rport); | ||
1881 | vha = shost_priv(host); | ||
1882 | ha = vha->hw; | ||
1883 | type = "FC_BSG_RPT_ELS"; | ||
1884 | |||
1885 | DEBUG2(printk(KERN_INFO | ||
1886 | "scsi(%ld): loop-id=%x portid=%02x%02x%02x.\n", | ||
1887 | fcport->vha->host_no, fcport->loop_id, | ||
1888 | fcport->d_id.b.domain, fcport->d_id.b.area, | ||
1889 | fcport->d_id.b.al_pa)); | ||
1890 | |||
1891 | /* make sure the rport is logged in, | ||
1892 | * if not perform fabric login | ||
1893 | */ | ||
1894 | if (qla2x00_fabric_login(vha, fcport, &nextlid)) { | ||
1895 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1896 | "failed to login port %06X for ELS passthru\n", | ||
1897 | fcport->d_id.b24)); | ||
1898 | rval = -EIO; | ||
1899 | goto done; | ||
1900 | } | ||
1901 | } else { | ||
1902 | host = bsg_job->shost; | ||
1903 | vha = shost_priv(host); | ||
1904 | ha = vha->hw; | ||
1905 | type = "FC_BSG_HST_ELS_NOLOGIN"; | ||
1906 | |||
1907 | DEBUG2(printk(KERN_INFO | ||
1908 | "scsi(%ld): loop-id=%x portid=%02x%02x%02x.\n", | ||
1909 | vha->host_no, vha->loop_id, | ||
1910 | vha->d_id.b.domain, vha->d_id.b.area, vha->d_id.b.al_pa)); | ||
1911 | |||
1912 | /* Allocate a dummy fcport structure, since functions | ||
1913 | * preparing the IOCB and mailbox command retrieves port | ||
1914 | * specific information from fcport structure. For Host based | ||
1915 | * ELS commands there will be no fcport structure allocated | ||
1916 | */ | ||
1917 | fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); | ||
1918 | if (!fcport) { | ||
1919 | rval = -ENOMEM; | ||
1920 | goto done; | ||
1921 | } | ||
1922 | |||
1923 | /* Initialize all required fields of fcport */ | ||
1924 | fcport->vha = vha; | ||
1925 | fcport->vp_idx = vha->vp_idx; | ||
1926 | fcport->d_id.b.al_pa = | ||
1927 | bsg_job->request->rqst_data.h_els.port_id[0]; | ||
1928 | fcport->d_id.b.area = | ||
1929 | bsg_job->request->rqst_data.h_els.port_id[1]; | ||
1930 | fcport->d_id.b.domain = | ||
1931 | bsg_job->request->rqst_data.h_els.port_id[2]; | ||
1932 | fcport->loop_id = | ||
1933 | (fcport->d_id.b.al_pa == 0xFD) ? | ||
1934 | NPH_FABRIC_CONTROLLER : NPH_F_PORT; | ||
1935 | } | ||
1936 | |||
1937 | DEBUG2(printk(KERN_INFO | ||
1938 | "scsi(%ld): vendor-id = %llu\n", | ||
1939 | vha->host_no, host->hostt->vendor_id)); | ||
1940 | |||
1941 | req_sg_cnt = | ||
1942 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
1943 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1944 | if (!req_sg_cnt) { | ||
1945 | rval = -ENOMEM; | ||
1946 | goto done_free_fcport; | ||
1947 | } | ||
1948 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
1949 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1950 | if (!rsp_sg_cnt) { | ||
1951 | rval = -ENOMEM; | ||
1952 | goto done_free_fcport; | ||
1953 | } | ||
1954 | |||
1955 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
1956 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
1957 | { | ||
1958 | DEBUG2(printk(KERN_INFO | ||
1959 | "dma mapping resulted in different sg counts \ | ||
1960 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
1961 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
1962 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
1963 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt)); | ||
1964 | rval = -EAGAIN; | ||
1965 | goto done_unmap_sg; | ||
1966 | } | ||
1967 | |||
1968 | /* Alloc SRB structure */ | ||
1969 | sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg)); | ||
1970 | if (!sp) { | ||
1971 | rval = -ENOMEM; | ||
1972 | goto done_unmap_sg; | ||
1973 | } | ||
1974 | |||
1975 | els = sp->ctx; | ||
1976 | els->ctx.type = | ||
1977 | (bsg_job->request->msgcode == FC_BSG_RPT_ELS ? | ||
1978 | SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); | ||
1979 | els->bsg_job = bsg_job; | ||
1980 | |||
1981 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1982 | "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x " | ||
1983 | "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type, | ||
1984 | bsg_job->request->rqst_data.h_els.command_code, | ||
1985 | fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, | ||
1986 | fcport->d_id.b.al_pa)); | ||
1987 | |||
1988 | rval = qla2x00_start_sp(sp); | ||
1989 | if (rval != QLA_SUCCESS) { | ||
1990 | kfree(sp->ctx); | ||
1991 | mempool_free(sp, ha->srb_mempool); | ||
1992 | rval = -EIO; | ||
1993 | goto done_unmap_sg; | ||
1994 | } | ||
1995 | return rval; | ||
1996 | |||
1997 | done_unmap_sg: | ||
1998 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
1999 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2000 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2001 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2002 | goto done_free_fcport; | ||
2003 | |||
2004 | done_free_fcport: | ||
2005 | if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN) | ||
2006 | kfree(fcport); | ||
2007 | done: | ||
2008 | return rval; | ||
2009 | } | ||
2010 | |||
2011 | static int | ||
2012 | qla2x00_process_ct(struct fc_bsg_job *bsg_job) | ||
2013 | { | ||
2014 | srb_t *sp; | ||
2015 | struct Scsi_Host *host = bsg_job->shost; | ||
2016 | scsi_qla_host_t *vha = shost_priv(host); | ||
2017 | struct qla_hw_data *ha = vha->hw; | ||
2018 | int rval = (DRIVER_ERROR << 16); | ||
2019 | int req_sg_cnt, rsp_sg_cnt; | ||
2020 | uint16_t loop_id; | ||
2021 | struct fc_port *fcport; | ||
2022 | char *type = "FC_BSG_HST_CT"; | ||
2023 | struct srb_bsg *ct; | ||
2024 | |||
2025 | /* pass through is supported only for ISP 4Gb or higher */ | ||
2026 | if (!IS_FWI2_CAPABLE(ha)) { | ||
2027 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2028 | "scsi(%ld):Firmware is not capable to support FC " | ||
2029 | "CT pass thru\n", vha->host_no)); | ||
2030 | rval = -EPERM; | ||
2031 | goto done; | ||
2032 | } | ||
2033 | |||
2034 | req_sg_cnt = | ||
2035 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2036 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2037 | if (!req_sg_cnt) { | ||
2038 | rval = -ENOMEM; | ||
2039 | goto done; | ||
2040 | } | ||
2041 | |||
2042 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2043 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2044 | if (!rsp_sg_cnt) { | ||
2045 | rval = -ENOMEM; | ||
2046 | goto done; | ||
2047 | } | ||
2048 | |||
2049 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
2050 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
2051 | { | ||
2052 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2053 | "dma mapping resulted in different sg counts \ | ||
2054 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
2055 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
2056 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
2057 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt)); | ||
2058 | rval = -EAGAIN; | ||
2059 | goto done_unmap_sg; | ||
2060 | } | ||
2061 | |||
2062 | loop_id = | ||
2063 | (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000) | ||
2064 | >> 24; | ||
2065 | switch (loop_id) { | ||
2066 | case 0xFC: | ||
2067 | loop_id = cpu_to_le16(NPH_SNS); | ||
2068 | break; | ||
2069 | case 0xFA: | ||
2070 | loop_id = vha->mgmt_svr_loop_id; | ||
2071 | break; | ||
2072 | default: | ||
2073 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2074 | "Unknown loop id: %x\n", loop_id)); | ||
2075 | rval = -EINVAL; | ||
2076 | goto done_unmap_sg; | ||
2077 | } | ||
2078 | |||
2079 | /* Allocate a dummy fcport structure, since functions preparing the | ||
2080 | * IOCB and mailbox command retrieves port specific information | ||
2081 | * from fcport structure. For Host based ELS commands there will be | ||
2082 | * no fcport structure allocated | ||
2083 | */ | ||
2084 | fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); | ||
2085 | if (!fcport) | ||
2086 | { | ||
2087 | rval = -ENOMEM; | ||
2088 | goto done_unmap_sg; | ||
2089 | } | ||
2090 | |||
2091 | /* Initialize all required fields of fcport */ | ||
2092 | fcport->vha = vha; | ||
2093 | fcport->vp_idx = vha->vp_idx; | ||
2094 | fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0]; | ||
2095 | fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1]; | ||
2096 | fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2]; | ||
2097 | fcport->loop_id = loop_id; | ||
2098 | |||
2099 | /* Alloc SRB structure */ | ||
2100 | sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg)); | ||
2101 | if (!sp) { | ||
2102 | rval = -ENOMEM; | ||
2103 | goto done_free_fcport; | ||
2104 | } | ||
2105 | |||
2106 | ct = sp->ctx; | ||
2107 | ct->ctx.type = SRB_CT_CMD; | ||
2108 | ct->bsg_job = bsg_job; | ||
2109 | |||
2110 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2111 | "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x " | ||
2112 | "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type, | ||
2113 | (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16), | ||
2114 | fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, | ||
2115 | fcport->d_id.b.al_pa)); | ||
2116 | |||
2117 | rval = qla2x00_start_sp(sp); | ||
2118 | if (rval != QLA_SUCCESS) { | ||
2119 | kfree(sp->ctx); | ||
2120 | mempool_free(sp, ha->srb_mempool); | ||
2121 | rval = -EIO; | ||
2122 | goto done_free_fcport; | ||
2123 | } | ||
2124 | return rval; | ||
2125 | |||
2126 | done_free_fcport: | ||
2127 | kfree(fcport); | ||
2128 | done_unmap_sg: | ||
2129 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2130 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2131 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2132 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2133 | done: | ||
2134 | return rval; | ||
2135 | } | ||
2136 | |||
2137 | static int | ||
2138 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | ||
2139 | { | ||
2140 | struct Scsi_Host *host = bsg_job->shost; | ||
2141 | scsi_qla_host_t *vha = shost_priv(host); | ||
2142 | struct qla_hw_data *ha = vha->hw; | ||
2143 | int rval; | ||
2144 | uint8_t command_sent; | ||
2145 | uint32_t vendor_cmd; | ||
2146 | char *type; | ||
2147 | struct msg_echo_lb elreq; | ||
2148 | uint16_t response[MAILBOX_REGISTER_COUNT]; | ||
2149 | uint8_t* fw_sts_ptr; | ||
2150 | uint8_t *req_data; | ||
2151 | dma_addr_t req_data_dma; | ||
2152 | uint32_t req_data_len; | ||
2153 | uint8_t *rsp_data; | ||
2154 | dma_addr_t rsp_data_dma; | ||
2155 | uint32_t rsp_data_len; | ||
2156 | |||
2157 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
2158 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
2159 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | ||
2160 | rval = -EBUSY; | ||
2161 | goto done; | ||
2162 | } | ||
2163 | |||
2164 | elreq.req_sg_cnt = | ||
2165 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2166 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2167 | if (!elreq.req_sg_cnt) { | ||
2168 | rval = -ENOMEM; | ||
2169 | goto done; | ||
2170 | } | ||
2171 | elreq.rsp_sg_cnt = | ||
2172 | dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2173 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2174 | if (!elreq.rsp_sg_cnt) { | ||
2175 | rval = -ENOMEM; | ||
2176 | goto done; | ||
2177 | } | ||
2178 | |||
2179 | if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
2180 | (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
2181 | { | ||
2182 | DEBUG2(printk(KERN_INFO | ||
2183 | "dma mapping resulted in different sg counts \ | ||
2184 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
2185 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
2186 | bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt, | ||
2187 | bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt)); | ||
2188 | rval = -EAGAIN; | ||
2189 | goto done_unmap_sg; | ||
2190 | } | ||
2191 | req_data_len = rsp_data_len = bsg_job->request_payload.payload_len; | ||
2192 | req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len, | ||
2193 | &req_data_dma, GFP_KERNEL); | ||
2194 | |||
2195 | rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len, | ||
2196 | &rsp_data_dma, GFP_KERNEL); | ||
2197 | |||
2198 | /* Copy the request buffer in req_data now */ | ||
2199 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | ||
2200 | bsg_job->request_payload.sg_cnt, req_data, | ||
2201 | req_data_len); | ||
2202 | |||
2203 | elreq.send_dma = req_data_dma; | ||
2204 | elreq.rcv_dma = rsp_data_dma; | ||
2205 | elreq.transfer_size = req_data_len; | ||
2206 | |||
2207 | /* Vendor cmd : loopback or ECHO diagnostic | ||
2208 | * Options: | ||
2209 | * Loopback : Either internal or external loopback | ||
2210 | * ECHO: ECHO ELS or Vendor specific FC4 link data | ||
2211 | */ | ||
2212 | vendor_cmd = bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]; | ||
2213 | elreq.options = | ||
2214 | *(((uint32_t *)bsg_job->request->rqst_data.h_vendor.vendor_cmd) | ||
2215 | + 1); | ||
2216 | |||
2217 | switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { | ||
2218 | case QL_VND_LOOPBACK: | ||
2219 | if (ha->current_topology != ISP_CFG_F) { | ||
2220 | type = "FC_BSG_HST_VENDOR_LOOPBACK"; | ||
2221 | |||
2222 | if ((IS_QLA81XX(ha)) && | ||
2223 | ((elreq.options == 0) || (elreq.options == 2))) { | ||
2224 | DEBUG2(qla_printk(KERN_INFO, ha, "scsi(%ld)" | ||
2225 | "loopback option:0x%x not supported\n", vha->host_no, elreq.options)); | ||
2226 | rval = -EINVAL; | ||
2227 | goto done_unmap_sg; | ||
2228 | } | ||
2229 | |||
2230 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2231 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", | ||
2232 | vha->host_no, type, vendor_cmd, elreq.options)); | ||
2233 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2234 | "scsi(%ld) tx_addr: 0x%llx rx_addr: 0x%llx tx_sg_cnt: %x rx_sg_cnt: %x\n", | ||
2235 | vha->host_no, (unsigned long long)elreq.send_dma, (unsigned long long)elreq.rcv_dma, elreq.req_sg_cnt, elreq.rsp_sg_cnt)); | ||
2236 | command_sent = INT_DEF_LB_LOOPBACK_CMD; | ||
2237 | rval = qla2x00_loopback_test(vha, &elreq, response); | ||
2238 | if (IS_QLA81XX(ha)) { | ||
2239 | if (response[0] == MBS_COMMAND_ERROR && response[1] == MBS_LB_RESET) { | ||
2240 | DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing " | ||
2241 | "ISP\n", __func__, vha->host_no)); | ||
2242 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
2243 | qla2xxx_wake_dpc(vha); | ||
2244 | } | ||
2245 | } | ||
2246 | } else { | ||
2247 | type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; | ||
2248 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2249 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", | ||
2250 | vha->host_no, type, vendor_cmd, elreq.options)); | ||
2251 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2252 | "scsi(%ld) tx_addr: 0x%llx rx_addr: 0x%llx tx_sg_cnt: %x rx_sg_cnt: %x\n", | ||
2253 | vha->host_no, (unsigned long long)elreq.send_dma, (unsigned long long)elreq.rcv_dma, elreq.req_sg_cnt, elreq.rsp_sg_cnt)); | ||
2254 | command_sent = INT_DEF_LB_ECHO_CMD; | ||
2255 | rval = qla2x00_echo_test(vha, &elreq, response); | ||
2256 | } | ||
2257 | break; | ||
2258 | case QLA84_RESET: | ||
2259 | if (!IS_QLA84XX(vha->hw)) { | ||
2260 | rval = -EINVAL; | ||
2261 | DEBUG16(printk( | ||
2262 | "%s(%ld): 8xxx exiting.\n", | ||
2263 | __func__, vha->host_no)); | ||
2264 | return rval; | ||
2265 | } | ||
2266 | rval = qla84xx_reset(vha, &elreq, bsg_job); | ||
2267 | break; | ||
2268 | case QLA84_MGMT_CMD: | ||
2269 | if (!IS_QLA84XX(vha->hw)) { | ||
2270 | rval = -EINVAL; | ||
2271 | DEBUG16(printk( | ||
2272 | "%s(%ld): 8xxx exiting.\n", | ||
2273 | __func__, vha->host_no)); | ||
2274 | return rval; | ||
2275 | } | ||
2276 | rval = qla84xx_mgmt_cmd(vha, &elreq, bsg_job); | ||
2277 | break; | ||
2278 | default: | ||
2279 | rval = -ENOSYS; | ||
2280 | } | ||
2281 | |||
2282 | if (rval != QLA_SUCCESS) { | ||
2283 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2284 | "scsi(%ld) Vendor request %s failed\n", vha->host_no, type)); | ||
2285 | rval = 0; | ||
2286 | bsg_job->reply->result = (DID_ERROR << 16); | ||
2287 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
2288 | memcpy( fw_sts_ptr, response, sizeof(response)); | ||
2289 | fw_sts_ptr += sizeof(response); | ||
2290 | *fw_sts_ptr = command_sent; | ||
2291 | } else { | ||
2292 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2293 | "scsi(%ld) Vendor request %s completed\n", vha->host_no, type)); | ||
2294 | rval = bsg_job->reply->result = 0; | ||
2295 | bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(response) + sizeof(uint8_t); | ||
2296 | bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; | ||
2297 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
2298 | memcpy(fw_sts_ptr, response, sizeof(response)); | ||
2299 | fw_sts_ptr += sizeof(response); | ||
2300 | *fw_sts_ptr = command_sent; | ||
2301 | sg_copy_from_buffer(bsg_job->reply_payload.sg_list, | ||
2302 | bsg_job->reply_payload.sg_cnt, rsp_data, | ||
2303 | rsp_data_len); | ||
2304 | } | ||
2305 | bsg_job->job_done(bsg_job); | ||
2306 | |||
2307 | done_unmap_sg: | ||
2308 | |||
2309 | if(req_data) | ||
2310 | dma_free_coherent(&ha->pdev->dev, req_data_len, | ||
2311 | req_data, req_data_dma); | ||
2312 | dma_unmap_sg(&ha->pdev->dev, | ||
2313 | bsg_job->request_payload.sg_list, | ||
2314 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2315 | dma_unmap_sg(&ha->pdev->dev, | ||
2316 | bsg_job->reply_payload.sg_list, | ||
2317 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2318 | |||
2319 | done: | ||
2320 | return rval; | ||
2321 | } | ||
2322 | |||
2323 | static int | ||
2324 | qla24xx_bsg_request(struct fc_bsg_job *bsg_job) | ||
2325 | { | ||
2326 | int ret = -EINVAL; | ||
2327 | |||
2328 | switch (bsg_job->request->msgcode) { | ||
2329 | case FC_BSG_RPT_ELS: | ||
2330 | case FC_BSG_HST_ELS_NOLOGIN: | ||
2331 | ret = qla2x00_process_els(bsg_job); | ||
2332 | break; | ||
2333 | case FC_BSG_HST_CT: | ||
2334 | ret = qla2x00_process_ct(bsg_job); | ||
2335 | break; | ||
2336 | case FC_BSG_HST_VENDOR: | ||
2337 | ret = qla2x00_process_vendor_specific(bsg_job); | ||
2338 | break; | ||
2339 | case FC_BSG_HST_ADD_RPORT: | ||
2340 | case FC_BSG_HST_DEL_RPORT: | ||
2341 | case FC_BSG_RPT_CT: | ||
2342 | default: | ||
2343 | DEBUG2(printk("qla2xxx: unsupported BSG request\n")); | ||
2344 | break; | ||
2345 | } | ||
2346 | return ret; | ||
2347 | } | ||
2348 | |||
2349 | static int | ||
2350 | qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) | ||
2351 | { | ||
2352 | scsi_qla_host_t *vha = shost_priv(bsg_job->shost); | ||
2353 | struct qla_hw_data *ha = vha->hw; | ||
2354 | srb_t *sp; | ||
2355 | int i; | ||
2356 | unsigned long flags; | ||
2357 | uint16_t que_id; | ||
2358 | struct req_que *req; | ||
2359 | struct rsp_que *rsp; | ||
2360 | int found = 0; | ||
2361 | struct srb_bsg *sp_bsg; | ||
2362 | |||
2363 | /* find the bsg job from the active list of commands */ | ||
2364 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2365 | req = ha->req_q_map[0]; | ||
2366 | que_id = req->id; | ||
2367 | if (req->rsp) | ||
2368 | rsp = req->rsp; | ||
2369 | else | ||
2370 | rsp = ha->rsp_q_map[que_id]; | ||
2371 | |||
2372 | for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++ ) { | ||
2373 | sp = req->outstanding_cmds[i]; | ||
2374 | |||
2375 | if (sp == NULL) | ||
2376 | continue; | ||
2377 | |||
2378 | sp_bsg = (struct srb_bsg*)sp->ctx; | ||
2379 | |||
2380 | if (((sp_bsg->ctx.type == SRB_CT_CMD) || | ||
2381 | (sp_bsg->ctx.type == SRB_ELS_CMD_RPT) | ||
2382 | || ( sp_bsg->ctx.type == SRB_ELS_CMD_HST)) && | ||
2383 | (sp_bsg->bsg_job == bsg_job)) { | ||
2384 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2385 | "scsi(%ld) req_q: %p rsp_q: %p que_id: %x sp: %p\n", | ||
2386 | vha->host_no, req, rsp, que_id, sp)); | ||
2387 | found = 1; | ||
2388 | break; | ||
2389 | } | ||
2390 | } | ||
2391 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2392 | if (!found) { | ||
2393 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2394 | "scsi(%ld) SRB not found to abort\n", vha->host_no)); | ||
2395 | bsg_job->req->errors = bsg_job->reply->result = -ENXIO; | ||
2396 | return 0; | ||
2397 | } | ||
2398 | |||
2399 | if (ha->isp_ops->abort_command(sp)) { | ||
2400 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2401 | "scsi(%ld): mbx abort_command failed\n", vha->host_no)); | ||
2402 | bsg_job->req->errors = bsg_job->reply->result = -EIO; | ||
2403 | } else { | ||
2404 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2405 | "scsi(%ld): mbx abort_command success\n", vha->host_no)); | ||
2406 | bsg_job->req->errors = bsg_job->reply->result = 0; | ||
2407 | } | ||
2408 | |||
2409 | if (bsg_job->request->msgcode == FC_BSG_HST_CT) | ||
2410 | kfree(sp->fcport); | ||
2411 | kfree(sp->ctx); | ||
2412 | mempool_free(sp, ha->srb_mempool); | ||
2413 | return 0; | ||
2414 | } | ||
2415 | |||
1798 | struct fc_function_template qla2xxx_transport_functions = { | 2416 | struct fc_function_template qla2xxx_transport_functions = { |
1799 | 2417 | ||
1800 | .show_host_node_name = 1, | 2418 | .show_host_node_name = 1, |
@@ -1838,6 +2456,8 @@ struct fc_function_template qla2xxx_transport_functions = { | |||
1838 | .vport_create = qla24xx_vport_create, | 2456 | .vport_create = qla24xx_vport_create, |
1839 | .vport_disable = qla24xx_vport_disable, | 2457 | .vport_disable = qla24xx_vport_disable, |
1840 | .vport_delete = qla24xx_vport_delete, | 2458 | .vport_delete = qla24xx_vport_delete, |
2459 | .bsg_request = qla24xx_bsg_request, | ||
2460 | .bsg_timeout = qla24xx_bsg_timeout, | ||
1841 | }; | 2461 | }; |
1842 | 2462 | ||
1843 | struct fc_function_template qla2xxx_transport_vport_functions = { | 2463 | struct fc_function_template qla2xxx_transport_vport_functions = { |
@@ -1878,6 +2498,8 @@ struct fc_function_template qla2xxx_transport_vport_functions = { | |||
1878 | .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, | 2498 | .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, |
1879 | .terminate_rport_io = qla2x00_terminate_rport_io, | 2499 | .terminate_rport_io = qla2x00_terminate_rport_io, |
1880 | .get_fc_host_stats = qla2x00_get_fc_host_stats, | 2500 | .get_fc_host_stats = qla2x00_get_fc_host_stats, |
2501 | .bsg_request = qla24xx_bsg_request, | ||
2502 | .bsg_timeout = qla24xx_bsg_timeout, | ||
1881 | }; | 2503 | }; |
1882 | 2504 | ||
1883 | void | 2505 | void |
@@ -1906,3 +2528,125 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) | |||
1906 | speed = FC_PORTSPEED_1GBIT; | 2528 | speed = FC_PORTSPEED_1GBIT; |
1907 | fc_host_supported_speeds(vha->host) = speed; | 2529 | fc_host_supported_speeds(vha->host) = speed; |
1908 | } | 2530 | } |
2531 | static int | ||
2532 | qla84xx_reset(scsi_qla_host_t *ha, struct msg_echo_lb *mreq, struct fc_bsg_job *bsg_job) | ||
2533 | { | ||
2534 | int ret = 0; | ||
2535 | int cmd; | ||
2536 | uint16_t cmd_status; | ||
2537 | |||
2538 | DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2539 | |||
2540 | cmd = (*((bsg_job->request->rqst_data.h_vendor.vendor_cmd) + 2)) | ||
2541 | == A84_RESET_FLAG_ENABLE_DIAG_FW ? | ||
2542 | A84_ISSUE_RESET_DIAG_FW : A84_ISSUE_RESET_OP_FW; | ||
2543 | ret = qla84xx_reset_chip(ha, cmd == A84_ISSUE_RESET_DIAG_FW, | ||
2544 | &cmd_status); | ||
2545 | return ret; | ||
2546 | } | ||
2547 | |||
2548 | static int | ||
2549 | qla84xx_mgmt_cmd(scsi_qla_host_t *ha, struct msg_echo_lb *mreq, struct fc_bsg_job *bsg_job) | ||
2550 | { | ||
2551 | struct access_chip_84xx *mn; | ||
2552 | dma_addr_t mn_dma, mgmt_dma; | ||
2553 | void *mgmt_b = NULL; | ||
2554 | int ret = 0; | ||
2555 | int rsp_hdr_len, len = 0; | ||
2556 | struct qla84_msg_mgmt *ql84_mgmt; | ||
2557 | |||
2558 | ql84_mgmt = (struct qla84_msg_mgmt *) vmalloc(sizeof(struct qla84_msg_mgmt)); | ||
2559 | ql84_mgmt->cmd = | ||
2560 | *((uint16_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 2)); | ||
2561 | ql84_mgmt->mgmtp.u.mem.start_addr = | ||
2562 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 3)); | ||
2563 | ql84_mgmt->len = | ||
2564 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 4)); | ||
2565 | ql84_mgmt->mgmtp.u.config.id = | ||
2566 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 5)); | ||
2567 | ql84_mgmt->mgmtp.u.config.param0 = | ||
2568 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 6)); | ||
2569 | ql84_mgmt->mgmtp.u.config.param1 = | ||
2570 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 7)); | ||
2571 | ql84_mgmt->mgmtp.u.info.type = | ||
2572 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 8)); | ||
2573 | ql84_mgmt->mgmtp.u.info.context = | ||
2574 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 9)); | ||
2575 | |||
2576 | rsp_hdr_len = bsg_job->request_payload.payload_len; | ||
2577 | |||
2578 | mn = dma_pool_alloc(ha->hw->s_dma_pool, GFP_KERNEL, &mn_dma); | ||
2579 | if (mn == NULL) { | ||
2580 | DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer " | ||
2581 | "failed%lu\n", __func__, ha->host_no)); | ||
2582 | return -ENOMEM; | ||
2583 | } | ||
2584 | |||
2585 | memset(mn, 0, sizeof (struct access_chip_84xx)); | ||
2586 | |||
2587 | mn->entry_type = ACCESS_CHIP_IOCB_TYPE; | ||
2588 | mn->entry_count = 1; | ||
2589 | |||
2590 | switch (ql84_mgmt->cmd) { | ||
2591 | case QLA84_MGMT_READ_MEM: | ||
2592 | mn->options = cpu_to_le16(ACO_DUMP_MEMORY); | ||
2593 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr); | ||
2594 | break; | ||
2595 | case QLA84_MGMT_WRITE_MEM: | ||
2596 | mn->options = cpu_to_le16(ACO_LOAD_MEMORY); | ||
2597 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr); | ||
2598 | break; | ||
2599 | case QLA84_MGMT_CHNG_CONFIG: | ||
2600 | mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM); | ||
2601 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.id); | ||
2602 | mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param0); | ||
2603 | mn->parameter3 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param1); | ||
2604 | break; | ||
2605 | case QLA84_MGMT_GET_INFO: | ||
2606 | mn->options = cpu_to_le16(ACO_REQUEST_INFO); | ||
2607 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.type); | ||
2608 | mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.context); | ||
2609 | break; | ||
2610 | default: | ||
2611 | ret = -EIO; | ||
2612 | goto exit_mgmt0; | ||
2613 | } | ||
2614 | |||
2615 | if ((len == ql84_mgmt->len) && | ||
2616 | ql84_mgmt->cmd != QLA84_MGMT_CHNG_CONFIG) { | ||
2617 | mgmt_b = dma_alloc_coherent(&ha->hw->pdev->dev, len, | ||
2618 | &mgmt_dma, GFP_KERNEL); | ||
2619 | if (mgmt_b == NULL) { | ||
2620 | DEBUG2(printk(KERN_ERR "%s: dma alloc mgmt_b " | ||
2621 | "failed%lu\n", __func__, ha->host_no)); | ||
2622 | ret = -ENOMEM; | ||
2623 | goto exit_mgmt0; | ||
2624 | } | ||
2625 | mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->len); | ||
2626 | mn->dseg_count = cpu_to_le16(1); | ||
2627 | mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma)); | ||
2628 | mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma)); | ||
2629 | mn->dseg_length = cpu_to_le32(len); | ||
2630 | |||
2631 | if (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) { | ||
2632 | memcpy(mgmt_b, ql84_mgmt->payload, len); | ||
2633 | } | ||
2634 | } | ||
2635 | |||
2636 | ret = qla2x00_issue_iocb(ha, mn, mn_dma, 0); | ||
2637 | if ((ret != QLA_SUCCESS) || (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) | ||
2638 | || (ql84_mgmt->cmd == QLA84_MGMT_CHNG_CONFIG)) { | ||
2639 | if (ret != QLA_SUCCESS) | ||
2640 | DEBUG2(printk(KERN_ERR "%s(%lu): failed\n", | ||
2641 | __func__, ha->host_no)); | ||
2642 | } else if ((ql84_mgmt->cmd == QLA84_MGMT_READ_MEM) || | ||
2643 | (ql84_mgmt->cmd == QLA84_MGMT_GET_INFO)) { | ||
2644 | } | ||
2645 | |||
2646 | if (mgmt_b) | ||
2647 | dma_free_coherent(&ha->hw->pdev->dev, len, mgmt_b, mgmt_dma); | ||
2648 | |||
2649 | exit_mgmt0: | ||
2650 | dma_pool_free(ha->hw->s_dma_pool, mn, mn_dma); | ||
2651 | return ret; | ||
2652 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 1263d9796e89..afa95614aaf8 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <scsi/scsi_device.h> | 31 | #include <scsi/scsi_device.h> |
32 | #include <scsi/scsi_cmnd.h> | 32 | #include <scsi/scsi_cmnd.h> |
33 | #include <scsi/scsi_transport_fc.h> | 33 | #include <scsi/scsi_transport_fc.h> |
34 | #include <scsi/scsi_bsg_fc.h> | ||
34 | 35 | ||
35 | #define QLA2XXX_DRIVER_NAME "qla2xxx" | 36 | #define QLA2XXX_DRIVER_NAME "qla2xxx" |
36 | 37 | ||
@@ -228,6 +229,27 @@ struct srb_logio { | |||
228 | uint16_t flags; | 229 | uint16_t flags; |
229 | }; | 230 | }; |
230 | 231 | ||
232 | struct srb_bsg_ctx { | ||
233 | #define SRB_ELS_CMD_RPT 3 | ||
234 | #define SRB_ELS_CMD_HST 4 | ||
235 | #define SRB_CT_CMD 5 | ||
236 | uint16_t type; | ||
237 | }; | ||
238 | |||
239 | struct srb_bsg { | ||
240 | struct srb_bsg_ctx ctx; | ||
241 | struct fc_bsg_job *bsg_job; | ||
242 | }; | ||
243 | |||
244 | struct msg_echo_lb { | ||
245 | dma_addr_t send_dma; | ||
246 | dma_addr_t rcv_dma; | ||
247 | uint16_t req_sg_cnt; | ||
248 | uint16_t rsp_sg_cnt; | ||
249 | uint16_t options; | ||
250 | uint32_t transfer_size; | ||
251 | }; | ||
252 | |||
231 | /* | 253 | /* |
232 | * ISP I/O Register Set structure definitions. | 254 | * ISP I/O Register Set structure definitions. |
233 | */ | 255 | */ |
@@ -522,6 +544,8 @@ typedef struct { | |||
522 | #define MBA_DISCARD_RND_FRAME 0x8048 /* discard RND frame due to error. */ | 544 | #define MBA_DISCARD_RND_FRAME 0x8048 /* discard RND frame due to error. */ |
523 | #define MBA_REJECTED_FCP_CMD 0x8049 /* rejected FCP_CMD. */ | 545 | #define MBA_REJECTED_FCP_CMD 0x8049 /* rejected FCP_CMD. */ |
524 | 546 | ||
547 | /* ISP mailbox loopback echo diagnostic error code */ | ||
548 | #define MBS_LB_RESET 0x17 | ||
525 | /* | 549 | /* |
526 | * Firmware options 1, 2, 3. | 550 | * Firmware options 1, 2, 3. |
527 | */ | 551 | */ |
@@ -2230,6 +2254,13 @@ struct req_que { | |||
2230 | int max_q_depth; | 2254 | int max_q_depth; |
2231 | }; | 2255 | }; |
2232 | 2256 | ||
2257 | /* Place holder for FW buffer parameters */ | ||
2258 | struct qlfc_fw { | ||
2259 | void *fw_buf; | ||
2260 | dma_addr_t fw_dma; | ||
2261 | uint32_t len; | ||
2262 | }; | ||
2263 | |||
2233 | /* | 2264 | /* |
2234 | * Qlogic host adapter specific data structure. | 2265 | * Qlogic host adapter specific data structure. |
2235 | */ | 2266 | */ |
@@ -2594,6 +2625,7 @@ struct qla_hw_data { | |||
2594 | struct qla_statistics qla_stats; | 2625 | struct qla_statistics qla_stats; |
2595 | struct isp_operations *isp_ops; | 2626 | struct isp_operations *isp_ops; |
2596 | struct workqueue_struct *wq; | 2627 | struct workqueue_struct *wq; |
2628 | struct qlfc_fw fw_buf; | ||
2597 | }; | 2629 | }; |
2598 | 2630 | ||
2599 | /* | 2631 | /* |
@@ -2766,4 +2798,127 @@ typedef struct scsi_qla_host { | |||
2766 | 2798 | ||
2767 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) | 2799 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) |
2768 | 2800 | ||
2801 | /* | ||
2802 | * BSG Vendor specific commands | ||
2803 | */ | ||
2804 | |||
2805 | #define QL_VND_LOOPBACK 0x01 | ||
2806 | #define QLA84_RESET 0x02 | ||
2807 | #define QLA84_UPDATE_FW 0x03 | ||
2808 | #define QLA84_MGMT_CMD 0x04 | ||
2809 | |||
2810 | /* BSG definations for interpreting CommandSent field */ | ||
2811 | #define INT_DEF_LB_LOOPBACK_CMD 0 | ||
2812 | #define INT_DEF_LB_ECHO_CMD 1 | ||
2813 | |||
2814 | /* BSG Vendor specific definations */ | ||
2815 | typedef struct _A84_RESET { | ||
2816 | uint16_t Flags; | ||
2817 | uint16_t Reserved; | ||
2818 | #define A84_RESET_FLAG_ENABLE_DIAG_FW 1 | ||
2819 | } __attribute__((packed)) A84_RESET, *PA84_RESET; | ||
2820 | |||
2821 | #define A84_ISSUE_WRITE_TYPE_CMD 0 | ||
2822 | #define A84_ISSUE_READ_TYPE_CMD 1 | ||
2823 | #define A84_CLEANUP_CMD 2 | ||
2824 | #define A84_ISSUE_RESET_OP_FW 3 | ||
2825 | #define A84_ISSUE_RESET_DIAG_FW 4 | ||
2826 | #define A84_ISSUE_UPDATE_OPFW_CMD 5 | ||
2827 | #define A84_ISSUE_UPDATE_DIAGFW_CMD 6 | ||
2828 | |||
2829 | struct qla84_mgmt_param { | ||
2830 | union { | ||
2831 | struct { | ||
2832 | uint32_t start_addr; | ||
2833 | } mem; /* for QLA84_MGMT_READ/WRITE_MEM */ | ||
2834 | struct { | ||
2835 | uint32_t id; | ||
2836 | #define QLA84_MGMT_CONFIG_ID_UIF 1 | ||
2837 | #define QLA84_MGMT_CONFIG_ID_FCOE_COS 2 | ||
2838 | #define QLA84_MGMT_CONFIG_ID_PAUSE 3 | ||
2839 | #define QLA84_MGMT_CONFIG_ID_TIMEOUTS 4 | ||
2840 | |||
2841 | uint32_t param0; | ||
2842 | uint32_t param1; | ||
2843 | } config; /* for QLA84_MGMT_CHNG_CONFIG */ | ||
2844 | |||
2845 | struct { | ||
2846 | uint32_t type; | ||
2847 | #define QLA84_MGMT_INFO_CONFIG_LOG_DATA 1 /* Get Config Log Data */ | ||
2848 | #define QLA84_MGMT_INFO_LOG_DATA 2 /* Get Log Data */ | ||
2849 | #define QLA84_MGMT_INFO_PORT_STAT 3 /* Get Port Statistics */ | ||
2850 | #define QLA84_MGMT_INFO_LIF_STAT 4 /* Get LIF Statistics */ | ||
2851 | #define QLA84_MGMT_INFO_ASIC_STAT 5 /* Get ASIC Statistics */ | ||
2852 | #define QLA84_MGMT_INFO_CONFIG_PARAMS 6 /* Get Config Parameters */ | ||
2853 | #define QLA84_MGMT_INFO_PANIC_LOG 7 /* Get Panic Log */ | ||
2854 | |||
2855 | uint32_t context; | ||
2856 | /* | ||
2857 | * context definitions for QLA84_MGMT_INFO_CONFIG_LOG_DATA | ||
2858 | */ | ||
2859 | #define IC_LOG_DATA_LOG_ID_DEBUG_LOG 0 | ||
2860 | #define IC_LOG_DATA_LOG_ID_LEARN_LOG 1 | ||
2861 | #define IC_LOG_DATA_LOG_ID_FC_ACL_INGRESS_LOG 2 | ||
2862 | #define IC_LOG_DATA_LOG_ID_FC_ACL_EGRESS_LOG 3 | ||
2863 | #define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_INGRESS_LOG 4 | ||
2864 | #define IC_LOG_DATA_LOG_ID_ETHERNET_ACL_EGRESS_LOG 5 | ||
2865 | #define IC_LOG_DATA_LOG_ID_MESSAGE_TRANSMIT_LOG 6 | ||
2866 | #define IC_LOG_DATA_LOG_ID_MESSAGE_RECEIVE_LOG 7 | ||
2867 | #define IC_LOG_DATA_LOG_ID_LINK_EVENT_LOG 8 | ||
2868 | #define IC_LOG_DATA_LOG_ID_DCX_LOG 9 | ||
2869 | |||
2870 | /* | ||
2871 | * context definitions for QLA84_MGMT_INFO_PORT_STAT | ||
2872 | */ | ||
2873 | #define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT0 0 | ||
2874 | #define IC_PORT_STATISTICS_PORT_NUMBER_ETHERNET_PORT1 1 | ||
2875 | #define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT0 2 | ||
2876 | #define IC_PORT_STATISTICS_PORT_NUMBER_NSL_PORT1 3 | ||
2877 | #define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT0 4 | ||
2878 | #define IC_PORT_STATISTICS_PORT_NUMBER_FC_PORT1 5 | ||
2879 | |||
2880 | |||
2881 | /* | ||
2882 | * context definitions for QLA84_MGMT_INFO_LIF_STAT | ||
2883 | */ | ||
2884 | #define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT0 0 | ||
2885 | #define IC_LIF_STATISTICS_LIF_NUMBER_ETHERNET_PORT1 1 | ||
2886 | #define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT0 2 | ||
2887 | #define IC_LIF_STATISTICS_LIF_NUMBER_FC_PORT1 3 | ||
2888 | #define IC_LIF_STATISTICS_LIF_NUMBER_CPU 6 | ||
2889 | |||
2890 | } info; /* for QLA84_MGMT_GET_INFO */ | ||
2891 | } u; | ||
2892 | }; | ||
2893 | |||
2894 | struct qla84_msg_mgmt { | ||
2895 | uint16_t cmd; | ||
2896 | #define QLA84_MGMT_READ_MEM 0x00 | ||
2897 | #define QLA84_MGMT_WRITE_MEM 0x01 | ||
2898 | #define QLA84_MGMT_CHNG_CONFIG 0x02 | ||
2899 | #define QLA84_MGMT_GET_INFO 0x03 | ||
2900 | uint16_t rsrvd; | ||
2901 | struct qla84_mgmt_param mgmtp;/* parameters for cmd */ | ||
2902 | uint32_t len; /* bytes in payload following this struct */ | ||
2903 | uint8_t payload[0]; /* payload for cmd */ | ||
2904 | }; | ||
2905 | |||
2906 | struct msg_update_fw { | ||
2907 | /* | ||
2908 | * diag_fw = 0 operational fw | ||
2909 | * otherwise diagnostic fw | ||
2910 | * offset, len, fw_len are present to overcome the current limitation | ||
2911 | * of 128Kb xfer size. The fw is sent in smaller chunks. Each chunk | ||
2912 | * specifies the byte "offset" where it fits in the fw buffer. The | ||
2913 | * number of bytes in each chunk is specified in "len". "fw_len" | ||
2914 | * is the total size of fw. The first chunk should start at offset = 0. | ||
2915 | * When offset+len == fw_len, the fw is written to the HBA. | ||
2916 | */ | ||
2917 | uint32_t diag_fw; | ||
2918 | uint32_t offset;/* start offset */ | ||
2919 | uint32_t len; /* num bytes in cur xfer */ | ||
2920 | uint32_t fw_len; /* size of fw in bytes */ | ||
2921 | uint8_t fw_bytes[0]; | ||
2922 | }; | ||
2923 | |||
2769 | #endif | 2924 | #endif |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 66a8da5d7d08..cebf4f1bb7d9 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -627,6 +627,39 @@ struct els_entry_24xx { | |||
627 | uint32_t rx_len; /* Data segment 1 length. */ | 627 | uint32_t rx_len; /* Data segment 1 length. */ |
628 | }; | 628 | }; |
629 | 629 | ||
630 | struct els_sts_entry_24xx { | ||
631 | uint8_t entry_type; /* Entry type. */ | ||
632 | uint8_t entry_count; /* Entry count. */ | ||
633 | uint8_t sys_define; /* System Defined. */ | ||
634 | uint8_t entry_status; /* Entry Status. */ | ||
635 | |||
636 | uint32_t handle; /* System handle. */ | ||
637 | |||
638 | uint16_t comp_status; | ||
639 | |||
640 | uint16_t nport_handle; /* N_PORT handle. */ | ||
641 | |||
642 | uint16_t reserved_1; | ||
643 | |||
644 | uint8_t vp_index; | ||
645 | uint8_t sof_type; | ||
646 | |||
647 | uint32_t rx_xchg_address; /* Receive exchange address. */ | ||
648 | uint16_t reserved_2; | ||
649 | |||
650 | uint8_t opcode; | ||
651 | uint8_t reserved_3; | ||
652 | |||
653 | uint8_t port_id[3]; | ||
654 | uint8_t reserved_4; | ||
655 | |||
656 | uint16_t reserved_5; | ||
657 | |||
658 | uint16_t control_flags; /* Control flags. */ | ||
659 | uint32_t total_byte_count; | ||
660 | uint32_t error_subcode_1; | ||
661 | uint32_t error_subcode_2; | ||
662 | }; | ||
630 | /* | 663 | /* |
631 | * ISP queue - Mailbox Command entry structure definition. | 664 | * ISP queue - Mailbox Command entry structure definition. |
632 | */ | 665 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f61fb8d01330..b42e704bdca9 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -60,6 +60,8 @@ extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *, | |||
60 | extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, | 60 | extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, |
61 | uint16_t *); | 61 | uint16_t *); |
62 | 62 | ||
63 | extern fc_port_t * | ||
64 | qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t ); | ||
63 | /* | 65 | /* |
64 | * Global Data in qla_os.c source file. | 66 | * Global Data in qla_os.c source file. |
65 | */ | 67 | */ |
@@ -154,6 +156,7 @@ int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, | |||
154 | int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, | 156 | int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, |
155 | uint16_t, uint16_t, uint8_t); | 157 | uint16_t, uint16_t, uint8_t); |
156 | extern int qla2x00_start_sp(srb_t *); | 158 | extern int qla2x00_start_sp(srb_t *); |
159 | extern void qla2x00_ctx_sp_free(srb_t *); | ||
157 | 160 | ||
158 | /* | 161 | /* |
159 | * Global Function Prototypes in qla_mbx.c source file. | 162 | * Global Function Prototypes in qla_mbx.c source file. |
@@ -426,6 +429,8 @@ extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); | |||
426 | extern void qla2x00_init_host_attr(scsi_qla_host_t *); | 429 | extern void qla2x00_init_host_attr(scsi_qla_host_t *); |
427 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); | 430 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); |
428 | extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); | 431 | extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); |
432 | extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); | ||
433 | extern int qla2x00_echo_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *); | ||
429 | 434 | ||
430 | /* | 435 | /* |
431 | * Global Function Prototypes in qla_dfs.c source file. | 436 | * Global Function Prototypes in qla_dfs.c source file. |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3f8e8495b743..1128c8d5771b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -62,7 +62,7 @@ qla2x00_ctx_sp_timeout(unsigned long __data) | |||
62 | ctx->free(sp); | 62 | ctx->free(sp); |
63 | } | 63 | } |
64 | 64 | ||
65 | static void | 65 | void |
66 | qla2x00_ctx_sp_free(srb_t *sp) | 66 | qla2x00_ctx_sp_free(srb_t *sp) |
67 | { | 67 | { |
68 | struct srb_ctx *ctx = sp->ctx; | 68 | struct srb_ctx *ctx = sp->ctx; |
@@ -338,6 +338,16 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
338 | rval = qla2x00_init_rings(vha); | 338 | rval = qla2x00_init_rings(vha); |
339 | ha->flags.chip_reset_done = 1; | 339 | ha->flags.chip_reset_done = 1; |
340 | 340 | ||
341 | if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) { | ||
342 | /* Issue verify 84xx FW IOCB to complete 84xx initialization */ | ||
343 | rval = qla84xx_init_chip(vha); | ||
344 | if (rval != QLA_SUCCESS) { | ||
345 | qla_printk(KERN_ERR, ha, | ||
346 | "Unable to initialize ISP84XX.\n"); | ||
347 | qla84xx_put_chip(vha); | ||
348 | } | ||
349 | } | ||
350 | |||
341 | return (rval); | 351 | return (rval); |
342 | } | 352 | } |
343 | 353 | ||
@@ -2216,7 +2226,7 @@ qla2x00_rport_del(void *data) | |||
2216 | * | 2226 | * |
2217 | * Returns a pointer to the allocated fcport, or NULL, if none available. | 2227 | * Returns a pointer to the allocated fcport, or NULL, if none available. |
2218 | */ | 2228 | */ |
2219 | static fc_port_t * | 2229 | fc_port_t * |
2220 | qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) | 2230 | qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) |
2221 | { | 2231 | { |
2222 | fc_port_t *fcport; | 2232 | fc_port_t *fcport; |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index c5ccac0bef76..8299a9891bfe 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -1025,6 +1025,119 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) | |||
1025 | /* Implicit: mbx->mbx10 = 0. */ | 1025 | /* Implicit: mbx->mbx10 = 0. */ |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | static void | ||
1029 | qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) | ||
1030 | { | ||
1031 | struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job; | ||
1032 | |||
1033 | els_iocb->entry_type = ELS_IOCB_TYPE; | ||
1034 | els_iocb->entry_count = 1; | ||
1035 | els_iocb->sys_define = 0; | ||
1036 | els_iocb->entry_status = 0; | ||
1037 | els_iocb->handle = sp->handle; | ||
1038 | els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1039 | els_iocb->tx_dsd_count = __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); | ||
1040 | els_iocb->vp_index = sp->fcport->vp_idx; | ||
1041 | els_iocb->sof_type = EST_SOFI3; | ||
1042 | els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); | ||
1043 | |||
1044 | els_iocb->opcode =(((struct srb_bsg*)sp->ctx)->ctx.type == SRB_ELS_CMD_RPT) ? | ||
1045 | bsg_job->request->rqst_data.r_els.els_code : bsg_job->request->rqst_data.h_els.command_code; | ||
1046 | els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
1047 | els_iocb->port_id[1] = sp->fcport->d_id.b.area; | ||
1048 | els_iocb->port_id[2] = sp->fcport->d_id.b.domain; | ||
1049 | els_iocb->control_flags = 0; | ||
1050 | els_iocb->rx_byte_count = | ||
1051 | cpu_to_le32(bsg_job->reply_payload.payload_len); | ||
1052 | els_iocb->tx_byte_count = | ||
1053 | cpu_to_le32(bsg_job->request_payload.payload_len); | ||
1054 | |||
1055 | els_iocb->tx_address[0] = cpu_to_le32(LSD(sg_dma_address | ||
1056 | (bsg_job->request_payload.sg_list))); | ||
1057 | els_iocb->tx_address[1] = cpu_to_le32(MSD(sg_dma_address | ||
1058 | (bsg_job->request_payload.sg_list))); | ||
1059 | els_iocb->tx_len = cpu_to_le32(sg_dma_len | ||
1060 | (bsg_job->request_payload.sg_list)); | ||
1061 | |||
1062 | els_iocb->rx_address[0] = cpu_to_le32(LSD(sg_dma_address | ||
1063 | (bsg_job->reply_payload.sg_list))); | ||
1064 | els_iocb->rx_address[1] = cpu_to_le32(MSD(sg_dma_address | ||
1065 | (bsg_job->reply_payload.sg_list))); | ||
1066 | els_iocb->rx_len = cpu_to_le32(sg_dma_len | ||
1067 | (bsg_job->reply_payload.sg_list)); | ||
1068 | } | ||
1069 | |||
1070 | static void | ||
1071 | qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) | ||
1072 | { | ||
1073 | uint16_t avail_dsds; | ||
1074 | uint32_t *cur_dsd; | ||
1075 | struct scatterlist *sg; | ||
1076 | int index; | ||
1077 | uint16_t tot_dsds; | ||
1078 | scsi_qla_host_t *vha = sp->fcport->vha; | ||
1079 | struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job; | ||
1080 | int loop_iterartion = 0; | ||
1081 | int cont_iocb_prsnt = 0; | ||
1082 | int entry_count = 1; | ||
1083 | |||
1084 | ct_iocb->entry_type = CT_IOCB_TYPE; | ||
1085 | ct_iocb->entry_status = 0; | ||
1086 | ct_iocb->sys_define = 0; | ||
1087 | ct_iocb->handle = sp->handle; | ||
1088 | |||
1089 | ct_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1090 | ct_iocb->vp_index = sp->fcport->vp_idx; | ||
1091 | ct_iocb->comp_status = __constant_cpu_to_le16(0); | ||
1092 | |||
1093 | ct_iocb->cmd_dsd_count = | ||
1094 | __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); | ||
1095 | ct_iocb->timeout = 0; | ||
1096 | ct_iocb->rsp_dsd_count = | ||
1097 | __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); | ||
1098 | ct_iocb->rsp_byte_count = | ||
1099 | cpu_to_le32(bsg_job->reply_payload.payload_len); | ||
1100 | ct_iocb->cmd_byte_count = | ||
1101 | cpu_to_le32(bsg_job->request_payload.payload_len); | ||
1102 | ct_iocb->dseg_0_address[0] = cpu_to_le32(LSD(sg_dma_address | ||
1103 | (bsg_job->request_payload.sg_list))); | ||
1104 | ct_iocb->dseg_0_address[1] = cpu_to_le32(MSD(sg_dma_address | ||
1105 | (bsg_job->request_payload.sg_list))); | ||
1106 | ct_iocb->dseg_0_len = cpu_to_le32(sg_dma_len | ||
1107 | (bsg_job->request_payload.sg_list)); | ||
1108 | |||
1109 | avail_dsds = 1; | ||
1110 | cur_dsd = (uint32_t *)ct_iocb->dseg_1_address; | ||
1111 | index = 0; | ||
1112 | tot_dsds = bsg_job->reply_payload.sg_cnt; | ||
1113 | |||
1114 | for_each_sg(bsg_job->reply_payload.sg_list, sg, tot_dsds, index) { | ||
1115 | dma_addr_t sle_dma; | ||
1116 | cont_a64_entry_t *cont_pkt; | ||
1117 | |||
1118 | /* Allocate additional continuation packets? */ | ||
1119 | if (avail_dsds == 0) { | ||
1120 | /* | ||
1121 | * Five DSDs are available in the Cont. | ||
1122 | * Type 1 IOCB. | ||
1123 | */ | ||
1124 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha); | ||
1125 | cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; | ||
1126 | avail_dsds = 5; | ||
1127 | cont_iocb_prsnt = 1; | ||
1128 | entry_count++; | ||
1129 | } | ||
1130 | |||
1131 | sle_dma = sg_dma_address(sg); | ||
1132 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
1133 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
1134 | *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); | ||
1135 | loop_iterartion++; | ||
1136 | avail_dsds--; | ||
1137 | } | ||
1138 | ct_iocb->entry_count = entry_count; | ||
1139 | } | ||
1140 | |||
1028 | int | 1141 | int |
1029 | qla2x00_start_sp(srb_t *sp) | 1142 | qla2x00_start_sp(srb_t *sp) |
1030 | { | 1143 | { |
@@ -1052,6 +1165,13 @@ qla2x00_start_sp(srb_t *sp) | |||
1052 | qla24xx_logout_iocb(sp, pkt): | 1165 | qla24xx_logout_iocb(sp, pkt): |
1053 | qla2x00_logout_iocb(sp, pkt); | 1166 | qla2x00_logout_iocb(sp, pkt); |
1054 | break; | 1167 | break; |
1168 | case SRB_ELS_CMD_RPT: | ||
1169 | case SRB_ELS_CMD_HST: | ||
1170 | qla24xx_els_iocb(sp, pkt); | ||
1171 | break; | ||
1172 | case SRB_CT_CMD: | ||
1173 | qla24xx_ct_iocb(sp, pkt); | ||
1174 | break; | ||
1055 | default: | 1175 | default: |
1056 | break; | 1176 | break; |
1057 | } | 1177 | } |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 5613456dbbb1..09ba26bc230c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <scsi/scsi_tcq.h> | 10 | #include <scsi/scsi_tcq.h> |
11 | #include <scsi/scsi_bsg_fc.h> | ||
11 | 12 | ||
12 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); | 13 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); |
13 | static void qla2x00_process_completed_request(struct scsi_qla_host *, | 14 | static void qla2x00_process_completed_request(struct scsi_qla_host *, |
@@ -881,7 +882,9 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, | |||
881 | index); | 882 | index); |
882 | return NULL; | 883 | return NULL; |
883 | } | 884 | } |
885 | |||
884 | req->outstanding_cmds[index] = NULL; | 886 | req->outstanding_cmds[index] = NULL; |
887 | |||
885 | done: | 888 | done: |
886 | return sp; | 889 | return sp; |
887 | } | 890 | } |
@@ -982,6 +985,100 @@ done_post_logio_done_work: | |||
982 | } | 985 | } |
983 | 986 | ||
984 | static void | 987 | static void |
988 | qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, | ||
989 | struct sts_entry_24xx *pkt, int iocb_type) | ||
990 | { | ||
991 | const char func[] = "ELS_CT_IOCB"; | ||
992 | const char *type; | ||
993 | struct qla_hw_data *ha = vha->hw; | ||
994 | srb_t *sp; | ||
995 | struct srb_bsg *sp_bsg; | ||
996 | struct fc_bsg_job *bsg_job; | ||
997 | uint16_t comp_status; | ||
998 | uint32_t fw_status[3]; | ||
999 | uint8_t* fw_sts_ptr; | ||
1000 | |||
1001 | sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); | ||
1002 | if (!sp) | ||
1003 | return; | ||
1004 | sp_bsg = (struct srb_bsg*)sp->ctx; | ||
1005 | bsg_job = sp_bsg->bsg_job; | ||
1006 | |||
1007 | type = NULL; | ||
1008 | switch (sp_bsg->ctx.type) { | ||
1009 | case SRB_ELS_CMD_RPT: | ||
1010 | case SRB_ELS_CMD_HST: | ||
1011 | type = "els"; | ||
1012 | break; | ||
1013 | case SRB_CT_CMD: | ||
1014 | type = "ct pass-through"; | ||
1015 | break; | ||
1016 | default: | ||
1017 | qla_printk(KERN_WARNING, ha, | ||
1018 | "%s: Unrecognized SRB: (%p) type=%d.\n", func, sp, | ||
1019 | sp_bsg->ctx.type); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status); | ||
1024 | fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1); | ||
1025 | fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2); | ||
1026 | |||
1027 | /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT | ||
1028 | * fc payload to the caller | ||
1029 | */ | ||
1030 | bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; | ||
1031 | bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(fw_status); | ||
1032 | |||
1033 | if (comp_status != CS_COMPLETE) { | ||
1034 | if (comp_status == CS_DATA_UNDERRUN) { | ||
1035 | bsg_job->reply->result = DID_OK << 16; | ||
1036 | bsg_job->reply->reply_payload_rcv_len = | ||
1037 | le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count); | ||
1038 | |||
1039 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1040 | "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x " | ||
1041 | "error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n", | ||
1042 | vha->host_no, sp->handle, type, comp_status, fw_status[1], fw_status[2], | ||
1043 | le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->total_byte_count))); | ||
1044 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
1045 | memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); | ||
1046 | } | ||
1047 | else { | ||
1048 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1049 | "scsi(%ld:0x%x): ELS-CT pass-through-%s error comp_status-status=0x%x " | ||
1050 | "error subcode 1=0x%x error subcode 2=0x%x.\n", | ||
1051 | vha->host_no, sp->handle, type, comp_status, | ||
1052 | le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1), | ||
1053 | le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2))); | ||
1054 | bsg_job->reply->result = DID_ERROR << 16; | ||
1055 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
1056 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
1057 | memcpy( fw_sts_ptr, fw_status, sizeof(fw_status)); | ||
1058 | } | ||
1059 | DEBUG2(qla2x00_dump_buffer((uint8_t *)pkt, sizeof(*pkt))); | ||
1060 | } | ||
1061 | else { | ||
1062 | bsg_job->reply->result = DID_OK << 16;; | ||
1063 | bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; | ||
1064 | bsg_job->reply_len = 0; | ||
1065 | } | ||
1066 | |||
1067 | dma_unmap_sg(&ha->pdev->dev, | ||
1068 | bsg_job->request_payload.sg_list, | ||
1069 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1070 | dma_unmap_sg(&ha->pdev->dev, | ||
1071 | bsg_job->reply_payload.sg_list, | ||
1072 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1073 | if ((sp_bsg->ctx.type == SRB_ELS_CMD_HST) || | ||
1074 | (sp_bsg->ctx.type == SRB_CT_CMD)) | ||
1075 | kfree(sp->fcport); | ||
1076 | kfree(sp->ctx); | ||
1077 | mempool_free(sp, ha->srb_mempool); | ||
1078 | bsg_job->job_done(bsg_job); | ||
1079 | } | ||
1080 | |||
1081 | static void | ||
985 | qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, | 1082 | qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, |
986 | struct logio_entry_24xx *logio) | 1083 | struct logio_entry_24xx *logio) |
987 | { | 1084 | { |
@@ -1749,6 +1846,13 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1749 | qla24xx_logio_entry(vha, rsp->req, | 1846 | qla24xx_logio_entry(vha, rsp->req, |
1750 | (struct logio_entry_24xx *)pkt); | 1847 | (struct logio_entry_24xx *)pkt); |
1751 | break; | 1848 | break; |
1849 | case CT_IOCB_TYPE: | ||
1850 | qla24xx_els_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); | ||
1851 | clear_bit(MBX_INTERRUPT, &vha->hw->mbx_cmd_flags); | ||
1852 | break; | ||
1853 | case ELS_IOCB_TYPE: | ||
1854 | qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); | ||
1855 | break; | ||
1752 | default: | 1856 | default: |
1753 | /* Type Not Supported. */ | 1857 | /* Type Not Supported. */ |
1754 | DEBUG4(printk(KERN_WARNING | 1858 | DEBUG4(printk(KERN_WARNING |
@@ -2046,7 +2150,6 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2046 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | 2150 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); |
2047 | complete(&ha->mbx_intr_comp); | 2151 | complete(&ha->mbx_intr_comp); |
2048 | } | 2152 | } |
2049 | |||
2050 | return IRQ_HANDLED; | 2153 | return IRQ_HANDLED; |
2051 | } | 2154 | } |
2052 | 2155 | ||
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 056e4d4505f3..6e53bdbb1da8 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -3636,6 +3636,157 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data) | |||
3636 | } | 3636 | } |
3637 | 3637 | ||
3638 | int | 3638 | int |
3639 | qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mresp) | ||
3640 | { | ||
3641 | int rval; | ||
3642 | mbx_cmd_t mc; | ||
3643 | mbx_cmd_t *mcp = &mc; | ||
3644 | uint32_t iter_cnt = 0x1; | ||
3645 | |||
3646 | DEBUG11(printk("scsi(%ld): entered.\n", vha->host_no)); | ||
3647 | |||
3648 | memset(mcp->mb, 0 , sizeof(mcp->mb)); | ||
3649 | mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; | ||
3650 | mcp->mb[1] = mreq->options | BIT_6; // BIT_6 specifies 64 bit addressing | ||
3651 | |||
3652 | /* transfer count */ | ||
3653 | mcp->mb[10] = LSW(mreq->transfer_size); | ||
3654 | mcp->mb[11] = MSW(mreq->transfer_size); | ||
3655 | |||
3656 | /* send data address */ | ||
3657 | mcp->mb[14] = LSW(mreq->send_dma); | ||
3658 | mcp->mb[15] = MSW(mreq->send_dma); | ||
3659 | mcp->mb[20] = LSW(MSD(mreq->send_dma)); | ||
3660 | mcp->mb[21] = MSW(MSD(mreq->send_dma)); | ||
3661 | |||
3662 | /* recieve data address */ | ||
3663 | mcp->mb[16] = LSW(mreq->rcv_dma); | ||
3664 | mcp->mb[17] = MSW(mreq->rcv_dma); | ||
3665 | mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); | ||
3666 | mcp->mb[7] = MSW(MSD(mreq->rcv_dma)); | ||
3667 | |||
3668 | /* Iteration count */ | ||
3669 | mcp->mb[18] = LSW(iter_cnt); | ||
3670 | mcp->mb[19] = MSW(iter_cnt); | ||
3671 | |||
3672 | mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15| | ||
3673 | MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; | ||
3674 | if (IS_QLA81XX(vha->hw)) | ||
3675 | mcp->out_mb |= MBX_2; | ||
3676 | mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0; | ||
3677 | |||
3678 | mcp->buf_size = mreq->transfer_size; | ||
3679 | mcp->tov = MBX_TOV_SECONDS; | ||
3680 | mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; | ||
3681 | |||
3682 | rval = qla2x00_mailbox_command(vha, mcp); | ||
3683 | |||
3684 | if (rval != QLA_SUCCESS) { | ||
3685 | DEBUG2(printk(KERN_WARNING | ||
3686 | "(%ld): failed=%x mb[0]=0x%x " | ||
3687 | "mb[1]=0x%x mb[2]=0x%x mb[3]=0x%x mb[18]=0x%x mb[19]=0x%x. \n", vha->host_no, rval, | ||
3688 | mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[18], mcp->mb[19])); | ||
3689 | } else { | ||
3690 | DEBUG2(printk(KERN_WARNING | ||
3691 | "scsi(%ld): done.\n", vha->host_no)); | ||
3692 | } | ||
3693 | |||
3694 | /* Copy mailbox information */ | ||
3695 | memcpy( mresp, mcp->mb, 64); | ||
3696 | mresp[3] = mcp->mb[18]; | ||
3697 | mresp[4] = mcp->mb[19]; | ||
3698 | return rval; | ||
3699 | } | ||
3700 | |||
3701 | int | ||
3702 | qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mresp) | ||
3703 | { | ||
3704 | int rval; | ||
3705 | mbx_cmd_t mc; | ||
3706 | mbx_cmd_t *mcp = &mc; | ||
3707 | struct qla_hw_data *ha = vha->hw; | ||
3708 | |||
3709 | DEBUG11(printk("scsi(%ld): entered.\n", vha->host_no)); | ||
3710 | |||
3711 | memset(mcp->mb, 0 , sizeof(mcp->mb)); | ||
3712 | mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; | ||
3713 | mcp->mb[1] = mreq->options | BIT_6; /* BIT_6 specifies 64bit address */ | ||
3714 | if (IS_QLA81XX(ha)) | ||
3715 | mcp->mb[1] |= BIT_15; | ||
3716 | mcp->mb[2] = IS_QLA81XX(ha) ? vha->fcoe_fcf_idx : 0; | ||
3717 | mcp->mb[16] = LSW(mreq->rcv_dma); | ||
3718 | mcp->mb[17] = MSW(mreq->rcv_dma); | ||
3719 | mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); | ||
3720 | mcp->mb[7] = MSW(MSD(mreq->rcv_dma)); | ||
3721 | |||
3722 | mcp->mb[10] = LSW(mreq->transfer_size); | ||
3723 | |||
3724 | mcp->mb[14] = LSW(mreq->send_dma); | ||
3725 | mcp->mb[15] = MSW(mreq->send_dma); | ||
3726 | mcp->mb[20] = LSW(MSD(mreq->send_dma)); | ||
3727 | mcp->mb[21] = MSW(MSD(mreq->send_dma)); | ||
3728 | |||
3729 | mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15| | ||
3730 | MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; | ||
3731 | if (IS_QLA81XX(ha)) | ||
3732 | mcp->out_mb |= MBX_2; | ||
3733 | |||
3734 | mcp->in_mb = MBX_0; | ||
3735 | if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha)) | ||
3736 | mcp->in_mb |= MBX_1; | ||
3737 | if (IS_QLA81XX(ha)) | ||
3738 | mcp->in_mb |= MBX_3; | ||
3739 | |||
3740 | mcp->tov = MBX_TOV_SECONDS; | ||
3741 | mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; | ||
3742 | mcp->buf_size = mreq->transfer_size; | ||
3743 | |||
3744 | rval = qla2x00_mailbox_command(vha, mcp); | ||
3745 | |||
3746 | if (rval != QLA_SUCCESS) { | ||
3747 | DEBUG2(printk(KERN_WARNING | ||
3748 | "(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n", | ||
3749 | vha->host_no, rval, mcp->mb[0], mcp->mb[1])); | ||
3750 | } else { | ||
3751 | DEBUG2(printk(KERN_WARNING | ||
3752 | "scsi(%ld): done.\n", vha->host_no)); | ||
3753 | } | ||
3754 | |||
3755 | /* Copy mailbox information */ | ||
3756 | memcpy( mresp, mcp->mb, 32); | ||
3757 | return rval; | ||
3758 | } | ||
3759 | int | ||
3760 | qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic, | ||
3761 | uint16_t *cmd_status) | ||
3762 | { | ||
3763 | int rval; | ||
3764 | mbx_cmd_t mc; | ||
3765 | mbx_cmd_t *mcp = &mc; | ||
3766 | |||
3767 | DEBUG16(printk("%s(%ld): enable_diag=%d entered.\n", __func__, | ||
3768 | ha->host_no, enable_diagnostic)); | ||
3769 | |||
3770 | mcp->mb[0] = MBC_ISP84XX_RESET; | ||
3771 | mcp->mb[1] = enable_diagnostic; | ||
3772 | mcp->out_mb = MBX_1|MBX_0; | ||
3773 | mcp->in_mb = MBX_1|MBX_0; | ||
3774 | mcp->tov = MBX_TOV_SECONDS; | ||
3775 | mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; | ||
3776 | rval = qla2x00_mailbox_command(ha, mcp); | ||
3777 | |||
3778 | /* Return mailbox statuses. */ | ||
3779 | *cmd_status = mcp->mb[0]; | ||
3780 | if (rval != QLA_SUCCESS) | ||
3781 | DEBUG16(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no, | ||
3782 | rval)); | ||
3783 | else | ||
3784 | DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
3785 | |||
3786 | return rval; | ||
3787 | } | ||
3788 | |||
3789 | int | ||
3639 | qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) | 3790 | qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) |
3640 | { | 3791 | { |
3641 | int rval; | 3792 | int rval; |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index fe34b7f9dee6..15ddfc435ea8 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1969,6 +1969,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1969 | host->max_channel = MAX_BUSES - 1; | 1969 | host->max_channel = MAX_BUSES - 1; |
1970 | host->max_lun = MAX_LUNS; | 1970 | host->max_lun = MAX_LUNS; |
1971 | host->transportt = qla2xxx_transport_template; | 1971 | host->transportt = qla2xxx_transport_template; |
1972 | sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC); | ||
1972 | 1973 | ||
1973 | /* Set up the irqs */ | 1974 | /* Set up the irqs */ |
1974 | ret = qla2x00_request_irqs(ha, rsp); | 1975 | ret = qla2x00_request_irqs(ha, rsp); |