qla2xxx: Enable Extended Logins support
authorHimanshu Madhani <himanshu.madhani@qlogic.com>
Thu, 17 Dec 2015 19:56:56 +0000 (14:56 -0500)
committerNicholas Bellinger <nab@linux-iscsi.org>
Thu, 7 Jan 2016 21:57:41 +0000 (13:57 -0800)
This patch enables Extended Logins support in Qlogic ISP.
To enable extended login with Qlogic ISP24XX/25XX/26XX,
set module parameter ql2xexlogins to any non-zero number.
This will alow ISP firmware to store port database structure
information of remote login sessions to host memory provided
by driver. ISP firmware supports upto 16k total logins.

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 34dc9a35670b9b1cb458bef2e20128370704ff33..576664072a59d27398f98313197dc43e2e1fb977 100644 (file)
@@ -14,7 +14,7 @@
  * | Module Init and Probe        |       0x017f       | 0x0146         |
  * |                              |                    | 0x015b-0x0160 |
  * |                              |                    | 0x016e-0x0170  |
- * | Mailbox commands             |       0x118d       | 0x1115-0x1116 |
+ * | Mailbox commands             |       0x1192       | 0x1018-0x1019 |
  * |                              |                    | 0x111a-0x111b  |
  * | Device Discovery             |       0x2016       | 0x2020-0x2022, |
  * |                              |                    | 0x2011-0x2012, |
  * |                              |                    | 0xb13c-0xb140  |
  * |                              |                    | 0xb149                |
  * | MultiQ                       |       0xc00c       |               |
- * | Misc                         |       0xd300       | 0xd016-0xd017 |
- * |                              |                    | 0xd021,0xd024 |
- * |                              |                    | 0xd025,0xd029 |
- * |                              |                    | 0xd02a,0xd02e |
+ * | Misc                         |       0xd300       | 0xd012-0xd014 |
+ * |                              |                    | 0xd016-0xd017 |
+ * |                              |                    | 0xd02e                |
  * |                              |                    | 0xd031-0xd0ff |
  * |                              |                    | 0xd101-0xd1fe |
  * |                              |                    | 0xd214-0xd2fe |
index 388d79088b5990a13705bd66f60663d884cc828c..8f465b7965fcab6fcb75770ce800d1c3361a19c4 100644 (file)
@@ -891,6 +891,7 @@ struct mbx_cmd_32 {
 #define MBC_DISABLE_VI                 0x24    /* Disable VI operation. */
 #define MBC_ENABLE_VI                  0x25    /* Enable VI operation. */
 #define MBC_GET_FIRMWARE_OPTION                0x28    /* Get Firmware Options. */
+#define MBC_GET_MEM_OFFLOAD_CNTRL_STAT 0x34    /* Memory Offload ctrl/Stat*/
 #define MBC_SET_FIRMWARE_OPTION                0x38    /* Set Firmware Options. */
 #define MBC_LOOP_PORT_BYPASS           0x40    /* Loop Port Bypass. */
 #define MBC_LOOP_PORT_ENABLE           0x41    /* Loop Port Enable. */
@@ -2962,11 +2963,12 @@ struct qla_hw_data {
                uint32_t        isp82xx_no_md_cap:1;
                uint32_t        host_shutting_down:1;
                uint32_t        idc_compl_status:1;
-
                uint32_t        mr_reset_hdlr_active:1;
                uint32_t        mr_intr_valid:1;
+
                uint32_t        fawwpn_enabled:1;
-               /* 35 bits */
+               uint32_t        exlogins_enabled:1;
+               /* 34 bits */
        } flags;
 
        /* This spinlock is used to protect "io transactions", you must
@@ -3237,6 +3239,13 @@ struct qla_hw_data {
        void            *async_pd;
        dma_addr_t      async_pd_dma;
 
+#define ENABLE_EXTENDED_LOGIN  BIT_7
+
+       /* Extended Logins  */
+       void            *exlogin_buf;
+       dma_addr_t      exlogin_buf_dma;
+       int             exlogin_size;
+
        void            *swl;
 
        /* These are used by mailbox operations. */
index 7686bfe9a4a9e7ac42022c99321d20e0ff4c55f5..d396c490e2044cbb2f26571f50982c0e50e80e74 100644 (file)
@@ -117,6 +117,7 @@ extern int ql2xdontresethba;
 extern uint64_t ql2xmaxlun;
 extern int ql2xmdcapmask;
 extern int ql2xmdenable;
+extern int ql2xexlogins;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -135,6 +136,8 @@ extern int qla2x00_post_async_adisc_work(struct scsi_qla_host *, fc_port_t *,
     uint16_t *);
 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 qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
 
@@ -766,4 +769,8 @@ extern int qla8044_abort_isp(scsi_qla_host_t *);
 extern int qla8044_check_fw_alive(struct scsi_qla_host *);
 
 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);
+
 #endif /* _QLA_GBL_H */
index 16a1935cc9c1131359e514befb04b6a7bb155f9b..ef61a241a350350df845f0564b8b3117f41ce3c2 100644 (file)
@@ -1843,9 +1843,16 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
                        ql_dbg(ql_dbg_init, vha, 0x00ca,
                            "Starting firmware.\n");
 
+                       if (ql2xexlogins)
+                               ha->flags.exlogins_enabled = 1;
+
                        rval = qla2x00_execute_fw(vha, srisc_address);
                        /* Retrieve firmware information. */
                        if (rval == QLA_SUCCESS) {
+                               rval = qla2x00_set_exlogins_buffer(vha);
+                               if (rval != QLA_SUCCESS)
+                                       goto failed;
+
 enable_82xx_npiv:
                                fw_major_version = ha->fw_major_version;
                                if (IS_P3P_TYPE(ha))
index cb11e04be5685fc42d4dc5c6afa89635835be63e..a0ae178acf611a9cef0425c37610b9a05b680086 100644 (file)
@@ -489,6 +489,10 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                            EXTENDED_BB_CREDITS);
                } else
                        mcp->mb[4] = 0;
