diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 773 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 78 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.h | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 174 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 51 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 14 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 91 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 120 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 444 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 274 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 13 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 350 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 6 |
14 files changed, 1950 insertions, 451 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index fbcb82a2f7f4..1c7ef55966fb 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -8,10 +8,13 @@ | |||
8 | 8 | ||
9 | #include <linux/kthread.h> | 9 | #include <linux/kthread.h> |
10 | #include <linux/vmalloc.h> | 10 | #include <linux/vmalloc.h> |
11 | #include <linux/slab.h> | ||
11 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
12 | 13 | ||
13 | static int qla24xx_vport_disable(struct fc_vport *, bool); | 14 | static int qla24xx_vport_disable(struct fc_vport *, bool); |
14 | 15 | static int qla84xx_reset(scsi_qla_host_t *, struct msg_echo_lb *, struct fc_bsg_job *); | |
16 | int qla84xx_reset_chip(scsi_qla_host_t *, uint16_t, uint16_t *); | ||
17 | static int qla84xx_mgmt_cmd(scsi_qla_host_t *, struct msg_echo_lb *, struct fc_bsg_job *); | ||
15 | /* SYSFS attributes --------------------------------------------------------- */ | 18 | /* SYSFS attributes --------------------------------------------------------- */ |
16 | 19 | ||
17 | static ssize_t | 20 | static ssize_t |
@@ -232,6 +235,9 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
232 | if (off) | 235 | if (off) |
233 | return 0; | 236 | return 0; |
234 | 237 | ||
238 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
239 | return 0; | ||
240 | |||
235 | if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) | 241 | if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) |
236 | return -EINVAL; | 242 | return -EINVAL; |
237 | if (start > ha->optrom_size) | 243 | if (start > ha->optrom_size) |
@@ -379,6 +385,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, | |||
379 | struct device, kobj))); | 385 | struct device, kobj))); |
380 | struct qla_hw_data *ha = vha->hw; | 386 | struct qla_hw_data *ha = vha->hw; |
381 | 387 | ||
388 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
389 | return 0; | ||
390 | |||
382 | if (!capable(CAP_SYS_ADMIN)) | 391 | if (!capable(CAP_SYS_ADMIN)) |
383 | return 0; | 392 | return 0; |
384 | 393 | ||
@@ -398,6 +407,9 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, | |||
398 | struct qla_hw_data *ha = vha->hw; | 407 | struct qla_hw_data *ha = vha->hw; |
399 | uint8_t *tmp_data; | 408 | uint8_t *tmp_data; |
400 | 409 | ||
410 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
411 | return 0; | ||
412 | |||
401 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size || | 413 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size || |
402 | !ha->isp_ops->write_nvram) | 414 | !ha->isp_ops->write_nvram) |
403 | return 0; | 415 | return 0; |
@@ -1159,6 +1171,28 @@ qla2x00_total_isp_aborts_show(struct device *dev, | |||
1159 | } | 1171 | } |
1160 | 1172 | ||
1161 | static ssize_t | 1173 | static ssize_t |
1174 | qla24xx_84xx_fw_version_show(struct device *dev, | ||
1175 | struct device_attribute *attr, char *buf) | ||
1176 | { | ||
1177 | int rval = QLA_SUCCESS; | ||
1178 | uint16_t status[2] = {0, 0}; | ||
1179 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1180 | struct qla_hw_data *ha = vha->hw; | ||
1181 | |||
1182 | if (IS_QLA84XX(ha) && ha->cs84xx) { | ||
1183 | if (ha->cs84xx->op_fw_version == 0) { | ||
1184 | rval = qla84xx_verify_chip(vha, status); | ||
1185 | } | ||
1186 | |||
1187 | if ((rval == QLA_SUCCESS) && (status[0] == 0)) | ||
1188 | return snprintf(buf, PAGE_SIZE, "%u\n", | ||
1189 | (uint32_t)ha->cs84xx->op_fw_version); | ||
1190 | } | ||
1191 | |||
1192 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1193 | } | ||
1194 | |||
1195 | static ssize_t | ||
1162 | qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, | 1196 | qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr, |
1163 | char *buf) | 1197 | char *buf) |
1164 | { | 1198 | { |
@@ -1238,10 +1272,15 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr, | |||
1238 | char *buf) | 1272 | char *buf) |
1239 | { | 1273 | { |
1240 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | 1274 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); |
1241 | int rval; | 1275 | int rval = QLA_FUNCTION_FAILED; |
1242 | uint16_t state[5]; | 1276 | uint16_t state[5]; |
1243 | 1277 | ||
1244 | rval = qla2x00_get_firmware_state(vha, state); | 1278 | if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || |
1279 | test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) | ||
1280 | DEBUG2_3_11(printk("%s(%ld): isp reset in progress.\n", | ||
1281 | __func__, vha->host_no)); | ||
1282 | else if (!vha->hw->flags.eeh_busy) | ||
1283 | rval = qla2x00_get_firmware_state(vha, state); | ||
1245 | if (rval != QLA_SUCCESS) | 1284 | if (rval != QLA_SUCCESS) |
1246 | memset(state, -1, sizeof(state)); | 1285 | memset(state, -1, sizeof(state)); |
1247 | 1286 | ||
@@ -1271,6 +1310,8 @@ static DEVICE_ATTR(optrom_fcode_version, S_IRUGO, | |||
1271 | qla2x00_optrom_fcode_version_show, NULL); | 1310 | qla2x00_optrom_fcode_version_show, NULL); |
1272 | static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, | 1311 | static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, |
1273 | NULL); | 1312 | NULL); |
1313 | static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show, | ||
1314 | NULL); | ||
1274 | static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, | 1315 | static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, |
1275 | NULL); | 1316 | NULL); |
1276 | static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); | 1317 | static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL); |
@@ -1300,6 +1341,7 @@ struct device_attribute *qla2x00_host_attrs[] = { | |||
1300 | &dev_attr_optrom_efi_version, | 1341 | &dev_attr_optrom_efi_version, |
1301 | &dev_attr_optrom_fcode_version, | 1342 | &dev_attr_optrom_fcode_version, |
1302 | &dev_attr_optrom_fw_version, | 1343 | &dev_attr_optrom_fw_version, |
1344 | &dev_attr_84xx_fw_version, | ||
1303 | &dev_attr_total_isp_aborts, | 1345 | &dev_attr_total_isp_aborts, |
1304 | &dev_attr_mpi_version, | 1346 | &dev_attr_mpi_version, |
1305 | &dev_attr_phy_version, | 1347 | &dev_attr_phy_version, |
@@ -1452,10 +1494,13 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
1452 | if (!fcport) | 1494 | if (!fcport) |
1453 | return; | 1495 | return; |
1454 | 1496 | ||
1455 | if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) | 1497 | if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) |
1498 | return; | ||
1499 | |||
1500 | if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { | ||
1456 | qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); | 1501 | qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); |
1457 | else | 1502 | return; |
1458 | qla2x00_abort_fcport_cmds(fcport); | 1503 | } |
1459 | 1504 | ||
1460 | /* | 1505 | /* |
1461 | * Transport has effectively 'deleted' the rport, clear | 1506 | * Transport has effectively 'deleted' the rport, clear |
@@ -1475,6 +1520,9 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) | |||
1475 | if (!fcport) | 1520 | if (!fcport) |
1476 | return; | 1521 | return; |
1477 | 1522 | ||
1523 | if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) | ||
1524 | return; | ||
1525 | |||
1478 | if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { | 1526 | if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { |
1479 | qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); | 1527 | qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); |
1480 | return; | 1528 | return; |
@@ -1488,8 +1536,6 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) | |||
1488 | fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, | 1536 | fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, |
1489 | fcport->loop_id, fcport->d_id.b.domain, | 1537 | fcport->loop_id, fcport->d_id.b.domain, |
1490 | fcport->d_id.b.area, fcport->d_id.b.al_pa); | 1538 | fcport->d_id.b.area, fcport->d_id.b.al_pa); |
1491 | |||
1492 | qla2x00_abort_fcport_cmds(fcport); | ||
1493 | } | 1539 | } |
1494 | 1540 | ||
1495 | static int | 1541 | static int |
@@ -1515,6 +1561,12 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) | |||
1515 | pfc_host_stat = &ha->fc_host_stat; | 1561 | pfc_host_stat = &ha->fc_host_stat; |
1516 | memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); | 1562 | memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); |
1517 | 1563 | ||
1564 | if (test_bit(UNLOADING, &vha->dpc_flags)) | ||
1565 | goto done; | ||
1566 | |||
1567 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
1568 | goto done; | ||
1569 | |||
1518 | stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma); | 1570 | stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma); |
1519 | if (stats == NULL) { | 1571 | if (stats == NULL) { |
1520 | DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n", | 1572 | DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n", |
@@ -1654,7 +1706,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | |||
1654 | fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); | 1706 | fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); |
1655 | } | 1707 | } |
1656 | 1708 | ||
1657 | if (scsi_add_host(vha->host, &fc_vport->dev)) { | 1709 | if (scsi_add_host_with_dma(vha->host, &fc_vport->dev, |
1710 | &ha->pdev->dev)) { | ||
1658 | DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", | 1711 | DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", |
1659 | vha->host_no, vha->vp_idx)); | 1712 | vha->host_no, vha->vp_idx)); |
1660 | goto vport_create_failed_2; | 1713 | goto vport_create_failed_2; |
@@ -1772,6 +1825,582 @@ qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable) | |||
1772 | return 0; | 1825 | return 0; |
1773 | } | 1826 | } |
1774 | 1827 | ||
1828 | /* BSG support for ELS/CT pass through */ | ||
1829 | inline srb_t * | ||
1830 | qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size) | ||
1831 | { | ||
1832 | srb_t *sp; | ||
1833 | struct qla_hw_data *ha = vha->hw; | ||
1834 | struct srb_bsg_ctx *ctx; | ||
1835 | |||
1836 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | ||
1837 | if (!sp) | ||
1838 | goto done; | ||
1839 | ctx = kzalloc(size, GFP_KERNEL); | ||
1840 | if (!ctx) { | ||
1841 | mempool_free(sp, ha->srb_mempool); | ||
1842 | goto done; | ||
1843 | } | ||
1844 | |||
1845 | memset(sp, 0, sizeof(*sp)); | ||
1846 | sp->fcport = fcport; | ||
1847 | sp->ctx = ctx; | ||
1848 | done: | ||
1849 | return sp; | ||
1850 | } | ||
1851 | |||
1852 | static int | ||
1853 | qla2x00_process_els(struct fc_bsg_job *bsg_job) | ||
1854 | { | ||
1855 | struct fc_rport *rport; | ||
1856 | fc_port_t *fcport; | ||
1857 | struct Scsi_Host *host; | ||
1858 | scsi_qla_host_t *vha; | ||
1859 | struct qla_hw_data *ha; | ||
1860 | srb_t *sp; | ||
1861 | const char *type; | ||
1862 | int req_sg_cnt, rsp_sg_cnt; | ||
1863 | int rval = (DRIVER_ERROR << 16); | ||
1864 | uint16_t nextlid = 0; | ||
1865 | struct srb_bsg *els; | ||
1866 | |||
1867 | /* Multiple SG's are not supported for ELS requests */ | ||
1868 | if (bsg_job->request_payload.sg_cnt > 1 || | ||
1869 | bsg_job->reply_payload.sg_cnt > 1) { | ||
1870 | DEBUG2(printk(KERN_INFO | ||
1871 | "multiple SG's are not supported for ELS requests" | ||
1872 | " [request_sg_cnt: %x reply_sg_cnt: %x]\n", | ||
1873 | bsg_job->request_payload.sg_cnt, | ||
1874 | bsg_job->reply_payload.sg_cnt)); | ||
1875 | rval = -EPERM; | ||
1876 | goto done; | ||
1877 | } | ||
1878 | |||
1879 | /* ELS request for rport */ | ||
1880 | if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) { | ||
1881 | rport = bsg_job->rport; | ||
1882 | fcport = *(fc_port_t **) rport->dd_data; | ||
1883 | host = rport_to_shost(rport); | ||
1884 | vha = shost_priv(host); | ||
1885 | ha = vha->hw; | ||
1886 | type = "FC_BSG_RPT_ELS"; | ||
1887 | |||
1888 | /* make sure the rport is logged in, | ||
1889 | * if not perform fabric login | ||
1890 | */ | ||
1891 | if (qla2x00_fabric_login(vha, fcport, &nextlid)) { | ||
1892 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1893 | "failed to login port %06X for ELS passthru\n", | ||
1894 | fcport->d_id.b24)); | ||
1895 | rval = -EIO; | ||
1896 | goto done; | ||
1897 | } | ||
1898 | } else { | ||
1899 | host = bsg_job->shost; | ||
1900 | vha = shost_priv(host); | ||
1901 | ha = vha->hw; | ||
1902 | type = "FC_BSG_HST_ELS_NOLOGIN"; | ||
1903 | |||
1904 | /* Allocate a dummy fcport structure, since functions | ||
1905 | * preparing the IOCB and mailbox command retrieves port | ||
1906 | * specific information from fcport structure. For Host based | ||
1907 | * ELS commands there will be no fcport structure allocated | ||
1908 | */ | ||
1909 | fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); | ||
1910 | if (!fcport) { | ||
1911 | rval = -ENOMEM; | ||
1912 | goto done; | ||
1913 | } | ||
1914 | |||
1915 | /* Initialize all required fields of fcport */ | ||
1916 | fcport->vha = vha; | ||
1917 | fcport->vp_idx = vha->vp_idx; | ||
1918 | fcport->d_id.b.al_pa = | ||
1919 | bsg_job->request->rqst_data.h_els.port_id[0]; | ||
1920 | fcport->d_id.b.area = | ||
1921 | bsg_job->request->rqst_data.h_els.port_id[1]; | ||
1922 | fcport->d_id.b.domain = | ||
1923 | bsg_job->request->rqst_data.h_els.port_id[2]; | ||
1924 | fcport->loop_id = | ||
1925 | (fcport->d_id.b.al_pa == 0xFD) ? | ||
1926 | NPH_FABRIC_CONTROLLER : NPH_F_PORT; | ||
1927 | } | ||
1928 | |||
1929 | if (!vha->flags.online) { | ||
1930 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
1931 | "host not online\n")); | ||
1932 | rval = -EIO; | ||
1933 | goto done; | ||
1934 | } | ||
1935 | |||
1936 | req_sg_cnt = | ||
1937 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
1938 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1939 | if (!req_sg_cnt) { | ||
1940 | rval = -ENOMEM; | ||
1941 | goto done_free_fcport; | ||
1942 | } | ||
1943 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
1944 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1945 | if (!rsp_sg_cnt) { | ||
1946 | rval = -ENOMEM; | ||
1947 | goto done_free_fcport; | ||
1948 | } | ||
1949 | |||
1950 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
1951 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
1952 | { | ||
1953 | DEBUG2(printk(KERN_INFO | ||
1954 | "dma mapping resulted in different sg counts \ | ||
1955 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
1956 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
1957 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
1958 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt)); | ||
1959 | rval = -EAGAIN; | ||
1960 | goto done_unmap_sg; | ||
1961 | } | ||
1962 | |||
1963 | /* Alloc SRB structure */ | ||
1964 | sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg)); | ||
1965 | if (!sp) { | ||
1966 | rval = -ENOMEM; | ||
1967 | goto done_unmap_sg; | ||
1968 | } | ||
1969 | |||
1970 | els = sp->ctx; | ||
1971 | els->ctx.type = | ||
1972 | (bsg_job->request->msgcode == FC_BSG_RPT_ELS ? | ||
1973 | SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST); | ||
1974 | els->bsg_job = bsg_job; | ||
1975 | |||
1976 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1977 | "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x " | ||
1978 | "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type, | ||
1979 | bsg_job->request->rqst_data.h_els.command_code, | ||
1980 | fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, | ||
1981 | fcport->d_id.b.al_pa)); | ||
1982 | |||
1983 | rval = qla2x00_start_sp(sp); | ||
1984 | if (rval != QLA_SUCCESS) { | ||
1985 | kfree(sp->ctx); | ||
1986 | mempool_free(sp, ha->srb_mempool); | ||
1987 | rval = -EIO; | ||
1988 | goto done_unmap_sg; | ||
1989 | } | ||
1990 | return rval; | ||
1991 | |||
1992 | done_unmap_sg: | ||
1993 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
1994 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1995 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
1996 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1997 | goto done_free_fcport; | ||
1998 | |||
1999 | done_free_fcport: | ||
2000 | if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN) | ||
2001 | kfree(fcport); | ||
2002 | done: | ||
2003 | return rval; | ||
2004 | } | ||
2005 | |||
2006 | static int | ||
2007 | qla2x00_process_ct(struct fc_bsg_job *bsg_job) | ||
2008 | { | ||
2009 | srb_t *sp; | ||
2010 | struct Scsi_Host *host = bsg_job->shost; | ||
2011 | scsi_qla_host_t *vha = shost_priv(host); | ||
2012 | struct qla_hw_data *ha = vha->hw; | ||
2013 | int rval = (DRIVER_ERROR << 16); | ||
2014 | int req_sg_cnt, rsp_sg_cnt; | ||
2015 | uint16_t loop_id; | ||
2016 | struct fc_port *fcport; | ||
2017 | char *type = "FC_BSG_HST_CT"; | ||
2018 | struct srb_bsg *ct; | ||
2019 | |||
2020 | /* pass through is supported only for ISP 4Gb or higher */ | ||
2021 | if (!IS_FWI2_CAPABLE(ha)) { | ||
2022 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2023 | "scsi(%ld):Firmware is not capable to support FC " | ||
2024 | "CT pass thru\n", vha->host_no)); | ||
2025 | rval = -EPERM; | ||
2026 | goto done; | ||
2027 | } | ||
2028 | |||
2029 | req_sg_cnt = | ||
2030 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2031 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2032 | if (!req_sg_cnt) { | ||
2033 | rval = -ENOMEM; | ||
2034 | goto done; | ||
2035 | } | ||
2036 | |||
2037 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2038 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2039 | if (!rsp_sg_cnt) { | ||
2040 | rval = -ENOMEM; | ||
2041 | goto done; | ||
2042 | } | ||
2043 | |||
2044 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
2045 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
2046 | { | ||
2047 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2048 | "dma mapping resulted in different sg counts \ | ||
2049 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
2050 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
2051 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
2052 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt)); | ||
2053 | rval = -EAGAIN; | ||
2054 | goto done_unmap_sg; | ||
2055 | } | ||
2056 | |||
2057 | if (!vha->flags.online) { | ||
2058 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2059 | "host not online\n")); | ||
2060 | rval = -EIO; | ||
2061 | goto done_unmap_sg; | ||
2062 | } | ||
2063 | |||
2064 | loop_id = | ||
2065 | (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000) | ||
2066 | >> 24; | ||
2067 | switch (loop_id) { | ||
2068 | case 0xFC: | ||
2069 | loop_id = cpu_to_le16(NPH_SNS); | ||
2070 | break; | ||
2071 | case 0xFA: | ||
2072 | loop_id = vha->mgmt_svr_loop_id; | ||
2073 | break; | ||
2074 | default: | ||
2075 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2076 | "Unknown loop id: %x\n", loop_id)); | ||
2077 | rval = -EINVAL; | ||
2078 | goto done_unmap_sg; | ||
2079 | } | ||
2080 | |||
2081 | /* Allocate a dummy fcport structure, since functions preparing the | ||
2082 | * IOCB and mailbox command retrieves port specific information | ||
2083 | * from fcport structure. For Host based ELS commands there will be | ||
2084 | * no fcport structure allocated | ||
2085 | */ | ||
2086 | fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); | ||
2087 | if (!fcport) | ||
2088 | { | ||
2089 | rval = -ENOMEM; | ||
2090 | goto done_unmap_sg; | ||
2091 | } | ||
2092 | |||
2093 | /* Initialize all required fields of fcport */ | ||
2094 | fcport->vha = vha; | ||
2095 | fcport->vp_idx = vha->vp_idx; | ||
2096 | fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0]; | ||
2097 | fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1]; | ||
2098 | fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2]; | ||
2099 | fcport->loop_id = loop_id; | ||
2100 | |||
2101 | /* Alloc SRB structure */ | ||
2102 | sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_bsg)); | ||
2103 | if (!sp) { | ||
2104 | rval = -ENOMEM; | ||
2105 | goto done_free_fcport; | ||
2106 | } | ||
2107 | |||
2108 | ct = sp->ctx; | ||
2109 | ct->ctx.type = SRB_CT_CMD; | ||
2110 | ct->bsg_job = bsg_job; | ||
2111 | |||
2112 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2113 | "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x " | ||
2114 | "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type, | ||
2115 | (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16), | ||
2116 | fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, | ||
2117 | fcport->d_id.b.al_pa)); | ||
2118 | |||
2119 | rval = qla2x00_start_sp(sp); | ||
2120 | if (rval != QLA_SUCCESS) { | ||
2121 | kfree(sp->ctx); | ||
2122 | mempool_free(sp, ha->srb_mempool); | ||
2123 | rval = -EIO; | ||
2124 | goto done_free_fcport; | ||
2125 | } | ||
2126 | return rval; | ||
2127 | |||
2128 | done_free_fcport: | ||
2129 | kfree(fcport); | ||
2130 | done_unmap_sg: | ||
2131 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2132 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2133 | dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2134 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2135 | done: | ||
2136 | return rval; | ||
2137 | } | ||
2138 | |||
2139 | static int | ||
2140 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | ||
2141 | { | ||
2142 | struct Scsi_Host *host = bsg_job->shost; | ||
2143 | scsi_qla_host_t *vha = shost_priv(host); | ||
2144 | struct qla_hw_data *ha = vha->hw; | ||
2145 | int rval; | ||
2146 | uint8_t command_sent; | ||
2147 | uint32_t vendor_cmd; | ||
2148 | char *type; | ||
2149 | struct msg_echo_lb elreq; | ||
2150 | uint16_t response[MAILBOX_REGISTER_COUNT]; | ||
2151 | uint8_t* fw_sts_ptr; | ||
2152 | uint8_t *req_data; | ||
2153 | dma_addr_t req_data_dma; | ||
2154 | uint32_t req_data_len; | ||
2155 | uint8_t *rsp_data; | ||
2156 | dma_addr_t rsp_data_dma; | ||
2157 | uint32_t rsp_data_len; | ||
2158 | |||
2159 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
2160 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
2161 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | ||
2162 | rval = -EBUSY; | ||
2163 | goto done; | ||
2164 | } | ||
2165 | |||
2166 | if (!vha->flags.online) { | ||
2167 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2168 | "host not online\n")); | ||
2169 | rval = -EIO; | ||
2170 | goto done; | ||
2171 | } | ||
2172 | |||
2173 | elreq.req_sg_cnt = | ||
2174 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | ||
2175 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2176 | if (!elreq.req_sg_cnt) { | ||
2177 | rval = -ENOMEM; | ||
2178 | goto done; | ||
2179 | } | ||
2180 | elreq.rsp_sg_cnt = | ||
2181 | dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list, | ||
2182 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2183 | if (!elreq.rsp_sg_cnt) { | ||
2184 | rval = -ENOMEM; | ||
2185 | goto done; | ||
2186 | } | ||
2187 | |||
2188 | if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
2189 | (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) | ||
2190 | { | ||
2191 | DEBUG2(printk(KERN_INFO | ||
2192 | "dma mapping resulted in different sg counts \ | ||
2193 | [request_sg_cnt: %x dma_request_sg_cnt: %x\ | ||
2194 | reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n", | ||
2195 | bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt, | ||
2196 | bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt)); | ||
2197 | rval = -EAGAIN; | ||
2198 | goto done_unmap_sg; | ||
2199 | } | ||
2200 | req_data_len = rsp_data_len = bsg_job->request_payload.payload_len; | ||
2201 | req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len, | ||
2202 | &req_data_dma, GFP_KERNEL); | ||
2203 | |||
2204 | rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len, | ||
2205 | &rsp_data_dma, GFP_KERNEL); | ||
2206 | |||
2207 | /* Copy the request buffer in req_data now */ | ||
2208 | sg_copy_to_buffer(bsg_job->request_payload.sg_list, | ||
2209 | bsg_job->request_payload.sg_cnt, req_data, | ||
2210 | req_data_len); | ||
2211 | |||
2212 | elreq.send_dma = req_data_dma; | ||
2213 | elreq.rcv_dma = rsp_data_dma; | ||
2214 | elreq.transfer_size = req_data_len; | ||
2215 | |||
2216 | /* Vendor cmd : loopback or ECHO diagnostic | ||
2217 | * Options: | ||
2218 | * Loopback : Either internal or external loopback | ||
2219 | * ECHO: ECHO ELS or Vendor specific FC4 link data | ||
2220 | */ | ||
2221 | vendor_cmd = bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]; | ||
2222 | elreq.options = | ||
2223 | *(((uint32_t *)bsg_job->request->rqst_data.h_vendor.vendor_cmd) | ||
2224 | + 1); | ||
2225 | |||
2226 | switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { | ||
2227 | case QL_VND_LOOPBACK: | ||
2228 | if (ha->current_topology != ISP_CFG_F) { | ||
2229 | type = "FC_BSG_HST_VENDOR_LOOPBACK"; | ||
2230 | |||
2231 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2232 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", | ||
2233 | vha->host_no, type, vendor_cmd, elreq.options)); | ||
2234 | |||
2235 | command_sent = INT_DEF_LB_LOOPBACK_CMD; | ||
2236 | rval = qla2x00_loopback_test(vha, &elreq, response); | ||
2237 | if (IS_QLA81XX(ha)) { | ||
2238 | if (response[0] == MBS_COMMAND_ERROR && response[1] == MBS_LB_RESET) { | ||
2239 | DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing " | ||
2240 | "ISP\n", __func__, vha->host_no)); | ||
2241 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
2242 | qla2xxx_wake_dpc(vha); | ||
2243 | } | ||
2244 | } | ||
2245 | } else { | ||
2246 | type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; | ||
2247 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2248 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", | ||
2249 | vha->host_no, type, vendor_cmd, elreq.options)); | ||
2250 | |||
2251 | command_sent = INT_DEF_LB_ECHO_CMD; | ||
2252 | rval = qla2x00_echo_test(vha, &elreq, response); | ||
2253 | } | ||
2254 | break; | ||
2255 | case QLA84_RESET: | ||
2256 | if (!IS_QLA84XX(vha->hw)) { | ||
2257 | rval = -EINVAL; | ||
2258 | DEBUG16(printk( | ||
2259 | "%s(%ld): 8xxx exiting.\n", | ||
2260 | __func__, vha->host_no)); | ||
2261 | return rval; | ||
2262 | } | ||
2263 | rval = qla84xx_reset(vha, &elreq, bsg_job); | ||
2264 | break; | ||
2265 | case QLA84_MGMT_CMD: | ||
2266 | if (!IS_QLA84XX(vha->hw)) { | ||
2267 | rval = -EINVAL; | ||
2268 | DEBUG16(printk( | ||
2269 | "%s(%ld): 8xxx exiting.\n", | ||
2270 | __func__, vha->host_no)); | ||
2271 | return rval; | ||
2272 | } | ||
2273 | rval = qla84xx_mgmt_cmd(vha, &elreq, bsg_job); | ||
2274 | break; | ||
2275 | default: | ||
2276 | rval = -ENOSYS; | ||
2277 | } | ||
2278 | |||
2279 | if (rval != QLA_SUCCESS) { | ||
2280 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2281 | "scsi(%ld) Vendor request %s failed\n", vha->host_no, type)); | ||
2282 | rval = 0; | ||
2283 | bsg_job->reply->result = (DID_ERROR << 16); | ||
2284 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
2285 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
2286 | memcpy( fw_sts_ptr, response, sizeof(response)); | ||
2287 | fw_sts_ptr += sizeof(response); | ||
2288 | *fw_sts_ptr = command_sent; | ||
2289 | } else { | ||
2290 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2291 | "scsi(%ld) Vendor request %s completed\n", vha->host_no, type)); | ||
2292 | rval = bsg_job->reply->result = 0; | ||
2293 | bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(response) + sizeof(uint8_t); | ||
2294 | bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; | ||
2295 | fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply); | ||
2296 | memcpy(fw_sts_ptr, response, sizeof(response)); | ||
2297 | fw_sts_ptr += sizeof(response); | ||
2298 | *fw_sts_ptr = command_sent; | ||
2299 | sg_copy_from_buffer(bsg_job->reply_payload.sg_list, | ||
2300 | bsg_job->reply_payload.sg_cnt, rsp_data, | ||
2301 | rsp_data_len); | ||
2302 | } | ||
2303 | bsg_job->job_done(bsg_job); | ||
2304 | |||
2305 | done_unmap_sg: | ||
2306 | |||
2307 | if(req_data) | ||
2308 | dma_free_coherent(&ha->pdev->dev, req_data_len, | ||
2309 | req_data, req_data_dma); | ||
2310 | dma_unmap_sg(&ha->pdev->dev, | ||
2311 | bsg_job->request_payload.sg_list, | ||
2312 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
2313 | dma_unmap_sg(&ha->pdev->dev, | ||
2314 | bsg_job->reply_payload.sg_list, | ||
2315 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
2316 | |||
2317 | done: | ||
2318 | return rval; | ||
2319 | } | ||
2320 | |||
2321 | static int | ||
2322 | qla24xx_bsg_request(struct fc_bsg_job *bsg_job) | ||
2323 | { | ||
2324 | int ret = -EINVAL; | ||
2325 | |||
2326 | switch (bsg_job->request->msgcode) { | ||
2327 | case FC_BSG_RPT_ELS: | ||
2328 | case FC_BSG_HST_ELS_NOLOGIN: | ||
2329 | ret = qla2x00_process_els(bsg_job); | ||
2330 | break; | ||
2331 | case FC_BSG_HST_CT: | ||
2332 | ret = qla2x00_process_ct(bsg_job); | ||
2333 | break; | ||
2334 | case FC_BSG_HST_VENDOR: | ||
2335 | ret = qla2x00_process_vendor_specific(bsg_job); | ||
2336 | break; | ||
2337 | case FC_BSG_HST_ADD_RPORT: | ||
2338 | case FC_BSG_HST_DEL_RPORT: | ||
2339 | case FC_BSG_RPT_CT: | ||
2340 | default: | ||
2341 | DEBUG2(printk("qla2xxx: unsupported BSG request\n")); | ||
2342 | break; | ||
2343 | } | ||
2344 | return ret; | ||
2345 | } | ||
2346 | |||
2347 | static int | ||
2348 | qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) | ||
2349 | { | ||
2350 | scsi_qla_host_t *vha = shost_priv(bsg_job->shost); | ||
2351 | struct qla_hw_data *ha = vha->hw; | ||
2352 | srb_t *sp; | ||
2353 | int cnt, que; | ||
2354 | unsigned long flags; | ||
2355 | struct req_que *req; | ||
2356 | struct srb_bsg *sp_bsg; | ||
2357 | |||
2358 | /* find the bsg job from the active list of commands */ | ||
2359 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2360 | for (que = 0; que < ha->max_req_queues; que++) { | ||
2361 | req = ha->req_q_map[que]; | ||
2362 | if (!req) | ||
2363 | continue; | ||
2364 | |||
2365 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++ ) { | ||
2366 | sp = req->outstanding_cmds[cnt]; | ||
2367 | |||
2368 | if (sp) { | ||
2369 | sp_bsg = (struct srb_bsg*)sp->ctx; | ||
2370 | |||
2371 | if (((sp_bsg->ctx.type == SRB_CT_CMD) || | ||
2372 | (sp_bsg->ctx.type == SRB_ELS_CMD_RPT) | ||
2373 | || ( sp_bsg->ctx.type == SRB_ELS_CMD_HST)) && | ||
2374 | (sp_bsg->bsg_job == bsg_job)) { | ||
2375 | if (ha->isp_ops->abort_command(sp)) { | ||
2376 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2377 | "scsi(%ld): mbx abort_command failed\n", vha->host_no)); | ||
2378 | bsg_job->req->errors = bsg_job->reply->result = -EIO; | ||
2379 | } else { | ||
2380 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2381 | "scsi(%ld): mbx abort_command success\n", vha->host_no)); | ||
2382 | bsg_job->req->errors = bsg_job->reply->result = 0; | ||
2383 | } | ||
2384 | goto done; | ||
2385 | } | ||
2386 | } | ||
2387 | } | ||
2388 | } | ||
2389 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2390 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2391 | "scsi(%ld) SRB not found to abort\n", vha->host_no)); | ||
2392 | bsg_job->req->errors = bsg_job->reply->result = -ENXIO; | ||
2393 | return 0; | ||
2394 | |||
2395 | done: | ||
2396 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2397 | if (bsg_job->request->msgcode == FC_BSG_HST_CT) | ||
2398 | kfree(sp->fcport); | ||
2399 | kfree(sp->ctx); | ||
2400 | mempool_free(sp, ha->srb_mempool); | ||
2401 | return 0; | ||
2402 | } | ||
2403 | |||
1775 | struct fc_function_template qla2xxx_transport_functions = { | 2404 | struct fc_function_template qla2xxx_transport_functions = { |
1776 | 2405 | ||
1777 | .show_host_node_name = 1, | 2406 | .show_host_node_name = 1, |
@@ -1815,6 +2444,8 @@ struct fc_function_template qla2xxx_transport_functions = { | |||
1815 | .vport_create = qla24xx_vport_create, | 2444 | .vport_create = qla24xx_vport_create, |
1816 | .vport_disable = qla24xx_vport_disable, | 2445 | .vport_disable = qla24xx_vport_disable, |
1817 | .vport_delete = qla24xx_vport_delete, | 2446 | .vport_delete = qla24xx_vport_delete, |
2447 | .bsg_request = qla24xx_bsg_request, | ||
2448 | .bsg_timeout = qla24xx_bsg_timeout, | ||
1818 | }; | 2449 | }; |
1819 | 2450 | ||
1820 | struct fc_function_template qla2xxx_transport_vport_functions = { | 2451 | struct fc_function_template qla2xxx_transport_vport_functions = { |
@@ -1855,6 +2486,8 @@ struct fc_function_template qla2xxx_transport_vport_functions = { | |||
1855 | .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, | 2486 | .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, |
1856 | .terminate_rport_io = qla2x00_terminate_rport_io, | 2487 | .terminate_rport_io = qla2x00_terminate_rport_io, |
1857 | .get_fc_host_stats = qla2x00_get_fc_host_stats, | 2488 | .get_fc_host_stats = qla2x00_get_fc_host_stats, |
2489 | .bsg_request = qla24xx_bsg_request, | ||
2490 | .bsg_timeout = qla24xx_bsg_timeout, | ||
1858 | }; | 2491 | }; |
1859 | 2492 | ||
1860 | void | 2493 | void |
@@ -1883,3 +2516,125 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) | |||
1883 | speed = FC_PORTSPEED_1GBIT; | 2516 | speed = FC_PORTSPEED_1GBIT; |
1884 | fc_host_supported_speeds(vha->host) = speed; | 2517 | fc_host_supported_speeds(vha->host) = speed; |
1885 | } | 2518 | } |
2519 | static int | ||
2520 | qla84xx_reset(scsi_qla_host_t *ha, struct msg_echo_lb *mreq, struct fc_bsg_job *bsg_job) | ||
2521 | { | ||
2522 | int ret = 0; | ||
2523 | int cmd; | ||
2524 | uint16_t cmd_status; | ||
2525 | |||
2526 | DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2527 | |||
2528 | cmd = (*((bsg_job->request->rqst_data.h_vendor.vendor_cmd) + 2)) | ||
2529 | == A84_RESET_FLAG_ENABLE_DIAG_FW ? | ||
2530 | A84_ISSUE_RESET_DIAG_FW : A84_ISSUE_RESET_OP_FW; | ||
2531 | ret = qla84xx_reset_chip(ha, cmd == A84_ISSUE_RESET_DIAG_FW, | ||
2532 | &cmd_status); | ||
2533 | return ret; | ||
2534 | } | ||
2535 | |||
2536 | static int | ||
2537 | qla84xx_mgmt_cmd(scsi_qla_host_t *ha, struct msg_echo_lb *mreq, struct fc_bsg_job *bsg_job) | ||
2538 | { | ||
2539 | struct access_chip_84xx *mn; | ||
2540 | dma_addr_t mn_dma, mgmt_dma; | ||
2541 | void *mgmt_b = NULL; | ||
2542 | int ret = 0; | ||
2543 | int rsp_hdr_len, len = 0; | ||
2544 | struct qla84_msg_mgmt *ql84_mgmt; | ||
2545 | |||
2546 | ql84_mgmt = (struct qla84_msg_mgmt *) vmalloc(sizeof(struct qla84_msg_mgmt)); | ||
2547 | ql84_mgmt->cmd = | ||
2548 | *((uint16_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 2)); | ||
2549 | ql84_mgmt->mgmtp.u.mem.start_addr = | ||
2550 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 3)); | ||
2551 | ql84_mgmt->len = | ||
2552 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 4)); | ||
2553 | ql84_mgmt->mgmtp.u.config.id = | ||
2554 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 5)); | ||
2555 | ql84_mgmt->mgmtp.u.config.param0 = | ||
2556 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 6)); | ||
2557 | ql84_mgmt->mgmtp.u.config.param1 = | ||
2558 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 7)); | ||
2559 | ql84_mgmt->mgmtp.u.info.type = | ||
2560 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 8)); | ||
2561 | ql84_mgmt->mgmtp.u.info.context = | ||
2562 | *((uint32_t *)(bsg_job->request->rqst_data.h_vendor.vendor_cmd + 9)); | ||
2563 | |||
2564 | rsp_hdr_len = bsg_job->request_payload.payload_len; | ||
2565 | |||
2566 | mn = dma_pool_alloc(ha->hw->s_dma_pool, GFP_KERNEL, &mn_dma); | ||
2567 | if (mn == NULL) { | ||
2568 | DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer " | ||
2569 | "failed%lu\n", __func__, ha->host_no)); | ||
2570 | return -ENOMEM; | ||
2571 | } | ||
2572 | |||
2573 | memset(mn, 0, sizeof (struct access_chip_84xx)); | ||
2574 | |||
2575 | mn->entry_type = ACCESS_CHIP_IOCB_TYPE; | ||
2576 | mn->entry_count = 1; | ||
2577 | |||
2578 | switch (ql84_mgmt->cmd) { | ||
2579 | case QLA84_MGMT_READ_MEM: | ||
2580 | mn->options = cpu_to_le16(ACO_DUMP_MEMORY); | ||
2581 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr); | ||
2582 | break; | ||
2583 | case QLA84_MGMT_WRITE_MEM: | ||
2584 | mn->options = cpu_to_le16(ACO_LOAD_MEMORY); | ||
2585 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.mem.start_addr); | ||
2586 | break; | ||
2587 | case QLA84_MGMT_CHNG_CONFIG: | ||
2588 | mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM); | ||
2589 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.id); | ||
2590 | mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param0); | ||
2591 | mn->parameter3 = cpu_to_le32(ql84_mgmt->mgmtp.u.config.param1); | ||
2592 | break; | ||
2593 | case QLA84_MGMT_GET_INFO: | ||
2594 | mn->options = cpu_to_le16(ACO_REQUEST_INFO); | ||
2595 | mn->parameter1 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.type); | ||
2596 | mn->parameter2 = cpu_to_le32(ql84_mgmt->mgmtp.u.info.context); | ||
2597 | break; | ||
2598 | default: | ||
2599 | ret = -EIO; | ||
2600 | goto exit_mgmt0; | ||
2601 | } | ||
2602 | |||
2603 | if ((len == ql84_mgmt->len) && | ||
2604 | ql84_mgmt->cmd != QLA84_MGMT_CHNG_CONFIG) { | ||
2605 | mgmt_b = dma_alloc_coherent(&ha->hw->pdev->dev, len, | ||
2606 | &mgmt_dma, GFP_KERNEL); | ||
2607 | if (mgmt_b == NULL) { | ||
2608 | DEBUG2(printk(KERN_ERR "%s: dma alloc mgmt_b " | ||
2609 | "failed%lu\n", __func__, ha->host_no)); | ||
2610 | ret = -ENOMEM; | ||
2611 | goto exit_mgmt0; | ||
2612 | } | ||
2613 | mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->len); | ||
2614 | mn->dseg_count = cpu_to_le16(1); | ||
2615 | mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma)); | ||
2616 | mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma)); | ||
2617 | mn->dseg_length = cpu_to_le32(len); | ||
2618 | |||
2619 | if (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) { | ||
2620 | memcpy(mgmt_b, ql84_mgmt->payload, len); | ||
2621 | } | ||
2622 | } | ||
2623 | |||
2624 | ret = qla2x00_issue_iocb(ha, mn, mn_dma, 0); | ||
2625 | if ((ret != QLA_SUCCESS) || (ql84_mgmt->cmd == QLA84_MGMT_WRITE_MEM) | ||
2626 | || (ql84_mgmt->cmd == QLA84_MGMT_CHNG_CONFIG)) { | ||
2627 | if (ret != QLA_SUCCESS) | ||
2628 | DEBUG2(printk(KERN_ERR "%s(%lu): failed\n", | ||
2629 | __func__, ha->host_no)); | ||
2630 | } else if ((ql84_mgmt->cmd == QLA84_MGMT_READ_MEM) || | ||
2631 | (ql84_mgmt->cmd == QLA84_MGMT_GET_INFO)) { | ||
2632 | } | ||
2633 | |||
2634 | if (mgmt_b) | ||
2635 | dma_free_coherent(&ha->hw->pdev->dev, len, mgmt_b, mgmt_dma); | ||
2636 | |||
2637 | exit_mgmt0: | ||
2638 | dma_pool_free(ha->hw->s_dma_pool, mn, mn_dma); | ||
2639 | return ret; | ||
2640 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index cca8e4ab0372..cb2eca4c26d8 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -377,6 +377,24 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) | |||
377 | return ptr + sizeof(struct qla2xxx_mq_chain); | 377 | return ptr + sizeof(struct qla2xxx_mq_chain); |
378 | } | 378 | } |
379 | 379 | ||
380 | static void | ||
381 | qla2xxx_dump_post_process(scsi_qla_host_t *vha, int rval) | ||
382 | { | ||
383 | struct qla_hw_data *ha = vha->hw; | ||
384 | |||
385 | if (rval != QLA_SUCCESS) { | ||
386 | qla_printk(KERN_WARNING, ha, | ||
387 | "Failed to dump firmware (%x)!!!\n", rval); | ||
388 | ha->fw_dumped = 0; | ||
389 | } else { | ||
390 | qla_printk(KERN_INFO, ha, | ||
391 | "Firmware dump saved to temp buffer (%ld/%p).\n", | ||
392 | vha->host_no, ha->fw_dump); | ||
393 | ha->fw_dumped = 1; | ||
394 | qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP); | ||
395 | } | ||
396 | } | ||
397 | |||
380 | /** | 398 | /** |
381 | * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. | 399 | * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. |
382 | * @ha: HA context | 400 | * @ha: HA context |
@@ -530,17 +548,7 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
530 | if (rval == QLA_SUCCESS) | 548 | if (rval == QLA_SUCCESS) |
531 | qla2xxx_copy_queues(ha, nxt); | 549 | qla2xxx_copy_queues(ha, nxt); |
532 | 550 | ||
533 | if (rval != QLA_SUCCESS) { | 551 | qla2xxx_dump_post_process(base_vha, rval); |
534 | qla_printk(KERN_WARNING, ha, | ||
535 | "Failed to dump firmware (%x)!!!\n", rval); | ||
536 | ha->fw_dumped = 0; | ||
537 | |||
538 | } else { | ||
539 | qla_printk(KERN_INFO, ha, | ||
540 | "Firmware dump saved to temp buffer (%ld/%p).\n", | ||
541 | base_vha->host_no, ha->fw_dump); | ||
542 | ha->fw_dumped = 1; | ||
543 | } | ||
544 | 552 | ||
545 | qla2300_fw_dump_failed: | 553 | qla2300_fw_dump_failed: |
546 | if (!hardware_locked) | 554 | if (!hardware_locked) |
@@ -737,17 +745,7 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
737 | if (rval == QLA_SUCCESS) | 745 | if (rval == QLA_SUCCESS) |
738 | qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]); | 746 | qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]); |
739 | 747 | ||
740 | if (rval != QLA_SUCCESS) { | 748 | qla2xxx_dump_post_process(base_vha, rval); |
741 | qla_printk(KERN_WARNING, ha, | ||
742 | "Failed to dump firmware (%x)!!!\n", rval); | ||
743 | ha->fw_dumped = 0; | ||
744 | |||
745 | } else { | ||
746 | qla_printk(KERN_INFO, ha, | ||
747 | "Firmware dump saved to temp buffer (%ld/%p).\n", | ||
748 | base_vha->host_no, ha->fw_dump); | ||
749 | ha->fw_dumped = 1; | ||
750 | } | ||
751 | 749 | ||
752 | qla2100_fw_dump_failed: | 750 | qla2100_fw_dump_failed: |
753 | if (!hardware_locked) | 751 | if (!hardware_locked) |
@@ -984,17 +982,7 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
984 | qla24xx_copy_eft(ha, nxt); | 982 | qla24xx_copy_eft(ha, nxt); |
985 | 983 | ||
986 | qla24xx_fw_dump_failed_0: | 984 | qla24xx_fw_dump_failed_0: |
987 | if (rval != QLA_SUCCESS) { | 985 | qla2xxx_dump_post_process(base_vha, rval); |
988 | qla_printk(KERN_WARNING, ha, | ||
989 | "Failed to dump firmware (%x)!!!\n", rval); | ||
990 | ha->fw_dumped = 0; | ||
991 | |||
992 | } else { | ||
993 | qla_printk(KERN_INFO, ha, | ||
994 | "Firmware dump saved to temp buffer (%ld/%p).\n", | ||
995 | base_vha->host_no, ha->fw_dump); | ||
996 | ha->fw_dumped = 1; | ||
997 | } | ||
998 | 986 | ||
999 | qla24xx_fw_dump_failed: | 987 | qla24xx_fw_dump_failed: |
1000 | if (!hardware_locked) | 988 | if (!hardware_locked) |
@@ -1305,17 +1293,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
1305 | } | 1293 | } |
1306 | 1294 | ||
1307 | qla25xx_fw_dump_failed_0: | 1295 | qla25xx_fw_dump_failed_0: |
1308 | if (rval != QLA_SUCCESS) { | 1296 | qla2xxx_dump_post_process(base_vha, rval); |
1309 | qla_printk(KERN_WARNING, ha, | ||
1310 | "Failed to dump firmware (%x)!!!\n", rval); | ||
1311 | ha->fw_dumped = 0; | ||
1312 | |||
1313 | } else { | ||
1314 | qla_printk(KERN_INFO, ha, | ||
1315 | "Firmware dump saved to temp buffer (%ld/%p).\n", | ||
1316 | base_vha->host_no, ha->fw_dump); | ||
1317 | ha->fw_dumped = 1; | ||
1318 | } | ||
1319 | 1297 | ||
1320 | qla25xx_fw_dump_failed: | 1298 | qla25xx_fw_dump_failed: |
1321 | if (!hardware_locked) | 1299 | if (!hardware_locked) |
@@ -1628,17 +1606,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
1628 | } | 1606 | } |
1629 | 1607 | ||
1630 | qla81xx_fw_dump_failed_0: | 1608 | qla81xx_fw_dump_failed_0: |
1631 | if (rval != QLA_SUCCESS) { | 1609 | qla2xxx_dump_post_process(base_vha, rval); |
1632 | qla_printk(KERN_WARNING, ha, | ||
1633 | "Failed to dump firmware (%x)!!!\n", rval); | ||
1634 | ha->fw_dumped = 0; | ||
1635 | |||
1636 | } else { | ||
1637 | qla_printk(KERN_INFO, ha, | ||
1638 | "Firmware dump saved to temp buffer (%ld/%p).\n", | ||
1639 | base_vha->host_no, ha->fw_dump); | ||
1640 | ha->fw_dumped = 1; | ||
1641 | } | ||
1642 | 1610 | ||
1643 | qla81xx_fw_dump_failed: | 1611 | qla81xx_fw_dump_failed: |
1644 | if (!hardware_locked) | 1612 | if (!hardware_locked) |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index f660dd70b72e..d6d9c86cb058 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
@@ -26,7 +26,7 @@ | |||
26 | /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */ | 26 | /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */ |
27 | /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */ | 27 | /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */ |
28 | /* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */ | 28 | /* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */ |
29 | /* #define QL_DEBUG_LEVEL_17 */ /* Output MULTI-Q trace messages */ | 29 | /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * Macros use for debugging the driver. | 32 | * Macros use for debugging the driver. |
@@ -132,6 +132,13 @@ | |||
132 | #else | 132 | #else |
133 | #define DEBUG16(x) do {} while (0) | 133 | #define DEBUG16(x) do {} while (0) |
134 | #endif | 134 | #endif |
135 | |||
136 | #if defined(QL_DEBUG_LEVEL_17) | ||
137 | #define DEBUG17(x) do {x;} while (0) | ||
138 | #else | ||
139 | #define DEBUG17(x) do {} while (0) | ||
140 | #endif | ||
141 | |||
135 | /* | 142 | /* |
136 | * Firmware Dump structure definition | 143 | * Firmware Dump structure definition |
137 | */ | 144 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 215061861794..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 | */ |
@@ -1570,9 +1594,6 @@ typedef struct fc_port { | |||
1570 | struct fc_rport *rport, *drport; | 1594 | struct fc_rport *rport, *drport; |
1571 | u32 supported_classes; | 1595 | u32 supported_classes; |
1572 | 1596 | ||
1573 | unsigned long last_queue_full; | ||
1574 | unsigned long last_ramp_up; | ||
1575 | |||
1576 | uint16_t vp_idx; | 1597 | uint16_t vp_idx; |
1577 | } fc_port_t; | 1598 | } fc_port_t; |
1578 | 1599 | ||
@@ -1589,8 +1610,7 @@ typedef struct fc_port { | |||
1589 | */ | 1610 | */ |
1590 | #define FCF_FABRIC_DEVICE BIT_0 | 1611 | #define FCF_FABRIC_DEVICE BIT_0 |
1591 | #define FCF_LOGIN_NEEDED BIT_1 | 1612 | #define FCF_LOGIN_NEEDED BIT_1 |
1592 | #define FCF_TAPE_PRESENT BIT_2 | 1613 | #define FCF_FCP2_DEVICE BIT_2 |
1593 | #define FCF_FCP2_DEVICE BIT_3 | ||
1594 | 1614 | ||
1595 | /* No loop ID flag. */ | 1615 | /* No loop ID flag. */ |
1596 | #define FC_NO_LOOP_ID 0x1000 | 1616 | #define FC_NO_LOOP_ID 0x1000 |
@@ -2123,6 +2143,7 @@ enum qla_work_type { | |||
2123 | QLA_EVT_ASYNC_LOGIN_DONE, | 2143 | QLA_EVT_ASYNC_LOGIN_DONE, |
2124 | QLA_EVT_ASYNC_LOGOUT, | 2144 | QLA_EVT_ASYNC_LOGOUT, |
2125 | QLA_EVT_ASYNC_LOGOUT_DONE, | 2145 | QLA_EVT_ASYNC_LOGOUT_DONE, |
2146 | QLA_EVT_UEVENT, | ||
2126 | }; | 2147 | }; |
2127 | 2148 | ||
2128 | 2149 | ||
@@ -2146,6 +2167,10 @@ struct qla_work_evt { | |||
2146 | #define QLA_LOGIO_LOGIN_RETRIED BIT_0 | 2167 | #define QLA_LOGIO_LOGIN_RETRIED BIT_0 |
2147 | u16 data[2]; | 2168 | u16 data[2]; |
2148 | } logio; | 2169 | } logio; |
2170 | struct { | ||
2171 | u32 code; | ||
2172 | #define QLA_UEVENT_CODE_FW_DUMP 0 | ||
2173 | } uevent; | ||
2149 | } u; | 2174 | } u; |
2150 | }; | 2175 | }; |
2151 | 2176 | ||
@@ -2229,6 +2254,13 @@ struct req_que { | |||
2229 | int max_q_depth; | 2254 | int max_q_depth; |
2230 | }; | 2255 | }; |
2231 | 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 | |||
2232 | /* | 2264 | /* |
2233 | * Qlogic host adapter specific data structure. | 2265 | * Qlogic host adapter specific data structure. |
2234 | */ | 2266 | */ |
@@ -2254,12 +2286,15 @@ struct qla_hw_data { | |||
2254 | uint32_t disable_serdes :1; | 2286 | uint32_t disable_serdes :1; |
2255 | uint32_t gpsc_supported :1; | 2287 | uint32_t gpsc_supported :1; |
2256 | uint32_t npiv_supported :1; | 2288 | uint32_t npiv_supported :1; |
2289 | uint32_t pci_channel_io_perm_failure :1; | ||
2257 | uint32_t fce_enabled :1; | 2290 | uint32_t fce_enabled :1; |
2258 | uint32_t fac_supported :1; | 2291 | uint32_t fac_supported :1; |
2259 | uint32_t chip_reset_done :1; | 2292 | uint32_t chip_reset_done :1; |
2260 | uint32_t port0 :1; | 2293 | uint32_t port0 :1; |
2261 | uint32_t running_gold_fw :1; | 2294 | uint32_t running_gold_fw :1; |
2295 | uint32_t eeh_busy :1; | ||
2262 | uint32_t cpu_affinity_enabled :1; | 2296 | uint32_t cpu_affinity_enabled :1; |
2297 | uint32_t disable_msix_handshake :1; | ||
2263 | } flags; | 2298 | } flags; |
2264 | 2299 | ||
2265 | /* This spinlock is used to protect "io transactions", you must | 2300 | /* This spinlock is used to protect "io transactions", you must |
@@ -2382,6 +2417,7 @@ struct qla_hw_data { | |||
2382 | #define IS_QLA81XX(ha) (IS_QLA8001(ha)) | 2417 | #define IS_QLA81XX(ha) (IS_QLA8001(ha)) |
2383 | #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \ | 2418 | #define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \ |
2384 | IS_QLA25XX(ha) || IS_QLA81XX(ha)) | 2419 | IS_QLA25XX(ha) || IS_QLA81XX(ha)) |
2420 | #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha)) | ||
2385 | #define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \ | 2421 | #define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \ |
2386 | (ha)->flags.msix_enabled) | 2422 | (ha)->flags.msix_enabled) |
2387 | #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha)) | 2423 | #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha)) |
@@ -2435,11 +2471,11 @@ struct qla_hw_data { | |||
2435 | dma_addr_t edc_data_dma; | 2471 | dma_addr_t edc_data_dma; |
2436 | uint16_t edc_data_len; | 2472 | uint16_t edc_data_len; |
2437 | 2473 | ||
2438 | #define XGMAC_DATA_SIZE PAGE_SIZE | 2474 | #define XGMAC_DATA_SIZE 4096 |
2439 | void *xgmac_data; | 2475 | void *xgmac_data; |
2440 | dma_addr_t xgmac_data_dma; | 2476 | dma_addr_t xgmac_data_dma; |
2441 | 2477 | ||
2442 | #define DCBX_TLV_DATA_SIZE PAGE_SIZE | 2478 | #define DCBX_TLV_DATA_SIZE 4096 |
2443 | void *dcbx_tlv; | 2479 | void *dcbx_tlv; |
2444 | dma_addr_t dcbx_tlv_dma; | 2480 | dma_addr_t dcbx_tlv_dma; |
2445 | 2481 | ||
@@ -2589,6 +2625,7 @@ struct qla_hw_data { | |||
2589 | struct qla_statistics qla_stats; | 2625 | struct qla_statistics qla_stats; |
2590 | struct isp_operations *isp_ops; | 2626 | struct isp_operations *isp_ops; |
2591 | struct workqueue_struct *wq; | 2627 | struct workqueue_struct *wq; |
2628 | struct qlfc_fw fw_buf; | ||
2592 | }; | 2629 | }; |
2593 | 2630 | ||
2594 | /* | 2631 | /* |
@@ -2761,4 +2798,127 @@ typedef struct scsi_qla_host { | |||
2761 | 2798 | ||
2762 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) | 2799 | #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) |
2763 | 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 | |||
2764 | #endif | 2924 | #endif |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 66a8da5d7d08..42c5587cc50c 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 | */ |
@@ -1559,10 +1592,22 @@ struct nvram_81xx { | |||
1559 | 1592 | ||
1560 | /* Offset 384. */ | 1593 | /* Offset 384. */ |
1561 | uint8_t reserved_21[16]; | 1594 | uint8_t reserved_21[16]; |
1562 | uint16_t reserved_22[8]; | 1595 | uint16_t reserved_22[3]; |
1596 | |||
1597 | /* | ||
1598 | * BIT 0 = Extended BB credits for LR | ||
1599 | * BIT 1 = Virtual Fabric Enable | ||
1600 | * BIT 2 = Enhanced Features Unused | ||
1601 | * BIT 3-7 = Enhanced Features Reserved | ||
1602 | */ | ||
1603 | /* Enhanced Features */ | ||
1604 | uint8_t enhanced_features; | ||
1605 | |||
1606 | uint8_t reserved_23; | ||
1607 | uint16_t reserved_24[4]; | ||
1563 | 1608 | ||
1564 | /* Offset 416. */ | 1609 | /* Offset 416. */ |
1565 | uint16_t reserved_23[32]; | 1610 | uint16_t reserved_25[32]; |
1566 | 1611 | ||
1567 | /* Offset 480. */ | 1612 | /* Offset 480. */ |
1568 | uint8_t model_name[16]; | 1613 | uint8_t model_name[16]; |
@@ -1570,7 +1615,7 @@ struct nvram_81xx { | |||
1570 | /* Offset 496. */ | 1615 | /* Offset 496. */ |
1571 | uint16_t feature_mask_l; | 1616 | uint16_t feature_mask_l; |
1572 | uint16_t feature_mask_h; | 1617 | uint16_t feature_mask_h; |
1573 | uint16_t reserved_24[2]; | 1618 | uint16_t reserved_26[2]; |
1574 | 1619 | ||
1575 | uint16_t subsystem_vendor_id; | 1620 | uint16_t subsystem_vendor_id; |
1576 | uint16_t subsystem_device_id; | 1621 | uint16_t subsystem_device_id; |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f3d1d1afa95b..3a89bc514e2b 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 | */ |
@@ -72,12 +74,11 @@ extern int ql2xloginretrycount; | |||
72 | extern int ql2xfdmienable; | 74 | extern int ql2xfdmienable; |
73 | extern int ql2xallocfwdump; | 75 | extern int ql2xallocfwdump; |
74 | extern int ql2xextended_error_logging; | 76 | extern int ql2xextended_error_logging; |
75 | extern int ql2xqfullrampup; | ||
76 | extern int ql2xqfulltracking; | ||
77 | extern int ql2xiidmaenable; | 77 | extern int ql2xiidmaenable; |
78 | extern int ql2xmaxqueues; | 78 | extern int ql2xmaxqueues; |
79 | extern int ql2xmultique_tag; | 79 | extern int ql2xmultique_tag; |
80 | extern int ql2xfwloadbin; | 80 | extern int ql2xfwloadbin; |
81 | extern int ql2xetsenable; | ||
81 | 82 | ||
82 | extern int qla2x00_loop_reset(scsi_qla_host_t *); | 83 | extern int qla2x00_loop_reset(scsi_qla_host_t *); |
83 | extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); | 84 | extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); |
@@ -92,10 +93,10 @@ extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *, | |||
92 | uint16_t *); | 93 | uint16_t *); |
93 | extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *, | 94 | extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *, |
94 | fc_port_t *, uint16_t *); | 95 | fc_port_t *, uint16_t *); |
96 | extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); | ||
95 | 97 | ||
96 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); | 98 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); |
97 | 99 | ||
98 | extern void qla2x00_abort_fcport_cmds(fc_port_t *); | ||
99 | extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *, | 100 | extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *, |
100 | struct qla_hw_data *); | 101 | struct qla_hw_data *); |
101 | extern void qla2x00_free_host(struct scsi_qla_host *); | 102 | extern void qla2x00_free_host(struct scsi_qla_host *); |
@@ -155,6 +156,7 @@ int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, | |||
155 | 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 *, |
156 | uint16_t, uint16_t, uint8_t); | 157 | uint16_t, uint16_t, uint8_t); |
157 | extern int qla2x00_start_sp(srb_t *); | 158 | extern int qla2x00_start_sp(srb_t *); |
159 | extern void qla2x00_ctx_sp_free(srb_t *); | ||
158 | 160 | ||
159 | /* | 161 | /* |
160 | * Global Function Prototypes in qla_mbx.c source file. | 162 | * Global Function Prototypes in qla_mbx.c source file. |
@@ -246,7 +248,7 @@ qla2x00_get_id_list(scsi_qla_host_t *, void *, dma_addr_t, uint16_t *); | |||
246 | 248 | ||
247 | extern int | 249 | extern int |
248 | qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, | 250 | qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, |
249 | uint16_t *, uint16_t *, uint16_t *); | 251 | uint16_t *, uint16_t *, uint16_t *, uint16_t *); |
250 | 252 | ||
251 | extern int | 253 | extern int |
252 | qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); | 254 | qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); |
@@ -325,6 +327,7 @@ qla2x00_read_ram_word(scsi_qla_host_t *, uint32_t, uint32_t *); | |||
325 | extern int | 327 | extern int |
326 | qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); | 328 | qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); |
327 | 329 | ||
330 | extern int qla2x00_get_data_rate(scsi_qla_host_t *); | ||
328 | /* | 331 | /* |
329 | * Global Function Prototypes in qla_isr.c source file. | 332 | * Global Function Prototypes in qla_isr.c source file. |
330 | */ | 333 | */ |
@@ -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. |
@@ -453,6 +458,5 @@ extern void qla24xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t); | |||
453 | extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t); | 458 | extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t); |
454 | extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); | 459 | extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); |
455 | extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); | 460 | extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t); |
456 | extern struct scsi_qla_host * qla25xx_get_host(struct rsp_que *); | ||
457 | 461 | ||
458 | #endif /* _QLA_GBL_H */ | 462 | #endif /* _QLA_GBL_H */ |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 9e3eaac25596..4229bb483c5e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "qla_gbl.h" | 8 | #include "qla_gbl.h" |
9 | 9 | ||
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/slab.h> | ||
11 | #include <linux/vmalloc.h> | 12 | #include <linux/vmalloc.h> |
12 | 13 | ||
13 | #include "qla_devtbl.h" | 14 | #include "qla_devtbl.h" |
@@ -62,7 +63,7 @@ qla2x00_ctx_sp_timeout(unsigned long __data) | |||
62 | ctx->free(sp); | 63 | ctx->free(sp); |
63 | } | 64 | } |
64 | 65 | ||
65 | static void | 66 | void |
66 | qla2x00_ctx_sp_free(srb_t *sp) | 67 | qla2x00_ctx_sp_free(srb_t *sp) |
67 | { | 68 | { |
68 | struct srb_ctx *ctx = sp->ctx; | 69 | struct srb_ctx *ctx = sp->ctx; |
@@ -205,7 +206,7 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
205 | 206 | ||
206 | switch (data[0]) { | 207 | switch (data[0]) { |
207 | case MBS_COMMAND_COMPLETE: | 208 | case MBS_COMMAND_COMPLETE: |
208 | if (fcport->flags & FCF_TAPE_PRESENT) | 209 | if (fcport->flags & FCF_FCP2_DEVICE) |
209 | opts |= BIT_1; | 210 | opts |= BIT_1; |
210 | rval = qla2x00_get_port_database(vha, fcport, opts); | 211 | rval = qla2x00_get_port_database(vha, fcport, opts); |
211 | if (rval != QLA_SUCCESS) | 212 | if (rval != QLA_SUCCESS) |
@@ -269,6 +270,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
269 | vha->flags.online = 0; | 270 | vha->flags.online = 0; |
270 | ha->flags.chip_reset_done = 0; | 271 | ha->flags.chip_reset_done = 0; |
271 | vha->flags.reset_active = 0; | 272 | vha->flags.reset_active = 0; |
273 | ha->flags.pci_channel_io_perm_failure = 0; | ||
274 | ha->flags.eeh_busy = 0; | ||
272 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | 275 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); |
273 | atomic_set(&vha->loop_state, LOOP_DOWN); | 276 | atomic_set(&vha->loop_state, LOOP_DOWN); |
274 | vha->device_flags = DFLG_NO_CABLE; | 277 | vha->device_flags = DFLG_NO_CABLE; |
@@ -277,7 +280,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
277 | vha->marker_needed = 0; | 280 | vha->marker_needed = 0; |
278 | ha->isp_abort_cnt = 0; | 281 | ha->isp_abort_cnt = 0; |
279 | ha->beacon_blink_led = 0; | 282 | ha->beacon_blink_led = 0; |
280 | set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); | ||
281 | 283 | ||
282 | set_bit(0, ha->req_qid_map); | 284 | set_bit(0, ha->req_qid_map); |
283 | set_bit(0, ha->rsp_qid_map); | 285 | set_bit(0, ha->rsp_qid_map); |
@@ -337,6 +339,16 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
337 | rval = qla2x00_init_rings(vha); | 339 | rval = qla2x00_init_rings(vha); |
338 | ha->flags.chip_reset_done = 1; | 340 | ha->flags.chip_reset_done = 1; |
339 | 341 | ||
342 | if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) { | ||
343 | /* Issue verify 84xx FW IOCB to complete 84xx initialization */ | ||
344 | rval = qla84xx_init_chip(vha); | ||
345 | if (rval != QLA_SUCCESS) { | ||
346 | qla_printk(KERN_ERR, ha, | ||
347 | "Unable to initialize ISP84XX.\n"); | ||
348 | qla84xx_put_chip(vha); | ||
349 | } | ||
350 | } | ||
351 | |||
340 | return (rval); | 352 | return (rval); |
341 | } | 353 | } |
342 | 354 | ||
@@ -582,6 +594,9 @@ qla2x00_reset_chip(scsi_qla_host_t *vha) | |||
582 | uint32_t cnt; | 594 | uint32_t cnt; |
583 | uint16_t cmd; | 595 | uint16_t cmd; |
584 | 596 | ||
597 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
598 | return; | ||
599 | |||
585 | ha->isp_ops->disable_intrs(ha); | 600 | ha->isp_ops->disable_intrs(ha); |
586 | 601 | ||
587 | spin_lock_irqsave(&ha->hardware_lock, flags); | 602 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -787,6 +802,12 @@ void | |||
787 | qla24xx_reset_chip(scsi_qla_host_t *vha) | 802 | qla24xx_reset_chip(scsi_qla_host_t *vha) |
788 | { | 803 | { |
789 | struct qla_hw_data *ha = vha->hw; | 804 | struct qla_hw_data *ha = vha->hw; |
805 | |||
806 | if (pci_channel_offline(ha->pdev) && | ||
807 | ha->flags.pci_channel_io_perm_failure) { | ||
808 | return; | ||
809 | } | ||
810 | |||
790 | ha->isp_ops->disable_intrs(ha); | 811 | ha->isp_ops->disable_intrs(ha); |
791 | 812 | ||
792 | /* Perform RISC reset. */ | 813 | /* Perform RISC reset. */ |
@@ -1203,7 +1224,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) | |||
1203 | } | 1224 | } |
1204 | qla2x00_get_resource_cnts(vha, NULL, | 1225 | qla2x00_get_resource_cnts(vha, NULL, |
1205 | &ha->fw_xcb_count, NULL, NULL, | 1226 | &ha->fw_xcb_count, NULL, NULL, |
1206 | &ha->max_npiv_vports); | 1227 | &ha->max_npiv_vports, NULL); |
1207 | 1228 | ||
1208 | if (!fw_major_version && ql2xallocfwdump) | 1229 | if (!fw_major_version && ql2xallocfwdump) |
1209 | qla2x00_alloc_fw_dump(vha); | 1230 | qla2x00_alloc_fw_dump(vha); |
@@ -1443,7 +1464,17 @@ qla24xx_config_rings(struct scsi_qla_host *vha) | |||
1443 | icb->firmware_options_2 |= | 1464 | icb->firmware_options_2 |= |
1444 | __constant_cpu_to_le32(BIT_18); | 1465 | __constant_cpu_to_le32(BIT_18); |
1445 | 1466 | ||
1446 | icb->firmware_options_2 &= __constant_cpu_to_le32(~BIT_22); | 1467 | /* Use Disable MSIX Handshake mode for capable adapters */ |
1468 | if (IS_MSIX_NACK_CAPABLE(ha)) { | ||
1469 | icb->firmware_options_2 &= | ||
1470 | __constant_cpu_to_le32(~BIT_22); | ||
1471 | ha->flags.disable_msix_handshake = 1; | ||
1472 | qla_printk(KERN_INFO, ha, | ||
1473 | "MSIX Handshake Disable Mode turned on\n"); | ||
1474 | } else { | ||
1475 | icb->firmware_options_2 |= | ||
1476 | __constant_cpu_to_le32(BIT_22); | ||
1477 | } | ||
1447 | icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23); | 1478 | icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23); |
1448 | 1479 | ||
1449 | WRT_REG_DWORD(®->isp25mq.req_q_in, 0); | 1480 | WRT_REG_DWORD(®->isp25mq.req_q_in, 0); |
@@ -2196,7 +2227,7 @@ qla2x00_rport_del(void *data) | |||
2196 | * | 2227 | * |
2197 | * Returns a pointer to the allocated fcport, or NULL, if none available. | 2228 | * Returns a pointer to the allocated fcport, or NULL, if none available. |
2198 | */ | 2229 | */ |
2199 | static fc_port_t * | 2230 | fc_port_t * |
2200 | qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) | 2231 | qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) |
2201 | { | 2232 | { |
2202 | fc_port_t *fcport; | 2233 | fc_port_t *fcport; |
@@ -2257,6 +2288,8 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) | |||
2257 | clear_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); | 2288 | clear_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); |
2258 | clear_bit(RSCN_UPDATE, &vha->dpc_flags); | 2289 | clear_bit(RSCN_UPDATE, &vha->dpc_flags); |
2259 | 2290 | ||
2291 | qla2x00_get_data_rate(vha); | ||
2292 | |||
2260 | /* Determine what we need to do */ | 2293 | /* Determine what we need to do */ |
2261 | if (ha->current_topology == ISP_CFG_FL && | 2294 | if (ha->current_topology == ISP_CFG_FL && |
2262 | (test_bit(LOCAL_LOOP_UPDATE, &flags))) { | 2295 | (test_bit(LOCAL_LOOP_UPDATE, &flags))) { |
@@ -2704,7 +2737,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
2704 | 2737 | ||
2705 | /* | 2738 | /* |
2706 | * Logout all previous fabric devices marked lost, except | 2739 | * Logout all previous fabric devices marked lost, except |
2707 | * tape devices. | 2740 | * FCP2 devices. |
2708 | */ | 2741 | */ |
2709 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 2742 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
2710 | if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) | 2743 | if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) |
@@ -2717,7 +2750,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
2717 | qla2x00_mark_device_lost(vha, fcport, | 2750 | qla2x00_mark_device_lost(vha, fcport, |
2718 | ql2xplogiabsentdevice, 0); | 2751 | ql2xplogiabsentdevice, 0); |
2719 | if (fcport->loop_id != FC_NO_LOOP_ID && | 2752 | if (fcport->loop_id != FC_NO_LOOP_ID && |
2720 | (fcport->flags & FCF_TAPE_PRESENT) == 0 && | 2753 | (fcport->flags & FCF_FCP2_DEVICE) == 0 && |
2721 | fcport->port_type != FCT_INITIATOR && | 2754 | fcport->port_type != FCT_INITIATOR && |
2722 | fcport->port_type != FCT_BROADCAST) { | 2755 | fcport->port_type != FCT_BROADCAST) { |
2723 | ha->isp_ops->fabric_logout(vha, | 2756 | ha->isp_ops->fabric_logout(vha, |
@@ -2878,8 +2911,13 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
2878 | if (qla2x00_is_reserved_id(vha, loop_id)) | 2911 | if (qla2x00_is_reserved_id(vha, loop_id)) |
2879 | continue; | 2912 | continue; |
2880 | 2913 | ||
2881 | if (atomic_read(&vha->loop_down_timer) || LOOP_TRANSITION(vha)) | 2914 | if (atomic_read(&vha->loop_down_timer) || |
2915 | LOOP_TRANSITION(vha)) { | ||
2916 | atomic_set(&vha->loop_down_timer, 0); | ||
2917 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | ||
2918 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); | ||
2882 | break; | 2919 | break; |
2920 | } | ||
2883 | 2921 | ||
2884 | if (swl != NULL) { | 2922 | if (swl != NULL) { |
2885 | if (last_dev) { | 2923 | if (last_dev) { |
@@ -2996,7 +3034,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
2996 | fcport->d_id.b24 = new_fcport->d_id.b24; | 3034 | fcport->d_id.b24 = new_fcport->d_id.b24; |
2997 | fcport->flags |= FCF_LOGIN_NEEDED; | 3035 | fcport->flags |= FCF_LOGIN_NEEDED; |
2998 | if (fcport->loop_id != FC_NO_LOOP_ID && | 3036 | if (fcport->loop_id != FC_NO_LOOP_ID && |
2999 | (fcport->flags & FCF_TAPE_PRESENT) == 0 && | 3037 | (fcport->flags & FCF_FCP2_DEVICE) == 0 && |
3000 | fcport->port_type != FCT_INITIATOR && | 3038 | fcport->port_type != FCT_INITIATOR && |
3001 | fcport->port_type != FCT_BROADCAST) { | 3039 | fcport->port_type != FCT_BROADCAST) { |
3002 | ha->isp_ops->fabric_logout(vha, fcport->loop_id, | 3040 | ha->isp_ops->fabric_logout(vha, fcport->loop_id, |
@@ -3250,9 +3288,9 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *vha, fc_port_t *fcport, | |||
3250 | 3288 | ||
3251 | rval = qla2x00_fabric_login(vha, fcport, next_loopid); | 3289 | rval = qla2x00_fabric_login(vha, fcport, next_loopid); |
3252 | if (rval == QLA_SUCCESS) { | 3290 | if (rval == QLA_SUCCESS) { |
3253 | /* Send an ADISC to tape devices.*/ | 3291 | /* Send an ADISC to FCP2 devices.*/ |
3254 | opts = 0; | 3292 | opts = 0; |
3255 | if (fcport->flags & FCF_TAPE_PRESENT) | 3293 | if (fcport->flags & FCF_FCP2_DEVICE) |
3256 | opts |= BIT_1; | 3294 | opts |= BIT_1; |
3257 | rval = qla2x00_get_port_database(vha, fcport, opts); | 3295 | rval = qla2x00_get_port_database(vha, fcport, opts); |
3258 | if (rval != QLA_SUCCESS) { | 3296 | if (rval != QLA_SUCCESS) { |
@@ -3551,6 +3589,13 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
3551 | /* Requeue all commands in outstanding command list. */ | 3589 | /* Requeue all commands in outstanding command list. */ |
3552 | qla2x00_abort_all_cmds(vha, DID_RESET << 16); | 3590 | qla2x00_abort_all_cmds(vha, DID_RESET << 16); |
3553 | 3591 | ||
3592 | if (unlikely(pci_channel_offline(ha->pdev) && | ||
3593 | ha->flags.pci_channel_io_perm_failure)) { | ||
3594 | clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); | ||
3595 | status = 0; | ||
3596 | return status; | ||
3597 | } | ||
3598 | |||
3554 | ha->isp_ops->get_flash_version(vha, req->ring); | 3599 | ha->isp_ops->get_flash_version(vha, req->ring); |
3555 | 3600 | ||
3556 | ha->isp_ops->nvram_config(vha); | 3601 | ha->isp_ops->nvram_config(vha); |
@@ -3573,6 +3618,15 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
3573 | ha->isp_abort_cnt = 0; | 3618 | ha->isp_abort_cnt = 0; |
3574 | clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); | 3619 | clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); |
3575 | 3620 | ||
3621 | if (IS_QLA81XX(ha)) | ||
3622 | qla2x00_get_fw_version(vha, | ||
3623 | &ha->fw_major_version, | ||
3624 | &ha->fw_minor_version, | ||
3625 | &ha->fw_subminor_version, | ||
3626 | &ha->fw_attributes, &ha->fw_memory_size, | ||
3627 | ha->mpi_version, &ha->mpi_capabilities, | ||
3628 | ha->phy_version); | ||
3629 | |||
3576 | if (ha->fce) { | 3630 | if (ha->fce) { |
3577 | ha->flags.fce_enabled = 1; | 3631 | ha->flags.fce_enabled = 1; |
3578 | memset(ha->fce, 0, | 3632 | memset(ha->fce, 0, |
@@ -4440,6 +4494,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha) | |||
4440 | int ret, retries; | 4494 | int ret, retries; |
4441 | struct qla_hw_data *ha = vha->hw; | 4495 | struct qla_hw_data *ha = vha->hw; |
4442 | 4496 | ||
4497 | if (ha->flags.pci_channel_io_perm_failure) | ||
4498 | return; | ||
4443 | if (!IS_FWI2_CAPABLE(ha)) | 4499 | if (!IS_FWI2_CAPABLE(ha)) |
4444 | return; | 4500 | return; |
4445 | if (!ha->fw_major_version) | 4501 | if (!ha->fw_major_version) |
@@ -4837,6 +4893,15 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) | |||
4837 | } | 4893 | } |
4838 | 4894 | ||
4839 | void | 4895 | void |
4840 | qla81xx_update_fw_options(scsi_qla_host_t *ha) | 4896 | qla81xx_update_fw_options(scsi_qla_host_t *vha) |
4841 | { | 4897 | { |
4898 | struct qla_hw_data *ha = vha->hw; | ||
4899 | |||
4900 | if (!ql2xetsenable) | ||
4901 | return; | ||
4902 | |||
4903 | /* Enable ETS Burst. */ | ||
4904 | memset(ha->fw_options, 0, sizeof(ha->fw_options)); | ||
4905 | ha->fw_options[2] |= BIT_9; | ||
4906 | qla2x00_set_fw_options(vha, ha->fw_options); | ||
4842 | } | 4907 | } |
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 b20a7169aac2..db539b0c3dae 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -7,7 +7,9 @@ | |||
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/slab.h> | ||
10 | #include <scsi/scsi_tcq.h> | 11 | #include <scsi/scsi_tcq.h> |
12 | #include <scsi/scsi_bsg_fc.h> | ||
11 | 13 | ||
12 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); | 14 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); |
13 | static void qla2x00_process_completed_request(struct scsi_qla_host *, | 15 | static void qla2x00_process_completed_request(struct scsi_qla_host *, |
@@ -152,7 +154,7 @@ qla2300_intr_handler(int irq, void *dev_id) | |||
152 | for (iter = 50; iter--; ) { | 154 | for (iter = 50; iter--; ) { |
153 | stat = RD_REG_DWORD(®->u.isp2300.host_status); | 155 | stat = RD_REG_DWORD(®->u.isp2300.host_status); |
154 | if (stat & HSR_RISC_PAUSED) { | 156 | if (stat & HSR_RISC_PAUSED) { |
155 | if (pci_channel_offline(ha->pdev)) | 157 | if (unlikely(pci_channel_offline(ha->pdev))) |
156 | break; | 158 | break; |
157 | 159 | ||
158 | hccr = RD_REG_WORD(®->hccr); | 160 | hccr = RD_REG_WORD(®->hccr); |
@@ -313,10 +315,11 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) | |||
313 | static char *link_speeds[] = { "1", "2", "?", "4", "8", "10" }; | 315 | static char *link_speeds[] = { "1", "2", "?", "4", "8", "10" }; |
314 | char *link_speed; | 316 | char *link_speed; |
315 | uint16_t handle_cnt; | 317 | uint16_t handle_cnt; |
316 | uint16_t cnt; | 318 | uint16_t cnt, mbx; |
317 | uint32_t handles[5]; | 319 | uint32_t handles[5]; |
318 | struct qla_hw_data *ha = vha->hw; | 320 | struct qla_hw_data *ha = vha->hw; |
319 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 321 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
322 | struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; | ||
320 | uint32_t rscn_entry, host_pid; | 323 | uint32_t rscn_entry, host_pid; |
321 | uint8_t rscn_queue_index; | 324 | uint8_t rscn_queue_index; |
322 | unsigned long flags; | 325 | unsigned long flags; |
@@ -395,9 +398,10 @@ skip_rio: | |||
395 | break; | 398 | break; |
396 | 399 | ||
397 | case MBA_SYSTEM_ERR: /* System Error */ | 400 | case MBA_SYSTEM_ERR: /* System Error */ |
401 | mbx = IS_QLA81XX(ha) ? RD_REG_WORD(®24->mailbox7) : 0; | ||
398 | qla_printk(KERN_INFO, ha, | 402 | qla_printk(KERN_INFO, ha, |
399 | "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", | 403 | "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh " |
400 | mb[1], mb[2], mb[3]); | 404 | "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx); |
401 | 405 | ||
402 | ha->isp_ops->fw_dump(vha, 1); | 406 | ha->isp_ops->fw_dump(vha, 1); |
403 | 407 | ||
@@ -419,9 +423,10 @@ skip_rio: | |||
419 | break; | 423 | break; |
420 | 424 | ||
421 | case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ | 425 | case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ |
422 | DEBUG2(printk("scsi(%ld): ISP Request Transfer Error.\n", | 426 | DEBUG2(printk("scsi(%ld): ISP Request Transfer Error (%x).\n", |
423 | vha->host_no)); | 427 | vha->host_no, mb[1])); |
424 | qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n"); | 428 | qla_printk(KERN_WARNING, ha, |
429 | "ISP Request Transfer Error (%x).\n", mb[1]); | ||
425 | 430 | ||
426 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 431 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
427 | break; | 432 | break; |
@@ -485,10 +490,13 @@ skip_rio: | |||
485 | break; | 490 | break; |
486 | 491 | ||
487 | case MBA_LOOP_DOWN: /* Loop Down Event */ | 492 | case MBA_LOOP_DOWN: /* Loop Down Event */ |
493 | mbx = IS_QLA81XX(ha) ? RD_REG_WORD(®24->mailbox4) : 0; | ||
488 | DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN " | 494 | DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN " |
489 | "(%x %x %x).\n", vha->host_no, mb[1], mb[2], mb[3])); | 495 | "(%x %x %x %x).\n", vha->host_no, mb[1], mb[2], mb[3], |
490 | qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x %x %x).\n", | 496 | mbx)); |
491 | mb[1], mb[2], mb[3]); | 497 | qla_printk(KERN_INFO, ha, |
498 | "LOOP DOWN detected (%x %x %x %x).\n", mb[1], mb[2], mb[3], | ||
499 | mbx); | ||
492 | 500 | ||
493 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | 501 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { |
494 | atomic_set(&vha->loop_state, LOOP_DOWN); | 502 | atomic_set(&vha->loop_state, LOOP_DOWN); |
@@ -613,11 +621,10 @@ skip_rio: | |||
613 | * vp_idx does not match | 621 | * vp_idx does not match |
614 | * Event is not global, vp_idx does not match | 622 | * Event is not global, vp_idx does not match |
615 | */ | 623 | */ |
616 | if ((mb[1] == 0xffff && (mb[3] & 0xff) != 0xff) | 624 | if (IS_QLA2XXX_MIDTYPE(ha) && |
617 | || (mb[1] != 0xffff)) { | 625 | ((mb[1] == 0xffff && (mb[3] & 0xff) != 0xff) || |
618 | if (vha->vp_idx != (mb[3] & 0xff)) | 626 | (mb[1] != 0xffff)) && vha->vp_idx != (mb[3] & 0xff)) |
619 | break; | 627 | break; |
620 | } | ||
621 | 628 | ||
622 | /* Global event -- port logout or port unavailable. */ | 629 | /* Global event -- port logout or port unavailable. */ |
623 | if (mb[1] == 0xffff && mb[2] == 0x7) { | 630 | if (mb[1] == 0xffff && mb[2] == 0x7) { |
@@ -805,78 +812,6 @@ skip_rio: | |||
805 | qla2x00_alert_all_vps(rsp, mb); | 812 | qla2x00_alert_all_vps(rsp, mb); |
806 | } | 813 | } |
807 | 814 | ||
808 | static void | ||
809 | qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data) | ||
810 | { | ||
811 | fc_port_t *fcport = data; | ||
812 | struct scsi_qla_host *vha = fcport->vha; | ||
813 | struct qla_hw_data *ha = vha->hw; | ||
814 | struct req_que *req = NULL; | ||
815 | |||
816 | if (!ql2xqfulltracking) | ||
817 | return; | ||
818 | |||
819 | req = vha->req; | ||
820 | if (!req) | ||
821 | return; | ||
822 | if (req->max_q_depth <= sdev->queue_depth) | ||
823 | return; | ||
824 | |||
825 | if (sdev->ordered_tags) | ||
826 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, | ||
827 | sdev->queue_depth + 1); | ||
828 | else | ||
829 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, | ||
830 | sdev->queue_depth + 1); | ||
831 | |||
832 | fcport->last_ramp_up = jiffies; | ||
833 | |||
834 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
835 | "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n", | ||
836 | fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun, | ||
837 | sdev->queue_depth)); | ||
838 | } | ||
839 | |||
840 | static void | ||
841 | qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data) | ||
842 | { | ||
843 | fc_port_t *fcport = data; | ||
844 | |||
845 | if (!scsi_track_queue_full(sdev, sdev->queue_depth - 1)) | ||
846 | return; | ||
847 | |||
848 | DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw, | ||
849 | "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n", | ||
850 | fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun, | ||
851 | sdev->queue_depth)); | ||
852 | } | ||
853 | |||
854 | static inline void | ||
855 | qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, struct req_que *req, | ||
856 | srb_t *sp) | ||
857 | { | ||
858 | fc_port_t *fcport; | ||
859 | struct scsi_device *sdev; | ||
860 | |||
861 | if (!ql2xqfulltracking) | ||
862 | return; | ||
863 | |||
864 | sdev = sp->cmd->device; | ||
865 | if (sdev->queue_depth >= req->max_q_depth) | ||
866 | return; | ||
867 | |||
868 | fcport = sp->fcport; | ||
869 | if (time_before(jiffies, | ||
870 | fcport->last_ramp_up + ql2xqfullrampup * HZ)) | ||
871 | return; | ||
872 | if (time_before(jiffies, | ||
873 | fcport->last_queue_full + ql2xqfullrampup * HZ)) | ||
874 | return; | ||
875 | |||
876 | starget_for_each_device(sdev->sdev_target, fcport, | ||
877 | qla2x00_adjust_sdev_qdepth_up); | ||
878 | } | ||
879 | |||
880 | /** | 815 | /** |
881 | * qla2x00_process_completed_request() - Process a Fast Post response. | 816 | * qla2x00_process_completed_request() - Process a Fast Post response. |
882 | * @ha: SCSI driver HA context | 817 | * @ha: SCSI driver HA context |
@@ -907,8 +842,6 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, | |||
907 | 842 | ||
908 | /* Save ISP completion status */ | 843 | /* Save ISP completion status */ |
909 | sp->cmd->result = DID_OK << 16; | 844 | sp->cmd->result = DID_OK << 16; |
910 | |||
911 | qla2x00_ramp_up_queue_depth(vha, req, sp); | ||
912 | qla2x00_sp_compl(ha, sp); | 845 | qla2x00_sp_compl(ha, sp); |
913 | } else { | 846 | } else { |
914 | DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion" | 847 | DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion" |
@@ -949,7 +882,9 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, | |||
949 | index); | 882 | index); |
950 | return NULL; | 883 | return NULL; |
951 | } | 884 | } |
885 | |||
952 | req->outstanding_cmds[index] = NULL; | 886 | req->outstanding_cmds[index] = NULL; |
887 | |||
953 | done: | 888 | done: |
954 | return sp; | 889 | return sp; |
955 | } | 890 | } |
@@ -1050,6 +985,100 @@ done_post_logio_done_work: | |||
1050 | } | 985 | } |
1051 | 986 | ||
1052 | 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 | ||
1053 | 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, |
1054 | struct logio_entry_24xx *logio) | 1083 | struct logio_entry_24xx *logio) |
1055 | { | 1084 | { |
@@ -1347,16 +1376,22 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1347 | 1376 | ||
1348 | sense_len = rsp_info_len = resid_len = fw_resid_len = 0; | 1377 | sense_len = rsp_info_len = resid_len = fw_resid_len = 0; |
1349 | if (IS_FWI2_CAPABLE(ha)) { | 1378 | if (IS_FWI2_CAPABLE(ha)) { |
1350 | sense_len = le32_to_cpu(sts24->sense_len); | 1379 | if (scsi_status & SS_SENSE_LEN_VALID) |
1351 | rsp_info_len = le32_to_cpu(sts24->rsp_data_len); | 1380 | sense_len = le32_to_cpu(sts24->sense_len); |
1352 | resid_len = le32_to_cpu(sts24->rsp_residual_count); | 1381 | if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) |
1353 | fw_resid_len = le32_to_cpu(sts24->residual_len); | 1382 | rsp_info_len = le32_to_cpu(sts24->rsp_data_len); |
1383 | if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) | ||
1384 | resid_len = le32_to_cpu(sts24->rsp_residual_count); | ||
1385 | if (comp_status == CS_DATA_UNDERRUN) | ||
1386 | fw_resid_len = le32_to_cpu(sts24->residual_len); | ||
1354 | rsp_info = sts24->data; | 1387 | rsp_info = sts24->data; |
1355 | sense_data = sts24->data; | 1388 | sense_data = sts24->data; |
1356 | host_to_fcp_swap(sts24->data, sizeof(sts24->data)); | 1389 | host_to_fcp_swap(sts24->data, sizeof(sts24->data)); |
1357 | } else { | 1390 | } else { |
1358 | sense_len = le16_to_cpu(sts->req_sense_length); | 1391 | if (scsi_status & SS_SENSE_LEN_VALID) |
1359 | rsp_info_len = le16_to_cpu(sts->rsp_info_len); | 1392 | sense_len = le16_to_cpu(sts->req_sense_length); |
1393 | if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) | ||
1394 | rsp_info_len = le16_to_cpu(sts->rsp_info_len); | ||
1360 | resid_len = le32_to_cpu(sts->residual_length); | 1395 | resid_len = le32_to_cpu(sts->residual_length); |
1361 | rsp_info = sts->rsp_info; | 1396 | rsp_info = sts->rsp_info; |
1362 | sense_data = sts->req_sense_data; | 1397 | sense_data = sts->req_sense_data; |
@@ -1423,13 +1458,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1423 | "scsi(%ld): QUEUE FULL status detected " | 1458 | "scsi(%ld): QUEUE FULL status detected " |
1424 | "0x%x-0x%x.\n", vha->host_no, comp_status, | 1459 | "0x%x-0x%x.\n", vha->host_no, comp_status, |
1425 | scsi_status)); | 1460 | scsi_status)); |
1426 | |||
1427 | /* Adjust queue depth for all luns on the port. */ | ||
1428 | if (!ql2xqfulltracking) | ||
1429 | break; | ||
1430 | fcport->last_queue_full = jiffies; | ||
1431 | starget_for_each_device(cp->device->sdev_target, | ||
1432 | fcport, qla2x00_adjust_sdev_qdepth_down); | ||
1433 | break; | 1461 | break; |
1434 | } | 1462 | } |
1435 | if (lscsi_status != SS_CHECK_CONDITION) | 1463 | if (lscsi_status != SS_CHECK_CONDITION) |
@@ -1443,54 +1471,67 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1443 | break; | 1471 | break; |
1444 | 1472 | ||
1445 | case CS_DATA_UNDERRUN: | 1473 | case CS_DATA_UNDERRUN: |
1446 | resid = resid_len; | 1474 | DEBUG2(printk(KERN_INFO |
1475 | "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x. " | ||
1476 | "resid=0x%x fw_resid=0x%x cdb=0x%x os_underflow=0x%x\n", | ||
1477 | vha->host_no, cp->device->id, cp->device->lun, comp_status, | ||
1478 | scsi_status, resid_len, fw_resid_len, cp->cmnd[0], | ||
1479 | cp->underflow)); | ||
1480 | |||
1447 | /* Use F/W calculated residual length. */ | 1481 | /* Use F/W calculated residual length. */ |
1448 | if (IS_FWI2_CAPABLE(ha)) { | 1482 | resid = IS_FWI2_CAPABLE(ha) ? fw_resid_len : resid_len; |
1449 | if (!(scsi_status & SS_RESIDUAL_UNDER)) { | 1483 | scsi_set_resid(cp, resid); |
1450 | lscsi_status = 0; | 1484 | if (scsi_status & SS_RESIDUAL_UNDER) { |
1451 | } else if (resid != fw_resid_len) { | 1485 | if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) { |
1452 | scsi_status &= ~SS_RESIDUAL_UNDER; | 1486 | DEBUG2(printk( |
1453 | lscsi_status = 0; | 1487 | "scsi(%ld:%d:%d:%d) Dropped frame(s) " |
1488 | "detected (%x of %x bytes)...residual " | ||
1489 | "length mismatch...retrying command.\n", | ||
1490 | vha->host_no, cp->device->channel, | ||
1491 | cp->device->id, cp->device->lun, resid, | ||
1492 | scsi_bufflen(cp))); | ||
1493 | |||
1494 | cp->result = DID_ERROR << 16 | lscsi_status; | ||
1495 | break; | ||
1454 | } | 1496 | } |
1455 | resid = fw_resid_len; | ||
1456 | } | ||
1457 | 1497 | ||
1458 | if (scsi_status & SS_RESIDUAL_UNDER) { | 1498 | if (!lscsi_status && |
1459 | scsi_set_resid(cp, resid); | 1499 | ((unsigned)(scsi_bufflen(cp) - resid) < |
1460 | } else { | 1500 | cp->underflow)) { |
1461 | DEBUG2(printk(KERN_INFO | 1501 | qla_printk(KERN_INFO, ha, |
1462 | "scsi(%ld:%d:%d) UNDERRUN status detected " | 1502 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " |
1463 | "0x%x-0x%x. resid=0x%x fw_resid=0x%x cdb=0x%x " | 1503 | "detected (%x of %x bytes)...returning " |
1464 | "os_underflow=0x%x\n", vha->host_no, | 1504 | "error status.\n", vha->host_no, |
1465 | cp->device->id, cp->device->lun, comp_status, | 1505 | cp->device->channel, cp->device->id, |
1466 | scsi_status, resid_len, resid, cp->cmnd[0], | 1506 | cp->device->lun, resid, scsi_bufflen(cp)); |
1467 | cp->underflow)); | ||
1468 | 1507 | ||
1508 | cp->result = DID_ERROR << 16; | ||
1509 | break; | ||
1510 | } | ||
1511 | } else if (!lscsi_status) { | ||
1512 | DEBUG2(printk( | ||
1513 | "scsi(%ld:%d:%d:%d) Dropped frame(s) detected " | ||
1514 | "(%x of %x bytes)...firmware reported underrun..." | ||
1515 | "retrying command.\n", vha->host_no, | ||
1516 | cp->device->channel, cp->device->id, | ||
1517 | cp->device->lun, resid, scsi_bufflen(cp))); | ||
1518 | |||
1519 | cp->result = DID_ERROR << 16; | ||
1520 | break; | ||
1469 | } | 1521 | } |
1470 | 1522 | ||
1523 | cp->result = DID_OK << 16 | lscsi_status; | ||
1524 | |||
1471 | /* | 1525 | /* |
1472 | * Check to see if SCSI Status is non zero. If so report SCSI | 1526 | * Check to see if SCSI Status is non zero. If so report SCSI |
1473 | * Status. | 1527 | * Status. |
1474 | */ | 1528 | */ |
1475 | if (lscsi_status != 0) { | 1529 | if (lscsi_status != 0) { |
1476 | cp->result = DID_OK << 16 | lscsi_status; | ||
1477 | |||
1478 | if (lscsi_status == SAM_STAT_TASK_SET_FULL) { | 1530 | if (lscsi_status == SAM_STAT_TASK_SET_FULL) { |
1479 | DEBUG2(printk(KERN_INFO | 1531 | DEBUG2(printk(KERN_INFO |
1480 | "scsi(%ld): QUEUE FULL status detected " | 1532 | "scsi(%ld): QUEUE FULL status detected " |
1481 | "0x%x-0x%x.\n", vha->host_no, comp_status, | 1533 | "0x%x-0x%x.\n", vha->host_no, comp_status, |
1482 | scsi_status)); | 1534 | scsi_status)); |
1483 | |||
1484 | /* | ||
1485 | * Adjust queue depth for all luns on the | ||
1486 | * port. | ||
1487 | */ | ||
1488 | if (!ql2xqfulltracking) | ||
1489 | break; | ||
1490 | fcport->last_queue_full = jiffies; | ||
1491 | starget_for_each_device( | ||
1492 | cp->device->sdev_target, fcport, | ||
1493 | qla2x00_adjust_sdev_qdepth_down); | ||
1494 | break; | 1535 | break; |
1495 | } | 1536 | } |
1496 | if (lscsi_status != SS_CHECK_CONDITION) | 1537 | if (lscsi_status != SS_CHECK_CONDITION) |
@@ -1501,42 +1542,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1501 | break; | 1542 | break; |
1502 | 1543 | ||
1503 | qla2x00_handle_sense(sp, sense_data, sense_len, rsp); | 1544 | qla2x00_handle_sense(sp, sense_data, sense_len, rsp); |
1504 | } else { | ||
1505 | /* | ||
1506 | * If RISC reports underrun and target does not report | ||
1507 | * it then we must have a lost frame, so tell upper | ||
1508 | * layer to retry it by reporting an error. | ||
1509 | */ | ||
1510 | if (!(scsi_status & SS_RESIDUAL_UNDER)) { | ||
1511 | DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped " | ||
1512 | "frame(s) detected (%x of %x bytes)..." | ||
1513 | "retrying command.\n", | ||
1514 | vha->host_no, cp->device->channel, | ||
1515 | cp->device->id, cp->device->lun, resid, | ||
1516 | scsi_bufflen(cp))); | ||
1517 | |||
1518 | scsi_set_resid(cp, resid); | ||
1519 | cp->result = DID_ERROR << 16; | ||
1520 | break; | ||
1521 | } | ||
1522 | |||
1523 | /* Handle mid-layer underflow */ | ||
1524 | if ((unsigned)(scsi_bufflen(cp) - resid) < | ||
1525 | cp->underflow) { | ||
1526 | qla_printk(KERN_INFO, ha, | ||
1527 | "scsi(%ld:%d:%d:%d): Mid-layer underflow " | ||
1528 | "detected (%x of %x bytes)...returning " | ||
1529 | "error status.\n", vha->host_no, | ||
1530 | cp->device->channel, cp->device->id, | ||
1531 | cp->device->lun, resid, | ||
1532 | scsi_bufflen(cp)); | ||
1533 | |||
1534 | cp->result = DID_ERROR << 16; | ||
1535 | break; | ||
1536 | } | ||
1537 | |||
1538 | /* Everybody online, looking good... */ | ||
1539 | cp->result = DID_OK << 16; | ||
1540 | } | 1545 | } |
1541 | break; | 1546 | break; |
1542 | 1547 | ||
@@ -1841,6 +1846,13 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
1841 | qla24xx_logio_entry(vha, rsp->req, | 1846 | qla24xx_logio_entry(vha, rsp->req, |
1842 | (struct logio_entry_24xx *)pkt); | 1847 | (struct logio_entry_24xx *)pkt); |
1843 | 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; | ||
1844 | default: | 1856 | default: |
1845 | /* Type Not Supported. */ | 1857 | /* Type Not Supported. */ |
1846 | DEBUG4(printk(KERN_WARNING | 1858 | DEBUG4(printk(KERN_WARNING |
@@ -1938,12 +1950,15 @@ qla24xx_intr_handler(int irq, void *dev_id) | |||
1938 | reg = &ha->iobase->isp24; | 1950 | reg = &ha->iobase->isp24; |
1939 | status = 0; | 1951 | status = 0; |
1940 | 1952 | ||
1953 | if (unlikely(pci_channel_offline(ha->pdev))) | ||
1954 | return IRQ_HANDLED; | ||
1955 | |||
1941 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1956 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1942 | vha = pci_get_drvdata(ha->pdev); | 1957 | vha = pci_get_drvdata(ha->pdev); |
1943 | for (iter = 50; iter--; ) { | 1958 | for (iter = 50; iter--; ) { |
1944 | stat = RD_REG_DWORD(®->host_status); | 1959 | stat = RD_REG_DWORD(®->host_status); |
1945 | if (stat & HSRX_RISC_PAUSED) { | 1960 | if (stat & HSRX_RISC_PAUSED) { |
1946 | if (pci_channel_offline(ha->pdev)) | 1961 | if (unlikely(pci_channel_offline(ha->pdev))) |
1947 | break; | 1962 | break; |
1948 | 1963 | ||
1949 | hccr = RD_REG_DWORD(®->hccr); | 1964 | hccr = RD_REG_DWORD(®->hccr); |
@@ -2006,6 +2021,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) | |||
2006 | struct rsp_que *rsp; | 2021 | struct rsp_que *rsp; |
2007 | struct device_reg_24xx __iomem *reg; | 2022 | struct device_reg_24xx __iomem *reg; |
2008 | struct scsi_qla_host *vha; | 2023 | struct scsi_qla_host *vha; |
2024 | unsigned long flags; | ||
2009 | 2025 | ||
2010 | rsp = (struct rsp_que *) dev_id; | 2026 | rsp = (struct rsp_que *) dev_id; |
2011 | if (!rsp) { | 2027 | if (!rsp) { |
@@ -2016,15 +2032,15 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) | |||
2016 | ha = rsp->hw; | 2032 | ha = rsp->hw; |
2017 | reg = &ha->iobase->isp24; | 2033 | reg = &ha->iobase->isp24; |
2018 | 2034 | ||
2019 | spin_lock_irq(&ha->hardware_lock); | 2035 | spin_lock_irqsave(&ha->hardware_lock, flags); |
2020 | 2036 | ||
2021 | vha = qla25xx_get_host(rsp); | 2037 | vha = pci_get_drvdata(ha->pdev); |
2022 | qla24xx_process_response_queue(vha, rsp); | 2038 | qla24xx_process_response_queue(vha, rsp); |
2023 | if (!ha->mqenable) { | 2039 | if (!ha->flags.disable_msix_handshake) { |
2024 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 2040 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); |
2025 | RD_REG_DWORD_RELAXED(®->hccr); | 2041 | RD_REG_DWORD_RELAXED(®->hccr); |
2026 | } | 2042 | } |
2027 | spin_unlock_irq(&ha->hardware_lock); | 2043 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2028 | 2044 | ||
2029 | return IRQ_HANDLED; | 2045 | return IRQ_HANDLED; |
2030 | } | 2046 | } |
@@ -2034,6 +2050,8 @@ qla25xx_msix_rsp_q(int irq, void *dev_id) | |||
2034 | { | 2050 | { |
2035 | struct qla_hw_data *ha; | 2051 | struct qla_hw_data *ha; |
2036 | struct rsp_que *rsp; | 2052 | struct rsp_que *rsp; |
2053 | struct device_reg_24xx __iomem *reg; | ||
2054 | unsigned long flags; | ||
2037 | 2055 | ||
2038 | rsp = (struct rsp_que *) dev_id; | 2056 | rsp = (struct rsp_que *) dev_id; |
2039 | if (!rsp) { | 2057 | if (!rsp) { |
@@ -2043,6 +2061,14 @@ qla25xx_msix_rsp_q(int irq, void *dev_id) | |||
2043 | } | 2061 | } |
2044 | ha = rsp->hw; | 2062 | ha = rsp->hw; |
2045 | 2063 | ||
2064 | /* Clear the interrupt, if enabled, for this response queue */ | ||
2065 | if (rsp->options & ~BIT_6) { | ||
2066 | reg = &ha->iobase->isp24; | ||
2067 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2068 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | ||
2069 | RD_REG_DWORD_RELAXED(®->hccr); | ||
2070 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2071 | } | ||
2046 | queue_work_on((int) (rsp->id - 1), ha->wq, &rsp->q_work); | 2072 | queue_work_on((int) (rsp->id - 1), ha->wq, &rsp->q_work); |
2047 | 2073 | ||
2048 | return IRQ_HANDLED; | 2074 | return IRQ_HANDLED; |
@@ -2059,6 +2085,7 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2059 | uint32_t stat; | 2085 | uint32_t stat; |
2060 | uint32_t hccr; | 2086 | uint32_t hccr; |
2061 | uint16_t mb[4]; | 2087 | uint16_t mb[4]; |
2088 | unsigned long flags; | ||
2062 | 2089 | ||
2063 | rsp = (struct rsp_que *) dev_id; | 2090 | rsp = (struct rsp_que *) dev_id; |
2064 | if (!rsp) { | 2091 | if (!rsp) { |
@@ -2070,12 +2097,12 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2070 | reg = &ha->iobase->isp24; | 2097 | reg = &ha->iobase->isp24; |
2071 | status = 0; | 2098 | status = 0; |
2072 | 2099 | ||
2073 | spin_lock_irq(&ha->hardware_lock); | 2100 | spin_lock_irqsave(&ha->hardware_lock, flags); |
2074 | vha = pci_get_drvdata(ha->pdev); | 2101 | vha = pci_get_drvdata(ha->pdev); |
2075 | do { | 2102 | do { |
2076 | stat = RD_REG_DWORD(®->host_status); | 2103 | stat = RD_REG_DWORD(®->host_status); |
2077 | if (stat & HSRX_RISC_PAUSED) { | 2104 | if (stat & HSRX_RISC_PAUSED) { |
2078 | if (pci_channel_offline(ha->pdev)) | 2105 | if (unlikely(pci_channel_offline(ha->pdev))) |
2079 | break; | 2106 | break; |
2080 | 2107 | ||
2081 | hccr = RD_REG_DWORD(®->hccr); | 2108 | hccr = RD_REG_DWORD(®->hccr); |
@@ -2119,14 +2146,13 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2119 | } | 2146 | } |
2120 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 2147 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); |
2121 | } while (0); | 2148 | } while (0); |
2122 | spin_unlock_irq(&ha->hardware_lock); | 2149 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2123 | 2150 | ||
2124 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | 2151 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && |
2125 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | 2152 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { |
2126 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); | 2153 | set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); |
2127 | complete(&ha->mbx_intr_comp); | 2154 | complete(&ha->mbx_intr_comp); |
2128 | } | 2155 | } |
2129 | |||
2130 | return IRQ_HANDLED; | 2156 | return IRQ_HANDLED; |
2131 | } | 2157 | } |
2132 | 2158 | ||
@@ -2246,30 +2272,28 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) | |||
2246 | 2272 | ||
2247 | /* If possible, enable MSI-X. */ | 2273 | /* If possible, enable MSI-X. */ |
2248 | if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && | 2274 | if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && |
2249 | !IS_QLA8432(ha) && !IS_QLA8001(ha)) | 2275 | !IS_QLA8432(ha) && !IS_QLA8001(ha)) |
2250 | goto skip_msix; | 2276 | goto skip_msi; |
2277 | |||
2278 | if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP && | ||
2279 | (ha->pdev->subsystem_device == 0x7040 || | ||
2280 | ha->pdev->subsystem_device == 0x7041 || | ||
2281 | ha->pdev->subsystem_device == 0x1705)) { | ||
2282 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2283 | "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X,0x%X).\n", | ||
2284 | ha->pdev->subsystem_vendor, | ||
2285 | ha->pdev->subsystem_device)); | ||
2286 | goto skip_msi; | ||
2287 | } | ||
2251 | 2288 | ||
2252 | if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX || | 2289 | if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX || |
2253 | !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) { | 2290 | !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) { |
2254 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2291 | DEBUG2(qla_printk(KERN_WARNING, ha, |
2255 | "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", | 2292 | "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", |
2256 | ha->pdev->revision, ha->fw_attributes)); | 2293 | ha->pdev->revision, ha->fw_attributes)); |
2257 | |||
2258 | goto skip_msix; | 2294 | goto skip_msix; |
2259 | } | 2295 | } |
2260 | 2296 | ||
2261 | if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP && | ||
2262 | (ha->pdev->subsystem_device == 0x7040 || | ||
2263 | ha->pdev->subsystem_device == 0x7041 || | ||
2264 | ha->pdev->subsystem_device == 0x1705)) { | ||
2265 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2266 | "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X, 0x%X).\n", | ||
2267 | ha->pdev->subsystem_vendor, | ||
2268 | ha->pdev->subsystem_device)); | ||
2269 | |||
2270 | goto skip_msi; | ||
2271 | } | ||
2272 | |||
2273 | ret = qla24xx_enable_msix(ha, rsp); | 2297 | ret = qla24xx_enable_msix(ha, rsp); |
2274 | if (!ret) { | 2298 | if (!ret) { |
2275 | DEBUG2(qla_printk(KERN_INFO, ha, | 2299 | DEBUG2(qla_printk(KERN_INFO, ha, |
@@ -2332,10 +2356,11 @@ qla2x00_free_irqs(scsi_qla_host_t *vha) | |||
2332 | 2356 | ||
2333 | if (ha->flags.msix_enabled) | 2357 | if (ha->flags.msix_enabled) |
2334 | qla24xx_disable_msix(ha); | 2358 | qla24xx_disable_msix(ha); |
2335 | else if (ha->flags.inta_enabled) { | 2359 | else if (ha->flags.msi_enabled) { |
2336 | free_irq(ha->pdev->irq, rsp); | 2360 | free_irq(ha->pdev->irq, rsp); |
2337 | pci_disable_msi(ha->pdev); | 2361 | pci_disable_msi(ha->pdev); |
2338 | } | 2362 | } else |
2363 | free_irq(ha->pdev->irq, rsp); | ||
2339 | } | 2364 | } |
2340 | 2365 | ||
2341 | 2366 | ||
@@ -2357,30 +2382,3 @@ int qla25xx_request_irq(struct rsp_que *rsp) | |||
2357 | msix->rsp = rsp; | 2382 | msix->rsp = rsp; |
2358 | return ret; | 2383 | return ret; |
2359 | } | 2384 | } |
2360 | |||
2361 | struct scsi_qla_host * | ||
2362 | qla25xx_get_host(struct rsp_que *rsp) | ||
2363 | { | ||
2364 | srb_t *sp; | ||
2365 | struct qla_hw_data *ha = rsp->hw; | ||
2366 | struct scsi_qla_host *vha = NULL; | ||
2367 | struct sts_entry_24xx *pkt; | ||
2368 | struct req_que *req; | ||
2369 | uint16_t que; | ||
2370 | uint32_t handle; | ||
2371 | |||
2372 | pkt = (struct sts_entry_24xx *) rsp->ring_ptr; | ||
2373 | que = MSW(pkt->handle); | ||
2374 | handle = (uint32_t) LSW(pkt->handle); | ||
2375 | req = ha->req_q_map[que]; | ||
2376 | if (handle < MAX_OUTSTANDING_COMMANDS) { | ||
2377 | sp = req->outstanding_cmds[handle]; | ||
2378 | if (sp) | ||
2379 | return sp->fcport->vha; | ||
2380 | else | ||
2381 | goto base_que; | ||
2382 | } | ||
2383 | base_que: | ||
2384 | vha = pci_get_drvdata(ha->pdev); | ||
2385 | return vha; | ||
2386 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index b6202fe118ac..42eb7ffd5942 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/gfp.h> | ||
10 | 11 | ||
11 | 12 | ||
12 | /* | 13 | /* |
@@ -56,6 +57,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
56 | 57 | ||
57 | DEBUG11(printk("%s(%ld): entered.\n", __func__, base_vha->host_no)); | 58 | DEBUG11(printk("%s(%ld): entered.\n", __func__, base_vha->host_no)); |
58 | 59 | ||
60 | if (ha->flags.pci_channel_io_perm_failure) { | ||
61 | DEBUG(printk("%s(%ld): Perm failure on EEH, timeout MBX " | ||
62 | "Exiting.\n", __func__, vha->host_no)); | ||
63 | return QLA_FUNCTION_TIMEOUT; | ||
64 | } | ||
65 | |||
59 | /* | 66 | /* |
60 | * Wait for active mailbox commands to finish by waiting at most tov | 67 | * Wait for active mailbox commands to finish by waiting at most tov |
61 | * seconds. This is to serialize actual issuing of mailbox cmds during | 68 | * seconds. This is to serialize actual issuing of mailbox cmds during |
@@ -154,10 +161,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
154 | /* Check for pending interrupts. */ | 161 | /* Check for pending interrupts. */ |
155 | qla2x00_poll(ha->rsp_q_map[0]); | 162 | qla2x00_poll(ha->rsp_q_map[0]); |
156 | 163 | ||
157 | if (command != MBC_LOAD_RISC_RAM_EXTENDED && | 164 | if (!ha->flags.mbox_int && |
158 | !ha->flags.mbox_int) | 165 | !(IS_QLA2200(ha) && |
166 | command == MBC_LOAD_RISC_RAM_EXTENDED)) | ||
159 | msleep(10); | 167 | msleep(10); |
160 | } /* while */ | 168 | } /* while */ |
169 | DEBUG17(qla_printk(KERN_WARNING, ha, | ||
170 | "Waited %d sec\n", | ||
171 | (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ))); | ||
161 | } | 172 | } |
162 | 173 | ||
163 | /* Check whether we timed out */ | 174 | /* Check whether we timed out */ |
@@ -227,7 +238,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
227 | 238 | ||
228 | if (rval == QLA_FUNCTION_TIMEOUT && | 239 | if (rval == QLA_FUNCTION_TIMEOUT && |
229 | mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) { | 240 | mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) { |
230 | if (!io_lock_on || (mcp->flags & IOCTL_CMD)) { | 241 | if (!io_lock_on || (mcp->flags & IOCTL_CMD) || |
242 | ha->flags.eeh_busy) { | ||
231 | /* not in dpc. schedule it for dpc to take over. */ | 243 | /* not in dpc. schedule it for dpc to take over. */ |
232 | DEBUG(printk("%s(%ld): timeout schedule " | 244 | DEBUG(printk("%s(%ld): timeout schedule " |
233 | "isp_abort_needed.\n", __func__, | 245 | "isp_abort_needed.\n", __func__, |
@@ -237,7 +249,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
237 | base_vha->host_no)); | 249 | base_vha->host_no)); |
238 | qla_printk(KERN_WARNING, ha, | 250 | qla_printk(KERN_WARNING, ha, |
239 | "Mailbox command timeout occurred. Scheduling ISP " | 251 | "Mailbox command timeout occurred. Scheduling ISP " |
240 | "abort.\n"); | 252 | "abort. eeh_busy: 0x%x\n", ha->flags.eeh_busy); |
241 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); | 253 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); |
242 | qla2xxx_wake_dpc(vha); | 254 | qla2xxx_wake_dpc(vha); |
243 | } else if (!abort_active) { | 255 | } else if (!abort_active) { |
@@ -328,6 +340,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, | |||
328 | return rval; | 340 | return rval; |
329 | } | 341 | } |
330 | 342 | ||
343 | #define EXTENDED_BB_CREDITS BIT_0 | ||
331 | /* | 344 | /* |
332 | * qla2x00_execute_fw | 345 | * qla2x00_execute_fw |
333 | * Start adapter firmware. | 346 | * Start adapter firmware. |
@@ -360,7 +373,12 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) | |||
360 | mcp->mb[1] = MSW(risc_addr); | 373 | mcp->mb[1] = MSW(risc_addr); |
361 | mcp->mb[2] = LSW(risc_addr); | 374 | mcp->mb[2] = LSW(risc_addr); |
362 | mcp->mb[3] = 0; | 375 | mcp->mb[3] = 0; |
363 | mcp->mb[4] = 0; | 376 | if (IS_QLA81XX(ha)) { |
377 | struct nvram_81xx *nv = ha->nvram; | ||
378 | mcp->mb[4] = (nv->enhanced_features & | ||
379 | EXTENDED_BB_CREDITS); | ||
380 | } else | ||
381 | mcp->mb[4] = 0; | ||
364 | mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1; | 382 | mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1; |
365 | mcp->in_mb |= MBX_1; | 383 | mcp->in_mb |= MBX_1; |
366 | } else { | 384 | } else { |
@@ -2006,7 +2024,7 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma, | |||
2006 | int | 2024 | int |
2007 | qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, | 2025 | qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, |
2008 | uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, | 2026 | uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, |
2009 | uint16_t *orig_iocb_cnt, uint16_t *max_npiv_vports) | 2027 | uint16_t *orig_iocb_cnt, uint16_t *max_npiv_vports, uint16_t *max_fcfs) |
2010 | { | 2028 | { |
2011 | int rval; | 2029 | int rval; |
2012 | mbx_cmd_t mc; | 2030 | mbx_cmd_t mc; |
@@ -2017,6 +2035,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, | |||
2017 | mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; | 2035 | mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; |
2018 | mcp->out_mb = MBX_0; | 2036 | mcp->out_mb = MBX_0; |
2019 | mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; | 2037 | mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; |
2038 | if (IS_QLA81XX(vha->hw)) | ||
2039 | mcp->in_mb |= MBX_12; | ||
2020 | mcp->tov = MBX_TOV_SECONDS; | 2040 | mcp->tov = MBX_TOV_SECONDS; |
2021 | mcp->flags = 0; | 2041 | mcp->flags = 0; |
2022 | rval = qla2x00_mailbox_command(vha, mcp); | 2042 | rval = qla2x00_mailbox_command(vha, mcp); |
@@ -2027,9 +2047,10 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, | |||
2027 | vha->host_no, mcp->mb[0])); | 2047 | vha->host_no, mcp->mb[0])); |
2028 | } else { | 2048 | } else { |
2029 | DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x " | 2049 | DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x " |
2030 | "mb7=%x mb10=%x mb11=%x.\n", __func__, vha->host_no, | 2050 | "mb7=%x mb10=%x mb11=%x mb12=%x.\n", __func__, |
2031 | mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[6], mcp->mb[7], | 2051 | vha->host_no, mcp->mb[1], mcp->mb[2], mcp->mb[3], |
2032 | mcp->mb[10], mcp->mb[11])); | 2052 | mcp->mb[6], mcp->mb[7], mcp->mb[10], mcp->mb[11], |
2053 | mcp->mb[12])); | ||
2033 | 2054 | ||
2034 | if (cur_xchg_cnt) | 2055 | if (cur_xchg_cnt) |
2035 | *cur_xchg_cnt = mcp->mb[3]; | 2056 | *cur_xchg_cnt = mcp->mb[3]; |
@@ -2041,6 +2062,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, | |||
2041 | *orig_iocb_cnt = mcp->mb[10]; | 2062 | *orig_iocb_cnt = mcp->mb[10]; |
2042 | if (vha->hw->flags.npiv_supported && max_npiv_vports) | 2063 | if (vha->hw->flags.npiv_supported && max_npiv_vports) |
2043 | *max_npiv_vports = mcp->mb[11]; | 2064 | *max_npiv_vports = mcp->mb[11]; |
2065 | if (IS_QLA81XX(vha->hw) && max_fcfs) | ||
2066 | *max_fcfs = mcp->mb[12]; | ||
2044 | } | 2067 | } |
2045 | 2068 | ||
2046 | return (rval); | 2069 | return (rval); |
@@ -2313,6 +2336,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2313 | { | 2336 | { |
2314 | int rval, rval2; | 2337 | int rval, rval2; |
2315 | struct tsk_mgmt_cmd *tsk; | 2338 | struct tsk_mgmt_cmd *tsk; |
2339 | struct sts_entry_24xx *sts; | ||
2316 | dma_addr_t tsk_dma; | 2340 | dma_addr_t tsk_dma; |
2317 | scsi_qla_host_t *vha; | 2341 | scsi_qla_host_t *vha; |
2318 | struct qla_hw_data *ha; | 2342 | struct qla_hw_data *ha; |
@@ -2352,20 +2376,37 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2352 | sizeof(tsk->p.tsk.lun)); | 2376 | sizeof(tsk->p.tsk.lun)); |
2353 | } | 2377 | } |
2354 | 2378 | ||
2379 | sts = &tsk->p.sts; | ||
2355 | rval = qla2x00_issue_iocb(vha, tsk, tsk_dma, 0); | 2380 | rval = qla2x00_issue_iocb(vha, tsk, tsk_dma, 0); |
2356 | if (rval != QLA_SUCCESS) { | 2381 | if (rval != QLA_SUCCESS) { |
2357 | DEBUG2_3_11(printk("%s(%ld): failed to issue %s Reset IOCB " | 2382 | DEBUG2_3_11(printk("%s(%ld): failed to issue %s Reset IOCB " |
2358 | "(%x).\n", __func__, vha->host_no, name, rval)); | 2383 | "(%x).\n", __func__, vha->host_no, name, rval)); |
2359 | } else if (tsk->p.sts.entry_status != 0) { | 2384 | } else if (sts->entry_status != 0) { |
2360 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | 2385 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " |
2361 | "-- error status (%x).\n", __func__, vha->host_no, | 2386 | "-- error status (%x).\n", __func__, vha->host_no, |
2362 | tsk->p.sts.entry_status)); | 2387 | sts->entry_status)); |
2363 | rval = QLA_FUNCTION_FAILED; | 2388 | rval = QLA_FUNCTION_FAILED; |
2364 | } else if (tsk->p.sts.comp_status != | 2389 | } else if (sts->comp_status != |
2365 | __constant_cpu_to_le16(CS_COMPLETE)) { | 2390 | __constant_cpu_to_le16(CS_COMPLETE)) { |
2366 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | 2391 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " |
2367 | "-- completion status (%x).\n", __func__, | 2392 | "-- completion status (%x).\n", __func__, |
2368 | vha->host_no, le16_to_cpu(tsk->p.sts.comp_status))); | 2393 | vha->host_no, le16_to_cpu(sts->comp_status))); |
2394 | rval = QLA_FUNCTION_FAILED; | ||
2395 | } else if (!(le16_to_cpu(sts->scsi_status) & | ||
2396 | SS_RESPONSE_INFO_LEN_VALID)) { | ||
2397 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2398 | "-- no response info (%x).\n", __func__, vha->host_no, | ||
2399 | le16_to_cpu(sts->scsi_status))); | ||
2400 | rval = QLA_FUNCTION_FAILED; | ||
2401 | } else if (le32_to_cpu(sts->rsp_data_len) < 4) { | ||
2402 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2403 | "-- not enough response info (%d).\n", __func__, | ||
2404 | vha->host_no, le32_to_cpu(sts->rsp_data_len))); | ||
2405 | rval = QLA_FUNCTION_FAILED; | ||
2406 | } else if (sts->data[3]) { | ||
2407 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2408 | "-- response (%x).\n", __func__, | ||
2409 | vha->host_no, sts->data[3])); | ||
2369 | rval = QLA_FUNCTION_FAILED; | 2410 | rval = QLA_FUNCTION_FAILED; |
2370 | } | 2411 | } |
2371 | 2412 | ||
@@ -2507,6 +2548,9 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma, | |||
2507 | if (!IS_FWI2_CAPABLE(vha->hw)) | 2548 | if (!IS_FWI2_CAPABLE(vha->hw)) |
2508 | return QLA_FUNCTION_FAILED; | 2549 | return QLA_FUNCTION_FAILED; |
2509 | 2550 | ||
2551 | if (unlikely(pci_channel_offline(vha->hw->pdev))) | ||
2552 | return QLA_FUNCTION_FAILED; | ||
2553 | |||
2510 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 2554 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
2511 | 2555 | ||
2512 | mcp->mb[0] = MBC_TRACE_CONTROL; | 2556 | mcp->mb[0] = MBC_TRACE_CONTROL; |
@@ -2542,6 +2586,9 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha) | |||
2542 | if (!IS_FWI2_CAPABLE(vha->hw)) | 2586 | if (!IS_FWI2_CAPABLE(vha->hw)) |
2543 | return QLA_FUNCTION_FAILED; | 2587 | return QLA_FUNCTION_FAILED; |
2544 | 2588 | ||
2589 | if (unlikely(pci_channel_offline(vha->hw->pdev))) | ||
2590 | return QLA_FUNCTION_FAILED; | ||
2591 | |||
2545 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 2592 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
2546 | 2593 | ||
2547 | mcp->mb[0] = MBC_TRACE_CONTROL; | 2594 | mcp->mb[0] = MBC_TRACE_CONTROL; |
@@ -2572,6 +2619,9 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, | |||
2572 | if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw)) | 2619 | if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw)) |
2573 | return QLA_FUNCTION_FAILED; | 2620 | return QLA_FUNCTION_FAILED; |
2574 | 2621 | ||
2622 | if (unlikely(pci_channel_offline(vha->hw->pdev))) | ||
2623 | return QLA_FUNCTION_FAILED; | ||
2624 | |||
2575 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 2625 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
2576 | 2626 | ||
2577 | mcp->mb[0] = MBC_TRACE_CONTROL; | 2627 | mcp->mb[0] = MBC_TRACE_CONTROL; |
@@ -2616,6 +2666,9 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd) | |||
2616 | if (!IS_FWI2_CAPABLE(vha->hw)) | 2666 | if (!IS_FWI2_CAPABLE(vha->hw)) |
2617 | return QLA_FUNCTION_FAILED; | 2667 | return QLA_FUNCTION_FAILED; |
2618 | 2668 | ||
2669 | if (unlikely(pci_channel_offline(vha->hw->pdev))) | ||
2670 | return QLA_FUNCTION_FAILED; | ||
2671 | |||
2619 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 2672 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
2620 | 2673 | ||
2621 | mcp->mb[0] = MBC_TRACE_CONTROL; | 2674 | mcp->mb[0] = MBC_TRACE_CONTROL; |
@@ -2759,8 +2812,10 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, | |||
2759 | vp_idx, MSB(stat), | 2812 | vp_idx, MSB(stat), |
2760 | rptid_entry->port_id[2], rptid_entry->port_id[1], | 2813 | rptid_entry->port_id[2], rptid_entry->port_id[1], |
2761 | rptid_entry->port_id[0])); | 2814 | rptid_entry->port_id[0])); |
2762 | if (vp_idx == 0) | 2815 | |
2763 | return; | 2816 | vp = vha; |
2817 | if (vp_idx == 0 && (MSB(stat) != 1)) | ||
2818 | goto reg_needed; | ||
2764 | 2819 | ||
2765 | if (MSB(stat) == 1) { | 2820 | if (MSB(stat) == 1) { |
2766 | DEBUG2(printk("scsi(%ld): Could not acquire ID for " | 2821 | DEBUG2(printk("scsi(%ld): Could not acquire ID for " |
@@ -2783,8 +2838,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, | |||
2783 | * response queue. Handle it in dpc context. | 2838 | * response queue. Handle it in dpc context. |
2784 | */ | 2839 | */ |
2785 | set_bit(VP_IDX_ACQUIRED, &vp->vp_flags); | 2840 | set_bit(VP_IDX_ACQUIRED, &vp->vp_flags); |
2786 | set_bit(VP_DPC_NEEDED, &vha->dpc_flags); | ||
2787 | 2841 | ||
2842 | reg_needed: | ||
2843 | set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags); | ||
2844 | set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags); | ||
2845 | set_bit(VP_DPC_NEEDED, &vha->dpc_flags); | ||
2788 | qla2xxx_wake_dpc(vha); | 2846 | qla2xxx_wake_dpc(vha); |
2789 | } | 2847 | } |
2790 | } | 2848 | } |
@@ -3585,6 +3643,157 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data) | |||
3585 | } | 3643 | } |
3586 | 3644 | ||
3587 | int | 3645 | int |
3646 | qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mresp) | ||
3647 | { | ||
3648 | int rval; | ||
3649 | mbx_cmd_t mc; | ||
3650 | mbx_cmd_t *mcp = &mc; | ||
3651 | uint32_t iter_cnt = 0x1; | ||
3652 | |||
3653 | DEBUG11(printk("scsi(%ld): entered.\n", vha->host_no)); | ||
3654 | |||
3655 | memset(mcp->mb, 0 , sizeof(mcp->mb)); | ||
3656 | mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; | ||
3657 | mcp->mb[1] = mreq->options | BIT_6; // BIT_6 specifies 64 bit addressing | ||
3658 | |||
3659 | /* transfer count */ | ||
3660 | mcp->mb[10] = LSW(mreq->transfer_size); | ||
3661 | mcp->mb[11] = MSW(mreq->transfer_size); | ||
3662 | |||
3663 | /* send data address */ | ||
3664 | mcp->mb[14] = LSW(mreq->send_dma); | ||
3665 | mcp->mb[15] = MSW(mreq->send_dma); | ||
3666 | mcp->mb[20] = LSW(MSD(mreq->send_dma)); | ||
3667 | mcp->mb[21] = MSW(MSD(mreq->send_dma)); | ||
3668 | |||
3669 | /* recieve data address */ | ||
3670 | mcp->mb[16] = LSW(mreq->rcv_dma); | ||
3671 | mcp->mb[17] = MSW(mreq->rcv_dma); | ||
3672 | mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); | ||
3673 | mcp->mb[7] = MSW(MSD(mreq->rcv_dma)); | ||
3674 | |||
3675 | /* Iteration count */ | ||
3676 | mcp->mb[18] = LSW(iter_cnt); | ||
3677 | mcp->mb[19] = MSW(iter_cnt); | ||
3678 | |||
3679 | mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15| | ||
3680 | MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; | ||
3681 | if (IS_QLA81XX(vha->hw)) | ||
3682 | mcp->out_mb |= MBX_2; | ||
3683 | mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0; | ||
3684 | |||
3685 | mcp->buf_size = mreq->transfer_size; | ||
3686 | mcp->tov = MBX_TOV_SECONDS; | ||
3687 | mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; | ||
3688 | |||
3689 | rval = qla2x00_mailbox_command(vha, mcp); | ||
3690 | |||
3691 | if (rval != QLA_SUCCESS) { | ||
3692 | DEBUG2(printk(KERN_WARNING | ||
3693 | "(%ld): failed=%x mb[0]=0x%x " | ||
3694 | "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, | ||
3695 | mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[18], mcp->mb[19])); | ||
3696 | } else { | ||
3697 | DEBUG2(printk(KERN_WARNING | ||
3698 | "scsi(%ld): done.\n", vha->host_no)); | ||
3699 | } | ||
3700 | |||
3701 | /* Copy mailbox information */ | ||
3702 | memcpy( mresp, mcp->mb, 64); | ||
3703 | mresp[3] = mcp->mb[18]; | ||
3704 | mresp[4] = mcp->mb[19]; | ||
3705 | return rval; | ||
3706 | } | ||
3707 | |||
3708 | int | ||
3709 | qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, uint16_t *mresp) | ||
3710 | { | ||
3711 | int rval; | ||
3712 | mbx_cmd_t mc; | ||
3713 | mbx_cmd_t *mcp = &mc; | ||
3714 | struct qla_hw_data *ha = vha->hw; | ||
3715 | |||
3716 | DEBUG11(printk("scsi(%ld): entered.\n", vha->host_no)); | ||
3717 | |||
3718 | memset(mcp->mb, 0 , sizeof(mcp->mb)); | ||
3719 | mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; | ||
3720 | mcp->mb[1] = mreq->options | BIT_6; /* BIT_6 specifies 64bit address */ | ||
3721 | if (IS_QLA81XX(ha)) | ||
3722 | mcp->mb[1] |= BIT_15; | ||
3723 | mcp->mb[2] = IS_QLA81XX(ha) ? vha->fcoe_fcf_idx : 0; | ||
3724 | mcp->mb[16] = LSW(mreq->rcv_dma); | ||
3725 | mcp->mb[17] = MSW(mreq->rcv_dma); | ||
3726 | mcp->mb[6] = LSW(MSD(mreq->rcv_dma)); | ||
3727 | mcp->mb[7] = MSW(MSD(mreq->rcv_dma)); | ||
3728 | |||
3729 | mcp->mb[10] = LSW(mreq->transfer_size); | ||
3730 | |||
3731 | mcp->mb[14] = LSW(mreq->send_dma); | ||
3732 | mcp->mb[15] = MSW(mreq->send_dma); | ||
3733 | mcp->mb[20] = LSW(MSD(mreq->send_dma)); | ||
3734 | mcp->mb[21] = MSW(MSD(mreq->send_dma)); | ||
3735 | |||
3736 | mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15| | ||
3737 | MBX_14|MBX_10|MBX_7|MBX_6|MBX_1|MBX_0; | ||
3738 | if (IS_QLA81XX(ha)) | ||
3739 | mcp->out_mb |= MBX_2; | ||
3740 | |||
3741 | mcp->in_mb = MBX_0; | ||
3742 | if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha)) | ||
3743 | mcp->in_mb |= MBX_1; | ||
3744 | if (IS_QLA81XX(ha)) | ||
3745 | mcp->in_mb |= MBX_3; | ||
3746 | |||
3747 | mcp->tov = MBX_TOV_SECONDS; | ||
3748 | mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; | ||
3749 | mcp->buf_size = mreq->transfer_size; | ||
3750 | |||
3751 | rval = qla2x00_mailbox_command(vha, mcp); | ||
3752 | |||
3753 | if (rval != QLA_SUCCESS) { | ||
3754 | DEBUG2(printk(KERN_WARNING | ||
3755 | "(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n", | ||
3756 | vha->host_no, rval, mcp->mb[0], mcp->mb[1])); | ||
3757 | } else { | ||
3758 | DEBUG2(printk(KERN_WARNING | ||
3759 | "scsi(%ld): done.\n", vha->host_no)); | ||
3760 | } | ||
3761 | |||
3762 | /* Copy mailbox information */ | ||
3763 | memcpy( mresp, mcp->mb, 32); | ||
3764 | return rval; | ||
3765 | } | ||
3766 | int | ||
3767 | qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic, | ||
3768 | uint16_t *cmd_status) | ||
3769 | { | ||
3770 | int rval; | ||
3771 | mbx_cmd_t mc; | ||
3772 | mbx_cmd_t *mcp = &mc; | ||
3773 | |||
3774 | DEBUG16(printk("%s(%ld): enable_diag=%d entered.\n", __func__, | ||
3775 | ha->host_no, enable_diagnostic)); | ||
3776 | |||
3777 | mcp->mb[0] = MBC_ISP84XX_RESET; | ||
3778 | mcp->mb[1] = enable_diagnostic; | ||
3779 | mcp->out_mb = MBX_1|MBX_0; | ||
3780 | mcp->in_mb = MBX_1|MBX_0; | ||
3781 | mcp->tov = MBX_TOV_SECONDS; | ||
3782 | mcp->flags = MBX_DMA_OUT|MBX_DMA_IN|IOCTL_CMD; | ||
3783 | rval = qla2x00_mailbox_command(ha, mcp); | ||
3784 | |||
3785 | /* Return mailbox statuses. */ | ||
3786 | *cmd_status = mcp->mb[0]; | ||
3787 | if (rval != QLA_SUCCESS) | ||
3788 | DEBUG16(printk("%s(%ld): failed=%x.\n", __func__, ha->host_no, | ||
3789 | rval)); | ||
3790 | else | ||
3791 | DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
3792 | |||
3793 | return rval; | ||
3794 | } | ||
3795 | |||
3796 | int | ||
3588 | qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) | 3797 | qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) |
3589 | { | 3798 | { |
3590 | int rval; | 3799 | int rval; |
@@ -3615,3 +3824,36 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) | |||
3615 | 3824 | ||
3616 | return rval; | 3825 | return rval; |
3617 | } | 3826 | } |
3827 | |||
3828 | int | ||
3829 | qla2x00_get_data_rate(scsi_qla_host_t *vha) | ||
3830 | { | ||
3831 | int rval; | ||
3832 | mbx_cmd_t mc; | ||
3833 | mbx_cmd_t *mcp = &mc; | ||
3834 | struct qla_hw_data *ha = vha->hw; | ||
3835 | |||
3836 | if (!IS_FWI2_CAPABLE(ha)) | ||
3837 | return QLA_FUNCTION_FAILED; | ||
3838 | |||
3839 | DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, vha->host_no)); | ||
3840 | |||
3841 | mcp->mb[0] = MBC_DATA_RATE; | ||
3842 | mcp->mb[1] = 0; | ||
3843 | mcp->out_mb = MBX_1|MBX_0; | ||
3844 | mcp->in_mb = MBX_2|MBX_1|MBX_0; | ||
3845 | mcp->tov = MBX_TOV_SECONDS; | ||
3846 | mcp->flags = 0; | ||
3847 | rval = qla2x00_mailbox_command(vha, mcp); | ||
3848 | if (rval != QLA_SUCCESS) { | ||
3849 | DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n", | ||
3850 | __func__, vha->host_no, rval, mcp->mb[0])); | ||
3851 | } else { | ||
3852 | DEBUG11(printk(KERN_INFO | ||
3853 | "%s(%ld): done.\n", __func__, vha->host_no)); | ||
3854 | if (mcp->mb[1] != 0x7) | ||
3855 | ha->link_data_rate = mcp->mb[1]; | ||
3856 | } | ||
3857 | |||
3858 | return rval; | ||
3859 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index e07b3617f019..8220e7b9799b 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/moduleparam.h> | 10 | #include <linux/moduleparam.h> |
11 | #include <linux/vmalloc.h> | 11 | #include <linux/vmalloc.h> |
12 | #include <linux/slab.h> | ||
12 | #include <linux/list.h> | 13 | #include <linux/list.h> |
13 | 14 | ||
14 | #include <scsi/scsi_tcq.h> | 15 | #include <scsi/scsi_tcq.h> |
@@ -382,8 +383,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) | |||
382 | vha->mgmt_svr_loop_id = 10 + vha->vp_idx; | 383 | vha->mgmt_svr_loop_id = 10 + vha->vp_idx; |
383 | 384 | ||
384 | vha->dpc_flags = 0L; | 385 | vha->dpc_flags = 0L; |
385 | set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); | ||
386 | set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); | ||
387 | 386 | ||
388 | /* | 387 | /* |
389 | * To fix the issue of processing a parent's RSCN for the vport before | 388 | * To fix the issue of processing a parent's RSCN for the vport before |
@@ -638,11 +637,15 @@ failed: | |||
638 | 637 | ||
639 | static void qla_do_work(struct work_struct *work) | 638 | static void qla_do_work(struct work_struct *work) |
640 | { | 639 | { |
640 | unsigned long flags; | ||
641 | struct rsp_que *rsp = container_of(work, struct rsp_que, q_work); | 641 | struct rsp_que *rsp = container_of(work, struct rsp_que, q_work); |
642 | struct scsi_qla_host *vha; | 642 | struct scsi_qla_host *vha; |
643 | struct qla_hw_data *ha = rsp->hw; | ||
643 | 644 | ||
644 | vha = qla25xx_get_host(rsp); | 645 | spin_lock_irqsave(&rsp->hw->hardware_lock, flags); |
646 | vha = pci_get_drvdata(ha->pdev); | ||
645 | qla24xx_process_response_queue(vha, rsp); | 647 | qla24xx_process_response_queue(vha, rsp); |
648 | spin_unlock_irqrestore(&rsp->hw->hardware_lock, flags); | ||
646 | } | 649 | } |
647 | 650 | ||
648 | /* create response queue */ | 651 | /* create response queue */ |
@@ -698,6 +701,10 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, | |||
698 | /* Use alternate PCI devfn */ | 701 | /* Use alternate PCI devfn */ |
699 | if (LSB(rsp->rid)) | 702 | if (LSB(rsp->rid)) |
700 | options |= BIT_5; | 703 | options |= BIT_5; |
704 | /* Enable MSIX handshake mode on for uncapable adapters */ | ||
705 | if (!IS_MSIX_NACK_CAPABLE(ha)) | ||
706 | options |= BIT_6; | ||
707 | |||
701 | rsp->options = options; | 708 | rsp->options = options; |
702 | rsp->id = que_id; | 709 | rsp->id = que_id; |
703 | reg = ISP_QUE_REG(ha, que_id); | 710 | reg = ISP_QUE_REG(ha, que_id); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b79fca7d461b..48c37e38ed01 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include <linux/mutex.h> | 13 | #include <linux/mutex.h> |
14 | #include <linux/kobject.h> | ||
15 | #include <linux/slab.h> | ||
14 | 16 | ||
15 | #include <scsi/scsi_tcq.h> | 17 | #include <scsi/scsi_tcq.h> |
16 | #include <scsi/scsicam.h> | 18 | #include <scsi/scsicam.h> |
@@ -77,21 +79,6 @@ module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR); | |||
77 | MODULE_PARM_DESC(ql2xmaxqdepth, | 79 | MODULE_PARM_DESC(ql2xmaxqdepth, |
78 | "Maximum queue depth to report for target devices."); | 80 | "Maximum queue depth to report for target devices."); |
79 | 81 | ||
80 | int ql2xqfulltracking = 1; | ||
81 | module_param(ql2xqfulltracking, int, S_IRUGO|S_IWUSR); | ||
82 | MODULE_PARM_DESC(ql2xqfulltracking, | ||
83 | "Controls whether the driver tracks queue full status " | ||
84 | "returns and dynamically adjusts a scsi device's queue " | ||
85 | "depth. Default is 1, perform tracking. Set to 0 to " | ||
86 | "disable dynamic tracking and adjustment of queue depth."); | ||
87 | |||
88 | int ql2xqfullrampup = 120; | ||
89 | module_param(ql2xqfullrampup, int, S_IRUGO|S_IWUSR); | ||
90 | MODULE_PARM_DESC(ql2xqfullrampup, | ||
91 | "Number of seconds to wait to begin to ramp-up the queue " | ||
92 | "depth for a device after a queue-full condition has been " | ||
93 | "detected. Default is 120 seconds."); | ||
94 | |||
95 | int ql2xiidmaenable=1; | 82 | int ql2xiidmaenable=1; |
96 | module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR); | 83 | module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR); |
97 | MODULE_PARM_DESC(ql2xiidmaenable, | 84 | MODULE_PARM_DESC(ql2xiidmaenable, |
@@ -121,6 +108,12 @@ MODULE_PARM_DESC(ql2xfwloadbin, | |||
121 | " 1 -- load firmware from flash.\n" | 108 | " 1 -- load firmware from flash.\n" |
122 | " 0 -- use default semantics.\n"); | 109 | " 0 -- use default semantics.\n"); |
123 | 110 | ||
111 | int ql2xetsenable; | ||
112 | module_param(ql2xetsenable, int, S_IRUGO|S_IRUSR); | ||
113 | MODULE_PARM_DESC(ql2xetsenable, | ||
114 | "Enables firmware ETS burst." | ||
115 | "Default is 0 - skip ETS enablement."); | ||
116 | |||
124 | /* | 117 | /* |
125 | * SCSI host template entry points | 118 | * SCSI host template entry points |
126 | */ | 119 | */ |
@@ -137,7 +130,7 @@ static int qla2xxx_eh_target_reset(struct scsi_cmnd *); | |||
137 | static int qla2xxx_eh_bus_reset(struct scsi_cmnd *); | 130 | static int qla2xxx_eh_bus_reset(struct scsi_cmnd *); |
138 | static int qla2xxx_eh_host_reset(struct scsi_cmnd *); | 131 | static int qla2xxx_eh_host_reset(struct scsi_cmnd *); |
139 | 132 | ||
140 | static int qla2x00_change_queue_depth(struct scsi_device *, int); | 133 | static int qla2x00_change_queue_depth(struct scsi_device *, int, int); |
141 | static int qla2x00_change_queue_type(struct scsi_device *, int); | 134 | static int qla2x00_change_queue_type(struct scsi_device *, int); |
142 | 135 | ||
143 | struct scsi_host_template qla2xxx_driver_template = { | 136 | struct scsi_host_template qla2xxx_driver_template = { |
@@ -489,11 +482,11 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
489 | srb_t *sp; | 482 | srb_t *sp; |
490 | int rval; | 483 | int rval; |
491 | 484 | ||
492 | if (unlikely(pci_channel_offline(ha->pdev))) { | 485 | if (ha->flags.eeh_busy) { |
493 | if (ha->pdev->error_state == pci_channel_io_frozen) | 486 | if (ha->flags.pci_channel_io_perm_failure) |
494 | cmd->result = DID_REQUEUE << 16; | ||
495 | else | ||
496 | cmd->result = DID_NO_CONNECT << 16; | 487 | cmd->result = DID_NO_CONNECT << 16; |
488 | else | ||
489 | cmd->result = DID_REQUEUE << 16; | ||
497 | goto qc24_fail_command; | 490 | goto qc24_fail_command; |
498 | } | 491 | } |
499 | 492 | ||
@@ -566,8 +559,15 @@ qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) | |||
566 | #define ABORT_POLLING_PERIOD 1000 | 559 | #define ABORT_POLLING_PERIOD 1000 |
567 | #define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD)) | 560 | #define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD)) |
568 | unsigned long wait_iter = ABORT_WAIT_ITER; | 561 | unsigned long wait_iter = ABORT_WAIT_ITER; |
562 | scsi_qla_host_t *vha = shost_priv(cmd->device->host); | ||
563 | struct qla_hw_data *ha = vha->hw; | ||
569 | int ret = QLA_SUCCESS; | 564 | int ret = QLA_SUCCESS; |
570 | 565 | ||
566 | if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) { | ||
567 | DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n")); | ||
568 | return ret; | ||
569 | } | ||
570 | |||
571 | while (CMD_SP(cmd) && wait_iter--) { | 571 | while (CMD_SP(cmd) && wait_iter--) { |
572 | msleep(ABORT_POLLING_PERIOD); | 572 | msleep(ABORT_POLLING_PERIOD); |
573 | } | 573 | } |
@@ -689,61 +689,6 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha) | |||
689 | return (return_status); | 689 | return (return_status); |
690 | } | 690 | } |
691 | 691 | ||
692 | void | ||
693 | qla2x00_abort_fcport_cmds(fc_port_t *fcport) | ||
694 | { | ||
695 | int cnt; | ||
696 | unsigned long flags; | ||
697 | srb_t *sp; | ||
698 | scsi_qla_host_t *vha = fcport->vha; | ||
699 | struct qla_hw_data *ha = vha->hw; | ||
700 | struct req_que *req; | ||
701 | |||
702 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
703 | req = vha->req; | ||
704 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { | ||
705 | sp = req->outstanding_cmds[cnt]; | ||
706 | if (!sp) | ||
707 | continue; | ||
708 | if (sp->fcport != fcport) | ||
709 | continue; | ||
710 | if (sp->ctx) | ||
711 | continue; | ||
712 | |||
713 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
714 | if (ha->isp_ops->abort_command(sp)) { | ||
715 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
716 | "Abort failed -- %lx\n", | ||
717 | sp->cmd->serial_number)); | ||
718 | } else { | ||
719 | if (qla2x00_eh_wait_on_command(sp->cmd) != | ||
720 | QLA_SUCCESS) | ||
721 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
722 | "Abort failed while waiting -- %lx\n", | ||
723 | sp->cmd->serial_number)); | ||
724 | } | ||
725 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
726 | } | ||
727 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
728 | } | ||
729 | |||
730 | static void | ||
731 | qla2x00_block_error_handler(struct scsi_cmnd *cmnd) | ||
732 | { | ||
733 | struct Scsi_Host *shost = cmnd->device->host; | ||
734 | struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); | ||
735 | unsigned long flags; | ||
736 | |||
737 | spin_lock_irqsave(shost->host_lock, flags); | ||
738 | while (rport->port_state == FC_PORTSTATE_BLOCKED) { | ||
739 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
740 | msleep(1000); | ||
741 | spin_lock_irqsave(shost->host_lock, flags); | ||
742 | } | ||
743 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
744 | return; | ||
745 | } | ||
746 | |||
747 | /************************************************************************** | 692 | /************************************************************************** |
748 | * qla2xxx_eh_abort | 693 | * qla2xxx_eh_abort |
749 | * | 694 | * |
@@ -773,7 +718,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
773 | struct req_que *req = vha->req; | 718 | struct req_que *req = vha->req; |
774 | srb_t *spt; | 719 | srb_t *spt; |
775 | 720 | ||
776 | qla2x00_block_error_handler(cmd); | 721 | fc_block_scsi_eh(cmd); |
777 | 722 | ||
778 | if (!CMD_SP(cmd)) | 723 | if (!CMD_SP(cmd)) |
779 | return SUCCESS; | 724 | return SUCCESS; |
@@ -904,7 +849,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, | |||
904 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 849 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
905 | int err; | 850 | int err; |
906 | 851 | ||
907 | qla2x00_block_error_handler(cmd); | 852 | fc_block_scsi_eh(cmd); |
908 | 853 | ||
909 | if (!fcport) | 854 | if (!fcport) |
910 | return FAILED; | 855 | return FAILED; |
@@ -984,7 +929,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
984 | unsigned long serial; | 929 | unsigned long serial; |
985 | srb_t *sp = (srb_t *) CMD_SP(cmd); | 930 | srb_t *sp = (srb_t *) CMD_SP(cmd); |
986 | 931 | ||
987 | qla2x00_block_error_handler(cmd); | 932 | fc_block_scsi_eh(cmd); |
988 | 933 | ||
989 | id = cmd->device->id; | 934 | id = cmd->device->id; |
990 | lun = cmd->device->lun; | 935 | lun = cmd->device->lun; |
@@ -1047,7 +992,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1047 | srb_t *sp = (srb_t *) CMD_SP(cmd); | 992 | srb_t *sp = (srb_t *) CMD_SP(cmd); |
1048 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | 993 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); |
1049 | 994 | ||
1050 | qla2x00_block_error_handler(cmd); | 995 | fc_block_scsi_eh(cmd); |
1051 | 996 | ||
1052 | id = cmd->device->id; | 997 | id = cmd->device->id; |
1053 | lun = cmd->device->lun; | 998 | lun = cmd->device->lun; |
@@ -1119,6 +1064,20 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) | |||
1119 | struct fc_port *fcport; | 1064 | struct fc_port *fcport; |
1120 | struct qla_hw_data *ha = vha->hw; | 1065 | struct qla_hw_data *ha = vha->hw; |
1121 | 1066 | ||
1067 | if (ha->flags.enable_target_reset) { | ||
1068 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | ||
1069 | if (fcport->port_type != FCT_TARGET) | ||
1070 | continue; | ||
1071 | |||
1072 | ret = ha->isp_ops->target_reset(fcport, 0, 0); | ||
1073 | if (ret != QLA_SUCCESS) { | ||
1074 | DEBUG2_3(printk("%s(%ld): bus_reset failed: " | ||
1075 | "target_reset=%d d_id=%x.\n", __func__, | ||
1076 | vha->host_no, ret, fcport->d_id.b24)); | ||
1077 | } | ||
1078 | } | ||
1079 | } | ||
1080 | |||
1122 | if (ha->flags.enable_lip_full_login && !IS_QLA81XX(ha)) { | 1081 | if (ha->flags.enable_lip_full_login && !IS_QLA81XX(ha)) { |
1123 | ret = qla2x00_full_login_lip(vha); | 1082 | ret = qla2x00_full_login_lip(vha); |
1124 | if (ret != QLA_SUCCESS) { | 1083 | if (ret != QLA_SUCCESS) { |
@@ -1141,19 +1100,6 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) | |||
1141 | qla2x00_wait_for_loop_ready(vha); | 1100 | qla2x00_wait_for_loop_ready(vha); |
1142 | } | 1101 | } |
1143 | 1102 | ||
1144 | if (ha->flags.enable_target_reset) { | ||
1145 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | ||
1146 | if (fcport->port_type != FCT_TARGET) | ||
1147 | continue; | ||
1148 | |||
1149 | ret = ha->isp_ops->target_reset(fcport, 0, 0); | ||
1150 | if (ret != QLA_SUCCESS) { | ||
1151 | DEBUG2_3(printk("%s(%ld): bus_reset failed: " | ||
1152 | "target_reset=%d d_id=%x.\n", __func__, | ||
1153 | vha->host_no, ret, fcport->d_id.b24)); | ||
1154 | } | ||
1155 | } | ||
1156 | } | ||
1157 | /* Issue marker command only when we are going to start the I/O */ | 1103 | /* Issue marker command only when we are going to start the I/O */ |
1158 | vha->marker_needed = 1; | 1104 | vha->marker_needed = 1; |
1159 | 1105 | ||
@@ -1184,8 +1130,19 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1184 | qla2x00_sp_compl(ha, sp); | 1130 | qla2x00_sp_compl(ha, sp); |
1185 | } else { | 1131 | } else { |
1186 | ctx = sp->ctx; | 1132 | ctx = sp->ctx; |
1187 | del_timer_sync(&ctx->timer); | 1133 | if (ctx->type == SRB_LOGIN_CMD || ctx->type == SRB_LOGOUT_CMD) { |
1188 | ctx->free(sp); | 1134 | del_timer_sync(&ctx->timer); |
1135 | ctx->free(sp); | ||
1136 | } else { | ||
1137 | struct srb_bsg* sp_bsg = (struct srb_bsg*)sp->ctx; | ||
1138 | if (sp_bsg->bsg_job->request->msgcode == FC_BSG_HST_CT) | ||
1139 | kfree(sp->fcport); | ||
1140 | sp_bsg->bsg_job->req->errors = 0; | ||
1141 | sp_bsg->bsg_job->reply->result = res; | ||
1142 | sp_bsg->bsg_job->job_done(sp_bsg->bsg_job); | ||
1143 | kfree(sp->ctx); | ||
1144 | mempool_free(sp, ha->srb_mempool); | ||
1145 | } | ||
1189 | } | 1146 | } |
1190 | } | 1147 | } |
1191 | } | 1148 | } |
@@ -1212,7 +1169,6 @@ qla2xxx_slave_configure(struct scsi_device *sdev) | |||
1212 | scsi_qla_host_t *vha = shost_priv(sdev->host); | 1169 | scsi_qla_host_t *vha = shost_priv(sdev->host); |
1213 | struct qla_hw_data *ha = vha->hw; | 1170 | struct qla_hw_data *ha = vha->hw; |
1214 | struct fc_rport *rport = starget_to_rport(sdev->sdev_target); | 1171 | struct fc_rport *rport = starget_to_rport(sdev->sdev_target); |
1215 | fc_port_t *fcport = *(fc_port_t **)rport->dd_data; | ||
1216 | struct req_que *req = vha->req; | 1172 | struct req_que *req = vha->req; |
1217 | 1173 | ||
1218 | if (sdev->tagged_supported) | 1174 | if (sdev->tagged_supported) |
@@ -1221,8 +1177,6 @@ qla2xxx_slave_configure(struct scsi_device *sdev) | |||
1221 | scsi_deactivate_tcq(sdev, req->max_q_depth); | 1177 | scsi_deactivate_tcq(sdev, req->max_q_depth); |
1222 | 1178 | ||
1223 | rport->dev_loss_tmo = ha->port_down_retry_count; | 1179 | rport->dev_loss_tmo = ha->port_down_retry_count; |
1224 | if (sdev->type == TYPE_TAPE) | ||
1225 | fcport->flags |= FCF_TAPE_PRESENT; | ||
1226 | 1180 | ||
1227 | return 0; | 1181 | return 0; |
1228 | } | 1182 | } |
@@ -1233,10 +1187,61 @@ qla2xxx_slave_destroy(struct scsi_device *sdev) | |||
1233 | sdev->hostdata = NULL; | 1187 | sdev->hostdata = NULL; |
1234 | } | 1188 | } |
1235 | 1189 | ||
1190 | static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth) | ||
1191 | { | ||
1192 | fc_port_t *fcport = (struct fc_port *) sdev->hostdata; | ||
1193 | |||
1194 | if (!scsi_track_queue_full(sdev, qdepth)) | ||
1195 | return; | ||
1196 | |||
1197 | DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw, | ||
1198 | "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n", | ||
1199 | fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun, | ||
1200 | sdev->queue_depth)); | ||
1201 | } | ||
1202 | |||
1203 | static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth) | ||
1204 | { | ||
1205 | fc_port_t *fcport = sdev->hostdata; | ||
1206 | struct scsi_qla_host *vha = fcport->vha; | ||
1207 | struct qla_hw_data *ha = vha->hw; | ||
1208 | struct req_que *req = NULL; | ||
1209 | |||
1210 | req = vha->req; | ||
1211 | if (!req) | ||
1212 | return; | ||
1213 | |||
1214 | if (req->max_q_depth <= sdev->queue_depth || req->max_q_depth < qdepth) | ||
1215 | return; | ||
1216 | |||
1217 | if (sdev->ordered_tags) | ||
1218 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, qdepth); | ||
1219 | else | ||
1220 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth); | ||
1221 | |||
1222 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
1223 | "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n", | ||
1224 | fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun, | ||
1225 | sdev->queue_depth)); | ||
1226 | } | ||
1227 | |||
1236 | static int | 1228 | static int |
1237 | qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth) | 1229 | qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) |
1238 | { | 1230 | { |
1239 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); | 1231 | switch (reason) { |
1232 | case SCSI_QDEPTH_DEFAULT: | ||
1233 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); | ||
1234 | break; | ||
1235 | case SCSI_QDEPTH_QFULL: | ||
1236 | qla2x00_handle_queue_full(sdev, qdepth); | ||
1237 | break; | ||
1238 | case SCSI_QDEPTH_RAMP_UP: | ||
1239 | qla2x00_adjust_sdev_qdepth_up(sdev, qdepth); | ||
1240 | break; | ||
1241 | default: | ||
1242 | return -EOPNOTSUPP; | ||
1243 | } | ||
1244 | |||
1240 | return sdev->queue_depth; | 1245 | return sdev->queue_depth; |
1241 | } | 1246 | } |
1242 | 1247 | ||
@@ -1672,9 +1677,11 @@ skip_pio: | |||
1672 | 1677 | ||
1673 | /* Determine queue resources */ | 1678 | /* Determine queue resources */ |
1674 | ha->max_req_queues = ha->max_rsp_queues = 1; | 1679 | ha->max_req_queues = ha->max_rsp_queues = 1; |
1675 | if ((ql2xmaxqueues <= 1 || ql2xmultique_tag < 1) && | 1680 | if ((ql2xmaxqueues <= 1 && !ql2xmultique_tag) || |
1681 | (ql2xmaxqueues > 1 && ql2xmultique_tag) || | ||
1676 | (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))) | 1682 | (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))) |
1677 | goto mqiobase_exit; | 1683 | goto mqiobase_exit; |
1684 | |||
1678 | ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), | 1685 | ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), |
1679 | pci_resource_len(ha->pdev, 3)); | 1686 | pci_resource_len(ha->pdev, 3)); |
1680 | if (ha->mqiobase) { | 1687 | if (ha->mqiobase) { |
@@ -1790,6 +1797,12 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1790 | 1797 | ||
1791 | /* Set ISP-type information. */ | 1798 | /* Set ISP-type information. */ |
1792 | qla2x00_set_isp_flags(ha); | 1799 | qla2x00_set_isp_flags(ha); |
1800 | |||
1801 | /* Set EEH reset type to fundamental if required by hba */ | ||
1802 | if ( IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha)) { | ||
1803 | pdev->needs_freset = 1; | ||
1804 | } | ||
1805 | |||
1793 | /* Configure PCI I/O space */ | 1806 | /* Configure PCI I/O space */ |
1794 | ret = qla2x00_iospace_config(ha); | 1807 | ret = qla2x00_iospace_config(ha); |
1795 | if (ret) | 1808 | if (ret) |
@@ -1939,11 +1952,15 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1939 | host->max_channel = MAX_BUSES - 1; | 1952 | host->max_channel = MAX_BUSES - 1; |
1940 | host->max_lun = MAX_LUNS; | 1953 | host->max_lun = MAX_LUNS; |
1941 | host->transportt = qla2xxx_transport_template; | 1954 | host->transportt = qla2xxx_transport_template; |
1955 | sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC); | ||
1942 | 1956 | ||
1943 | /* Set up the irqs */ | 1957 | /* Set up the irqs */ |
1944 | ret = qla2x00_request_irqs(ha, rsp); | 1958 | ret = qla2x00_request_irqs(ha, rsp); |
1945 | if (ret) | 1959 | if (ret) |
1946 | goto probe_init_failed; | 1960 | goto probe_init_failed; |
1961 | |||
1962 | pci_save_state(pdev); | ||
1963 | |||
1947 | /* Alloc arrays of request and response ring ptrs */ | 1964 | /* Alloc arrays of request and response ring ptrs */ |
1948 | que_init: | 1965 | que_init: |
1949 | if (!qla2x00_alloc_queues(ha)) { | 1966 | if (!qla2x00_alloc_queues(ha)) { |
@@ -2016,13 +2033,13 @@ skip_dpc: | |||
2016 | DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", | 2033 | DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", |
2017 | base_vha->host_no, ha)); | 2034 | base_vha->host_no, ha)); |
2018 | 2035 | ||
2019 | base_vha->flags.init_done = 1; | ||
2020 | base_vha->flags.online = 1; | ||
2021 | |||
2022 | ret = scsi_add_host(host, &pdev->dev); | 2036 | ret = scsi_add_host(host, &pdev->dev); |
2023 | if (ret) | 2037 | if (ret) |
2024 | goto probe_failed; | 2038 | goto probe_failed; |
2025 | 2039 | ||
2040 | base_vha->flags.init_done = 1; | ||
2041 | base_vha->flags.online = 1; | ||
2042 | |||
2026 | ha->isp_ops->enable_intrs(ha); | 2043 | ha->isp_ops->enable_intrs(ha); |
2027 | 2044 | ||
2028 | scsi_scan_host(host); | 2045 | scsi_scan_host(host); |
@@ -2145,6 +2162,8 @@ qla2x00_remove_one(struct pci_dev *pdev) | |||
2145 | kfree(ha); | 2162 | kfree(ha); |
2146 | ha = NULL; | 2163 | ha = NULL; |
2147 | 2164 | ||
2165 | pci_disable_pcie_error_reporting(pdev); | ||
2166 | |||
2148 | pci_disable_device(pdev); | 2167 | pci_disable_device(pdev); |
2149 | pci_set_drvdata(pdev, NULL); | 2168 | pci_set_drvdata(pdev, NULL); |
2150 | } | 2169 | } |
@@ -2154,6 +2173,24 @@ qla2x00_free_device(scsi_qla_host_t *vha) | |||
2154 | { | 2173 | { |
2155 | struct qla_hw_data *ha = vha->hw; | 2174 | struct qla_hw_data *ha = vha->hw; |
2156 | 2175 | ||
2176 | qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); | ||
2177 | |||
2178 | /* Disable timer */ | ||
2179 | if (vha->timer_active) | ||
2180 | qla2x00_stop_timer(vha); | ||
2181 | |||
2182 | /* Kill the kernel thread for this host */ | ||
2183 | if (ha->dpc_thread) { | ||
2184 | struct task_struct *t = ha->dpc_thread; | ||
2185 | |||
2186 | /* | ||
2187 | * qla2xxx_wake_dpc checks for ->dpc_thread | ||
2188 | * so we need to zero it out. | ||
2189 | */ | ||
2190 | ha->dpc_thread = NULL; | ||
2191 | kthread_stop(t); | ||
2192 | } | ||
2193 | |||
2157 | qla25xx_delete_queues(vha); | 2194 | qla25xx_delete_queues(vha); |
2158 | 2195 | ||
2159 | if (ha->flags.fce_enabled) | 2196 | if (ha->flags.fce_enabled) |
@@ -2165,6 +2202,8 @@ qla2x00_free_device(scsi_qla_host_t *vha) | |||
2165 | /* Stop currently executing firmware. */ | 2202 | /* Stop currently executing firmware. */ |
2166 | qla2x00_try_to_stop_firmware(vha); | 2203 | qla2x00_try_to_stop_firmware(vha); |
2167 | 2204 | ||
2205 | vha->flags.online = 0; | ||
2206 | |||
2168 | /* turn-off interrupts on the card */ | 2207 | /* turn-off interrupts on the card */ |
2169 | if (ha->interrupts_on) | 2208 | if (ha->interrupts_on) |
2170 | ha->isp_ops->disable_intrs(ha); | 2209 | ha->isp_ops->disable_intrs(ha); |
@@ -2653,6 +2692,37 @@ qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE); | |||
2653 | qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); | 2692 | qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); |
2654 | qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); | 2693 | qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE); |
2655 | 2694 | ||
2695 | int | ||
2696 | qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code) | ||
2697 | { | ||
2698 | struct qla_work_evt *e; | ||
2699 | |||
2700 | e = qla2x00_alloc_work(vha, QLA_EVT_UEVENT); | ||
2701 | if (!e) | ||
2702 | return QLA_FUNCTION_FAILED; | ||
2703 | |||
2704 | e->u.uevent.code = code; | ||
2705 | return qla2x00_post_work(vha, e); | ||
2706 | } | ||
2707 | |||
2708 | static void | ||
2709 | qla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code) | ||
2710 | { | ||
2711 | char event_string[40]; | ||
2712 | char *envp[] = { event_string, NULL }; | ||
2713 | |||
2714 | switch (code) { | ||
2715 | case QLA_UEVENT_CODE_FW_DUMP: | ||
2716 | snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld", | ||
2717 | vha->host_no); | ||
2718 | break; | ||
2719 | default: | ||
2720 | /* do nothing */ | ||
2721 | break; | ||
2722 | } | ||
2723 | kobject_uevent_env(&vha->hw->pdev->dev.kobj, KOBJ_CHANGE, envp); | ||
2724 | } | ||
2725 | |||
2656 | void | 2726 | void |
2657 | qla2x00_do_work(struct scsi_qla_host *vha) | 2727 | qla2x00_do_work(struct scsi_qla_host *vha) |
2658 | { | 2728 | { |
@@ -2690,6 +2760,9 @@ qla2x00_do_work(struct scsi_qla_host *vha) | |||
2690 | qla2x00_async_logout_done(vha, e->u.logio.fcport, | 2760 | qla2x00_async_logout_done(vha, e->u.logio.fcport, |
2691 | e->u.logio.data); | 2761 | e->u.logio.data); |
2692 | break; | 2762 | break; |
2763 | case QLA_EVT_UEVENT: | ||
2764 | qla2x00_uevent_emit(vha, e->u.uevent.code); | ||
2765 | break; | ||
2693 | } | 2766 | } |
2694 | if (e->flags & QLA_EVT_FLAG_FREE) | 2767 | if (e->flags & QLA_EVT_FLAG_FREE) |
2695 | kfree(e); | 2768 | kfree(e); |
@@ -2717,7 +2790,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha) | |||
2717 | 2790 | ||
2718 | fcport->login_retry--; | 2791 | fcport->login_retry--; |
2719 | if (fcport->flags & FCF_FABRIC_DEVICE) { | 2792 | if (fcport->flags & FCF_FABRIC_DEVICE) { |
2720 | if (fcport->flags & FCF_TAPE_PRESENT) | 2793 | if (fcport->flags & FCF_FCP2_DEVICE) |
2721 | ha->isp_ops->fabric_logout(vha, | 2794 | ha->isp_ops->fabric_logout(vha, |
2722 | fcport->loop_id, | 2795 | fcport->loop_id, |
2723 | fcport->d_id.b.domain, | 2796 | fcport->d_id.b.domain, |
@@ -2805,6 +2878,13 @@ qla2x00_do_dpc(void *data) | |||
2805 | if (!base_vha->flags.init_done) | 2878 | if (!base_vha->flags.init_done) |
2806 | continue; | 2879 | continue; |
2807 | 2880 | ||
2881 | if (ha->flags.eeh_busy) { | ||
2882 | DEBUG17(qla_printk(KERN_WARNING, ha, | ||
2883 | "qla2x00_do_dpc: dpc_flags: %lx\n", | ||
2884 | base_vha->dpc_flags)); | ||
2885 | continue; | ||
2886 | } | ||
2887 | |||
2808 | DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no)); | 2888 | DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no)); |
2809 | 2889 | ||
2810 | ha->dpc_active = 1; | 2890 | ha->dpc_active = 1; |
@@ -2995,8 +3075,13 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
2995 | int index; | 3075 | int index; |
2996 | srb_t *sp; | 3076 | srb_t *sp; |
2997 | int t; | 3077 | int t; |
3078 | uint16_t w; | ||
2998 | struct qla_hw_data *ha = vha->hw; | 3079 | struct qla_hw_data *ha = vha->hw; |
2999 | struct req_que *req; | 3080 | struct req_que *req; |
3081 | |||
3082 | /* Hardware read to raise pending EEH errors during mailbox waits. */ | ||
3083 | if (!pci_channel_offline(ha->pdev)) | ||
3084 | pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); | ||
3000 | /* | 3085 | /* |
3001 | * Ports - Port down timer. | 3086 | * Ports - Port down timer. |
3002 | * | 3087 | * |
@@ -3041,7 +3126,10 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3041 | if (!IS_QLA2100(ha) && vha->link_down_timeout) | 3126 | if (!IS_QLA2100(ha) && vha->link_down_timeout) |
3042 | atomic_set(&vha->loop_state, LOOP_DEAD); | 3127 | atomic_set(&vha->loop_state, LOOP_DEAD); |
3043 | 3128 | ||
3044 | /* Schedule an ISP abort to return any tape commands. */ | 3129 | /* |
3130 | * Schedule an ISP abort to return any FCP2-device | ||
3131 | * commands. | ||
3132 | */ | ||
3045 | /* NPIV - scan physical port only */ | 3133 | /* NPIV - scan physical port only */ |
3046 | if (!vha->vp_idx) { | 3134 | if (!vha->vp_idx) { |
3047 | spin_lock_irqsave(&ha->hardware_lock, | 3135 | spin_lock_irqsave(&ha->hardware_lock, |
@@ -3058,7 +3146,7 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
3058 | if (sp->ctx) | 3146 | if (sp->ctx) |
3059 | continue; | 3147 | continue; |
3060 | sfcp = sp->fcport; | 3148 | sfcp = sp->fcport; |
3061 | if (!(sfcp->flags & FCF_TAPE_PRESENT)) | 3149 | if (!(sfcp->flags & FCF_FCP2_DEVICE)) |
3062 | continue; | 3150 | continue; |
3063 | 3151 | ||
3064 | set_bit(ISP_ABORT_NEEDED, | 3152 | set_bit(ISP_ABORT_NEEDED, |
@@ -3198,16 +3286,24 @@ qla2x00_release_firmware(void) | |||
3198 | static pci_ers_result_t | 3286 | static pci_ers_result_t |
3199 | qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | 3287 | qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) |
3200 | { | 3288 | { |
3201 | scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); | 3289 | scsi_qla_host_t *vha = pci_get_drvdata(pdev); |
3290 | struct qla_hw_data *ha = vha->hw; | ||
3291 | |||
3292 | DEBUG2(qla_printk(KERN_WARNING, ha, "error_detected:state %x\n", | ||
3293 | state)); | ||
3202 | 3294 | ||
3203 | switch (state) { | 3295 | switch (state) { |
3204 | case pci_channel_io_normal: | 3296 | case pci_channel_io_normal: |
3297 | ha->flags.eeh_busy = 0; | ||
3205 | return PCI_ERS_RESULT_CAN_RECOVER; | 3298 | return PCI_ERS_RESULT_CAN_RECOVER; |
3206 | case pci_channel_io_frozen: | 3299 | case pci_channel_io_frozen: |
3300 | ha->flags.eeh_busy = 1; | ||
3301 | qla2x00_free_irqs(vha); | ||
3207 | pci_disable_device(pdev); | 3302 | pci_disable_device(pdev); |
3208 | return PCI_ERS_RESULT_NEED_RESET; | 3303 | return PCI_ERS_RESULT_NEED_RESET; |
3209 | case pci_channel_io_perm_failure: | 3304 | case pci_channel_io_perm_failure: |
3210 | qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); | 3305 | ha->flags.pci_channel_io_perm_failure = 1; |
3306 | qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); | ||
3211 | return PCI_ERS_RESULT_DISCONNECT; | 3307 | return PCI_ERS_RESULT_DISCONNECT; |
3212 | } | 3308 | } |
3213 | return PCI_ERS_RESULT_NEED_RESET; | 3309 | return PCI_ERS_RESULT_NEED_RESET; |
@@ -3256,7 +3352,23 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev) | |||
3256 | pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; | 3352 | pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; |
3257 | scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); | 3353 | scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); |
3258 | struct qla_hw_data *ha = base_vha->hw; | 3354 | struct qla_hw_data *ha = base_vha->hw; |
3259 | int rc; | 3355 | struct rsp_que *rsp; |
3356 | int rc, retries = 10; | ||
3357 | |||
3358 | DEBUG17(qla_printk(KERN_WARNING, ha, "slot_reset\n")); | ||
3359 | |||
3360 | /* Workaround: qla2xxx driver which access hardware earlier | ||
3361 | * needs error state to be pci_channel_io_online. | ||
3362 | * Otherwise mailbox command timesout. | ||
3363 | */ | ||
3364 | pdev->error_state = pci_channel_io_normal; | ||
3365 | |||
3366 | pci_restore_state(pdev); | ||
3367 | |||
3368 | /* pci_restore_state() clears the saved_state flag of the device | ||
3369 | * save restored state which resets saved_state flag | ||
3370 | */ | ||
3371 | pci_save_state(pdev); | ||
3260 | 3372 | ||
3261 | if (ha->mem_only) | 3373 | if (ha->mem_only) |
3262 | rc = pci_enable_device_mem(pdev); | 3374 | rc = pci_enable_device_mem(pdev); |
@@ -3266,19 +3378,29 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev) | |||
3266 | if (rc) { | 3378 | if (rc) { |
3267 | qla_printk(KERN_WARNING, ha, | 3379 | qla_printk(KERN_WARNING, ha, |
3268 | "Can't re-enable PCI device after reset.\n"); | 3380 | "Can't re-enable PCI device after reset.\n"); |
3269 | |||
3270 | return ret; | 3381 | return ret; |
3271 | } | 3382 | } |
3272 | pci_set_master(pdev); | 3383 | |
3384 | rsp = ha->rsp_q_map[0]; | ||
3385 | if (qla2x00_request_irqs(ha, rsp)) | ||
3386 | return ret; | ||
3273 | 3387 | ||
3274 | if (ha->isp_ops->pci_config(base_vha)) | 3388 | if (ha->isp_ops->pci_config(base_vha)) |
3275 | return ret; | 3389 | return ret; |
3276 | 3390 | ||
3391 | while (ha->flags.mbox_busy && retries--) | ||
3392 | msleep(1000); | ||
3393 | |||
3277 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); | 3394 | set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
3278 | if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS) | 3395 | if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS) |
3279 | ret = PCI_ERS_RESULT_RECOVERED; | 3396 | ret = PCI_ERS_RESULT_RECOVERED; |
3280 | clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); | 3397 | clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); |
3281 | 3398 | ||
3399 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
3400 | |||
3401 | DEBUG17(qla_printk(KERN_WARNING, ha, | ||
3402 | "slot_reset-return:ret=%x\n", ret)); | ||
3403 | |||
3282 | return ret; | 3404 | return ret; |
3283 | } | 3405 | } |
3284 | 3406 | ||
@@ -3289,13 +3411,16 @@ qla2xxx_pci_resume(struct pci_dev *pdev) | |||
3289 | struct qla_hw_data *ha = base_vha->hw; | 3411 | struct qla_hw_data *ha = base_vha->hw; |
3290 | int ret; | 3412 | int ret; |
3291 | 3413 | ||
3414 | DEBUG17(qla_printk(KERN_WARNING, ha, "pci_resume\n")); | ||
3415 | |||
3292 | ret = qla2x00_wait_for_hba_online(base_vha); | 3416 | ret = qla2x00_wait_for_hba_online(base_vha); |
3293 | if (ret != QLA_SUCCESS) { | 3417 | if (ret != QLA_SUCCESS) { |
3294 | qla_printk(KERN_ERR, ha, | 3418 | qla_printk(KERN_ERR, ha, |
3295 | "the device failed to resume I/O " | 3419 | "the device failed to resume I/O " |
3296 | "from slot/link_reset"); | 3420 | "from slot/link_reset"); |
3297 | } | 3421 | } |
3298 | pci_cleanup_aer_uncorrect_error_status(pdev); | 3422 | |
3423 | ha->flags.eeh_busy = 0; | ||
3299 | } | 3424 | } |
3300 | 3425 | ||
3301 | static struct pci_error_handlers qla2xxx_err_handler = { | 3426 | static struct pci_error_handlers qla2xxx_err_handler = { |
@@ -3408,4 +3533,3 @@ MODULE_FIRMWARE(FW_FILE_ISP2300); | |||
3408 | MODULE_FIRMWARE(FW_FILE_ISP2322); | 3533 | MODULE_FIRMWARE(FW_FILE_ISP2322); |
3409 | MODULE_FIRMWARE(FW_FILE_ISP24XX); | 3534 | MODULE_FIRMWARE(FW_FILE_ISP24XX); |
3410 | MODULE_FIRMWARE(FW_FILE_ISP25XX); | 3535 | MODULE_FIRMWARE(FW_FILE_ISP25XX); |
3411 | MODULE_FIRMWARE(FW_FILE_ISP81XX); | ||
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 010e69b29afe..8b3de4e54c28 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/slab.h> | ||
10 | #include <linux/vmalloc.h> | 11 | #include <linux/vmalloc.h> |
11 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
12 | 13 | ||
@@ -2292,11 +2293,14 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf, | |||
2292 | uint32_t faddr, left, burst; | 2293 | uint32_t faddr, left, burst; |
2293 | struct qla_hw_data *ha = vha->hw; | 2294 | struct qla_hw_data *ha = vha->hw; |
2294 | 2295 | ||
2296 | if (IS_QLA25XX(ha) || IS_QLA81XX(ha)) | ||
2297 | goto try_fast; | ||
2295 | if (offset & 0xfff) | 2298 | if (offset & 0xfff) |
2296 | goto slow_read; | 2299 | goto slow_read; |
2297 | if (length < OPTROM_BURST_SIZE) | 2300 | if (length < OPTROM_BURST_SIZE) |
2298 | goto slow_read; | 2301 | goto slow_read; |
2299 | 2302 | ||
2303 | try_fast: | ||
2300 | optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, | 2304 | optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, |
2301 | &optrom_dma, GFP_KERNEL); | 2305 | &optrom_dma, GFP_KERNEL); |
2302 | if (!optrom) { | 2306 | if (!optrom) { |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index ac107a2c34a4..109068df933f 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -7,9 +7,9 @@ | |||
7 | /* | 7 | /* |
8 | * Driver version | 8 | * Driver version |
9 | */ | 9 | */ |
10 | #define QLA2XXX_VERSION "8.03.01-k6" | 10 | #define QLA2XXX_VERSION "8.03.02-k2" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 3 | 13 | #define QLA_DRIVER_MINOR_VER 3 |
14 | #define QLA_DRIVER_PATCH_VER 1 | 14 | #define QLA_DRIVER_PATCH_VER 2 |
15 | #define QLA_DRIVER_BETA_VER 0 | 15 | #define QLA_DRIVER_BETA_VER 2 |