]> git.karo-electronics.de Git - linux-beck.git/commitdiff
qla2xxx: Enable Exchange offload support.
authorHimanshu Madhani <himanshu.madhani@qlogic.com>
Thu, 17 Dec 2015 19:56:57 +0000 (14:56 -0500)
committerNicholas Bellinger <nab@linux-iscsi.org>
Thu, 7 Jan 2016 21:57:41 +0000 (13:57 -0800)
This patch enables Exchange offload support in Qlogic ISP.
To enable exchange offload with Qlogic ISP24XX/25XX/26XX,
set module parameter ql2xexchoffld to any non-zero number.
This will alow ISP firmware to store exchange data structures
used by firmware to host memory provided by driver. ISP firmware
can supports upto 32k total active exchanges.

Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c

index 576664072a59d27398f98313197dc43e2e1fb977..e8b38dbac7d4019ce9fa0ebb9fc32fb46660fc19 100644 (file)
@@ -14,8 +14,8 @@
  * | Module Init and Probe        |       0x017f       | 0x0146         |
  * |                              |                    | 0x015b-0x0160 |
  * |                              |                    | 0x016e-0x0170  |
- * | Mailbox commands             |       0x1192       | 0x1018-0x1019 |
- * |                              |                    | 0x111a-0x111b  |
+ * | Mailbox commands             |       0x1192       |               |
+ * |                              |                    |               |
  * | Device Discovery             |       0x2016       | 0x2020-0x2022, |
  * |                              |                    | 0x2011-0x2012, |
  * |                              |                    | 0x2099-0x20a4  |
  * |                              |                    | 0xb13c-0xb140  |
  * |                              |                    | 0xb149                |
  * | MultiQ                       |       0xc00c       |               |
- * | Misc                         |       0xd300       | 0xd012-0xd014 |
- * |                              |                    | 0xd016-0xd017 |
- * |                              |                    | 0xd02e                |
- * |                              |                    | 0xd031-0xd0ff |
+ * | Misc                         |       0xd300       | 0xd031-0xd0ff |
  * |                              |                    | 0xd101-0xd1fe |
  * |                              |                    | 0xd214-0xd2fe |
  * | Target Mode                 |       0xe080       |                |
index 8f465b7965fcab6fcb75770ce800d1c3361a19c4..d31401c5a7eb11c7a1abcd16bb1555d90f27fdab 100644 (file)
 #define RESPONSE_ENTRY_CNT_MQ          128     /* Number of response entries.*/
 #define ATIO_ENTRY_CNT_24XX            4096    /* Number of ATIO entries. */
 #define RESPONSE_ENTRY_CNT_FX00                256     /* Number of response entries.*/
+#define EXTENDED_EXCH_ENTRY_CNT                32768   /* Entries for offload case */
 
 struct req_que;
 struct qla_tgt_sess;
@@ -2968,7 +2969,8 @@ struct qla_hw_data {
 
                uint32_t        fawwpn_enabled:1;
                uint32_t        exlogins_enabled:1;
-               /* 34 bits */
+               uint32_t        exchoffld_enabled:1;
+               /* 35 bits */
        } flags;
 
        /* This spinlock is used to protect "io transactions", you must
@@ -3246,6 +3248,14 @@ struct qla_hw_data {
        dma_addr_t      exlogin_buf_dma;
        int             exlogin_size;
 
+#define ENABLE_EXCHANGE_OFFLD  BIT_2
+
+       /* Exchange Offload */
+       void            *exchoffld_buf;
+       dma_addr_t      exchoffld_buf_dma;
+       int             exchoffld_size;
+       int             exchoffld_count;
+
        void            *swl;
 
        /* These are used by mailbox operations. */
index d396c490e2044cbb2f26571f50982c0e50e80e74..3dc323caaa950d64db0e1af7fe45cc15ad06cb7e 100644 (file)
@@ -118,6 +118,7 @@ extern uint64_t ql2xmaxlun;
 extern int ql2xmdcapmask;
 extern int ql2xmdenable;
 extern int ql2xexlogins;
+extern int ql2xexchoffld;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -138,6 +139,8 @@ extern int qla2x00_post_async_adisc_done_work(struct scsi_qla_host *,
     fc_port_t *, uint16_t *);
 extern int qla2x00_set_exlogins_buffer(struct scsi_qla_host *);
 extern void qla2x00_free_exlogin_buffer(struct qla_hw_data *);
+extern int qla2x00_set_exchoffld_buffer(struct scsi_qla_host *);
+extern void qla2x00_free_exchoffld_buffer(struct qla_hw_data *);
 
 extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
 
@@ -772,5 +775,7 @@ extern void qlt_host_reset_handler(struct qla_hw_data *ha);
 extern int qla_get_exlogin_status(scsi_qla_host_t *, uint16_t *,
        uint16_t *);
 extern int qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr);
