Signed-off-by: Himanshu Madhani <[email protected]>
Signed-off-by: Giridhar Malavali <[email protected]>
---
 drivers/scsi/qla2xxx/qla_dbg.c  |    9 +--
 drivers/scsi/qla2xxx/qla_def.h  |   13 ++++-
 drivers/scsi/qla2xxx/qla_gbl.h  |    7 ++
 drivers/scsi/qla2xxx/qla_init.c |    7 ++
 drivers/scsi/qla2xxx/qla_mbx.c  |  119 +++++++++++++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_os.c   |   76 +++++++++++++++++++++++++
 6 files changed, 224 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 34dc9a3..5766640 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -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, |
@@ -60,10 +60,9 @@
  * |                              |                    | 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 |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 388d790..8f465b7 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -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. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 7686bfe..d396c49 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -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 */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 16a1935c..ef61a24 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -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))
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index cb11e04..a0ae178 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -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 {
@@ -521,6 +525,117 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t 
risc_addr)
 }
 
 /*
+ * 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)) {
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 6be32fd..bfe33d5 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -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.
-- 
1.7.7

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to