aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiridhar Malavali <giridhar.malavali@qlogic.com>2010-01-12 16:02:47 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-01-18 17:51:05 -0500
commit9a069e196767d7b87184fd8d8211d22bb5b9c0b8 (patch)
tree44bc0f206793a2e9bcf280ea168e468bd62c15bb
parent90a86fc05ffefe48581c88106d0b9cc37f6e060c (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>
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c746
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h155
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h33
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c120
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c105
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c151
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c1
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
13static int qla24xx_vport_disable(struct fc_vport *, bool); 13static int qla24xx_vport_disable(struct fc_vport *, bool);
14 14static int qla84xx_reset(scsi_qla_host_t *, struct msg_echo_lb *, struct fc_bsg_job *);
15int qla84xx_reset_chip(scsi_qla_host_t *, uint16_t, uint16_t *);
16static int qla84xx_mgmt_cmd(scsi_qla_host_t *, struct msg_echo_lb *, struct fc_bsg_job *);
15/* SYSFS attributes --------------------------------------------------------- */ 17/* SYSFS attributes --------------------------------------------------------- */
16 18
17static ssize_t 19static ssize_t
@@ -1168,6 +1170,28 @@ qla2x00_total_isp_aborts_show(struct device *dev,
1168} 1170}
1169 1171
1170static ssize_t 1172static ssize_t
1173qla24xx_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
1194static ssize_t
1171qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, 1195qla2x00_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);
1282static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, 1306static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
1283 NULL); 1307 NULL);
1308static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show,
1309 NULL);
1284static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, 1310static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
1285 NULL); 1311 NULL);
1286static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); 1312static 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 */
1826inline srb_t *
1827qla2x00_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;
1845done:
1846 return sp;
1847}
1848
1849static int
1850qla2x00_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
1997done_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
2004done_free_fcport:
2005 if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN)
2006 kfree(fcport);
2007done:
2008 return rval;
2009}
2010
2011static int
2012qla2x00_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
2126done_free_fcport:
2127 kfree(fcport);
2128done_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);
2133done:
2134 return rval;
2135}
2136
2137static int
2138qla2x00_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
2307done_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
2319done:
2320 return rval;
2321}
2322
2323static int
2324qla24xx_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
2349static int
2350qla24xx_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
1798struct fc_function_template qla2xxx_transport_functions = { 2416struct 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
1843struct fc_function_template qla2xxx_transport_vport_functions = { 2463struct 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
1883void 2505void
@@ -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}
2531static int
2532qla84xx_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
2548static int
2549qla84xx_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
2649exit_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
232struct 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
239struct srb_bsg {
240 struct srb_bsg_ctx ctx;
241 struct fc_bsg_job *bsg_job;
242};
243
244struct 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 */
2258struct 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 */
2815typedef 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
2829struct 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
2894struct 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
2906struct 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
630struct 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 *,
60extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *, 60extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
61 uint16_t *); 61 uint16_t *);
62 62
63extern fc_port_t *
64qla2x00_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 *,
154int __qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, 156int __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);
156extern int qla2x00_start_sp(srb_t *); 158extern int qla2x00_start_sp(srb_t *);
159extern 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 *);
426extern void qla2x00_init_host_attr(scsi_qla_host_t *); 429extern void qla2x00_init_host_attr(scsi_qla_host_t *);
427extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); 430extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
428extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); 431extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
432extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *);
433extern 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
65static void 65void
66qla2x00_ctx_sp_free(srb_t *sp) 66qla2x00_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 */
2219static fc_port_t * 2229fc_port_t *
2220qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) 2230qla2x00_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
1028static void
1029qla24xx_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
1070static void
1071qla24xx_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
1028int 1141int
1029qla2x00_start_sp(srb_t *sp) 1142qla2x00_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
12static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); 13static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
13static void qla2x00_process_completed_request(struct scsi_qla_host *, 14static 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
885done: 888done:
886 return sp; 889 return sp;
887} 890}
@@ -982,6 +985,100 @@ done_post_logio_done_work:
982} 985}
983 986
984static void 987static void
988qla24xx_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
1081static void
985qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, 1082qla24xx_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
3638int 3638int
3639qla2x00_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
3701int
3702qla2x00_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}
3759int
3760qla84xx_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
3789int
3639qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) 3790qla2x00_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);