From: Quinn Tran
Qlogic's adapter is able to behave in multiple modes:
initiator, target, exclusive/either, and dual/both.
This patch renames the qlini_mode -> qlop_mode and allow
different setting for each port and exchange resource control.
Usage:
modprobe qla2xxx qlop_mode=dual_mode
echo 95 > /sys/class/scsi_host//ql_dm_tgt_ex_pct
echo dual_mode > /sys/class/scsi_host//f_qlop_mode
echo ini_mode > /sys/class/scsi_host//f_qlop_mode
Signed-off-by: Quinn Tran
Signed-off-by: Himanshu Madhani
---
drivers/scsi/qla2xxx/qla_attr.c | 351 ++
drivers/scsi/qla2xxx/qla_def.h| 4 +
drivers/scsi/qla2xxx/qla_gbl.h| 4 +
drivers/scsi/qla2xxx/qla_os.c | 4 +
drivers/scsi/qla2xxx/qla_target.c | 117 ++---
drivers/scsi/qla2xxx/qla_target.h | 22 +--
6 files changed, 425 insertions(+), 77 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index f48b76c..d8b77aa 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1504,6 +1504,351 @@
ha->pep_version[0], ha->pep_version[1], ha->pep_version[2]);
}
+
+static ssize_t
+qla2x00_tgt_ex_pct_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ int len = 0;
+
+ if (ql2x_op_mode == QLA2XXX_OP_MODE_INITIATOR) {
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "This option is not supported. Driver need to be loaded
with "
+ "non-initiator mode (qlop_mode)");
+ return len;
+ }
+
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "target exchange percentage: new %d : current: %d\n\n",
+ vha->u_tgt_ex_pct, vha->tgt_ex_pct);
+
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "Please (re)set operating mode via \"f_qlop_mode\" to load new
setting\n");
+ return len;
+}
+
+static ssize_t
+qla2x00_tgt_ex_pct_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 (ql2x_op_mode == QLA2XXX_OP_MODE_INITIATOR)
+ goto out;
+
+ if (sscanf(buf, "%d", ) != 1)
+ return -EINVAL;
+
+ if (val > 100)
+ val = 100;
+ else if (val < 0)
+ val = 0;
+
+ vha->u_tgt_ex_pct = val;
+out:
+ return strlen(buf);
+}
+
+static ssize_t
+qla2x00_opmode_show(struct device *dev, struct device_attribute *attr,
+char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ int len = 0;
+
+ if (ql2x_op_mode == QLA2XXX_OP_MODE_INITIATOR) {
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "This option is not supported. Driver need to be
loaded with "
+ "non-initiator mode (qlop_mode)");
+ return len;
+ }
+
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ "Supported options: exclusive | tgt_mode | ini_mode | dual_mode\n");
+
+ /* --- */
+ len += scnprintf(buf + len, PAGE_SIZE-len, "Current selection: ");
+
+ switch (vha->qlop_mode) {
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ QLA2XXX_OP_MODE_STR_EXCLUSIVE);
+ break;
+ case QLA2XXX_OP_MODE_TARGET:
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ QLA2XXX_OP_MODE_STR_TARGET);
+ break;
+ case QLA2XXX_OP_MODE_INITIATOR:
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ QLA2XXX_OP_MODE_STR_INITIATOR);
+ break;
+ case QLA2XXX_OP_MODE_DUAL:
+ len += scnprintf(buf + len, PAGE_SIZE-len,
+ QLA2XXX_OP_MODE_STR_DUAL);
+ break;
+ }
+ len += scnprintf(buf + len, PAGE_SIZE-len, "\n");
+
+ return len;
+}
+
+
+void qla_adj_tgt_exch_pct(scsi_qla_host_t *vha, int op)
+{
+ /* reserve a few exchange for FW for mgt. */
+ switch (op) {
+ case QLA2XXX_OP_MODE_TARGET:
+ vha->u_tgt_ex_pct = MAX_TGT_EXCH_PCT;
+ break;
+
+ case QLA2XXX_OP_MODE_EXCLUSIVE:
+ if (qla_tgt_mode_enabled(vha) ||
+ qla_dual_mode_enabled(vha)) {
+ vha->u_tgt_ex_pct = MAX_TGT_EXCH_PCT;
+ } else
+ vha->u_tgt_ex_pct = 0;
+ break;
+
+ case QLA2XXX_OP_MODE_INITIATOR:
+ /* target mode does not need any exchange reserve. */
+ vha->u_tgt_ex_pct = 0;
+ break;
+
+ case QLA2XXX_OP_MODE_DUAL:
+ if