+extern int qla_get_exchoffld_status(scsi_qla_host_t *, uint16_t *, uint16_t *);
+extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *, dma_addr_t);
 
 #endif /* _QLA_GBL_H */
index ef61a241a350350df845f0564b8b3117f41ce3c2..b3ed3b3ff55ef2470facc489757acd2e3778b0f0 100644 (file)
@@ -1846,6 +1846,9 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
                        if (ql2xexlogins)
                                ha->flags.exlogins_enabled = 1;
 
+                       if (ql2xexchoffld)
+                               ha->flags.exchoffld_enabled = 1;
+
                        rval = qla2x00_execute_fw(vha, srisc_address);
                        /* Retrieve firmware information. */
                        if (rval == QLA_SUCCESS) {
@@ -1853,6 +1856,10 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
                                if (rval != QLA_SUCCESS)
                                        goto failed;
 
+                               rval = qla2x00_set_exchoffld_buffer(vha);
+                               if (rval != QLA_SUCCESS)
+                                       goto failed;
+
 enable_82xx_npiv:
                                fw_major_version = ha->fw_major_version;
                                if (IS_P3P_TYPE(ha))
index a0ae178acf611a9cef0425c37610b9a05b680086..c7ca2235c60afa9aa6c54c53b63b3ab7a303f078 100644 (file)
@@ -493,6 +493,9 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                if (ha->flags.exlogins_enabled)
                        mcp->mb[4] |= ENABLE_EXTENDED_LOGIN;
 
+               if (ha->flags.exchoffld_enabled)
+                       mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD;
+
                mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1;
                mcp->in_mb |= MBX_1;
        } else {
@@ -635,6 +638,115 @@ qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
        return rval;
 }
 
+/*
+ * qla_get_exchoffld_status
+ *     Get exchange offload status
+ *     uses the memory offload control/status Mailbox
+ *
+ * Input:
+ *     ha:             adapter state pointer.
+ *     fwopt:          firmware options
+ *
+ * Returns:
+ *     qla2x00 local function status
+ *
+ * Context:
+ *     Kernel context.
+ */
+#define        FETCH_XCHOFFLD_STAT     0x2
+int
+qla_get_exchoffld_status(scsi_qla_host_t *vha, uint16_t *buf_sz,
+       uint16_t *ex_logins_cnt)
+{
+       int rval;
+       mbx_cmd_t       mc;
+       mbx_cmd_t       *mcp = &mc;
+
+       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1019,
+           "Entered %s\n", __func__);
+
+       memset(mcp->mb, 0 , sizeof(mcp->mb));
+       mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
+       mcp->mb[1] = FETCH_XCHOFFLD_STAT;
+       mcp->out_mb = MBX_1|MBX_0;
+       mcp->in_mb = MBX_10|MBX_4|MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+
+       rval = qla2x00_mailbox_command(vha, mcp);
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0x1155, "Failed=%x.\n", rval);
+       } else {
+               *buf_sz = mcp->mb[4];
+               *ex_logins_cnt = mcp->mb[10];
+
+               ql_log(ql_log_info, vha, 0x118e,
+                   "buffer size 0x%x, exchange offload count=%d\n",
+                   mcp->mb[4], mcp->mb[10]);
+
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1156,
+                   "Done %s.\n", __func__);
+       }
+
+       return rval;
+}
+
+/*
+ * qla_set_exchoffld_mem_cfg
+ *     Set exchange offload memory configuration
+ *     Mbx needs to be issues before init_cb is set
+ *
+ * Input:
+ *     ha:             adapter state pointer.
+ *     buffer:         buffer pointer
+ *     phys_addr:      physical address of buffer
+ *     size:           size of buffer
+ *     TARGET_QUEUE_LOCK must be released
+ *     ADAPTER_STATE_LOCK must be release
+ *
+ * Returns:
+ *     qla2x00 local funxtion status code.
+ *
+ * Context:
+ *     Kernel context.
+ */
+#define CONFIG_XCHOFFLD_MEM    0x3
+int
+qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
+{
+       int             rval;
+       mbx_cmd_t       mc;
+       mbx_cmd_t       *mcp = &mc;
+       struct qla_hw_data *ha = vha->hw;
+
+       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1157,
+           "Entered %s.\n", __func__);
+
+       memset(mcp->mb, 0 , sizeof(mcp->mb));
+       mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
+       mcp->mb[1] = CONFIG_XCHOFFLD_MEM;
+       mcp->mb[2] = MSW(phys_addr);
+       mcp->mb[3] = LSW(phys_addr);
+       mcp->mb[6] = MSW(MSD(phys_addr));
+       mcp->mb[7] = LSW(MSD(phys_addr));
+       mcp->mb[8] = MSW(ha->exlogin_size);
+       mcp->mb[9] = LSW(ha->exlogin_size);
+       mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+       mcp->in_mb = MBX_11|MBX_0;
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       rval = qla2x00_mailbox_command(vha, mcp);
+       if (rval != QLA_SUCCESS) {
+               /*EMPTY*/
+               ql_dbg(ql_dbg_mbx, vha, 0x1158, "Failed=%x.\n", rval);
+       } else {
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1192,
+                   "Done %s.\n", __func__);
+       }
+
+       return rval;
+}
+
 /*
  * qla2x00_get_fw_version
  *     Get firmware version.
@@ -709,10 +821,16 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
                ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x112f,
                    "%s: Ext_FwAttributes Upper: 0x%x, Lower: 0x%x.\n",
                    __func__, mcp->mb[17], mcp->mb[16]);
+
                if (ha->fw_attributes_h & 0x4)
                        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118d,
                            "%s: Firmware supports Extended Login 0x%x\n",
                            __func__, ha->fw_attributes_h);
+
+               if (ha->fw_attributes_h & 0x8)
+                       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1191,
+                           "%s: Firmware supports Exchange Offload 0x%x\n",
+                           __func__, ha->fw_attributes_h);
        }
 
        if (IS_QLA27XX(ha)) {
index 3c4af7e1055083c1a48e27f2206c7b00d166a5eb..266dd746841adfd561b31f668aa9c519e52d612f 100644 (file)
@@ -227,6 +227,12 @@ MODULE_PARM_DESC(ql2xexlogins,
                 "Number of extended Logins. "
                 "0 (Default)- Disabled.");
 
+int ql2xexchoffld = 0;
+module_param(ql2xexchoffld, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xexchoffld,
+                "Number of exchanges to offload. "
+                "0 (Default)- Disabled.");
+
 /*
  * SCSI host template entry points
  */
