scsi: mpt3sas: Add support for shared host tagset for CPU hotplug
MPT Fusion adapters can steer completions to individual queues and we now have support for shared host-wide tags in the I/O stack. The addition of the host-wide tags allows us to enable multiqueue support for MPT Fusion adapters. Once host-wise tags are enabled, the CPU hotplug feature is also supported. Allow use of host-wide tags to be disabled through the "host_tagset_enable" module parameter. Once we do not have any major performance regressions using host-wide tags, we will drop the hand-crafted interrupt affinity settings. Performance is meeting expectations. About 3.1M IOPS using 24 Drive SSD on Aero controllers. Link: https://lore.kernel.org/r/20210202095832.23072-1-sreekanth.reddy@broadcom.com Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
d309ae0732
commit
664f0dce20
|
@ -3648,25 +3648,16 @@ _base_get_msix_index(struct MPT3SAS_ADAPTER *ioc,
|
||||||
base_mod64(atomic64_add_return(1,
|
base_mod64(atomic64_add_return(1,
|
||||||
&ioc->total_io_cnt), ioc->reply_queue_count) : 0;
|
&ioc->total_io_cnt), ioc->reply_queue_count) : 0;
|
||||||
|
|
||||||
|
if (scmd && ioc->shost->nr_hw_queues > 1) {
|
||||||
|
u32 tag = blk_mq_unique_tag(scmd->request);
|
||||||
|
|
||||||
|
return blk_mq_unique_tag_to_hwq(tag) +
|
||||||
|
ioc->high_iops_queues;
|
||||||
|
}
|
||||||
|
|
||||||
return ioc->cpu_msix_table[raw_smp_processor_id()];
|
return ioc->cpu_msix_table[raw_smp_processor_id()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* _base_sdev_nr_inflight_request -get number of inflight requests
|
|
||||||
* of a request queue.
|
|
||||||
* @q: request_queue object
|
|
||||||
*
|
|
||||||
* returns number of inflight request of a request queue.
|
|
||||||
*/
|
|
||||||
inline unsigned long
|
|
||||||
_base_sdev_nr_inflight_request(struct request_queue *q)
|
|
||||||
{
|
|
||||||
struct blk_mq_hw_ctx *hctx = q->queue_hw_ctx[0];
|
|
||||||
|
|
||||||
return atomic_read(&hctx->nr_active);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _base_get_high_iops_msix_index - get the msix index of
|
* _base_get_high_iops_msix_index - get the msix index of
|
||||||
* high iops queues
|
* high iops queues
|
||||||
|
@ -3686,7 +3677,8 @@ _base_get_high_iops_msix_index(struct MPT3SAS_ADAPTER *ioc,
|
||||||
* reply queues in terms of batch count 16 when outstanding
|
* reply queues in terms of batch count 16 when outstanding
|
||||||
* IOs on the target device is >=8.
|
* IOs on the target device is >=8.
|
||||||
*/
|
*/
|
||||||
if (_base_sdev_nr_inflight_request(scmd->device->request_queue) >
|
|
||||||
|
if (atomic_read(&scmd->device->device_busy) >
|
||||||
MPT3SAS_DEVICE_HIGH_IOPS_DEPTH)
|
MPT3SAS_DEVICE_HIGH_IOPS_DEPTH)
|
||||||
return base_mod64((
|
return base_mod64((
|
||||||
atomic64_add_return(1, &ioc->high_iops_outstanding) /
|
atomic64_add_return(1, &ioc->high_iops_outstanding) /
|
||||||
|
@ -3739,8 +3731,23 @@ mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
|
||||||
struct scsi_cmnd *scmd)
|
struct scsi_cmnd *scmd)
|
||||||
{
|
{
|
||||||
struct scsiio_tracker *request = scsi_cmd_priv(scmd);
|
struct scsiio_tracker *request = scsi_cmd_priv(scmd);
|
||||||
unsigned int tag = scmd->request->tag;
|
|
||||||
u16 smid;
|
u16 smid;
|
||||||
|
u32 tag, unique_tag;
|
||||||
|
|
||||||
|
unique_tag = blk_mq_unique_tag(scmd->request);
|
||||||
|
tag = blk_mq_unique_tag_to_tag(unique_tag);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store hw queue number corresponding to the tag.
|
||||||
|
* This hw queue number is used later to determine
|
||||||
|
* the unique_tag using the logic below. This unique_tag
|
||||||
|
* is used to retrieve the scmd pointer corresponding
|
||||||
|
* to tag using scsi_host_find_tag() API.
|
||||||
|
*
|
||||||
|
* tag = smid - 1;
|
||||||
|
* unique_tag = ioc->io_queue_num[tag] << BLK_MQ_UNIQUE_TAG_BITS | tag;
|
||||||
|
*/
|
||||||
|
ioc->io_queue_num[tag] = blk_mq_unique_tag_to_hwq(unique_tag);
|
||||||
|
|
||||||
smid = tag + 1;
|
smid = tag + 1;
|
||||||
request->cb_idx = cb_idx;
|
request->cb_idx = cb_idx;
|
||||||
|
@ -3831,6 +3838,7 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||||
|
|
||||||
mpt3sas_base_clear_st(ioc, st);
|
mpt3sas_base_clear_st(ioc, st);
|
||||||
_base_recovery_check(ioc);
|
_base_recovery_check(ioc);
|
||||||
|
ioc->io_queue_num[smid - 1] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5362,6 +5370,9 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
|
||||||
kfree(ioc->chain_lookup);
|
kfree(ioc->chain_lookup);
|
||||||
ioc->chain_lookup = NULL;
|
ioc->chain_lookup = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(ioc->io_queue_num);
|
||||||
|
ioc->io_queue_num = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5773,6 +5784,11 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
|
||||||
ioc_info(ioc, "internal(0x%p): depth(%d), start smid(%d)\n",
|
ioc_info(ioc, "internal(0x%p): depth(%d), start smid(%d)\n",
|
||||||
ioc->internal,
|
ioc->internal,
|
||||||
ioc->internal_depth, ioc->internal_smid));
|
ioc->internal_depth, ioc->internal_smid));
|
||||||
|
|
||||||
|
ioc->io_queue_num = kcalloc(ioc->scsiio_depth,
|
||||||
|
sizeof(u16), GFP_KERNEL);
|
||||||
|
if (!ioc->io_queue_num)
|
||||||
|
goto out;
|
||||||
/*
|
/*
|
||||||
* The number of NVMe page sized blocks needed is:
|
* The number of NVMe page sized blocks needed is:
|
||||||
* (((sg_tablesize * 8) - 1) / (page_size - 8)) + 1
|
* (((sg_tablesize * 8) - 1) / (page_size - 8)) + 1
|
||||||
|
|
|
@ -1439,6 +1439,7 @@ struct MPT3SAS_ADAPTER {
|
||||||
spinlock_t scsi_lookup_lock;
|
spinlock_t scsi_lookup_lock;
|
||||||
int pending_io_count;
|
int pending_io_count;
|
||||||
wait_queue_head_t reset_wq;
|
wait_queue_head_t reset_wq;
|
||||||
|
u16 *io_queue_num;
|
||||||
|
|
||||||
/* PCIe SGL */
|
/* PCIe SGL */
|
||||||
struct dma_pool *pcie_sgl_dma_pool;
|
struct dma_pool *pcie_sgl_dma_pool;
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
#include <linux/raid_class.h>
|
#include <linux/raid_class.h>
|
||||||
|
#include <linux/blk-mq-pci.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#include "mpt3sas_base.h"
|
#include "mpt3sas_base.h"
|
||||||
|
@ -168,6 +169,11 @@ MODULE_PARM_DESC(multipath_on_hba,
|
||||||
"\t SAS 2.0 & SAS 3.0 HBA - This will be disabled,\n\t\t"
|
"\t SAS 2.0 & SAS 3.0 HBA - This will be disabled,\n\t\t"
|
||||||
"\t SAS 3.5 HBA - This will be enabled)");
|
"\t SAS 3.5 HBA - This will be enabled)");
|
||||||
|
|
||||||
|
static int host_tagset_enable = 1;
|
||||||
|
module_param(host_tagset_enable, int, 0444);
|
||||||
|
MODULE_PARM_DESC(host_tagset_enable,
|
||||||
|
"Shared host tagset enable/disable Default: enable(1)");
|
||||||
|
|
||||||
/* raid transport support */
|
/* raid transport support */
|
||||||
static struct raid_template *mpt3sas_raid_template;
|
static struct raid_template *mpt3sas_raid_template;
|
||||||
static struct raid_template *mpt2sas_raid_template;
|
static struct raid_template *mpt2sas_raid_template;
|
||||||
|
@ -1743,10 +1749,12 @@ mpt3sas_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
|
||||||
struct scsi_cmnd *scmd = NULL;
|
struct scsi_cmnd *scmd = NULL;
|
||||||
struct scsiio_tracker *st;
|
struct scsiio_tracker *st;
|
||||||
Mpi25SCSIIORequest_t *mpi_request;
|
Mpi25SCSIIORequest_t *mpi_request;
|
||||||
|
u16 tag = smid - 1;
|
||||||
|
|
||||||
if (smid > 0 &&
|
if (smid > 0 &&
|
||||||
smid <= ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT) {
|
smid <= ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT) {
|
||||||
u32 unique_tag = smid - 1;
|
u32 unique_tag =
|
||||||
|
ioc->io_queue_num[tag] << BLK_MQ_UNIQUE_TAG_BITS | tag;
|
||||||
|
|
||||||
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
|
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
|
||||||
|
|
||||||
|
@ -11599,6 +11607,22 @@ scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scsih_map_queues - map reply queues with request queues
|
||||||
|
* @shost: SCSI host pointer
|
||||||
|
*/
|
||||||
|
static int scsih_map_queues(struct Scsi_Host *shost)
|
||||||
|
{
|
||||||
|
struct MPT3SAS_ADAPTER *ioc =
|
||||||
|
(struct MPT3SAS_ADAPTER *)shost->hostdata;
|
||||||
|
|
||||||
|
if (ioc->shost->nr_hw_queues == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
|
||||||
|
ioc->pdev, ioc->high_iops_queues);
|
||||||
|
}
|
||||||
|
|
||||||
/* shost template for SAS 2.0 HBA devices */
|
/* shost template for SAS 2.0 HBA devices */
|
||||||
static struct scsi_host_template mpt2sas_driver_template = {
|
static struct scsi_host_template mpt2sas_driver_template = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
|
@ -11666,6 +11690,7 @@ static struct scsi_host_template mpt3sas_driver_template = {
|
||||||
.sdev_attrs = mpt3sas_dev_attrs,
|
.sdev_attrs = mpt3sas_dev_attrs,
|
||||||
.track_queue_depth = 1,
|
.track_queue_depth = 1,
|
||||||
.cmd_size = sizeof(struct scsiio_tracker),
|
.cmd_size = sizeof(struct scsiio_tracker),
|
||||||
|
.map_queues = scsih_map_queues,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* raid transport support for SAS 3.0 HBA devices */
|
/* raid transport support for SAS 3.0 HBA devices */
|
||||||
|
@ -12028,6 +12053,21 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
} else
|
} else
|
||||||
ioc->hide_drives = 0;
|
ioc->hide_drives = 0;
|
||||||
|
|
||||||
|
shost->host_tagset = 0;
|
||||||
|
shost->nr_hw_queues = 1;
|
||||||
|
|
||||||
|
if (ioc->is_gen35_ioc && ioc->reply_queue_count > 1 &&
|
||||||
|
host_tagset_enable && ioc->smp_affinity_enable) {
|
||||||
|
|
||||||
|
shost->host_tagset = 1;
|
||||||
|
shost->nr_hw_queues =
|
||||||
|
ioc->reply_queue_count - ioc->high_iops_queues;
|
||||||
|
|
||||||
|
dev_info(&ioc->pdev->dev,
|
||||||
|
"Max SCSIIO MPT commands: %d shared with nr_hw_queues = %d\n",
|
||||||
|
shost->can_queue, shost->nr_hw_queues);
|
||||||
|
}
|
||||||
|
|
||||||
rv = scsi_add_host(shost, &pdev->dev);
|
rv = scsi_add_host(shost, &pdev->dev);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
ioc_err(ioc, "failure at %s:%d/%s()!\n",
|
||||||
|
|
Loading…
Reference in New Issue