diff options
author | Saurav Kashyap <saurav.kashyap@qlogic.com> | 2012-08-22 14:21:01 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-09-24 04:10:47 -0400 |
commit | a9b6f722f62d0a302b980a4fdcdf9c9933955772 (patch) | |
tree | d353225c380d8183faddbf535a6116ada1a41279 /drivers/scsi/qla2xxx | |
parent | 5f16b331d83757ad5154af07b449c722fef45d5e (diff) |
[SCSI] qla2xxx: Implementation of bidirectional.
[jejb: merge fix for introduced warning]
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 29 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.c | 183 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.h | 16 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 23 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 38 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 198 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 167 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 1 |
11 files changed, 656 insertions, 12 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 5ab953029f8d..ff2439bd9b4b 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -1251,6 +1251,31 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr, | |||
1251 | state[1], state[2], state[3], state[4]); | 1251 | state[1], state[2], state[3], state[4]); |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | static ssize_t | ||
1255 | qla2x00_diag_requests_show(struct device *dev, | ||
1256 | struct device_attribute *attr, char *buf) | ||
1257 | { | ||
1258 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1259 | |||
1260 | if (!IS_BIDI_CAPABLE(vha->hw)) | ||
1261 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1262 | |||
1263 | return snprintf(buf, PAGE_SIZE, "%llu\n", vha->bidi_stats.io_count); | ||
1264 | } | ||
1265 | |||
1266 | static ssize_t | ||
1267 | qla2x00_diag_megabytes_show(struct device *dev, | ||
1268 | struct device_attribute *attr, char *buf) | ||
1269 | { | ||
1270 | scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); | ||
1271 | |||
1272 | if (!IS_BIDI_CAPABLE(vha->hw)) | ||
1273 | return snprintf(buf, PAGE_SIZE, "\n"); | ||
1274 | |||
1275 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
1276 | vha->bidi_stats.transfer_bytes >> 20); | ||
1277 | } | ||
1278 | |||
1254 | static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); | 1279 | static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); |
1255 | static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); | 1280 | static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); |
1256 | static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); | 1281 | static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); |
@@ -1289,6 +1314,8 @@ static DEVICE_ATTR(vn_port_mac_address, S_IRUGO, | |||
1289 | static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL); | 1314 | static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL); |
1290 | static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL); | 1315 | static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL); |
1291 | static DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL); | 1316 | static DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL); |
1317 | static DEVICE_ATTR(diag_requests, S_IRUGO, qla2x00_diag_requests_show, NULL); | ||
1318 | static DEVICE_ATTR(diag_megabytes, S_IRUGO, qla2x00_diag_megabytes_show, NULL); | ||
1292 | 1319 | ||
1293 | struct device_attribute *qla2x00_host_attrs[] = { | 1320 | struct device_attribute *qla2x00_host_attrs[] = { |
1294 | &dev_attr_driver_version, | 1321 | &dev_attr_driver_version, |
@@ -1318,6 +1345,8 @@ struct device_attribute *qla2x00_host_attrs[] = { | |||
1318 | &dev_attr_fw_state, | 1345 | &dev_attr_fw_state, |
1319 | &dev_attr_optrom_gold_fw_version, | 1346 | &dev_attr_optrom_gold_fw_version, |
1320 | &dev_attr_thermal_temp, | 1347 | &dev_attr_thermal_temp, |
1348 | &dev_attr_diag_requests, | ||
1349 | &dev_attr_diag_megabytes, | ||
1321 | NULL, | 1350 | NULL, |
1322 | }; | 1351 | }; |
1323 | 1352 | ||
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 462ac707b8d6..dac3427ebf24 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c | |||
@@ -1650,6 +1650,186 @@ done: | |||
1650 | } | 1650 | } |
1651 | 1651 | ||
1652 | static int | 1652 | static int |
1653 | qla24xx_process_bidir_cmd(struct fc_bsg_job *bsg_job) | ||
1654 | { | ||
1655 | struct Scsi_Host *host = bsg_job->shost; | ||
1656 | scsi_qla_host_t *vha = shost_priv(host); | ||
1657 | struct qla_hw_data *ha = vha->hw; | ||
1658 | uint16_t thread_id; | ||
1659 | uint32_t rval = EXT_STATUS_OK; | ||
1660 | uint16_t req_sg_cnt = 0; | ||
1661 | uint16_t rsp_sg_cnt = 0; | ||
1662 | uint16_t nextlid = 0; | ||
1663 | uint32_t tot_dsds; | ||
1664 | srb_t *sp = NULL; | ||
1665 | uint32_t req_data_len = 0; | ||
1666 | uint32_t rsp_data_len = 0; | ||
1667 | |||
1668 | /* Check the type of the adapter */ | ||
1669 | if (!IS_BIDI_CAPABLE(ha)) { | ||
1670 | ql_log(ql_log_warn, vha, 0x70a0, | ||
1671 | "This adapter is not supported\n"); | ||
1672 | rval = EXT_STATUS_NOT_SUPPORTED; | ||
1673 | goto done; | ||
1674 | } | ||
1675 | |||
1676 | if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | ||
1677 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | ||
1678 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | ||
1679 | rval = EXT_STATUS_BUSY; | ||
1680 | goto done; | ||
1681 | } | ||
1682 | |||
1683 | /* Check if host is online */ | ||
1684 | if (!vha->flags.online) { | ||
1685 | ql_log(ql_log_warn, vha, 0x70a1, | ||
1686 | "Host is not online\n"); | ||
1687 | rval = EXT_STATUS_DEVICE_OFFLINE; | ||
1688 | goto done; | ||
1689 | } | ||
1690 | |||
1691 | /* Check if cable is plugged in or not */ | ||
1692 | if (vha->device_flags & DFLG_NO_CABLE) { | ||
1693 | ql_log(ql_log_warn, vha, 0x70a2, | ||
1694 | "Cable is unplugged...\n"); | ||
1695 | rval = EXT_STATUS_INVALID_CFG; | ||
1696 | goto done; | ||
1697 | } | ||
1698 | |||
1699 | /* Check if the switch is connected or not */ | ||
1700 | if (ha->current_topology != ISP_CFG_F) { | ||
1701 | ql_log(ql_log_warn, vha, 0x70a3, | ||
1702 | "Host is not connected to the switch\n"); | ||
1703 | rval = EXT_STATUS_INVALID_CFG; | ||
1704 | goto done; | ||
1705 | } | ||
1706 | |||
1707 | /* Check if operating mode is P2P */ | ||
1708 | if (ha->operating_mode != P2P) { | ||
1709 | ql_log(ql_log_warn, vha, 0x70a4, | ||
1710 | "Host is operating mode is not P2p\n"); | ||
1711 | rval = EXT_STATUS_INVALID_CFG; | ||
1712 | goto done; | ||
1713 | } | ||
1714 | |||
1715 | thread_id = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | ||
1716 | |||
1717 | mutex_lock(&ha->selflogin_lock); | ||
1718 | if (vha->self_login_loop_id == 0) { | ||
1719 | /* Initialize all required fields of fcport */ | ||
1720 | vha->bidir_fcport.vha = vha; | ||
1721 | vha->bidir_fcport.d_id.b.al_pa = vha->d_id.b.al_pa; | ||
1722 | vha->bidir_fcport.d_id.b.area = vha->d_id.b.area; | ||
1723 | vha->bidir_fcport.d_id.b.domain = vha->d_id.b.domain; | ||
1724 | vha->bidir_fcport.loop_id = vha->loop_id; | ||
1725 | |||
1726 | if (qla2x00_fabric_login(vha, &(vha->bidir_fcport), &nextlid)) { | ||
1727 | ql_log(ql_log_warn, vha, 0x70a7, | ||
1728 | "Failed to login port %06X for bidirectional IOCB\n", | ||
1729 | vha->bidir_fcport.d_id.b24); | ||
1730 | mutex_unlock(&ha->selflogin_lock); | ||
1731 | rval = EXT_STATUS_MAILBOX; | ||
1732 | goto done; | ||
1733 | } | ||
1734 | vha->self_login_loop_id = nextlid - 1; | ||
1735 | |||
1736 | } | ||
1737 | /* Assign the self login loop id to fcport */ | ||
1738 | mutex_unlock(&ha->selflogin_lock); | ||
1739 | |||
1740 | vha->bidir_fcport.loop_id = vha->self_login_loop_id; | ||
1741 | |||
1742 | req_sg_cnt = dma_map_sg(&ha->pdev->dev, | ||
1743 | bsg_job->request_payload.sg_list, | ||
1744 | bsg_job->request_payload.sg_cnt, | ||
1745 | DMA_TO_DEVICE); | ||
1746 | |||
1747 | if (!req_sg_cnt) { | ||
1748 | rval = EXT_STATUS_NO_MEMORY; | ||
1749 | goto done; | ||
1750 | } | ||
1751 | |||
1752 | rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, | ||
1753 | bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt, | ||
1754 | DMA_FROM_DEVICE); | ||
1755 | |||
1756 | if (!rsp_sg_cnt) { | ||
1757 | rval = EXT_STATUS_NO_MEMORY; | ||
1758 | goto done_unmap_req_sg; | ||
1759 | } | ||
1760 | |||
1761 | if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) || | ||
1762 | (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) { | ||
1763 | ql_dbg(ql_dbg_user, vha, 0x70a9, | ||
1764 | "Dma mapping resulted in different sg counts " | ||
1765 | "[request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt: " | ||
1766 | "%x dma_reply_sg_cnt: %x]\n", | ||
1767 | bsg_job->request_payload.sg_cnt, req_sg_cnt, | ||
1768 | bsg_job->reply_payload.sg_cnt, rsp_sg_cnt); | ||
1769 | rval = EXT_STATUS_NO_MEMORY; | ||
1770 | goto done_unmap_sg; | ||
1771 | } | ||
1772 | |||
1773 | if (req_data_len != rsp_data_len) { | ||
1774 | rval = EXT_STATUS_BUSY; | ||
1775 | ql_log(ql_log_warn, vha, 0x70aa, | ||
1776 | "req_data_len != rsp_data_len\n"); | ||
1777 | goto done_unmap_sg; | ||
1778 | } | ||
1779 | |||
1780 | req_data_len = bsg_job->request_payload.payload_len; | ||
1781 | rsp_data_len = bsg_job->reply_payload.payload_len; | ||
1782 | |||
1783 | |||
1784 | /* Alloc SRB structure */ | ||
1785 | sp = qla2x00_get_sp(vha, &(vha->bidir_fcport), GFP_KERNEL); | ||
1786 | if (!sp) { | ||
1787 | ql_dbg(ql_dbg_user, vha, 0x70ac, | ||
1788 | "Alloc SRB structure failed\n"); | ||
1789 | rval = EXT_STATUS_NO_MEMORY; | ||
1790 | goto done_unmap_sg; | ||
1791 | } | ||
1792 | |||
1793 | /*Populate srb->ctx with bidir ctx*/ | ||
1794 | sp->u.bsg_job = bsg_job; | ||
1795 | sp->free = qla2x00_bsg_sp_free; | ||
1796 | sp->type = SRB_BIDI_CMD; | ||
1797 | sp->done = qla2x00_bsg_job_done; | ||
1798 | |||
1799 | /* Add the read and write sg count */ | ||
1800 | tot_dsds = rsp_sg_cnt + req_sg_cnt; | ||
1801 | |||
1802 | rval = qla2x00_start_bidir(sp, vha, tot_dsds); | ||
1803 | if (rval != EXT_STATUS_OK) | ||
1804 | goto done_free_srb; | ||
1805 | /* the bsg request will be completed in the interrupt handler */ | ||
1806 | return rval; | ||
1807 | |||
1808 | done_free_srb: | ||
1809 | mempool_free(sp, ha->srb_mempool); | ||
1810 | done_unmap_sg: | ||
1811 | dma_unmap_sg(&ha->pdev->dev, | ||
1812 | bsg_job->reply_payload.sg_list, | ||
1813 | bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE); | ||
1814 | done_unmap_req_sg: | ||
1815 | dma_unmap_sg(&ha->pdev->dev, | ||
1816 | bsg_job->request_payload.sg_list, | ||
1817 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | ||
1818 | done: | ||
1819 | |||
1820 | /* Return an error vendor specific response | ||
1821 | * and complete the bsg request | ||
1822 | */ | ||
1823 | bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = rval; | ||
1824 | bsg_job->reply_len = sizeof(struct fc_bsg_reply); | ||
1825 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
1826 | bsg_job->reply->result = (DID_OK) << 16; | ||
1827 | bsg_job->job_done(bsg_job); | ||
1828 | /* Always retrun success, vendor rsp carries correct status */ | ||
1829 | return 0; | ||
1830 | } | ||
1831 | |||
1832 | static int | ||
1653 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | 1833 | qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) |
1654 | { | 1834 | { |
1655 | switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { | 1835 | switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) { |
@@ -1692,6 +1872,9 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | |||
1692 | case QL_VND_READ_I2C: | 1872 | case QL_VND_READ_I2C: |
1693 | return qla2x00_read_i2c(bsg_job); | 1873 | return qla2x00_read_i2c(bsg_job); |
1694 | 1874 | ||
1875 | case QL_VND_DIAG_IO_CMD: | ||
1876 | return qla24xx_process_bidir_cmd(bsg_job); | ||
1877 | |||
1695 | default: | 1878 | default: |
1696 | bsg_job->reply->result = (DID_ERROR << 16); | 1879 | bsg_job->reply->result = (DID_ERROR << 16); |
1697 | bsg_job->job_done(bsg_job); | 1880 | bsg_job->job_done(bsg_job); |
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index 1a0ab375ce43..1875ee10e589 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h | |||
@@ -19,15 +19,31 @@ | |||
19 | #define QL_VND_SET_FRU_VERSION 0x0B | 19 | #define QL_VND_SET_FRU_VERSION 0x0B |
20 | #define QL_VND_READ_FRU_STATUS 0x0C | 20 | #define QL_VND_READ_FRU_STATUS 0x0C |
21 | #define QL_VND_WRITE_FRU_STATUS 0x0D | 21 | #define QL_VND_WRITE_FRU_STATUS 0x0D |
22 | #define QL_VND_DIAG_IO_CMD 0x0A | ||
22 | #define QL_VND_WRITE_I2C 0x10 | 23 | #define QL_VND_WRITE_I2C 0x10 |
23 | #define QL_VND_READ_I2C 0x11 | 24 | #define QL_VND_READ_I2C 0x11 |
24 | 25 | ||
25 | /* BSG Vendor specific subcode returns */ | 26 | /* BSG Vendor specific subcode returns */ |
26 | #define EXT_STATUS_OK 0 | 27 | #define EXT_STATUS_OK 0 |
27 | #define EXT_STATUS_ERR 1 | 28 | #define EXT_STATUS_ERR 1 |
29 | #define EXT_STATUS_BUSY 2 | ||
28 | #define EXT_STATUS_INVALID_PARAM 6 | 30 | #define EXT_STATUS_INVALID_PARAM 6 |
31 | #define EXT_STATUS_DATA_OVERRUN 7 | ||
32 | #define EXT_STATUS_DATA_UNDERRUN 8 | ||
29 | #define EXT_STATUS_MAILBOX 11 | 33 | #define EXT_STATUS_MAILBOX 11 |
30 | #define EXT_STATUS_NO_MEMORY 17 | 34 | #define EXT_STATUS_NO_MEMORY 17 |
35 | #define EXT_STATUS_DEVICE_OFFLINE 22 | ||
36 | |||
37 | /* | ||
38 | * To support bidirectional iocb | ||
39 | * BSG Vendor specific returns | ||
40 | */ | ||
41 | #define EXT_STATUS_NOT_SUPPORTED 27 | ||
42 | #define EXT_STATUS_INVALID_CFG 28 | ||
43 | #define EXT_STATUS_DMA_ERR 29 | ||
44 | #define EXT_STATUS_TIMEOUT 30 | ||
45 | #define EXT_STATUS_THREAD_FAILED 31 | ||
46 | #define EXT_STATUS_DATA_CMP_FAILED 32 | ||
31 | 47 | ||
32 | /* BSG definations for interpreting CommandSent field */ | 48 | /* BSG definations for interpreting CommandSent field */ |
33 | #define INT_DEF_LB_LOOPBACK_CMD 0 | 49 | #define INT_DEF_LB_LOOPBACK_CMD 0 |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 0c4fd2cebc17..156f5341a7a3 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -15,17 +15,20 @@ | |||
15 | * | Mailbox commands | 0x1140 | 0x111a-0x111b | | 15 | * | Mailbox commands | 0x1140 | 0x111a-0x111b | |
16 | * | | | 0x112c-0x112e | | 16 | * | | | 0x112c-0x112e | |
17 | * | | | 0x113a | | 17 | * | | | 0x113a | |
18 | * | Device Discovery | 0x2086 | 0x2020-0x2022 | | 18 | * | Device Discovery | 0x2087 | 0x2020-0x2022 | |
19 | * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 | | 19 | * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 | |
20 | * | | | 0x302d-0x302e | | 20 | * | | | 0x302d-0x302e | |
21 | * | DPC Thread | 0x401c | 0x4002,0x4013 | | 21 | * | DPC Thread | 0x401c | 0x4002,0x4013 | |
22 | * | Async Events | 0x505f | 0x502b-0x502f | | 22 | * | Async Events | 0x505f | 0x502b-0x502f | |
23 | * | | | 0x5047,0x5052 | | 23 | * | | | 0x5047,0x5052 | |
24 | * | Timer Routines | 0x6011 | | | 24 | * | Timer Routines | 0x6011 | | |
25 | * | User Space Interactions | 0x709f | 0x7018,0x702e, | | 25 | * | User Space Interactions | 0x70bb | 0x7018,0x702e, | |
26 | * | | | 0x7039,0x7045, | | 26 | * | | | 0x7039,0x7045, | |
27 | * | | | 0x7073-0x7075, | | 27 | * | | | 0x7073-0x7075, | |
28 | * | | | 0x708c | | 28 | * | | | 0x708c, | |
29 | * | | | 0x70a5,0x70a6, | | ||
30 | * | | | 0x70a8,0x70ab, | | ||
31 | * | | | 0x70ad-0x70ae | | ||
29 | * | Task Management | 0x803c | 0x8025-0x8026 | | 32 | * | Task Management | 0x803c | 0x8025-0x8026 | |
30 | * | | | 0x800b,0x8039 | | 33 | * | | | 0x800b,0x8039 | |
31 | * | AER/EEH | 0x9011 | | | 34 | * | AER/EEH | 0x9011 | | |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 28c0b3575616..7ff92ce42821 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -260,6 +260,7 @@ struct srb_iocb { | |||
260 | #define SRB_ADISC_CMD 6 | 260 | #define SRB_ADISC_CMD 6 |
261 | #define SRB_TM_CMD 7 | 261 | #define SRB_TM_CMD 7 |
262 | #define SRB_SCSI_CMD 8 | 262 | #define SRB_SCSI_CMD 8 |
263 | #define SRB_BIDI_CMD 9 | ||
263 | 264 | ||
264 | typedef struct srb { | 265 | typedef struct srb { |
265 | atomic_t ref_count; | 266 | atomic_t ref_count; |
@@ -1510,6 +1511,13 @@ typedef struct { | |||
1510 | #define CS_RETRY 0x82 /* Driver defined */ | 1511 | #define CS_RETRY 0x82 /* Driver defined */ |
1511 | #define CS_LOOP_DOWN_ABORT 0x83 /* Driver defined */ | 1512 | #define CS_LOOP_DOWN_ABORT 0x83 /* Driver defined */ |
1512 | 1513 | ||
1514 | #define CS_BIDIR_RD_OVERRUN 0x700 | ||
1515 | #define CS_BIDIR_RD_WR_OVERRUN 0x707 | ||
1516 | #define CS_BIDIR_RD_OVERRUN_WR_UNDERRUN 0x715 | ||
1517 | #define CS_BIDIR_RD_UNDERRUN 0x1500 | ||
1518 | #define CS_BIDIR_RD_UNDERRUN_WR_OVERRUN 0x1507 | ||
1519 | #define CS_BIDIR_RD_WR_UNDERRUN 0x1515 | ||
1520 | #define CS_BIDIR_DMA 0x200 | ||
1513 | /* | 1521 | /* |
1514 | * Status entry status flags | 1522 | * Status entry status flags |
1515 | */ | 1523 | */ |
@@ -2374,6 +2382,11 @@ struct qla_statistics { | |||
2374 | uint64_t output_bytes; | 2382 | uint64_t output_bytes; |
2375 | }; | 2383 | }; |
2376 | 2384 | ||
2385 | struct bidi_statistics { | ||
2386 | unsigned long long io_count; | ||
2387 | unsigned long long transfer_bytes; | ||
2388 | }; | ||
2389 | |||
2377 | /* Multi queue support */ | 2390 | /* Multi queue support */ |
2378 | #define MBC_INITIALIZE_MULTIQ 0x1f | 2391 | #define MBC_INITIALIZE_MULTIQ 0x1f |
2379 | #define QLA_QUE_PAGE 0X1000 | 2392 | #define QLA_QUE_PAGE 0X1000 |
@@ -2671,6 +2684,7 @@ struct qla_hw_data { | |||
2671 | #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) | 2684 | #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) |
2672 | #define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED) | 2685 | #define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED) |
2673 | #define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha)) | 2686 | #define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha)) |
2687 | #define IS_BIDI_CAPABLE(ha) ((IS_QLA25XX(ha) || IS_QLA2031(ha))) | ||
2674 | 2688 | ||
2675 | /* HBA serial number */ | 2689 | /* HBA serial number */ |
2676 | uint8_t serial0; | 2690 | uint8_t serial0; |
@@ -2754,6 +2768,7 @@ struct qla_hw_data { | |||
2754 | struct completion mbx_intr_comp; /* Used for completion notification */ | 2768 | struct completion mbx_intr_comp; /* Used for completion notification */ |
2755 | struct completion dcbx_comp; /* For set port config notification */ | 2769 | struct completion dcbx_comp; /* For set port config notification */ |
2756 | int notify_dcbx_comp; | 2770 | int notify_dcbx_comp; |
2771 | struct mutex selflogin_lock; | ||
2757 | 2772 | ||
2758 | /* Basic firmware related information. */ | 2773 | /* Basic firmware related information. */ |
2759 | uint16_t fw_major_version; | 2774 | uint16_t fw_major_version; |
@@ -2987,6 +3002,13 @@ typedef struct scsi_qla_host { | |||
2987 | 3002 | ||
2988 | /* ISP configuration data. */ | 3003 | /* ISP configuration data. */ |
2989 | uint16_t loop_id; /* Host adapter loop id */ | 3004 | uint16_t loop_id; /* Host adapter loop id */ |
3005 | uint16_t self_login_loop_id; /* host adapter loop id | ||
3006 | * get it on self login | ||
3007 | */ | ||
3008 | fc_port_t bidir_fcport; /* fcport used for bidir cmnds | ||
3009 | * no need of allocating it for | ||
3010 | * each command | ||
3011 | */ | ||
2990 | 3012 | ||
2991 | port_id_t d_id; /* Host adapter port id */ | 3013 | port_id_t d_id; /* Host adapter port id */ |
2992 | uint8_t marker_needed; | 3014 | uint8_t marker_needed; |
@@ -3040,6 +3062,7 @@ typedef struct scsi_qla_host { | |||
3040 | int seconds_since_last_heartbeat; | 3062 | int seconds_since_last_heartbeat; |
3041 | struct fc_host_statistics fc_host_stat; | 3063 | struct fc_host_statistics fc_host_stat; |
3042 | struct qla_statistics qla_stats; | 3064 | struct qla_statistics qla_stats; |
3065 | struct bidi_statistics bidi_stats; | ||
3043 | 3066 | ||
3044 | atomic_t vref_count; | 3067 | atomic_t vref_count; |
3045 | } scsi_qla_host_t; | 3068 | } scsi_qla_host_t; |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 980b5a7d6471..a678ed5d6884 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -381,6 +381,44 @@ struct init_cb_24xx { | |||
381 | /* | 381 | /* |
382 | * ISP queue - command entry structure definition. | 382 | * ISP queue - command entry structure definition. |
383 | */ | 383 | */ |
384 | #define COMMAND_BIDIRECTIONAL 0x75 | ||
385 | struct cmd_bidir { | ||
386 | uint8_t entry_type; /* Entry type. */ | ||
387 | uint8_t entry_count; /* Entry count. */ | ||
388 | uint8_t sys_define; /* System defined */ | ||
389 | uint8_t entry_status; /* Entry status. */ | ||
390 | |||
391 | uint32_t handle; /* System handle. */ | ||
392 | |||
393 | uint16_t nport_handle; /* N_PORT hanlde. */ | ||
394 | |||
395 | uint16_t timeout; /* Commnad timeout. */ | ||
396 | |||
397 | uint16_t wr_dseg_count; /* Write Data segment count. */ | ||
398 | uint16_t rd_dseg_count; /* Read Data segment count. */ | ||
399 | |||
400 | struct scsi_lun lun; /* FCP LUN (BE). */ | ||
401 | |||
402 | uint16_t control_flags; /* Control flags. */ | ||
403 | #define BD_WRAP_BACK BIT_3 | ||
404 | #define BD_READ_DATA BIT_1 | ||
405 | #define BD_WRITE_DATA BIT_0 | ||
406 | |||
407 | uint16_t fcp_cmnd_dseg_len; /* Data segment length. */ | ||
408 | uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */ | ||
409 | |||
410 | uint16_t reserved[2]; /* Reserved */ | ||
411 | |||
412 | uint32_t rd_byte_count; /* Total Byte count Read. */ | ||
413 | uint32_t wr_byte_count; /* Total Byte count write. */ | ||
414 | |||
415 | uint8_t port_id[3]; /* PortID of destination port.*/ | ||
416 | uint8_t vp_index; | ||
417 | |||
418 | uint32_t fcp_data_dseg_address[2]; /* Data segment address. */ | ||
419 | uint16_t fcp_data_dseg_len; /* Data segment length. */ | ||
420 | }; | ||
421 | |||
384 | #define COMMAND_TYPE_6 0x48 /* Command Type 6 entry */ | 422 | #define COMMAND_TYPE_6 0x48 /* Command Type 6 entry */ |
385 | struct cmd_type_6 { | 423 | struct cmd_type_6 { |
386 | uint8_t entry_type; /* Entry type. */ | 424 | uint8_t entry_type; /* Entry type. */ |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 9eacd2df111b..d7588adc768b 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -188,6 +188,8 @@ extern int qla2x00_start_sp(srb_t *); | |||
188 | extern uint16_t qla24xx_calc_iocbs(scsi_qla_host_t *, uint16_t); | 188 | extern uint16_t qla24xx_calc_iocbs(scsi_qla_host_t *, uint16_t); |
189 | extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t); | 189 | extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t); |
190 | extern int qla24xx_dif_start_scsi(srb_t *); | 190 | extern int qla24xx_dif_start_scsi(srb_t *); |
191 | extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t); | ||
192 | extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *); | ||
191 | 193 | ||
192 | extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *); | 194 | extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *); |
193 | extern int qla2x00_issue_marker(scsi_qla_host_t *, int); | 195 | extern int qla2x00_issue_marker(scsi_qla_host_t *, int); |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 290052352619..fa39411597f9 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -77,7 +77,7 @@ qla2x00_sp_free(void *data, void *ptr) | |||
77 | 77 | ||
78 | /* Asynchronous Login/Logout Routines -------------------------------------- */ | 78 | /* Asynchronous Login/Logout Routines -------------------------------------- */ |
79 | 79 | ||
80 | static inline unsigned long | 80 | unsigned long |
81 | qla2x00_get_async_timeout(struct scsi_qla_host *vha) | 81 | qla2x00_get_async_timeout(struct scsi_qla_host *vha) |
82 | { | 82 | { |
83 | unsigned long tmo; | 83 | unsigned long tmo; |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 23e83757fa5d..74c69ba39a04 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -2665,3 +2665,201 @@ done: | |||
2665 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 2665 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2666 | return rval; | 2666 | return rval; |
2667 | } | 2667 | } |
2668 | |||
2669 | static void | ||
2670 | qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha, | ||
2671 | struct cmd_bidir *cmd_pkt, uint32_t tot_dsds) | ||
2672 | { | ||
2673 | uint16_t avail_dsds; | ||
2674 | uint32_t *cur_dsd; | ||
2675 | uint32_t req_data_len = 0; | ||
2676 | uint32_t rsp_data_len = 0; | ||
2677 | struct scatterlist *sg; | ||
2678 | int index; | ||
2679 | int entry_count = 1; | ||
2680 | struct fc_bsg_job *bsg_job = sp->u.bsg_job; | ||
2681 | |||
2682 | /*Update entry type to indicate bidir command */ | ||
2683 | *((uint32_t *)(&cmd_pkt->entry_type)) = | ||
2684 | __constant_cpu_to_le32(COMMAND_BIDIRECTIONAL); | ||
2685 | |||
2686 | /* Set the transfer direction, in this set both flags | ||
2687 | * Also set the BD_WRAP_BACK flag, firmware will take care | ||
2688 | * assigning DID=SID for outgoing pkts. | ||
2689 | */ | ||
2690 | cmd_pkt->wr_dseg_count = cpu_to_le16(bsg_job->request_payload.sg_cnt); | ||
2691 | cmd_pkt->rd_dseg_count = cpu_to_le16(bsg_job->reply_payload.sg_cnt); | ||
2692 | cmd_pkt->control_flags = | ||
2693 | __constant_cpu_to_le16(BD_WRITE_DATA | BD_READ_DATA | | ||
2694 | BD_WRAP_BACK); | ||
2695 | |||
2696 | req_data_len = rsp_data_len = bsg_job->request_payload.payload_len; | ||
2697 | cmd_pkt->wr_byte_count = cpu_to_le32(req_data_len); | ||
2698 | cmd_pkt->rd_byte_count = cpu_to_le32(rsp_data_len); | ||
2699 | cmd_pkt->timeout = cpu_to_le16(qla2x00_get_async_timeout(vha) + 2); | ||
2700 | |||
2701 | vha->bidi_stats.transfer_bytes += req_data_len; | ||
2702 | vha->bidi_stats.io_count++; | ||
2703 | |||
2704 | /* Only one dsd is available for bidirectional IOCB, remaining dsds | ||
2705 | * are bundled in continuation iocb | ||
2706 | */ | ||
2707 | avail_dsds = 1; | ||
2708 | cur_dsd = (uint32_t *)&cmd_pkt->fcp_data_dseg_address; | ||
2709 | |||
2710 | index = 0; | ||
2711 | |||
2712 | for_each_sg(bsg_job->request_payload.sg_list, sg, | ||
2713 | bsg_job->request_payload.sg_cnt, index) { | ||
2714 | dma_addr_t sle_dma; | ||
2715 | cont_a64_entry_t *cont_pkt; | ||
2716 | |||
2717 | /* Allocate additional continuation packets */ | ||
2718 | if (avail_dsds == 0) { | ||
2719 | /* Continuation type 1 IOCB can accomodate | ||
2720 | * 5 DSDS | ||
2721 | */ | ||
2722 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); | ||
2723 | cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; | ||
2724 | avail_dsds = 5; | ||
2725 | entry_count++; | ||
2726 | } | ||
2727 | sle_dma = sg_dma_address(sg); | ||
2728 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
2729 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
2730 | *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); | ||
2731 | avail_dsds--; | ||
2732 | } | ||
2733 | /* For read request DSD will always goes to continuation IOCB | ||
2734 | * and follow the write DSD. If there is room on the current IOCB | ||
2735 | * then it is added to that IOCB else new continuation IOCB is | ||
2736 | * allocated. | ||
2737 | */ | ||
2738 | for_each_sg(bsg_job->reply_payload.sg_list, sg, | ||
2739 | bsg_job->reply_payload.sg_cnt, index) { | ||
2740 | dma_addr_t sle_dma; | ||
2741 | cont_a64_entry_t *cont_pkt; | ||
2742 | |||
2743 | /* Allocate additional continuation packets */ | ||
2744 | if (avail_dsds == 0) { | ||
2745 | /* Continuation type 1 IOCB can accomodate | ||
2746 | * 5 DSDS | ||
2747 | */ | ||
2748 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); | ||
2749 | cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; | ||
2750 | avail_dsds = 5; | ||
2751 | entry_count++; | ||
2752 | } | ||
2753 | sle_dma = sg_dma_address(sg); | ||
2754 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
2755 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
2756 | *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); | ||
2757 | avail_dsds--; | ||
2758 | } | ||
2759 | /* This value should be same as number of IOCB required for this cmd */ | ||
2760 | cmd_pkt->entry_count = entry_count; | ||
2761 | } | ||
2762 | |||
2763 | int | ||
2764 | qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) | ||
2765 | { | ||
2766 | |||
2767 | struct qla_hw_data *ha = vha->hw; | ||
2768 | unsigned long flags; | ||
2769 | uint32_t handle; | ||
2770 | uint32_t index; | ||
2771 | uint16_t req_cnt; | ||
2772 | uint16_t cnt; | ||
2773 | uint32_t *clr_ptr; | ||
2774 | struct cmd_bidir *cmd_pkt = NULL; | ||
2775 | struct rsp_que *rsp; | ||
2776 | struct req_que *req; | ||
2777 | int rval = EXT_STATUS_OK; | ||
2778 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, vha->req->id); | ||
2779 | |||
2780 | rval = QLA_SUCCESS; | ||
2781 | |||
2782 | rsp = ha->rsp_q_map[0]; | ||
2783 | req = vha->req; | ||
2784 | |||
2785 | /* Send marker if required */ | ||
2786 | if (vha->marker_needed != 0) { | ||
2787 | if (qla2x00_marker(vha, req, | ||
2788 | rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) | ||
2789 | return EXT_STATUS_MAILBOX; | ||
2790 | vha->marker_needed = 0; | ||
2791 | } | ||
2792 | |||
2793 | /* Acquire ring specific lock */ | ||
2794 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
2795 | |||
2796 | /* Check for room in outstanding command list. */ | ||
2797 | handle = req->current_outstanding_cmd; | ||
2798 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { | ||
2799 | handle++; | ||
2800 | if (handle == MAX_OUTSTANDING_COMMANDS) | ||
2801 | handle = 1; | ||
2802 | if (!req->outstanding_cmds[handle]) | ||
2803 | break; | ||
2804 | } | ||
2805 | |||
2806 | if (index == MAX_OUTSTANDING_COMMANDS) { | ||
2807 | rval = EXT_STATUS_BUSY; | ||
2808 | goto queuing_error; | ||
2809 | } | ||
2810 | |||
2811 | /* Calculate number of IOCB required */ | ||
2812 | req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); | ||
2813 | |||
2814 | /* Check for room on request queue. */ | ||
2815 | if (req->cnt < req_cnt + 2) { | ||
2816 | if (ha->mqenable) | ||
2817 | cnt = RD_REG_DWORD(®->isp25mq.req_q_out); | ||
2818 | else if (IS_QLA82XX(ha)) | ||
2819 | cnt = RD_REG_DWORD(®->isp82.req_q_out); | ||
2820 | else if (IS_FWI2_CAPABLE(ha)) | ||
2821 | cnt = RD_REG_DWORD(®->isp24.req_q_out); | ||
2822 | else | ||
2823 | cnt = qla2x00_debounce_register( | ||
2824 | ISP_REQ_Q_OUT(ha, ®->isp)); | ||
2825 | |||
2826 | if (req->ring_index < cnt) | ||
2827 | req->cnt = cnt - req->ring_index; | ||
2828 | else | ||
2829 | req->cnt = req->length - | ||
2830 | (req->ring_index - cnt); | ||
2831 | } | ||
2832 | if (req->cnt < req_cnt + 2) { | ||
2833 | rval = EXT_STATUS_BUSY; | ||
2834 | goto queuing_error; | ||
2835 | } | ||
2836 | |||
2837 | cmd_pkt = (struct cmd_bidir *)req->ring_ptr; | ||
2838 | cmd_pkt->handle = MAKE_HANDLE(req->id, handle); | ||
2839 | |||
2840 | /* Zero out remaining portion of packet. */ | ||
2841 | /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ | ||
2842 | clr_ptr = (uint32_t *)cmd_pkt + 2; | ||
2843 | memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); | ||
2844 | |||
2845 | /* Set NPORT-ID (of vha)*/ | ||
2846 | cmd_pkt->nport_handle = cpu_to_le16(vha->self_login_loop_id); | ||
2847 | cmd_pkt->port_id[0] = vha->d_id.b.al_pa; | ||
2848 | cmd_pkt->port_id[1] = vha->d_id.b.area; | ||
2849 | cmd_pkt->port_id[2] = vha->d_id.b.domain; | ||
2850 | |||
2851 | qla25xx_build_bidir_iocb(sp, vha, cmd_pkt, tot_dsds); | ||
2852 | cmd_pkt->entry_status = (uint8_t) rsp->id; | ||
2853 | /* Build command packet. */ | ||
2854 | req->current_outstanding_cmd = handle; | ||
2855 | req->outstanding_cmds[handle] = sp; | ||
2856 | sp->handle = handle; | ||
2857 | req->cnt -= req_cnt; | ||
2858 | |||
2859 | /* Send the command to the firmware */ | ||
2860 | wmb(); | ||
2861 | qla2x00_start_iocbs(vha, req); | ||
2862 | queuing_error: | ||
2863 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
2864 | return rval; | ||
2865 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 0b097766f68d..31ef8e25a61d 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -1546,6 +1546,149 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) | |||
1546 | return 1; | 1546 | return 1; |
1547 | } | 1547 | } |
1548 | 1548 | ||
1549 | static void | ||
1550 | qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, | ||
1551 | struct req_que *req, uint32_t index) | ||
1552 | { | ||
1553 | struct qla_hw_data *ha = vha->hw; | ||
1554 | srb_t *sp; | ||
1555 | uint16_t comp_status; | ||
1556 | uint16_t scsi_status; | ||
1557 | uint16_t thread_id; | ||
1558 | uint32_t rval = EXT_STATUS_OK; | ||
1559 | struct fc_bsg_job *bsg_job = NULL; | ||
1560 | sts_entry_t *sts; | ||
1561 | struct sts_entry_24xx *sts24; | ||
1562 | sts = (sts_entry_t *) pkt; | ||
1563 | sts24 = (struct sts_entry_24xx *) pkt; | ||
1564 | |||
1565 | /* Validate handle. */ | ||
1566 | if (index >= MAX_OUTSTANDING_COMMANDS) { | ||
1567 | ql_log(ql_log_warn, vha, 0x70af, | ||
1568 | "Invalid SCSI completion handle 0x%x.\n", index); | ||
1569 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
1570 | return; | ||
1571 | } | ||
1572 | |||
1573 | sp = req->outstanding_cmds[index]; | ||
1574 | if (sp) { | ||
1575 | /* Free outstanding command slot. */ | ||
1576 | req->outstanding_cmds[index] = NULL; | ||
1577 | bsg_job = sp->u.bsg_job; | ||
1578 | } else { | ||
1579 | ql_log(ql_log_warn, vha, 0x70b0, | ||
1580 | "Req:%d: Invalid ISP SCSI completion handle(0x%x)\n", | ||
1581 | req->id, index); | ||
1582 | |||
1583 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
1584 | return; | ||
1585 | } | ||
1586 | |||
1587 | if (IS_FWI2_CAPABLE(ha)) { | ||
1588 | comp_status = le16_to_cpu(sts24->comp_status); | ||
1589 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; | ||
1590 | } else { | ||
1591 | comp_status = le16_to_cpu(sts->comp_status); | ||
1592 | scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; | ||
1593 | } | ||
1594 | |||
1595 | thread_id = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; | ||
1596 | switch (comp_status) { | ||
1597 | case CS_COMPLETE: | ||
1598 | if (scsi_status == 0) { | ||
1599 | bsg_job->reply->reply_payload_rcv_len = | ||
1600 | bsg_job->reply_payload.payload_len; | ||
1601 | rval = EXT_STATUS_OK; | ||
1602 | } | ||
1603 | goto done; | ||
1604 | |||
1605 | case CS_DATA_OVERRUN: | ||
1606 | ql_dbg(ql_dbg_user, vha, 0x70b1, | ||
1607 | "Command completed with date overrun thread_id=%d\n", | ||
1608 | thread_id); | ||
1609 | rval = EXT_STATUS_DATA_OVERRUN; | ||
1610 | break; | ||
1611 | |||
1612 | case CS_DATA_UNDERRUN: | ||
1613 | ql_dbg(ql_dbg_user, vha, 0x70b2, | ||
1614 | "Command completed with date underrun thread_id=%d\n", | ||
1615 | thread_id); | ||
1616 | rval = EXT_STATUS_DATA_UNDERRUN; | ||
1617 | break; | ||
1618 | case CS_BIDIR_RD_OVERRUN: | ||
1619 | ql_dbg(ql_dbg_user, vha, 0x70b3, | ||
1620 | "Command completed with read data overrun thread_id=%d\n", | ||
1621 | thread_id); | ||
1622 | rval = EXT_STATUS_DATA_OVERRUN; | ||
1623 | break; | ||
1624 | |||
1625 | case CS_BIDIR_RD_WR_OVERRUN: | ||
1626 | ql_dbg(ql_dbg_user, vha, 0x70b4, | ||
1627 | "Command completed with read and write data overrun " | ||
1628 | "thread_id=%d\n", thread_id); | ||
1629 | rval = EXT_STATUS_DATA_OVERRUN; | ||
1630 | break; | ||
1631 | |||
1632 | case CS_BIDIR_RD_OVERRUN_WR_UNDERRUN: | ||
1633 | ql_dbg(ql_dbg_user, vha, 0x70b5, | ||
1634 | "Command completed with read data over and write data " | ||
1635 | "underrun thread_id=%d\n", thread_id); | ||
1636 | rval = EXT_STATUS_DATA_OVERRUN; | ||
1637 | break; | ||
1638 | |||
1639 | case CS_BIDIR_RD_UNDERRUN: | ||
1640 | ql_dbg(ql_dbg_user, vha, 0x70b6, | ||
1641 | "Command completed with read data data underrun " | ||
1642 | "thread_id=%d\n", thread_id); | ||
1643 | rval = EXT_STATUS_DATA_UNDERRUN; | ||
1644 | break; | ||
1645 | |||
1646 | case CS_BIDIR_RD_UNDERRUN_WR_OVERRUN: | ||
1647 | ql_dbg(ql_dbg_user, vha, 0x70b7, | ||
1648 | "Command completed with read data under and write data " | ||
1649 | "overrun thread_id=%d\n", thread_id); | ||
1650 | rval = EXT_STATUS_DATA_UNDERRUN; | ||
1651 | break; | ||
1652 | |||
1653 | case CS_BIDIR_RD_WR_UNDERRUN: | ||
1654 | ql_dbg(ql_dbg_user, vha, 0x70b8, | ||
1655 | "Command completed with read and write data underrun " | ||
1656 | "thread_id=%d\n", thread_id); | ||
1657 | rval = EXT_STATUS_DATA_UNDERRUN; | ||
1658 | break; | ||
1659 | |||
1660 | case CS_BIDIR_DMA: | ||
1661 | ql_dbg(ql_dbg_user, vha, 0x70b9, | ||
1662 | "Command completed with data DMA error thread_id=%d\n", | ||
1663 | thread_id); | ||
1664 | rval = EXT_STATUS_DMA_ERR; | ||
1665 | break; | ||
1666 | |||
1667 | case CS_TIMEOUT: | ||
1668 | ql_dbg(ql_dbg_user, vha, 0x70ba, | ||
1669 | "Command completed with timeout thread_id=%d\n", | ||
1670 | thread_id); | ||
1671 | rval = EXT_STATUS_TIMEOUT; | ||
1672 | break; | ||
1673 | default: | ||
1674 | ql_dbg(ql_dbg_user, vha, 0x70bb, | ||
1675 | "Command completed with completion status=0x%x " | ||
1676 | "thread_id=%d\n", comp_status, thread_id); | ||
1677 | rval = EXT_STATUS_ERR; | ||
1678 | break; | ||
1679 | } | ||
1680 | bsg_job->reply->reply_payload_rcv_len = 0; | ||
1681 | |||
1682 | done: | ||
1683 | /* Return the vendor specific reply to API */ | ||
1684 | bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = rval; | ||
1685 | bsg_job->reply_len = sizeof(struct fc_bsg_reply); | ||
1686 | /* Always return DID_OK, bsg will send the vendor specific response | ||
1687 | * in this case only */ | ||
1688 | sp->done(vha, sp, (DID_OK << 6)); | ||
1689 | |||
1690 | } | ||
1691 | |||
1549 | /** | 1692 | /** |
1550 | * qla2x00_status_entry() - Process a Status IOCB entry. | 1693 | * qla2x00_status_entry() - Process a Status IOCB entry. |
1551 | * @ha: SCSI driver HA context | 1694 | * @ha: SCSI driver HA context |
@@ -1573,12 +1716,14 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1573 | struct req_que *req; | 1716 | struct req_que *req; |
1574 | int logit = 1; | 1717 | int logit = 1; |
1575 | int res = 0; | 1718 | int res = 0; |
1719 | uint16_t state_flags = 0; | ||
1576 | 1720 | ||
1577 | sts = (sts_entry_t *) pkt; | 1721 | sts = (sts_entry_t *) pkt; |
1578 | sts24 = (struct sts_entry_24xx *) pkt; | 1722 | sts24 = (struct sts_entry_24xx *) pkt; |
1579 | if (IS_FWI2_CAPABLE(ha)) { | 1723 | if (IS_FWI2_CAPABLE(ha)) { |
1580 | comp_status = le16_to_cpu(sts24->comp_status); | 1724 | comp_status = le16_to_cpu(sts24->comp_status); |
1581 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; | 1725 | scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; |
1726 | state_flags = le16_to_cpu(sts24->state_flags); | ||
1582 | } else { | 1727 | } else { |
1583 | comp_status = le16_to_cpu(sts->comp_status); | 1728 | comp_status = le16_to_cpu(sts->comp_status); |
1584 | scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; | 1729 | scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; |
@@ -1587,17 +1732,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1587 | que = MSW(sts->handle); | 1732 | que = MSW(sts->handle); |
1588 | req = ha->req_q_map[que]; | 1733 | req = ha->req_q_map[que]; |
1589 | 1734 | ||
1590 | /* Fast path completion. */ | ||
1591 | if (comp_status == CS_COMPLETE && scsi_status == 0) { | ||
1592 | qla2x00_process_completed_request(vha, req, handle); | ||
1593 | |||
1594 | return; | ||
1595 | } | ||
1596 | |||
1597 | /* Validate handle. */ | 1735 | /* Validate handle. */ |
1598 | if (handle < MAX_OUTSTANDING_COMMANDS) { | 1736 | if (handle < MAX_OUTSTANDING_COMMANDS) { |
1599 | sp = req->outstanding_cmds[handle]; | 1737 | sp = req->outstanding_cmds[handle]; |
1600 | req->outstanding_cmds[handle] = NULL; | ||
1601 | } else | 1738 | } else |
1602 | sp = NULL; | 1739 | sp = NULL; |
1603 | 1740 | ||
@@ -1612,6 +1749,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1612 | qla2xxx_wake_dpc(vha); | 1749 | qla2xxx_wake_dpc(vha); |
1613 | return; | 1750 | return; |
1614 | } | 1751 | } |
1752 | |||
1753 | if (unlikely((state_flags & BIT_1) && (sp->type == SRB_BIDI_CMD))) { | ||
1754 | qla25xx_process_bidir_status_iocb(vha, pkt, req, handle); | ||
1755 | return; | ||
1756 | } | ||
1757 | |||
1758 | /* Fast path completion. */ | ||
1759 | if (comp_status == CS_COMPLETE && scsi_status == 0) { | ||
1760 | qla2x00_process_completed_request(vha, req, handle); | ||
1761 | |||
1762 | return; | ||
1763 | } | ||
1764 | |||
1765 | req->outstanding_cmds[handle] = NULL; | ||
1615 | cp = GET_CMD_SP(sp); | 1766 | cp = GET_CMD_SP(sp); |
1616 | if (cp == NULL) { | 1767 | if (cp == NULL) { |
1617 | ql_dbg(ql_dbg_io, vha, 0x3018, | 1768 | ql_dbg(ql_dbg_io, vha, 0x3018, |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5f990291c259..3e775650c20c 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -2203,6 +2203,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2203 | ha->mem_only = mem_only; | 2203 | ha->mem_only = mem_only; |
2204 | spin_lock_init(&ha->hardware_lock); | 2204 | spin_lock_init(&ha->hardware_lock); |
2205 | spin_lock_init(&ha->vport_slock); | 2205 | spin_lock_init(&ha->vport_slock); |
2206 | mutex_init(&ha->selflogin_lock); | ||
2206 | 2207 | ||
2207 | /* Set ISP-type information. */ | 2208 | /* Set ISP-type information. */ |
2208 | qla2x00_set_isp_flags(ha); | 2209 | qla2x00_set_isp_flags(ha); |