diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 12 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 5 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 118 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 78 |
6 files changed, 222 insertions, 7 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 576664072a59..e8b38dbac7d4 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -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 | @@ -60,10 +60,7 @@ * | | | 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 | | diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 8f465b7965fc..d31401c5a7eb 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -272,6 +272,7 @@ #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. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index d396c490e204..3dc323caaa95 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -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 */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ef61a241a350..b3ed3b3ff55e 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -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)) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index a0ae178acf61..c7ca2235c60a 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -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 { @@ -636,6 +639,115 @@ qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr) } /* + * 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)) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3c4af7e10550..266dd746841a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -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. |