@@ -3138,6 +3144,10 @@ qla2x00_remove_one(struct pci_dev *pdev)
        if (ha->exlogin_buf)
                qla2x00_free_exlogin_buffer(ha);
 
+       /* free DMA memory */
+       if (ha->exchoffld_buf)
+               qla2x00_free_exchoffld_buffer(ha);
+
        qla2x00_destroy_deferred_work(ha);
 
        qlt_remove_target(ha, base_vha);
@@ -3663,6 +3673,74 @@ qla2x00_free_exlogin_buffer(struct qla_hw_data *ha)
        }
 }
 
+int
+qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
+{
+       int rval;
+       uint16_t        size, max_cnt, temp;
+       struct qla_hw_data *ha = vha->hw;
+
+       /* Return if we don't need to alloacate any extended logins */
+       if (!ql2xexchoffld)
+               return QLA_SUCCESS;
+
+       ql_log(ql_log_info, vha, 0xd014,
+           "Exchange offload count: %d.\n", ql2xexlogins);
+
+       max_cnt = 0;
+       rval = qla_get_exchoffld_status(vha, &size, &max_cnt);
+       if (rval != QLA_SUCCESS) {
+               ql_log_pci(ql_log_fatal, ha->pdev, 0xd012,
+                   "Failed to get exlogin status.\n");
+               return rval;
+       }
+
+       temp = (ql2xexchoffld > max_cnt) ? max_cnt : ql2xexchoffld;
+       ha->exchoffld_size = (size * temp);
+       ql_log(ql_log_info, vha, 0xd016,
+               "Exchange offload: max_count=%d, buffers=0x%x, total=%d.\n",
+               max_cnt, size, temp);
+
+       ql_log(ql_log_info, vha, 0xd017,
+           "Exchange Buffers requested size = 0x%x\n", ha->exchoffld_size);
+
+       /* Get consistent memory for extended logins */
+       ha->exchoffld_buf = dma_alloc_coherent(&ha->pdev->dev,
+           ha->exchoffld_size, &ha->exchoffld_buf_dma, GFP_KERNEL);
+       if (!ha->exchoffld_buf) {
+               ql_log_pci(ql_log_fatal, ha->pdev, 0xd013,
+                   "Failed to allocate memory for exchoffld_buf_dma.\n");
+               return -ENOMEM;
+       }
+
+       /* Now configure the dma buffer */
+       rval = qla_set_exchoffld_mem_cfg(vha, ha->exchoffld_buf_dma);
+       if (rval) {
+               ql_log(ql_log_fatal, vha, 0xd02e,
+                   "Setup exchange offload buffer ****FAILED****.\n");
+               qla2x00_free_exchoffld_buffer(ha);
+       }
+
+       return rval;
+}
+
+/*
+* qla2x00_free_exchoffld_buffer
+*
+* Input:
+*      ha = adapter block pointer
+*/
+void
+qla2x00_free_exchoffld_buffer(struct qla_hw_data *ha)
+{
+       if (ha->exchoffld_buf) {
+               dma_free_coherent(&ha->pdev->dev, ha->exchoffld_size,
+                   ha->exchoffld_buf, ha->exchoffld_buf_dma);
+               ha->exchoffld_buf = NULL;
+               ha->exchoffld_size = 0;
+       }
+}
+
 /*
 * qla2x00_free_fw_dump
 *      Frees fw dump stuff.