summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_dfs.c
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@cavium.com>2017-06-14 05:47:20 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2017-06-28 03:21:40 +0200
commit09620eeb62c4167d0c206f9a69730fa9e9251aae (patch)
tree7c03e5194e923553bebefd958d645e7c2eb8963f /drivers/scsi/qla2xxx/qla_dfs.c
parentscsi: qla2xxx: Fix mailbox failure while deleting Queue pairs (diff)
downloadlinux-09620eeb62c4167d0c206f9a69730fa9e9251aae.tar.xz
linux-09620eeb62c4167d0c206f9a69730fa9e9251aae.zip
scsi: qla2xxx: Add debug knob for user control workload
For Target mode, user can control the work load by placing qla2xxx's irq vector on certain CPU via the smp_affinity knob. This patch allows user to control the number of QPair's irq to be active. The irqs are allocated at driver load time until unload. The work itself is placed on the QPair based on user setting. Usage: modprobe qla2xxx qlini_mode=disabled ql2xuctrlirq=1 mount -t debugfs none /sys/kernel/debug echo 2 > /sys/kernel/debug/qla2xxx/qla2xxx_[host num]/naqp echo [cpu id] > /proc/irq/[irq id]/smp_affinity_list 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>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_dfs.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 391c50be2297..63d7374dce77 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -314,6 +314,81 @@ static const struct file_operations dfs_fce_ops = {
.release = qla2x00_dfs_fce_release,
};
+static int
+qla_dfs_naqp_show(struct seq_file *s, void *unused)
+{
+ struct scsi_qla_host *vha = s->private;
+ struct qla_hw_data *ha = vha->hw;
+
+ seq_printf(s, "%d\n", ha->tgt.num_act_qpairs);
+ return 0;
+}
+
+static int
+qla_dfs_naqp_open(struct inode *inode, struct file *file)
+{
+ struct scsi_qla_host *vha = inode->i_private;
+
+ return single_open(file, qla_dfs_naqp_show, vha);
+}
+
+static ssize_t
+qla_dfs_naqp_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *pos)
+{
+ struct seq_file *s = file->private_data;
+ struct scsi_qla_host *vha = s->private;
+ struct qla_hw_data *ha = vha->hw;
+ char *buf;
+ int rc = 0;
+ unsigned long num_act_qp;
+
+ if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha))) {
+ pr_err("host%ld: this adapter does not support Multi Q.",
+ vha->host_no);
+ return -EINVAL;
+ }
+
+ if (!vha->flags.qpairs_available) {
+ pr_err("host%ld: Driver is not setup with Multi Q.",
+ vha->host_no);
+ return -EINVAL;
+ }
+ buf = memdup_user_nul(buffer, count);
+ if (IS_ERR(buf)) {
+ pr_err("host%ld: fail to copy user buffer.",
+ vha->host_no);
+ return PTR_ERR(buf);
+ }
+
+ num_act_qp = simple_strtoul(buf, NULL, 0);
+
+ if (num_act_qp >= vha->hw->max_qpairs) {
+ pr_err("User set invalid number of qpairs %lu. Max = %d",
+ num_act_qp, vha->hw->max_qpairs);
+ rc = -EINVAL;
+ goto out_free;
+ }
+
+ if (num_act_qp != ha->tgt.num_act_qpairs) {
+ ha->tgt.num_act_qpairs = num_act_qp;
+ qlt_clr_qp_table(vha);
+ }
+ rc = count;
+out_free:
+ kfree(buf);
+ return rc;
+}
+
+static const struct file_operations dfs_naqp_ops = {
+ .open = qla_dfs_naqp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = qla_dfs_naqp_write,
+};
+
+
int
qla2x00_dfs_setup(scsi_qla_host_t *vha)
{
@@ -391,6 +466,15 @@ create_nodes:
goto out;
}
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
+ ha->tgt.dfs_naqp = debugfs_create_file("naqp",
+ 0400, ha->dfs_dir, vha, &dfs_naqp_ops);
+ if (!ha->tgt.dfs_naqp) {
+ ql_log(ql_log_warn, vha, 0xd011,
+ "Unable to create debugFS naqp node.\n");
+ goto out;
+ }
+ }
out:
return 0;
}
@@ -400,6 +484,11 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
+ if (ha->tgt.dfs_naqp) {
+ debugfs_remove(ha->tgt.dfs_naqp);
+ ha->tgt.dfs_naqp = NULL;
+ }
+
if (ha->tgt.dfs_tgt_sess) {
debugfs_remove(ha->tgt.dfs_tgt_sess);
ha->tgt.dfs_tgt_sess = NULL;