]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
scsi: qla2xxx: Add mode control for each physical port
authorQuinn Tran <quinn.tran@cavium.com>
Tue, 11 Sep 2018 17:18:18 +0000 (10:18 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 12 Sep 2018 00:28:09 +0000 (20:28 -0400)
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: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c

index e1ae880d5b682233195bda87fc18fc036edfe60a..a31d2390575357efda098283e8b539f09a3d5615 100644 (file)
@@ -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
index 8145636c759d6c97f95e241df623c9429b9af1ac..26b93c563f924fc67b523e5b0476415c0b5c1047 100644 (file)
@@ -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;
index 7018067b570703d73905cc1919895230d4ef2f80..3673fcdb033a2de3aa2278bf9cc513c5068a9277 100644 (file)
@@ -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 */
index 6f6739b945ea535cf9cee7aad1f4c250733f17a2..2e836d1427bbb6bc4957b1d0555ceb40ac8e8488 100644 (file)
@@ -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);
index bf9a6f01fd9f8a0bce2d7dd607b2412e89d8865c..512c3c37b447f2be2fd3bc01b7ed6b2d758a1490 100644 (file)
@@ -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;
index 3befe11d64255dfa0ddc6caa2323c951383836a9..d21dd7700d5daa88f2c2a64b67bfaa33edfffb42 100644 (file)
@@ -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) {
index d5f6ce8c86df99fd4faaa46af829a5a6b4ca4c7d..c0b9e0d079c04a49a6d2fef183953829e283225d 100644 (file)
@@ -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);