The device has several reply queues, so this patch implements
correct scsi-mq interrupt steering to take advantage of full
blk-mq support.
However, as performance results are inconclusive this patch
also adds a module parameter 'enable_scsi_mq' to expose all
completion queues via scsi-mq; default is off.

Signed-off-by: Hannes Reinecke <h...@suse.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 31 +++++++++++++++++++++++--------
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 34 +++++++++++++++++++++++++++++++++-
 2 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 24b5350..b5fe640 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -872,7 +872,13 @@ struct scsiio_tracker *
            WARN_ON(smid >= ioc->hi_priority_smid))
                return NULL;
 
-       unique_tag = smid - 1;
+       if (!ioc->shost->use_blk_mq)
+               unique_tag = smid - 1;
+       else {
+               u16 hwq = (smid - 1) % ioc->shost->nr_hw_queues;
+               u16 tag = (smid - 1) / ioc->shost->nr_hw_queues;
+               unique_tag = blk_mq_make_unique_tag(hwq, tag);
+       }
        cmd = scsi_host_find_tag(ioc->shost, unique_tag);
        if (cmd)
                return scsi_cmd_priv(cmd);
@@ -2351,17 +2357,22 @@ struct scsiio_tracker *
        struct scsiio_tracker *request = scsi_cmd_priv(scmd);
        unsigned int tag;
        u16 smid;
+       u16 hwq = 0;
 
        if (ioc->shost->use_blk_mq) {
                u32 unique_tag = blk_mq_unique_tag(scmd->request);
-
+               hwq = blk_mq_unique_tag_to_hwq(unique_tag);
                tag = blk_mq_unique_tag_to_tag(unique_tag);
-       } else
+               smid = (tag * ioc->shost->nr_hw_queues) + hwq + 1;
+       } else {
                tag = scmd->request->tag;
-
-       smid = tag + 1;
+               smid = tag + 1;
+       }
        request->cb_idx = cb_idx;
-       request->msix_io = mpt3sas_base_get_msix_index(ioc);
+       if (ioc->shost->nr_hw_queues > 1)
+               request->msix_io = hwq;
+       else
+               request->msix_io = mpt3sas_base_get_msix_index(ioc);
        request->smid = smid;
        INIT_LIST_HEAD(&request->chain_list);
        return smid;
@@ -3528,9 +3539,13 @@ void mpt3sas_base_clear_st(struct MPT3SAS_ADAPTER *ioc,
         */
        ioc->shost->reserved_cmds = INTERNAL_SCSIIO_CMDS_COUNT;
        ioc->shost->can_queue = ioc->scsiio_depth - ioc->shost->reserved_cmds;
+       if (ioc->shost->nr_hw_queues > 1) {
+               ioc->shost->nr_hw_queues = ioc->reply_queue_count;
+               ioc->shost->can_queue /= ioc->reply_queue_count;
+       }
        dinitprintk(ioc, pr_info(MPT3SAS_FMT
-               "scsi host: can_queue depth (%d)\n",
-               ioc->name, ioc->shost->can_queue));
+               "scsi host: can_queue depth (%d), nr_hw_queues (%d)\n",
+               ioc->name, ioc->shost->can_queue, ioc->shost->nr_hw_queues));
 
 
        /* contiguous pool for request and chains, 16 byte align, one extra "
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 839add2..474bccc 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -54,6 +54,7 @@
 #include <linux/interrupt.h>
 #include <linux/aer.h>
 #include <linux/raid_class.h>
+#include <linux/blk-mq-pci.h>
 #include <asm/unaligned.h>
 
 #include "mpt3sas_base.h"
@@ -147,6 +148,10 @@ static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, 
u16 handle,
 module_param(prot_mask, int, 0);
 MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
 
+static int enable_scsi_mq;
+module_param(enable_scsi_mq, int, S_IRUGO);
+MODULE_PARM_DESC(enable_scsi_mq,
+       "Enable scsi-mq (single queue=0/all queues=1/default=0)");
 
 /* raid transport support */
 struct raid_template *mpt3sas_raid_template;
@@ -1075,7 +1080,15 @@ struct scsi_cmnd *
        struct scsiio_tracker *st;
 
        if (smid > 0) {
-               u32 unique_tag = smid - 1;
+               u32 unique_tag;
+
+               if (ioc->shost->use_blk_mq) {
+                       u16 hwq = (smid - 1) % ioc->shost->nr_hw_queues;
+                       u16 tag = (smid - 1) / ioc->shost->nr_hw_queues;
+
+                       unique_tag = blk_mq_make_unique_tag(hwq, tag);
+               } else
+                       unique_tag = smid - 1;
 
                scmd = scsi_host_find_tag(ioc->shost, unique_tag);
                if (scmd) {
@@ -4139,6 +4152,11 @@ static inline bool ata_12_16_cmd(struct scsi_cmnd *scmd)
        if (raid_device && raid_device->direct_io_enabled)
                mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request);
 
+       if (shost_use_blk_mq(ioc->shost) && (ioc->shost->nr_hw_queues > 1)) {
+               u32 unique_tag = blk_mq_unique_tag(scmd->request);
+
+               msix_task = blk_mq_unique_tag_to_hwq(unique_tag);
+       }
        if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
                if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
                        mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
@@ -8536,6 +8554,16 @@ static void sas_device_make_active(struct 
MPT3SAS_ADAPTER *ioc,
        return 1;
 }
 
+static int scsih_map_queues(struct Scsi_Host *shost)
+{
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+
+       if (shost->nr_hw_queues > 1)
+               return blk_mq_pci_map_queues(&shost->tag_set, ioc->pdev);
+
+       return -EINVAL;
+}
+
 /* shost template for SAS 2.0 HBA devices */
 static struct scsi_host_template mpt2sas_driver_template = {
        .module                         = THIS_MODULE,
@@ -8549,6 +8577,7 @@ static void sas_device_make_active(struct MPT3SAS_ADAPTER 
*ioc,
        .slave_destroy                  = scsih_slave_destroy,
        .scan_finished                  = scsih_scan_finished,
        .scan_start                     = scsih_scan_start,
+       .map_queues                     = scsih_map_queues,
        .change_queue_depth             = scsih_change_queue_depth,
        .eh_abort_handler               = scsih_abort,
        .eh_device_reset_handler        = scsih_dev_reset,
@@ -8815,6 +8844,9 @@ static void sas_device_make_active(struct MPT3SAS_ADAPTER 
*ioc,
        shost->max_lun = max_lun;
        shost->transportt = mpt3sas_transport_template;
        shost->unique_id = ioc->id;
+       if (!shost->use_blk_mq)
+               enable_scsi_mq = 0;
+       shost->nr_hw_queues = enable_scsi_mq ? num_online_cpus() : 1;
 
        if (max_sectors != 0xFFFF) {
                if (max_sectors < 64) {
-- 
1.8.5.6

Reply via email to