Commit 99e1b683 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: Add ql2xiniexchg parameter

Previously, the ql2xexchoffld module parameter was used to control the
max number of exchanges to be offload onto host memory.

Module parameter ql_dm_tgt_ex_pct was used to control the percentage of
exchanges allocated to the Target side.

With this patch, module parameter ql_dm_tgt_ex_pct is no longer used to
control exchanges for the driver. New module parameter ql2xiniexchg is
added to control exchanges between target mode and initiator mode.

With the updated module parameters, users can control the exact number
of exchanges for either Initiator or Target. The exchange offload
feature will be automatically enabled when the total number of exchanges
exceeds 2048 limit.
Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f7e761f5
...@@ -286,7 +286,7 @@ struct name_list_extended { ...@@ -286,7 +286,7 @@ struct name_list_extended {
#define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/ #define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/
#define ATIO_ENTRY_CNT_24XX 4096 /* Number of ATIO entries. */ #define ATIO_ENTRY_CNT_24XX 4096 /* Number of ATIO entries. */
#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/ #define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
#define EXTENDED_EXCH_ENTRY_CNT 32768 /* Entries for offload case */ #define FW_DEF_EXCHANGES_CNT 2048
struct req_que; struct req_que;
struct qla_tgt_sess; struct qla_tgt_sess;
...@@ -3593,6 +3593,10 @@ struct qla_hw_data { ...@@ -3593,6 +3593,10 @@ struct qla_hw_data {
#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha)) #define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha))
#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) #define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_EXCHG_OFFLD_CAPABLE(ha) \
(IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_EXLOGIN_OFFLD_CAPABLE(ha) \
(IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
/* HBA serial number */ /* HBA serial number */
uint8_t serial0; uint8_t serial0;
......
...@@ -137,6 +137,7 @@ extern int ql2xmdcapmask; ...@@ -137,6 +137,7 @@ extern int ql2xmdcapmask;
extern int ql2xmdenable; extern int ql2xmdenable;
extern int ql2xexlogins; extern int ql2xexlogins;
extern int ql2xexchoffld; extern int ql2xexchoffld;
extern int ql2xiniexchg;
extern int ql2xfwholdabts; extern int ql2xfwholdabts;
extern int ql2xmvasynctoatio; extern int ql2xmvasynctoatio;
...@@ -839,7 +840,7 @@ extern int qla_get_exlogin_status(scsi_qla_host_t *, uint16_t *, ...@@ -839,7 +840,7 @@ extern int qla_get_exlogin_status(scsi_qla_host_t *, uint16_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_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_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); extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *);
extern void qlt_handle_abts_recv(struct scsi_qla_host *, response_t *); extern void qlt_handle_abts_recv(struct scsi_qla_host *, response_t *);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *, int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
......
...@@ -2723,7 +2723,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha) ...@@ -2723,7 +2723,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
if (ql2xexlogins) if (ql2xexlogins)
ha->flags.exlogins_enabled = 1; ha->flags.exlogins_enabled = 1;
if (ql2xexchoffld) if (qla_is_exch_offld_enabled(vha))
ha->flags.exchoffld_enabled = 1; ha->flags.exchoffld_enabled = 1;
rval = qla2x00_execute_fw(vha, srisc_address); rval = qla2x00_execute_fw(vha, srisc_address);
......
...@@ -307,3 +307,19 @@ qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t retry_delay) ...@@ -307,3 +307,19 @@ qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t retry_delay)
fcport->retry_delay_timestamp = jiffies + fcport->retry_delay_timestamp = jiffies +
(retry_delay * HZ / 10); (retry_delay * HZ / 10);
} }
static inline bool
qla_is_exch_offld_enabled(struct scsi_qla_host *vha)
{
if (qla_ini_mode_enabled(vha) &&
(ql2xiniexchg > FW_DEF_EXCHANGES_CNT))
return true;
else if (qla_tgt_mode_enabled(vha) &&
(ql2xexchoffld > FW_DEF_EXCHANGES_CNT))
return true;
else if (qla_dual_mode_enabled(vha) &&
((ql2xiniexchg + ql2xexchoffld) > FW_DEF_EXCHANGES_CNT))
return true;
else
return false;
}
...@@ -821,7 +821,7 @@ qla_get_exchoffld_status(scsi_qla_host_t *vha, uint16_t *buf_sz, ...@@ -821,7 +821,7 @@ qla_get_exchoffld_status(scsi_qla_host_t *vha, uint16_t *buf_sz,
*/ */
#define CONFIG_XCHOFFLD_MEM 0x3 #define CONFIG_XCHOFFLD_MEM 0x3
int int
qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr) qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha)
{ {
int rval; int rval;
mbx_cmd_t mc; mbx_cmd_t mc;
...@@ -834,12 +834,12 @@ qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr) ...@@ -834,12 +834,12 @@ qla_set_exchoffld_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
memset(mcp->mb, 0 , sizeof(mcp->mb)); memset(mcp->mb, 0 , sizeof(mcp->mb));
mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT; mcp->mb[0] = MBC_GET_MEM_OFFLOAD_CNTRL_STAT;
mcp->mb[1] = CONFIG_XCHOFFLD_MEM; mcp->mb[1] = CONFIG_XCHOFFLD_MEM;
mcp->mb[2] = MSW(phys_addr); mcp->mb[2] = MSW(ha->exchoffld_buf_dma);
mcp->mb[3] = LSW(phys_addr); mcp->mb[3] = LSW(ha->exchoffld_buf_dma);
mcp->mb[6] = MSW(MSD(phys_addr)); mcp->mb[6] = MSW(MSD(ha->exchoffld_buf_dma));
mcp->mb[7] = LSW(MSD(phys_addr)); mcp->mb[7] = LSW(MSD(ha->exchoffld_buf_dma));
mcp->mb[8] = MSW(ha->exlogin_size); mcp->mb[8] = MSW(ha->exchoffld_size);
mcp->mb[9] = LSW(ha->exlogin_size); mcp->mb[9] = LSW(ha->exchoffld_size);
mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; 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->in_mb = MBX_11|MBX_0;
mcp->tov = MBX_TOV_SECONDS; mcp->tov = MBX_TOV_SECONDS;
......
...@@ -224,11 +224,15 @@ MODULE_PARM_DESC(ql2xexlogins, ...@@ -224,11 +224,15 @@ MODULE_PARM_DESC(ql2xexlogins,
"Number of extended Logins. " "Number of extended Logins. "
"0 (Default)- Disabled."); "0 (Default)- Disabled.");
int ql2xexchoffld = 0; int ql2xexchoffld = 1024;
module_param(ql2xexchoffld, uint, S_IRUGO|S_IWUSR); module_param(ql2xexchoffld, uint, 0644);
MODULE_PARM_DESC(ql2xexchoffld, MODULE_PARM_DESC(ql2xexchoffld,
"Number of exchanges to offload. " "Number of target exchanges.");
"0 (Default)- Disabled.");
int ql2xiniexchg = 1024;
module_param(ql2xiniexchg, uint, 0644);
MODULE_PARM_DESC(ql2xiniexchg,
"Number of initiator exchanges.");
int ql2xfwholdabts = 0; int ql2xfwholdabts = 0;
module_param(ql2xfwholdabts, int, S_IRUGO); module_param(ql2xfwholdabts, int, S_IRUGO);
...@@ -3986,6 +3990,9 @@ qla2x00_set_exlogins_buffer(scsi_qla_host_t *vha) ...@@ -3986,6 +3990,9 @@ qla2x00_set_exlogins_buffer(scsi_qla_host_t *vha)
if (!ql2xexlogins) if (!ql2xexlogins)
return QLA_SUCCESS; return QLA_SUCCESS;
if (!IS_EXLOGIN_OFFLD_CAPABLE(ha))
return QLA_SUCCESS;
ql_log(ql_log_info, vha, 0xd021, "EXLOGIN count: %d.\n", ql2xexlogins); ql_log(ql_log_info, vha, 0xd021, "EXLOGIN count: %d.\n", ql2xexlogins);
max_cnt = 0; max_cnt = 0;
rval = qla_get_exlogin_status(vha, &size, &max_cnt); rval = qla_get_exlogin_status(vha, &size, &max_cnt);
...@@ -3996,21 +4003,27 @@ qla2x00_set_exlogins_buffer(scsi_qla_host_t *vha) ...@@ -3996,21 +4003,27 @@ qla2x00_set_exlogins_buffer(scsi_qla_host_t *vha)
} }
temp = (ql2xexlogins > max_cnt) ? max_cnt : ql2xexlogins; temp = (ql2xexlogins > max_cnt) ? max_cnt : ql2xexlogins;
ha->exlogin_size = (size * temp); temp *= size;
ql_log(ql_log_info, vha, 0xd024,
"EXLOGIN: max_logins=%d, portdb=0x%x, total=%d.\n", if (temp != ha->exlogin_size) {
max_cnt, size, temp); qla2x00_free_exlogin_buffer(ha);
ha->exlogin_size = temp;
ql_log(ql_log_info, vha, 0xd025, "EXLOGIN: requested size=0x%x\n",
ha->exlogin_size); ql_log(ql_log_info, vha, 0xd024,
"EXLOGIN: max_logins=%d, portdb=0x%x, total=%d.\n",
/* Get consistent memory for extended logins */ max_cnt, size, temp);
ha->exlogin_buf = dma_alloc_coherent(&ha->pdev->dev,
ha->exlogin_size, &ha->exlogin_buf_dma, GFP_KERNEL); ql_log(ql_log_info, vha, 0xd025,
if (!ha->exlogin_buf) { "EXLOGIN: requested size=0x%x\n", ha->exlogin_size);
ql_log_pci(ql_log_fatal, ha->pdev, 0xd02a,
/* 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"); "Failed to allocate memory for exlogin_buf_dma.\n");
return -ENOMEM; return -ENOMEM;
}
} }
/* Now configure the dma buffer */ /* Now configure the dma buffer */
...@@ -4041,15 +4054,49 @@ qla2x00_free_exlogin_buffer(struct qla_hw_data *ha) ...@@ -4041,15 +4054,49 @@ qla2x00_free_exlogin_buffer(struct qla_hw_data *ha)
} }
} }
static void
qla2x00_number_of_exch(scsi_qla_host_t *vha, u32 *ret_cnt, u16 max_cnt)
{
u32 temp;
*ret_cnt = FW_DEF_EXCHANGES_CNT;
if (qla_ini_mode_enabled(vha)) {
if (ql2xiniexchg > max_cnt)
ql2xiniexchg = max_cnt;
if (ql2xiniexchg > FW_DEF_EXCHANGES_CNT)
*ret_cnt = ql2xiniexchg;
} else if (qla_tgt_mode_enabled(vha)) {
if (ql2xexchoffld > max_cnt)
ql2xexchoffld = max_cnt;
if (ql2xexchoffld > FW_DEF_EXCHANGES_CNT)
*ret_cnt = ql2xexchoffld;
} else if (qla_dual_mode_enabled(vha)) {
temp = ql2xiniexchg + ql2xexchoffld;
if (temp > max_cnt) {
ql2xiniexchg -= (temp - max_cnt)/2;
ql2xexchoffld -= (((temp - max_cnt)/2) + 1);
temp = max_cnt;
}
if (temp > FW_DEF_EXCHANGES_CNT)
*ret_cnt = temp;
}
}
int int
qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha) qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
{ {
int rval; int rval;
uint16_t size, max_cnt, temp; u16 size, max_cnt;
u32 temp;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
/* Return if we don't need to alloacate any extended logins */ if (!ha->flags.exchoffld_enabled)
if (!ql2xexchoffld) return QLA_SUCCESS;
if (!IS_EXCHG_OFFLD_CAPABLE(ha))
return QLA_SUCCESS; return QLA_SUCCESS;
ql_log(ql_log_info, vha, 0xd014, ql_log(ql_log_info, vha, 0xd014,
...@@ -4063,30 +4110,45 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha) ...@@ -4063,30 +4110,45 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
return rval; return rval;
} }
temp = (ql2xexchoffld > max_cnt) ? max_cnt : ql2xexchoffld; qla2x00_number_of_exch(vha, &temp, max_cnt);
ha->exchoffld_size = (size * temp); temp *= size;
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, if (temp != ha->exchoffld_size) {
"Exchange Buffers requested size = 0x%x\n", ha->exchoffld_size); qla2x00_free_exchoffld_buffer(ha);
ha->exchoffld_size = temp;
/* Get consistent memory for extended logins */
ha->exchoffld_buf = dma_alloc_coherent(&ha->pdev->dev, ql_log(ql_log_info, vha, 0xd016,
ha->exchoffld_size, &ha->exchoffld_buf_dma, GFP_KERNEL); "Exchange offload: max_count=%d, buffers=0x%x, total=%d.\n",
if (!ha->exchoffld_buf) { max_cnt, size, temp);
ql_log_pci(ql_log_fatal, ha->pdev, 0xd013,
"Failed to allocate memory for exchoffld_buf_dma.\n"); ql_log(ql_log_info, vha, 0xd017,
return -ENOMEM; "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 */ /* Now configure the dma buffer */
rval = qla_set_exchoffld_mem_cfg(vha, ha->exchoffld_buf_dma); rval = qla_set_exchoffld_mem_cfg(vha);
if (rval) { if (rval) {
ql_log(ql_log_fatal, vha, 0xd02e, ql_log(ql_log_fatal, vha, 0xd02e,
"Setup exchange offload buffer ****FAILED****.\n"); "Setup exchange offload buffer ****FAILED****.\n");
qla2x00_free_exchoffld_buffer(ha); qla2x00_free_exchoffld_buffer(ha);
} else {
/* re-adjust number of target exchange */
struct init_cb_81xx *icb = (struct init_cb_81xx *)ha->init_cb;
if (qla_ini_mode_enabled(vha))
icb->exchange_count = 0;
else
icb->exchange_count = cpu_to_le16(ql2xexchoffld);
} }
return rval; return rval;
......
...@@ -59,7 +59,7 @@ MODULE_PARM_DESC(qlini_mode, ...@@ -59,7 +59,7 @@ MODULE_PARM_DESC(qlini_mode,
"when ready " "when ready "
"\"enabled\" (default) - initiator mode will always stay enabled."); "\"enabled\" (default) - initiator mode will always stay enabled.");
static int ql_dm_tgt_ex_pct = 50; static int ql_dm_tgt_ex_pct = 0;
module_param(ql_dm_tgt_ex_pct, int, S_IRUGO|S_IWUSR); module_param(ql_dm_tgt_ex_pct, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql_dm_tgt_ex_pct, MODULE_PARM_DESC(ql_dm_tgt_ex_pct,
"For Dual Mode (qlini_mode=dual), this parameter determines " "For Dual Mode (qlini_mode=dual), this parameter determines "
...@@ -6438,8 +6438,9 @@ void ...@@ -6438,8 +6438,9 @@ void
qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
{ {
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
u32 tmp;
u16 t; if (!QLA_TGT_MODE_ENABLED())
return;
if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) { if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
if (!ha->tgt.saved_set) { if (!ha->tgt.saved_set) {
...@@ -6454,24 +6455,10 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) ...@@ -6454,24 +6455,10 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
ha->tgt.saved_set = 1; ha->tgt.saved_set = 1;
} }
if (qla_tgt_mode_enabled(vha)) { if (qla_tgt_mode_enabled(vha))
nv->exchange_count = cpu_to_le16(0xFFFF); nv->exchange_count = cpu_to_le16(0xFFFF);
} else { /* dual */ else /* dual */
if (ql_dm_tgt_ex_pct > 100) { nv->exchange_count = cpu_to_le16(ql2xexchoffld);
ql_dm_tgt_ex_pct = 50;
} else if (ql_dm_tgt_ex_pct == 100) {
/* leave some for FW */
ql_dm_tgt_ex_pct = 95;
}
tmp = ha->orig_fw_xcb_count * ql_dm_tgt_ex_pct;
tmp = tmp/100;
if (tmp > 0xffff)
tmp = 0xffff;
t = tmp & 0xffff;
nv->exchange_count = cpu_to_le16(t);
}
/* Enable target mode */ /* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4); nv->firmware_options_1 |= cpu_to_le32(BIT_4);
...@@ -6556,8 +6543,6 @@ void ...@@ -6556,8 +6543,6 @@ void
qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv) qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
{ {
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
u32 tmp;
u16 t;
if (!QLA_TGT_MODE_ENABLED()) if (!QLA_TGT_MODE_ENABLED())
return; return;
...@@ -6575,23 +6560,10 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv) ...@@ -6575,23 +6560,10 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
ha->tgt.saved_set = 1; ha->tgt.saved_set = 1;
} }
if (qla_tgt_mode_enabled(vha)) { if (qla_tgt_mode_enabled(vha))
nv->exchange_count = cpu_to_le16(0xFFFF); nv->exchange_count = cpu_to_le16(0xFFFF);
} else { /* dual */ else /* dual */
if (ql_dm_tgt_ex_pct > 100) { nv->exchange_count = cpu_to_le16(ql2xexchoffld);
ql_dm_tgt_ex_pct = 50;
} else if (ql_dm_tgt_ex_pct == 100) {
/* leave some for FW */
ql_dm_tgt_ex_pct = 95;
}
tmp = ha->orig_fw_xcb_count * ql_dm_tgt_ex_pct;
tmp = tmp/100;
if (tmp > 0xffff)
tmp = 0xffff;
t = tmp & 0xffff;
nv->exchange_count = cpu_to_le16(t);
}
/* Enable target mode */ /* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4); nv->firmware_options_1 |= cpu_to_le32(BIT_4);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment