Skip to content

Commit

Permalink
qla2xxx: Enable Exchange offload support.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Himanshu Madhani authored and Nicholas Bellinger committed Jan 7, 2016
1 parent b0d6cab commit 2f56a7f
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 7 deletions.
9 changes: 3 additions & 6 deletions drivers/scsi/qla2xxx/qla_dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -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 | |
Expand Down
12 changes: 11 additions & 1 deletion drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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. */
Expand Down
5 changes: 5 additions & 0 deletions drivers/scsi/qla2xxx/qla_gbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 *);

Expand Down Expand Up @@ -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 */
7 changes: 7 additions & 0 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1846,13 +1846,20 @@ 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) {
rval = qla2x00_set_exlogins_buffer(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))
Expand Down
118 changes: 118 additions & 0 deletions drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)) {
Expand Down
78 changes: 78 additions & 0 deletions drivers/scsi/qla2xxx/qla_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 2f56a7f

Please sign in to comment.