aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_attr.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c732
1 files changed, 729 insertions, 3 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 3a9f5b288aee..90d1e062ec4f 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,
@@ -1504,8 +1531,6 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
1504 fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, 1531 fcport->vha->hw->isp_ops->fabric_logout(fcport->vha,
1505 fcport->loop_id, fcport->d_id.b.domain, 1532 fcport->loop_id, fcport->d_id.b.domain,
1506 fcport->d_id.b.area, fcport->d_id.b.al_pa); 1533 fcport->d_id.b.area, fcport->d_id.b.al_pa);
1507
1508 qla2x00_abort_fcport_cmds(fcport);
1509} 1534}
1510 1535
1511static int 1536static int
@@ -1795,6 +1820,581 @@ qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable)
1795 return 0; 1820 return 0;
1796} 1821}
1797 1822
1823/* BSG support for ELS/CT pass through */
1824inline srb_t *
1825qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size)
1826{
1827 srb_t *sp;
1828 struct qla_hw_data *ha = vha->hw;
1829 struct srb_bsg_ctx *ctx;
1830
1831 sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
1832 if (!sp)
1833 goto done;
1834 ctx = kzalloc(size, GFP_KERNEL);
1835 if (!ctx) {
1836 mempool_free(sp, ha->srb_mempool);
1837 goto done;
1838 }
1839
1840 memset(sp, 0, sizeof(*sp));
1841 sp->fcport = fcport;
1842 sp->ctx = ctx;
1843done:
1844 return sp;
1845}
1846
1847static int
1848qla2x00_process_els(struct fc_bsg_job *bsg_job)
1849{
1850 struct fc_rport *rport;
1851 fc_port_t *fcport;
1852 struct Scsi_Host *host;
1853 scsi_qla_host_t *vha;
1854 struct qla_hw_data *ha;
1855 srb_t *sp;
1856 const char *type;
1857 int req_sg_cnt, rsp_sg_cnt;
1858 int rval = (DRIVER_ERROR << 16);
1859 uint16_t nextlid = 0;
1860 struct srb_bsg *els;
1861
1862 /* Multiple SG's are not supported for ELS requests */
1863 if (bsg_job->request_payload.sg_cnt > 1 ||
1864 bsg_job->reply_payload.sg_cnt > 1) {
1865 DEBUG2(printk(KERN_INFO
1866 "multiple SG's are not supported for ELS requests"
1867 " [request_sg_cnt: %x reply_sg_cnt: %x]\n",
1868 bsg_job->request_payload.sg_cnt,
1869 bsg_job->reply_payload.sg_cnt));
1870 rval = -EPERM;
1871 goto done;
1872 }
1873
1874 /* ELS request for rport */
1875 if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
1876 rport = bsg_job->rport;
1877 fcport = *(fc_port_t **) rport->dd_data;
1878 host = rport_to_shost(rport);
1879 vha = shost_priv(host);
1880 ha = vha->hw;
1881 type = "FC_BSG_RPT_ELS";
1882
1883 /* make sure the rport is logged in,
1884 * if not perform fabric login
1885 */
1886 if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
1887 DEBUG2(qla_printk(KERN_WARNING, ha,
1888 "failed to login port %06X for ELS passthru\n",
1889 fcport->d_id.b24));
1890 rval = -EIO;
1891 goto done;
1892 }
1893 } else {
1894 host = bsg_job->shost;
1895 vha = shost_priv(host);
1896 ha = vha->hw;
1897 type = "FC_BSG_HST_ELS_NOLOGIN";
1898
1899 /* Allocate a dummy fcport structure, since functions
1900 * preparing the IOCB and mailbox command retrieves port
1901 * specific information from fcport structure. For Host based
1902 * ELS commands there will be no fcport structure allocated
1903 */
1904 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
1905 if (!fcport) {
1906 rval = -ENOMEM;
1907 goto done;
1908 }
1909
1910 /* Initialize all required fields of fcport */
1911 fcport->vha = vha;
1912 fcport->vp_idx = vha->vp_idx;
1913 fcport->d_id.b.al_pa =
1914 bsg_job->request->rqst_data.h_els.port_id[0];
1915 fcport->d_id.b.area =
1916 bsg_job->request->rqst_data.h_els.port_id[1];
1917 fcport->d_id.b.domain =
1918 bsg_job->request->rqst_data.h_els.port_id[2];
1919 fcport->loop_id =
1920 (fcport->d_id.b.al_pa == 0xFD) ?
1921 NPH_FABRIC_CONTROLLER : NPH_F_PORT;
1922 }
1923
1924 if (!vha->flags.online) {
1925 DEBUG2(qla_printk(KERN_WARNING, ha,
1926 "host not online\n"));
1927 rval = -EIO;
1928 goto done;
1929 }
1930
1931 req_sg_cnt =
1932 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1933 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1934 if (!req_sg_cnt) {
1935 rval = -ENOMEM;
1936 goto done_free_fcport;
1937 }
1938 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
1939 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1940 if (!rsp_sg_cnt) {
1941 rval = -ENOMEM;
1942 goto done_free_fcport;
1943 }
1944
1945 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
1946 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt))
1947 {
1948 DEBUG2(printk(KERN_INFO
1949 "dma mapping resulted in different sg counts \
1950 [request_sg_cnt: %x dma_request_sg_cnt: %x\
1951 reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
1952 bsg_job->request_payload.sg_cnt, req_sg_cnt,
1953 bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
1954 rval = -EAGAIN;
1955 goto done_unmap_sg;
1956 }
1957
1958 /* Alloc SRB structure */
1959 sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg));
1960 if (!sp) {
1961 rval = -ENOMEM;
1962 goto done_unmap_sg;
1963 }
1964
1965 els = sp->ctx;
1966 els->ctx.type =
1967 (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
1968 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
1969 els->bsg_job = bsg_job;
1970
1971 DEBUG2(qla_printk(KERN_INFO, ha,
1972 "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
1973 "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
1974 bsg_job->request->rqst_data.h_els.command_code,
1975 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
1976 fcport->d_id.b.al_pa));
1977
1978 rval = qla2x00_start_sp(sp);
1979 if (rval != QLA_SUCCESS) {
1980 kfree(sp->ctx);
1981 mempool_free(sp, ha->srb_mempool);
1982 rval = -EIO;
1983 goto done_unmap_sg;
1984 }
1985 return rval;
1986
1987done_unmap_sg:
1988 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1989 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1990 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
1991 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1992 goto done_free_fcport;
1993
1994done_free_fcport:
1995 if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN)
1996 kfree(fcport);
1997done:
1998 return rval;
1999}
2000
2001static int
2002qla2x00_process_ct(struct fc_bsg_job *bsg_job)
2003{
2004 srb_t *sp;
2005 struct Scsi_Host *host = bsg_job->shost;
2006 scsi_qla_host_t *vha = shost_priv(host);
2007 struct qla_hw_data *ha = vha->hw;
2008 int rval = (DRIVER_ERROR << 16);
2009 int req_sg_cnt, rsp_sg_cnt;
2010 uint16_t loop_id;
2011 struct fc_port *fcport;
2012 char *type = "FC_BSG_HST_CT";
2013 struct srb_bsg *ct;
2014
2015 /* pass through is supported only for ISP 4Gb or higher */
2016 if (!IS_FWI2_CAPABLE(ha)) {
2017 DEBUG2(qla_printk(KERN_INFO, ha,
2018 "scsi(%ld):Firmware is not capable to support FC "
2019 "CT pass thru\n", vha->host_no));
2020 rval = -EPERM;
2021 goto done;
2022 }
2023
2024 req_sg_cnt =
2025 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
2026 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
2027 if (!req_sg_cnt) {
2028 rval = -ENOMEM;
2029 goto done;
2030 }
2031
2032 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
2033 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2034 if (!rsp_sg_cnt) {
2035 rval = -ENOMEM;
2036 goto done;
2037 }
2038
2039 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
2040 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt))
2041 {
2042 DEBUG2(qla_printk(KERN_WARNING, ha,
2043 "dma mapping resulted in different sg counts \
2044 [request_sg_cnt: %x dma_request_sg_cnt: %x\
2045 reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
2046 bsg_job->request_payload.sg_cnt, req_sg_cnt,
2047 bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
2048 rval = -EAGAIN;
2049 goto done_unmap_sg;
2050 }
2051
2052 if (!vha->flags.online) {
2053 DEBUG2(qla_printk(KERN_WARNING, ha,
2054 "host not online\n"));
2055 rval = -EIO;
2056 goto done_unmap_sg;
2057 }
2058
2059 loop_id =
2060 (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
2061 >> 24;
2062 switch (loop_id) {
2063 case 0xFC:
2064 loop_id = cpu_to_le16(NPH_SNS);
2065 break;
2066 case 0xFA:
2067 loop_id = vha->mgmt_svr_loop_id;
2068 break;
2069 default:
2070 DEBUG2(qla_printk(KERN_INFO, ha,
2071 "Unknown loop id: %x\n", loop_id));
2072 rval = -EINVAL;
2073 goto done_unmap_sg;
2074 }
2075
2076 /* Allocate a dummy fcport structure, since functions preparing the
2077 * IOCB and mailbox command retrieves port specific information
2078 * from fcport structure. For Host based ELS commands there will be
2079 * no fcport structure allocated
2080 */
2081 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
2082 if (!fcport)
2083 {
2084 rval = -ENOMEM;
2085 goto done_unmap_sg;
2086 }
2087
2088 /* Initialize all required fields of fcport */
2089 fcport->vha = vha;
2090 fcport->vp_idx = vha->vp_idx;
2091 fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0];
2092 fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1];
2093 fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2];
2094 fcport->loop_id = loop_id;
2095
2096 /* Alloc SRB structure */
2097 sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg));
2098 if (!sp) {
2099 rval = -ENOMEM;
2100 goto done_free_fcport;
2101 }
2102
2103 ct = sp->ctx;
2104 ct->ctx.type = SRB_CT_CMD;
2105 ct->bsg_job = bsg_job;
2106
2107 DEBUG2(qla_printk(KERN_INFO, ha,
2108 "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
2109 "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
2110 (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
2111 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
2112 fcport->d_id.b.al_pa));
2113
2114 rval = qla2x00_start_sp(sp);
2115 if (rval != QLA_SUCCESS) {
2116 kfree(sp->ctx);
2117 mempool_free(sp, ha->srb_mempool);
2118 rval = -EIO;
2119 goto done_free_fcport;
2120 }
2121 return rval;
2122
2123done_free_fcport:
2124 kfree(fcport);
2125done_unmap_sg:
2126 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
2127 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
2128 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
2129 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2130done:
2131 return rval;
2132}
2133
2134static int
2135qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
2136{
2137 struct Scsi_Host *host = bsg_job->shost;
2138 scsi_qla_host_t *vha = shost_priv(host);
2139 struct qla_hw_data *ha = vha->hw;
2140 int rval;
2141 uint8_t command_sent;
2142 uint32_t vendor_cmd;
2143 char *type;
2144 struct msg_echo_lb elreq;
2145 uint16_t response[MAILBOX_REGISTER_COUNT];
2146 uint8_t* fw_sts_ptr;
2147 uint8_t *req_data;
2148 dma_addr_t req_data_dma;
2149 uint32_t req_data_len;
2150 uint8_t *rsp_data;
2151 dma_addr_t rsp_data_dma;
2152 uint32_t rsp_data_len;
2153
2154 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
2155 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
2156 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
2157 rval = -EBUSY;
2158 goto done;
2159 }
2160
2161 if (!vha->flags.online) {
2162 DEBUG2(qla_printk(KERN_WARNING, ha,
2163 "host not online\n"));
2164 rval = -EIO;
2165 goto done;
2166 }
2167
2168 elreq.req_sg_cnt =
2169 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
2170 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
2171 if (!elreq.req_sg_cnt) {
2172 rval = -ENOMEM;
2173 goto done;
2174 }
2175 elreq.rsp_sg_cnt =
2176 dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
2177 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2178 if (!elreq.rsp_sg_cnt) {
2179 rval = -ENOMEM;
2180 goto done;
2181 }
2182
2183 if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
2184 (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt))
2185 {
2186 DEBUG2(printk(KERN_INFO
2187 "dma mapping resulted in different sg counts \
2188 [request_sg_cnt: %x dma_request_sg_cnt: %x\
2189 reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
2190 bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
2191 bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt));
2192 rval = -EAGAIN;
2193 goto done_unmap_sg;
2194 }
2195 req_data_len = rsp_data_len = bsg_job->request_payload.payload_len;
2196 req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
2197 &req_data_dma, GFP_KERNEL);
2198
2199 rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
2200 &rsp_data_dma, GFP_KERNEL);
2201
2202 /* Copy the request buffer in req_data now */
2203 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2204 bsg_job->request_payload.sg_cnt, req_data,
2205 req_data_len);
2206
2207 elreq.send_dma = req_data_dma;
2208 elreq.rcv_dma = rsp_data_dma;
2209 elreq.transfer_size = req_data_len;
2210
2211 /* Vendor cmd : loopback or ECHO diagnostic
2212 * Options:
2213 * Loopback : Either internal or external loopback
2214 * ECHO: ECHO ELS or Vendor specific FC4 link data
2215 */
2216 vendor_cmd = bsg_job->request->rqst_data.h_vendor.vendor_cmd[0];
2217 elreq.options =
2218 *(((uint32_t *)bsg_job->request->rqst_data.h_vendor.vendor_cmd)
2219 + 1);
2220
2221 switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
2222 case QL_VND_LOOPBACK:
2223 if (ha->current_topology != ISP_CFG_F) {
2224 type = "FC_BSG_HST_VENDOR_LOOPBACK";
2225
2226 DEBUG2(qla_printk(KERN_INFO, ha,
2227 "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n",
2228 vha->host_no, type, vendor_cmd, elreq.options));
2229
2230 command_sent = INT_DEF_LB_LOOPBACK_CMD;
2231 rval = qla2x00_loopback_test(vha, &elreq, response);
2232 if (IS_QLA81XX(ha)) {
2233 if (response[0] == MBS_COMMAND_ERROR && response[1] == MBS_LB_RESET) {
2234 DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing "
2235 "ISP\n", __func__, vha->host_no));
2236 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2237 qla2xxx_wake_dpc(vha);
2238 }
2239 }
2240 } else {
2241 type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
2242 DEBUG2(qla_printk(KERN_INFO, ha,
2243 "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n",
2244 vha->host_no, type, vendor_cmd, elreq.options));
2245
2246 command_sent = INT_DEF_LB_ECHO_CMD;
2247 rval = qla2x00_echo_test(vha, &elreq, response);
2248 }
2249 break;
2250 case QLA84_RESET:
2251 if (!IS_QLA84XX(vha->hw)) {
2252 rval = -EINVAL;
2253 DEBUG16(printk(
2254 "%s(%ld): 8xxx exiting.\n",
2255 __func__, vha->host_no));
2256 return rval;
2257 }
2258 rval = qla84xx_reset(vha, &elreq, bsg_job);
2259 break;
2260 case QLA84_MGMT_CMD:
2261 if (!IS_QLA84XX(vha->hw)) {
2262 rval = -EINVAL;
2263 DEBUG16(printk(
2264 "%s(%ld): 8xxx exiting.\n",
2265 __func__, vha->host_no));
2266 return rval;
2267 }
2268 rval = qla84xx_mgmt_cmd(vha, &elreq, bsg_job);
2269 break;
2270 default:
2271 rval = -ENOSYS;
2272 }
2273
2274 if (rval != QLA_SUCCESS) {
2275 DEBUG2(qla_printk(KERN_WARNING, ha,
2276 "scsi(%ld) Vendor request %s failed\n", vha->host_no, type));
2277 rval = 0;
2278 bsg_job->reply->result = (DID_ERROR << 16);
2279 bsg_job->reply->reply_payload_rcv_len = 0;
2280 fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
2281 memcpy( fw_sts_ptr, response, sizeof(response));
2282 fw_sts_ptr += sizeof(response);
2283 *fw_sts_ptr = command_sent;
2284 } else {
2285 DEBUG2(qla_printk(KERN_WARNING, ha,
2286 "scsi(%ld) Vendor request %s completed\n", vha->host_no, type));
2287 rval = bsg_job->reply->result = 0;
2288 bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(response) + sizeof(uint8_t);
2289 bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
2290 fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
2291 memcpy(fw_sts_ptr, response, sizeof(response));
2292 fw_sts_ptr += sizeof(response);
2293 *fw_sts_ptr = command_sent;
2294 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2295 bsg_job->reply_payload.sg_cnt, rsp_data,
2296 rsp_data_len);
2297 }
2298 bsg_job->job_done(bsg_job);
2299
2300done_unmap_sg:
2301
2302 if(req_data)
2303 dma_free_coherent(&ha->pdev->dev, req_data_len,
2304 req_data, req_data_dma);
2305 dma_unmap_sg(&ha->pdev->dev,
2306 bsg_job->request_payload.sg_list,
2307 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
2308 dma_unmap_sg(&ha->pdev->dev,
2309 bsg_job->reply_payload.sg_list,
2310 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2311
2312done:
2313 return rval;
2314}
2315
2316static int
2317qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
2318{
2319 int ret = -EINVAL;
2320
2321 switch (bsg_job->request->msgcode) {
2322 case FC_BSG_RPT_ELS:
2323 case FC_BSG_HST_ELS_NOLOGIN:
2324 ret = qla2x00_process_els(bsg_job);
2325 break;
2326 case FC_BSG_HST_CT:
2327 ret = qla2x00_process_ct(bsg_job);
2328 break;
2329 case FC_BSG_HST_VENDOR:
2330 ret = qla2x00_process_vendor_specific(bsg_job);
2331 break;
2332 case FC_BSG_HST_ADD_RPORT:
2333 case FC_BSG_HST_DEL_RPORT:
2334 case FC_BSG_RPT_CT:
2335 default:
2336 DEBUG2(printk("qla2xxx: unsupported BSG request\n"));
2337 break;
2338 }
2339 return ret;
2340}
2341
2342static int
2343qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
2344{
2345 scsi_qla_host_t *vha = shost_priv(bsg_job->shost);
2346 struct qla_hw_data *ha = vha->hw;
2347 srb_t *sp;
2348 int cnt, que;
2349 unsigned long flags;
2350 struct req_que *req;
2351 struct srb_bsg *sp_bsg;
2352
2353 /* find the bsg job from the active list of commands */
2354 spin_lock_irqsave(&ha->hardware_lock, flags);
2355 for (que = 0; que < ha->max_req_queues; que++) {
2356 req = ha->req_q_map[que];
2357 if (!req)
2358 continue;
2359
2360 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++ ) {
2361 sp = req->outstanding_cmds[cnt];
2362
2363 if (sp) {
2364 sp_bsg = (struct srb_bsg*)sp->ctx;
2365
2366 if (((sp_bsg->ctx.type == SRB_CT_CMD) ||
2367 (sp_bsg->ctx.type == SRB_ELS_CMD_RPT)
2368 || ( sp_bsg->ctx.type == SRB_ELS_CMD_HST)) &&
2369 (sp_bsg->bsg_job == bsg_job)) {
2370 if (ha->isp_ops->abort_command(sp)) {
2371 DEBUG2(qla_printk(KERN_INFO, ha,
2372 "scsi(%ld): mbx abort_command failed\n", vha->host_no));
2373 bsg_job->req->errors = bsg_job->reply->result = -EIO;
2374 } else {
2375 DEBUG2(qla_printk(KERN_INFO, ha,
2376 "scsi(%ld): mbx abort_command success\n", vha->host_no));
2377 bsg_job->req->errors = bsg_job->reply->result = 0;
2378 }
2379 goto done;
2380 }
2381 }
2382 }
2383 }
2384 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2385 DEBUG2(qla_printk(KERN_INFO, ha,
2386 "scsi(%ld) SRB not found to abort\n", vha->host_no));
2387 bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
2388 return 0;
2389
2390done:
2391 if (bsg_job->request->msgcode == FC_BSG_HST_CT)
2392 kfree(sp->fcport);
2393 kfree(sp->ctx);
2394 mempool_free(sp, ha->srb_mempool);
2395 return 0;
2396}
2397
1798struct fc_function_template qla2xxx_transport_functions = { 2398struct fc_function_template qla2xxx_transport_functions = {
1799 2399
1800 .show_host_node_name = 1, 2400 .show_host_node_name = 1,
@@ -1838,6 +2438,8 @@ struct fc_function_template qla2xxx_transport_functions = {
1838 .vport_create = qla24xx_vport_create, 2438 .vport_create = qla24xx_vport_create,
1839 .vport_disable = qla24xx_vport_disable, 2439 .vport_disable = qla24xx_vport_disable,
1840 .vport_delete = qla24xx_vport_delete, 2440 .vport_delete = qla24xx_vport_delete,
2441 .bsg_request = qla24xx_bsg_request,
2442 .bsg_timeout = qla24xx_bsg_timeout,
1841}; 2443};
1842 2444
1843struct fc_function_template qla2xxx_transport_vport_functions = { 2445struct fc_function_template qla2xxx_transport_vport_functions = {
@@ -1878,6 +2480,8 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
1878 .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, 2480 .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
1879 .terminate_rport_io = qla2x00_terminate_rport_io, 2481 .terminate_rport_io = qla2x00_terminate_rport_io,
1880 .get_fc_host_stats = qla2x00_get_fc_host_stats, 2482 .get_fc_host_stats = qla2x00_get_fc_host_stats,
2483 .bsg_request = qla24xx_bsg_request,
2484 .bsg_timeout = qla24xx_bsg_timeout,
1881}; 2485};
1882 2486
1883void 2487void
@@ -1906,3 +2510,125 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
1906 speed = FC_PORTSPEED_1GBIT; 2510 speed = FC_PORTSPEED_1GBIT;
1907 fc_host_supported_speeds(vha->host) = speed; 2511 fc_host_supported_speeds(vha->host) = speed;
1908} 2512}
2513static int
2514qla84xx_reset(scsi_qla_host_t *ha, struct msg_echo_lb *mreq, struct fc_bsg_job *bsg_job)
2515{
2516 int ret = 0;
2517 int cmd;
2518 uint16_t cmd_status;
2519
2520 DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no));
2521
2522 cmd = (*((bsg_job->request->rqst_data.h_vendor.vendor_cmd) + 2))
2523 == A84_RESET_FLAG_ENABLE_DIAG_FW ?
2524 A84_ISSUE_RESET_DIAG_FW : A84_ISSUE_RESET_OP_FW;
2525 ret = qla84xx_reset_chip(ha, cmd == A84_ISSUE_RESET_DIAG_FW,
2526 &cmd_status);
2527 return ret;
2528}
2529
2530static int
2531qla84xx_mgmt_cmd(scsi_qla_host_t *ha, struct msg_echo_lb *mreq, struct fc_bsg_job *bsg_job)
2532{
2533 struct access_chip_84xx *mn;
2534 dma_addr_t mn_dma, mgmt_dma;
2535 void *mgmt_b = NULL;
2536 int ret = 0;
2537 int rsp_hdr_len, len = 0;
2538 struct qla84_msg_mgmt *ql84_mgmt;
2539
2540 ql84_mgmt = (struct qla84_msg_mgmt *) vmalloc(sizeof(struct qla84_msg_mgmt));
2541 ql84_mgmt->cmd =
2542 *((uint16_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 2));
2543 ql84_mgmt->mgmtp.u.mem.start_addr =
2544 *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 3));
2545 ql84_mgmt->len =
2546 *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 4));
2547 ql84_mgmt->mgmtp.u.config.id =
2548 *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 5));
2549 ql84_mgmt->mgmtp.u.config.param0 =
2550 *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 6));
2551 ql84_mgmt->mgmtp.u.config.param1 =
2552 *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 7));
2553 ql84_mgmt->mgmtp.u.info.type =
2554 *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 8));
2555 ql84_mgmt->mgmtp.u.info.context =
2556 *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 9));
2557
2558 rsp_hdr_len = bsg_job->request_payload.payload_len;
2559
2560 mn = dma_pool_alloc(ha->hw->s_dma_pool, GFP_KERNEL, &mn_dma);
2561 if (mn == NULL) {
2562 DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
2563 "failed%lu\n", __func__, ha->host_no));
2564 return -ENOMEM;
2565 }
2566
2567 memset(mn, 0, sizeof (struct access_chip_84xx));
2568
2569 mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
2570 mn->entry_count = 1;
2571
2572 switch (ql84_mgmt->cmd) {
2573 case QLA84_MGMT_READ_MEM:
2574 mn->options = cpu_to_le16(ACO_DUMP_MEMORY);
2575 mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr);
2576 break;
2577 case QLA84_MGMT_WRITE_MEM:
2578 mn->options = cpu_to_le16(ACO_LOAD_MEMORY);
2579 mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr);
2580 break;
2581 case QLA84_MGMT_CHNG_CONFIG:
2582 mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM);
2583 mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.id);
2584 mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param0);
2585 mn->parameter3 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param1);
2586 break;
2587 case QLA84_MGMT_GET_INFO:
2588 mn->options = cpu_to_le16(ACO_REQUEST_INFO);
2589 mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.type);
2590 mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.context);
2591 break;
2592 default:
2593 ret = -EIO;
2594 goto exit_mgmt0;
2595 }
2596
2597 if ((len == ql84_mgmt->len) &&
2598 ql84_mgmt->cmd != QLA84_MGMT_CHNG_CONFIG) {
2599 mgmt_b = dma_alloc_coherent(&ha->hw->pdev->dev, len,
2600 &mgmt_dma, GFP_KERNEL);
2601 if (mgmt_b == NULL) {
2602 DEBUG2(printk(KERN_ERR "%s: dma alloc mgmt_b "
2603 "failed%lu\n", __func__, ha->host_no));
2604 ret = -ENOMEM;
2605 goto exit_mgmt0;
2606 }
2607 mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->len);
2608 mn->dseg_count = cpu_to_le16(1);
2609 mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma));
2610 mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma));
2611 mn->dseg_length = cpu_to_le32(len);
2612
2613 if (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) {
2614 memcpy(mgmt_b, ql84_mgmt->payload, len);
2615 }
2616 }
2617
2618 ret = qla2x00_issue_iocb(ha, mn, mn_dma, 0);
2619 if ((ret != QLA_SUCCESS) || (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM)
2620 || (ql84_mgmt->cmd == QLA84_MGMT_CHNG_CONFIG)) {
2621 if (ret != QLA_SUCCESS)
2622 DEBUG2(printk(KERN_ERR "%s(%lu): failed\n",
2623 __func__, ha->host_no));
2624 } else if ((ql84_mgmt->cmd == QLA84_MGMT_READ_MEM) ||
2625 (ql84_mgmt->cmd == QLA84_MGMT_GET_INFO)) {
2626 }
2627
2628 if (mgmt_b)
2629 dma_free_coherent(&ha->hw->pdev->dev, len, mgmt_b, mgmt_dma);
2630
2631exit_mgmt0:
2632 dma_pool_free(ha->hw->s_dma_pool, mn, mn_dma);
2633 return ret;
2634}