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
......@@ -1632,6 +1632,433 @@ qla2x00_max_speed_sup_show(struct device *dev, struct device_attribute *attr,
ha->max_speed_sup ? "32Gps" : "16Gps");
}
/* ----- */
static ssize_t
qlini_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
int len = 0;
len += scnprintf(buf + len, PAGE_SIZE-len,
"Supported options: enabled | disabled | dual | exclusive\n");
/* --- */
len += scnprintf(buf + len, PAGE_SIZE-len, "Current selection: ");
switch (vha->qlini_mode) {
case QLA2XXX_INI_MODE_EXCLUSIVE:
len += scnprintf(buf + len, PAGE_SIZE-len,
QLA2XXX_INI_MODE_STR_EXCLUSIVE);
break;
case QLA2XXX_INI_MODE_DISABLED:
len += scnprintf(buf + len, PAGE_SIZE-len,
QLA2XXX_INI_MODE_STR_DISABLED);
break;
case QLA2XXX_INI_MODE_ENABLED:
len += scnprintf(buf + len, PAGE_SIZE-len,
QLA2XXX_INI_MODE_STR_ENABLED);
break;
case QLA2XXX_INI_MODE_DUAL:
len += scnprintf(buf + len, PAGE_SIZE-len,
QLA2XXX_INI_MODE_STR_DUAL);
break;
}
len += scnprintf(buf + len, PAGE_SIZE-len, "\n");
return len;
}
static char *mode_to_str[] = {
"exclusive",
"disabled",
"enabled",
"dual",
};
#define NEED_EXCH_OFFLOAD(_exchg) ((_exchg) > FW_DEF_EXCHANGES_CNT)
static int qla_set_ini_mode(scsi_qla_host_t *vha, int op)
{
int rc = 0;
enum {
NO_ACTION,
MODE_CHANGE_ACCEPT,
MODE_CHANGE_NO_ACTION,
TARGET_STILL_ACTIVE,
};
int action = NO_ACTION;
int set_mode = 0;
u8 eo_toggle = 0; /* exchange offload flipped */
switch (vha->qlini_mode) {
case QLA2XXX_INI_MODE_DISABLED:
switch (op) {
case QLA2XXX_INI_MODE_DISABLED:
if (qla_tgt_mode_enabled(vha)) {
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
vha->hw->flags.exchoffld_enabled)
eo_toggle = 1;
if (((vha->ql2xexchoffld !=
vha->u_ql2xexchoffld) &&
NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
eo_toggle) {
/*
* The number of exchange to be offload
* was tweaked or offload option was
* flipped
*/
action = MODE_CHANGE_ACCEPT;
} else {
action = MODE_CHANGE_NO_ACTION;
}
} else {
action = MODE_CHANGE_NO_ACTION;
}
break;
case QLA2XXX_INI_MODE_EXCLUSIVE:
if (qla_tgt_mode_enabled(vha)) {
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
vha->hw->flags.exchoffld_enabled)
eo_toggle = 1;
if (((vha->ql2xexchoffld !=
vha->u_ql2xexchoffld) &&
NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
eo_toggle) {
/*
* The number of exchange to be offload
* was tweaked or offload option was
* flipped
*/
action = MODE_CHANGE_ACCEPT;
} else {
action = MODE_CHANGE_NO_ACTION;
}
} else {
action = MODE_CHANGE_ACCEPT;
}
break;
case QLA2XXX_INI_MODE_DUAL:
action = MODE_CHANGE_ACCEPT;
/* active_mode is target only, reset it to dual */
if (qla_tgt_mode_enabled(vha)) {
set_mode = 1;
action = MODE_CHANGE_ACCEPT;
} else {
action = MODE_CHANGE_NO_ACTION;
}
break;
case QLA2XXX_INI_MODE_ENABLED:
if (qla_tgt_mode_enabled(vha))
action = TARGET_STILL_ACTIVE;
else {
action = MODE_CHANGE_ACCEPT;
set_mode = 1;
}
break;
}
break;
case QLA2XXX_INI_MODE_EXCLUSIVE:
switch (op) {
case QLA2XXX_INI_MODE_EXCLUSIVE:
if (qla_tgt_mode_enabled(vha)) {
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
vha->hw->flags.exchoffld_enabled)
eo_toggle = 1;
if (((vha->ql2xexchoffld !=
vha->u_ql2xexchoffld) &&
NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
eo_toggle)
/*
* The number of exchange to be offload
* was tweaked or offload option was
* flipped
*/
action = MODE_CHANGE_ACCEPT;
else
action = NO_ACTION;
} else
action = NO_ACTION;
break;
case QLA2XXX_INI_MODE_DISABLED:
if (qla_tgt_mode_enabled(vha)) {
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld) !=
vha->hw->flags.exchoffld_enabled)
eo_toggle = 1;
if (((vha->ql2xexchoffld !=
vha->u_ql2xexchoffld) &&
NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld)) ||
eo_toggle)
action = MODE_CHANGE_ACCEPT;
else
action = MODE_CHANGE_NO_ACTION;
} else
action = MODE_CHANGE_NO_ACTION;
break;
case QLA2XXX_INI_MODE_DUAL: /* exclusive -> dual */
if (qla_tgt_mode_enabled(vha)) {
action = MODE_CHANGE_ACCEPT;
set_mode = 1;
} else
action = MODE_CHANGE_ACCEPT;
break;
case QLA2XXX_INI_MODE_ENABLED:
if (qla_tgt_mode_enabled(vha))
action = TARGET_STILL_ACTIVE;
else {
if (vha->hw->flags.fw_started)
action = MODE_CHANGE_NO_ACTION;
else
action = MODE_CHANGE_ACCEPT;
}
break;
}
break;
case QLA2XXX_INI_MODE_ENABLED:
switch (op) {
case QLA2XXX_INI_MODE_ENABLED:
if (NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg) !=
vha->hw->flags.exchoffld_enabled)
eo_toggle = 1;
if (((vha->ql2xiniexchg != vha->u_ql2xiniexchg) &&
NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg)) ||
eo_toggle)
action = MODE_CHANGE_ACCEPT;
else
action = NO_ACTION;
break;
case QLA2XXX_INI_MODE_DUAL:
case QLA2XXX_INI_MODE_DISABLED:
action = MODE_CHANGE_ACCEPT;
break;
default:
action = MODE_CHANGE_NO_ACTION;
break;
}
break;
case QLA2XXX_INI_MODE_DUAL:
switch (op) {
case QLA2XXX_INI_MODE_DUAL:
if (qla_tgt_mode_enabled(vha) ||
qla_dual_mode_enabled(vha)) {
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld +
vha->u_ql2xiniexchg) !=
vha->hw->flags.exchoffld_enabled)
eo_toggle = 1;
if ((((vha->ql2xexchoffld +
vha->ql2xiniexchg) !=
(vha->u_ql2xiniexchg +
vha->u_ql2xexchoffld)) &&
NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg +
vha->u_ql2xexchoffld)) || eo_toggle)
action = MODE_CHANGE_ACCEPT;
else
action = NO_ACTION;
} else {
if (NEED_EXCH_OFFLOAD(vha->u_ql2xexchoffld +
vha->u_ql2xiniexchg) !=
vha->hw->flags.exchoffld_enabled)
eo_toggle = 1;
if ((((vha->ql2xexchoffld + vha->ql2xiniexchg)
!= (vha->u_ql2xiniexchg +
vha->u_ql2xexchoffld)) &&
NEED_EXCH_OFFLOAD(vha->u_ql2xiniexchg +
vha->u_ql2xexchoffld)) || eo_toggle)
action = MODE_CHANGE_NO_ACTION;
else
action = NO_ACTION;
}
break;
case QLA2XXX_INI_MODE_DISABLED:
if (qla_tgt_mode_enabled(vha) ||
qla_dual_mode_enabled(vha)) {
/* turning off initiator mode */
set_mode = 1;
action = MODE_CHANGE_ACCEPT;
} else {
action = MODE_CHANGE_NO_ACTION;
}
break;
case QLA2XXX_INI_MODE_EXCLUSIVE:
if (qla_tgt_mode_enabled(vha) ||
qla_dual_mode_enabled(vha)) {
set_mode = 1;
action = MODE_CHANGE_ACCEPT;
} else {
action = MODE_CHANGE_ACCEPT;
}
break;
case QLA2XXX_INI_MODE_ENABLED:
if (qla_tgt_mode_enabled(vha) ||
qla_dual_mode_enabled(vha)) {
action = TARGET_STILL_ACTIVE;
} else {
action = MODE_CHANGE_ACCEPT;
}
}
break;
}
switch (action) {
case MODE_CHANGE_ACCEPT:
ql_log(ql_log_warn, vha, 0xffff,
"Mode change accepted. From %s to %s, Tgt exchg %d|%d. ini exchg %d|%d\n",
mode_to_str[vha->qlini_mode], mode_to_str[op],
vha->ql2xexchoffld, vha->u_ql2xexchoffld,
vha->ql2xiniexchg, vha->u_ql2xiniexchg);
vha->qlini_mode = op;
vha->ql2xexchoffld = vha->u_ql2xexchoffld;
vha->ql2xiniexchg = vha->u_ql2xiniexchg;
if (set_mode)
qlt_set_mode(vha);
vha->flags.online = 1;
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
case MODE_CHANGE_NO_ACTION:
ql_log(ql_log_warn, vha, 0xffff,
"Mode is set. No action taken. From %s to %s, Tgt exchg %d|%d. ini exchg %d|%d\n",
mode_to_str[vha->qlini_mode], mode_to_str[op],
vha->ql2xexchoffld, vha->u_ql2xexchoffld,
vha->ql2xiniexchg, vha->u_ql2xiniexchg);
vha->qlini_mode = op;
vha->ql2xexchoffld = vha->u_ql2xexchoffld;
vha->ql2xiniexchg = vha->u_ql2xiniexchg;
break;
case TARGET_STILL_ACTIVE:
ql_log(ql_log_warn, vha, 0xffff,
"Target Mode is active. Unable to change Mode.\n");
break;
case NO_ACTION:
default:
ql_log(ql_log_warn, vha, 0xffff,
"Mode unchange. No action taken. %d|%d pct %d|%d.\n",
vha->qlini_mode, op,
vha->ql2xexchoffld, vha->u_ql2xexchoffld);
break;
}
return rc;
}
static ssize_t
qlini_mode_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
int ini;
if (!buf)
return -EINVAL;
if (strncasecmp(QLA2XXX_INI_MODE_STR_EXCLUSIVE, buf,
strlen(QLA2XXX_INI_MODE_STR_EXCLUSIVE)) == 0)
ini = QLA2XXX_INI_MODE_EXCLUSIVE;
else if (strncasecmp(QLA2XXX_INI_MODE_STR_DISABLED, buf,
strlen(QLA2XXX_INI_MODE_STR_DISABLED)) == 0)
ini = QLA2XXX_INI_MODE_DISABLED;
else if (strncasecmp(QLA2XXX_INI_MODE_STR_ENABLED, buf,
strlen(QLA2XXX_INI_MODE_STR_ENABLED)) == 0)
ini = QLA2XXX_INI_MODE_ENABLED;
else if (strncasecmp(QLA2XXX_INI_MODE_STR_DUAL, buf,
strlen(QLA2XXX_INI_MODE_STR_DUAL)) == 0)
ini = QLA2XXX_INI_MODE_DUAL;
else
return -EINVAL;
qla_set_ini_mode(vha, ini);
return strlen(buf);
}
static ssize_t
ql2xexchoffld_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
int len = 0;
len += scnprintf(buf + len, PAGE_SIZE-len,
"target exchange: new %d : current: %d\n\n",
vha->u_ql2xexchoffld, vha->ql2xexchoffld);
len += scnprintf(buf + len, PAGE_SIZE-len,
"Please (re)set operating mode via \"/sys/class/scsi_host/host%ld/qlini_mode\" to load new setting.\n",
vha->host_no);
return len;
}
static ssize_t
ql2xexchoffld_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
int val = 0;
if (sscanf(buf, "%d", &val) != 1)
return -EINVAL;
if (val > FW_MAX_EXCHANGES_CNT)
val = FW_MAX_EXCHANGES_CNT;
else if (val < 0)
val = 0;
vha->u_ql2xexchoffld = val;
return strlen(buf);
}
static ssize_t
ql2xiniexchg_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
int len = 0;
len += scnprintf(buf + len, PAGE_SIZE-len,
"target exchange: new %d : current: %d\n\n",
vha->u_ql2xiniexchg, vha->ql2xiniexchg);
len += scnprintf(buf + len, PAGE_SIZE-len,
"Please (re)set operating mode via \"/sys/class/scsi_host/host%ld/qlini_mode\" to load new setting.\n",
vha->host_no);
return len;
}
static ssize_t
ql2xiniexchg_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
int val = 0;
if (sscanf(buf, "%d", &val) != 1)
return -EINVAL;
if (val > FW_MAX_EXCHANGES_CNT)
val = FW_MAX_EXCHANGES_CNT;
else if (val < 0)
val = 0;
vha->u_ql2xiniexchg = val;
return strlen(buf);
}
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
......@@ -1682,6 +2109,10 @@ static DEVICE_ATTR(max_speed_sup, S_IRUGO, qla2x00_max_speed_sup_show, NULL);
static DEVICE_ATTR(zio_threshold, 0644,
qla_zio_threshold_show,
qla_zio_threshold_store);
static DEVICE_ATTR_RW(qlini_mode);
static DEVICE_ATTR_RW(ql2xexchoffld);
static DEVICE_ATTR_RW(ql2xiniexchg);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
......@@ -1719,9 +2150,27 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_min_link_speed,
&dev_attr_max_speed_sup,
&dev_attr_zio_threshold,
NULL, /* reserve for qlini_mode */
NULL, /* reserve for ql2xiniexchg */
NULL, /* reserve for ql2xexchoffld */
NULL,
};
void qla_insert_tgt_attrs(void)
{
struct device_attribute **attr;
/* advance to empty slot */
for (attr = &qla2x00_host_attrs[0]; *attr; ++attr)
continue;
*attr = &dev_attr_qlini_mode;
attr++;
*attr = &dev_attr_ql2xiniexchg;
attr++;
*attr = &dev_attr_ql2xexchoffld;
}
/* Host attributes. */
static void
......
......@@ -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