+
+               if (ha->flags.exlogins_enabled)
+                       mcp->mb[4] |= ENABLE_EXTENDED_LOGIN;
+
                mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1;
                mcp->in_mb |= MBX_1;
        } else {
@@ -520,6 +524,117 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
        return rval;
 }
 
+/*
+ * qla_get_exlogin_status
+ *     Get extended login 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_XLOGINS_STAT      0x8
+int
+qla_get_exlogin_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, 0x118f,
+           "Entered %s\n", __func__);
+
+       memset(mcp->mb, 0 , sizeof(mcp->mb));
+       mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
+       mcp->mb[1] = FETCH_XLOGINS_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, 0x1115, "Failed=%x.\n", rval);
+       } else {
+               *buf_sz = mcp->mb[4];
+               *ex_logins_cnt = mcp->mb[10];
+
+               ql_log(ql_log_info, vha, 0x1190,
+                   "buffer size 0x%x, exchange login count=%d\n",
+                   mcp->mb[4], mcp->mb[10]);
+
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1116,
+                   "Done %s.\n", __func__);
+       }
+
+       return rval;
+}
+
+/*
+ * qla_set_exlogin_mem_cfg
+ *     set extended login 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_XLOGINS_MEM     0x3
+int
+qla_set_exlogin_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;
+       int configured_count;
+
+       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111a,
+           "Entered %s.\n", __func__);
+
+       memset(mcp->mb, 0 , sizeof(mcp->mb));
+       mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
+       mcp->mb[1] = CONFIG_XLOGINS_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, 0x111b, "Failed=%x.\n", rval);
+       } else {
+               configured_count = mcp->mb[11];
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c,
+                   "Done %s.\n", __func__);
+       }
+
+       return rval;
+}
+
 /*
  * qla2x00_get_fw_version
  *     Get firmware version.
@@ -594,6 +709,10 @@ 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 (IS_QLA27XX(ha)) {
index bfa9a64c316b6ca2eec9a1b2277608f68101d92d..3c4af7e1055083c1a48e27f2206c7b00d166a5eb 100644 (file)
@@ -221,6 +221,12 @@ MODULE_PARM_DESC(ql2xmdenable,
                "0 - MiniDump disabled. "
                "1 (Default) - MiniDump enabled.");
 
+int ql2xexlogins = 0;
+module_param(ql2xexlogins, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ql2xexlogins,
+                "Number of extended Logins. "
+                "0 (Default)- Disabled.");
+
 /*
  * SCSI host template entry points
  */
@@ -3128,6 +3134,10 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
        base_vha->flags.online = 0;
 
+       /* free DMA memory */
+       if (ha->exlogin_buf)
+               qla2x00_free_exlogin_buffer(ha);
+
        qla2x00_destroy_deferred_work(ha);
 
        qlt_remove_target(ha, base_vha);
@@ -3587,6 +3597,72 @@ fail:
        return -ENOMEM;
 }
 
+int
+qla2x00_set_exlogins_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 (!ql2xexlogins)
+               return QLA_SUCCESS;
+
+       ql_log(ql_log_info, vha, 0xd021, "EXLOGIN count: %d.\n", ql2xexlogins);
+       max_cnt = 0;
+       rval = qla_get_exlogin_status(vha, &size, &max_cnt);
+       if (rval != QLA_SUCCESS) {
+               ql_log_pci(ql_log_fatal, ha->pdev, 0xd029,
+                   "Failed to get exlogin status.\n");
+               return rval;
+       }
+
+       temp = (ql2xexlogins > max_cnt) ? max_cnt : ql2xexlogins;
+       ha->exlogin_size = (size * temp);
+       ql_log(ql_log_info, vha, 0xd024,
+               "EXLOGIN: max_logins=%d, portdb=0x%x, total=%d.\n",
+               max_cnt, size, temp);
+
+       ql_log(ql_log_info, vha, 0xd025, "EXLOGIN: requested size=0x%x\n",
+               ha->exlogin_size);
+
+       /* Get consistent memory for extended logins */
+       ha->exlogin_buf = dma_alloc_coherent(&ha->pdev->dev,
+           ha->exlogin_size, &ha->exlogin_buf_dma, GFP_KERNEL);
+       if (!ha->exlogin_buf) {
+               ql_log_pci(ql_log_fatal, ha->pdev, 0xd02a,
+                   "Failed to allocate memory for exlogin_buf_dma.\n");
+               return -ENOMEM;
+       }
+
+       /* Now configure the dma buffer */
+       rval = qla_set_exlogin_mem_cfg(vha, ha->exlogin_buf_dma);
+       if (rval) {
+               ql_log(ql_log_fatal, vha, 0x00cf,
+                   "Setup extended login buffer  ****FAILED****.\n");
+               qla2x00_free_exlogin_buffer(ha);
+       }
+
+       return rval;
+}
+
+/*
+* qla2x00_free_exlogin_buffer
+*
+* Input:
+*      ha = adapter block pointer
+*/
+void
+qla2x00_free_exlogin_buffer(struct qla_hw_data *ha)
+{
+       if (ha->exlogin_buf) {
+               dma_free_coherent(&ha->pdev->dev, ha->exlogin_size,
+                   ha->exlogin_buf, ha->exlogin_buf_dma);
+               ha->exlogin_buf = NULL;
+               ha->exlogin_size = 0;
+       }
+}
+
 /*
 * qla2x00_free_fw_dump
 *      Frees fw dump stuff.