Commit 0645cb83 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: Add mode control for each physical port

Add ability to allow each physical port to control operating mode.  Current
code forces all ports to behave in one mode (i.e. initiator, target or
dual). This patch allows user to select the operating mode for each port.

- Driver must be loaded in dual mode to allow resource allocation

modprobe qla2xxx qlini_mode=dual

- In addition user can make adjustment to exchange resources using following
  command

echo 1024 > /sys/class/scsi_host/host<x>/ql2xiniexchg
echo 1024 > /sys/class/scsi_host/host<x>/ql2xexchoffld

- trigger mode change and new setting of ql2xexchoffld|ql2xiniexchg

echo [<value>] > /sys/class/scsi_host/host<x>/qlini_mode

where, value can be one of following
  - enabled
  - disabled
  - dual
  - exclusive
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 0e324e94
This diff is collapsed.
......@@ -4376,6 +4376,13 @@ typedef struct scsi_qla_host {
atomic_t vref_count;
struct qla8044_reset_template reset_tmplt;
uint16_t bbcr;
uint16_t u_ql2xexchoffld;
uint16_t u_ql2xiniexchg;
uint16_t qlini_mode;
uint16_t ql2xexchoffld;
uint16_t ql2xiniexchg;
struct name_list_extended gnl;
/* Count of active session/fcport */
int fcport_count;
......
......@@ -159,6 +159,7 @@ extern int ql2xnvmeenable;
extern int ql2xautodetectsfp;
extern int ql2xenablemsix;
extern int qla2xuseresexchforels;
extern int ql2xexlogins;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
......@@ -675,6 +676,7 @@ void qla_scan_work_fn(struct work_struct *);
*/
struct device_attribute;
extern struct device_attribute *qla2x00_host_attrs[];
extern struct device_attribute *qla2x00_host_attrs_dm[];
struct fc_function_template;
extern struct fc_function_template qla2xxx_transport_functions;
extern struct fc_function_template qla2xxx_transport_vport_functions;
......@@ -688,7 +690,7 @@ extern int qla2x00_echo_test(scsi_qla_host_t *,
extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *);
extern int qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *,
struct qla_fcp_prio_cfg *, uint8_t);
void qla_insert_tgt_attrs(void);
/*
* Global Function Prototypes in qla_dfs.c source file.
*/
......@@ -895,5 +897,6 @@ void qlt_unknown_atio_work_fn(struct work_struct *);
void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
void qlt_remove_target_resources(struct qla_hw_data *);
void qlt_clr_qp_table(struct scsi_qla_host *vha);
void qlt_set_mode(struct scsi_qla_host *);
#endif /* _QLA_GBL_H */
......@@ -4056,6 +4056,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_init, vha, 0x00d3,
"Init Firmware -- success.\n");
QLA_FW_STARTED(ha);
vha->u_ql2xexchoffld = vha->u_ql2xiniexchg = 0;
}
return (rval);
......@@ -6702,6 +6703,20 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
return status;
}
switch (vha->qlini_mode) {
case QLA2XXX_INI_MODE_DISABLED:
if (!qla_tgt_mode_enabled(vha))
return 0;
break;
case QLA2XXX_INI_MODE_DUAL:
if (!qla_dual_mode_enabled(vha))
return 0;
break;
case QLA2XXX_INI_MODE_ENABLED:
default:
break;
}
ha->isp_ops->get_flash_version(vha, req->ring);
ha->isp_ops->nvram_config(vha);
......
......@@ -318,13 +318,13 @@ static inline bool
qla_is_exch_offld_enabled(struct scsi_qla_host *vha)
{
if (qla_ini_mode_enabled(vha) &&
(ql2xiniexchg > FW_DEF_EXCHANGES_CNT))
(vha->ql2xiniexchg > FW_DEF_EXCHANGES_CNT))
return true;
else if (qla_tgt_mode_enabled(vha) &&
(ql2xexchoffld > FW_DEF_EXCHANGES_CNT))
(vha->ql2xexchoffld > FW_DEF_EXCHANGES_CNT))
return true;
else if (qla_dual_mode_enabled(vha) &&
((ql2xiniexchg + ql2xexchoffld) > FW_DEF_EXCHANGES_CNT))
((vha->ql2xiniexchg + vha->ql2xexchoffld) > FW_DEF_EXCHANGES_CNT))
return true;
else
return false;
......
......@@ -4290,29 +4290,34 @@ static void
qla2x00_number_of_exch(scsi_qla_host_t *vha, u32 *ret_cnt, u16 max_cnt)
{
u32 temp;
struct init_cb_81xx *icb = (struct init_cb_81xx *)&vha->hw->init_cb;
*ret_cnt = FW_DEF_EXCHANGES_CNT;
if (max_cnt > vha->hw->max_exchg)
max_cnt = vha->hw->max_exchg;
if (qla_ini_mode_enabled(vha)) {
if (ql2xiniexchg > max_cnt)
ql2xiniexchg = max_cnt;
if (vha->ql2xiniexchg > max_cnt)
vha->ql2xiniexchg = max_cnt;
if (vha->ql2xiniexchg > FW_DEF_EXCHANGES_CNT)
*ret_cnt = vha->ql2xiniexchg;
if (ql2xiniexchg > FW_DEF_EXCHANGES_CNT)
*ret_cnt = ql2xiniexchg;
} else if (qla_tgt_mode_enabled(vha)) {
if (ql2xexchoffld > max_cnt)
ql2xexchoffld = max_cnt;
if (vha->ql2xexchoffld > max_cnt) {
vha->ql2xexchoffld = max_cnt;
icb->exchange_count = cpu_to_le16(vha->ql2xexchoffld);
}
if (ql2xexchoffld > FW_DEF_EXCHANGES_CNT)
*ret_cnt = ql2xexchoffld;
if (vha->ql2xexchoffld > FW_DEF_EXCHANGES_CNT)
*ret_cnt = vha->ql2xexchoffld;
} else if (qla_dual_mode_enabled(vha)) {
temp = ql2xiniexchg + ql2xexchoffld;
temp = vha->ql2xiniexchg + vha->ql2xexchoffld;
if (temp > max_cnt) {
ql2xiniexchg -= (temp - max_cnt)/2;
ql2xexchoffld -= (((temp - max_cnt)/2) + 1);
vha->ql2xiniexchg -= (temp - max_cnt)/2;
vha->ql2xexchoffld -= (((temp - max_cnt)/2) + 1);
temp = max_cnt;
icb->exchange_count = cpu_to_le16(vha->ql2xexchoffld);
}
if (temp > FW_DEF_EXCHANGES_CNT)
......@@ -4350,6 +4355,12 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
if (totsz != ha->exchoffld_size) {
qla2x00_free_exchoffld_buffer(ha);
if (actual_cnt <= FW_DEF_EXCHANGES_CNT) {
ha->exchoffld_size = 0;
ha->flags.exchoffld_enabled = 0;
return QLA_SUCCESS;
}
ha->exchoffld_size = totsz;
ql_log(ql_log_info, vha, 0xd016,
......@@ -4382,6 +4393,15 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
return -ENOMEM;
}
} else if (!ha->exchoffld_buf || (actual_cnt <= FW_DEF_EXCHANGES_CNT)) {
/* pathological case */
qla2x00_free_exchoffld_buffer(ha);
ha->exchoffld_size = 0;
ha->flags.exchoffld_enabled = 0;
ql_log(ql_log_info, vha, 0xd016,
"Exchange offload not enable: offld size=%d, actual count=%d entry sz=0x%x, total sz=0x%x.\n",
ha->exchoffld_size, actual_cnt, size, totsz);
return 0;
}
/* Now configure the dma buffer */
......@@ -4397,7 +4417,7 @@ qla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha)
if (qla_ini_mode_enabled(vha))
icb->exchange_count = 0;
else
icb->exchange_count = cpu_to_le16(ql2xexchoffld);
icb->exchange_count = cpu_to_le16(vha->ql2xexchoffld);
}
return rval;
......@@ -4605,6 +4625,10 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
vha->host_no = host->host_no;
vha->hw = ha;
vha->qlini_mode = ql2x_ini_mode;
vha->ql2xexchoffld = ql2xexchoffld;
vha->ql2xiniexchg = ql2xiniexchg;
INIT_LIST_HEAD(&vha->vp_fcports);
INIT_LIST_HEAD(&vha->work_list);
INIT_LIST_HEAD(&vha->list);
......@@ -6081,15 +6105,17 @@ qla2x00_do_dpc(void *data)
!test_bit(UNLOADING, &base_vha->dpc_flags)) {
bool do_reset = true;
switch (ql2x_ini_mode) {
switch (base_vha->qlini_mode) {
case QLA2XXX_INI_MODE_ENABLED:
break;
case QLA2XXX_INI_MODE_DISABLED:
if (!qla_tgt_mode_enabled(base_vha))
if (!qla_tgt_mode_enabled(base_vha) &&
!ha->flags.fw_started)
do_reset = false;
break;
case QLA2XXX_INI_MODE_DUAL:
if (!qla_dual_mode_enabled(base_vha))
if (!qla_dual_mode_enabled(base_vha) &&
!ha->flags.fw_started)
do_reset = false;
break;
default:
......@@ -7020,6 +7046,9 @@ qla2x00_module_init(void)
if (ql2xextended_error_logging == 1)
ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
if (ql2x_ini_mode == QLA2XXX_INI_MODE_DUAL)
qla_insert_tgt_attrs();
qla2xxx_transport_template =
fc_attach_transport(&qla2xxx_transport_functions);
if (!qla2xxx_transport_template) {
......
......@@ -1570,6 +1570,15 @@ void qlt_stop_phase2(struct qla_tgt *tgt)
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00c, "Stop of tgt %p finished\n",
tgt);
switch (vha->qlini_mode) {
case QLA2XXX_INI_MODE_EXCLUSIVE:
vha->flags.online = 1;
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
default:
break;
}
}
EXPORT_SYMBOL(qlt_stop_phase2);
......@@ -6617,6 +6626,9 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
if (!(host->hostt->supported_mode & MODE_TARGET))
continue;
if (vha->qlini_mode == QLA2XXX_INI_MODE_ENABLED)
continue;
spin_lock_irqsave(&ha->hardware_lock, flags);
if ((!npiv_wwpn || !npiv_wwnn) && host->active_mode & MODE_TARGET) {
pr_debug("MODE_TARGET already active on qla2xxx(%d)\n",
......@@ -6679,15 +6691,15 @@ void qlt_lport_deregister(struct scsi_qla_host *vha)
EXPORT_SYMBOL(qlt_lport_deregister);
/* Must be called under HW lock */
static void qlt_set_mode(struct scsi_qla_host *vha)
void qlt_set_mode(struct scsi_qla_host *vha)
{
switch (ql2x_ini_mode) {
switch (vha->qlini_mode) {
case QLA2XXX_INI_MODE_DISABLED:
case QLA2XXX_INI_MODE_EXCLUSIVE:
vha->host->active_mode = MODE_TARGET;
break;
case QLA2XXX_INI_MODE_ENABLED:
vha->host->active_mode = MODE_UNKNOWN;
vha->host->active_mode = MODE_INITIATOR;
break;
case QLA2XXX_INI_MODE_DUAL:
vha->host->active_mode = MODE_DUAL;
......@@ -6700,7 +6712,7 @@ static void qlt_set_mode(struct scsi_qla_host *vha)
/* Must be called under HW lock */
static void qlt_clear_mode(struct scsi_qla_host *vha)
{
switch (ql2x_ini_mode) {
switch (vha->qlini_mode) {
case QLA2XXX_INI_MODE_DISABLED:
vha->host->active_mode = MODE_UNKNOWN;
break;
......@@ -6736,6 +6748,8 @@ qlt_enable_vha(struct scsi_qla_host *vha)
dump_stack();
return;
}
if (vha->qlini_mode == QLA2XXX_INI_MODE_ENABLED)
return;
spin_lock_irqsave(&ha->hardware_lock, flags);
tgt->tgt_stopped = 0;
......@@ -6975,7 +6989,7 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
if (qla_tgt_mode_enabled(vha))
nv->exchange_count = cpu_to_le16(0xFFFF);
else /* dual */
nv->exchange_count = cpu_to_le16(ql2xexchoffld);
nv->exchange_count = cpu_to_le16(vha->ql2xexchoffld);
/* Enable target mode */
nv->firmware_options_1 |= cpu_to_le32(BIT_4);
......@@ -7081,7 +7095,7 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
if (qla_tgt_mode_enabled(vha))
nv->exchange_count = cpu_to_le16(0xFFFF);
else /* dual */
nv->exchange_count = cpu_to_le16(ql2xexchoffld);
nv->exchange_count = cpu_to_le16(vha->ql2xexchoffld);
/* Enable target mode */
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