diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index e1ae880d5b682..a31d239057535 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -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 diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 8145636c759d6..26b93c563f924 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -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; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 7018067b57070..3673fcdb033a2 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -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 */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 6f6739b945ea5..2e836d1427bbb 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -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); diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index bf9a6f01fd9f8..512c3c37b447f 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -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; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3befe11d64255..d21dd7700d5da 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -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) { diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index d5f6ce8c86df9..c0b9e0d079c04 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -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);