scsi: mpt3sas: Introduce perf_mode module parameter

1. Introduce module parameter perf_mode for only Aero/Sea generation HBAs.

2. Update IOC page1 fields according to performance mode.

Below are the performance modes that can be enabled with module parameter
perf_mode:

 0: Balanced - Few high iops reply queues will be enabled.  Interrupt
    coalescing will be enabled only for these high iops reply descriptor
    queues.

 1: Iops - Interrupt coalescing will be enabled on all reply queues.
    Coalescing timeout is set to 0x20.This is default value for Aero.

 2: Latency - Interrupt coalescing will be enabled on all reply queues.
    Coalescing timeout is set to 0xA.  This is a legacy behavior similar to
    Ventura & Invader HBA series.

Default perf mode set by driver will be balanced mode if the following
conditions are met:

 - CPU vendor = Intel;
 - Aero controller working in 16GT/s pcie speed

Performance mode will be set to latency mode for all other cases.

4k Random Read IO performance numbers on 24 SAS SSD drives for above three
permormance modes. Performance data is from Intel Skylake and HGST SS300
(drive model SDLL1DLR400GCCA1).

IOPs:
 -----------------------------------------------------------------------
  |perf_mode    | qd = 1 | qd = 64 |   note                             |
  |-------------|--------|---------|-------------------------------------
  |balanced     |  259K  |  3061k  | Provides max performance numbers   |
  |             |        |         | both on lower QD workload &        |
  |             |        |         | also on higher QD workload         |
  |-------------|--------|---------|-------------------------------------
  |iops         |  220K  |  3100k  | Provides max performance numbers   |
  |             |        |         | only on higher QD workload.        |
  |-------------|--------|---------|-------------------------------------
  |latency      |  246k  |  2226k  | Provides good performance numbers  |
  |             |        |         | only on lower QD worklaod.         |
  -----------------------------------------------------------------------

Avarage Latency:
  -----------------------------------------------------
  |perf_mode    |  qd = 1      |    qd = 64           |
  |-------------|--------------|----------------------|
  |balanced     |  92.05 usec  |    501.12 usec       |
  |-------------|--------------|----------------------|
  |iops         |  108.40 usec |    498.10 usec       |
  |-------------|--------------|----------------------|
  |latency      |  97.10 usec  |    689.26 usec       |
  -----------------------------------------------------

Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Suganath Prabu S 2019-05-31 08:14:42 -04:00 committed by Martin K. Petersen
parent 2426f20903
commit ca7e1e9d88
1 changed files with 126 additions and 18 deletions

View File

@ -103,6 +103,27 @@ static int mpt3sas_fwfault_debug;
MODULE_PARM_DESC(mpt3sas_fwfault_debug,
" enable detection of firmware fault and halt firmware - (default=0)");
static int perf_mode = -1;
module_param(perf_mode, int, 0);
MODULE_PARM_DESC(perf_mode,
"Performance mode (only for Aero/Sea Generation), options:\n\t\t"
"0 - balanced: high iops mode is enabled &\n\t\t"
"interrupt coalescing is enabled only on high iops queues,\n\t\t"
"1 - iops: high iops mode is disabled &\n\t\t"
"interrupt coalescing is enabled on all queues,\n\t\t"
"2 - latency: high iops mode is disabled &\n\t\t"
"interrupt coalescing is enabled on all queues with timeout value 0xA,\n"
"\t\tdefault - on Intel architecture, default perf_mode is\n\t\t"
" 'balanced' and in others architectures the default mode is 'latency'"
);
enum mpt3sas_perf_mode {
MPT_PERF_MODE_DEFAULT = -1,
MPT_PERF_MODE_BALANCED = 0,
MPT_PERF_MODE_IOPS = 1,
MPT_PERF_MODE_LATENCY = 2,
};
static int
_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc);
@ -2959,6 +2980,42 @@ static void
_base_check_and_enable_high_iops_queues(struct MPT3SAS_ADAPTER *ioc,
int hba_msix_vector_count)
{
enum pci_bus_speed speed = PCI_SPEED_UNKNOWN;
if (perf_mode == MPT_PERF_MODE_IOPS ||
perf_mode == MPT_PERF_MODE_LATENCY) {
ioc->high_iops_queues = 0;
return;
}
if (perf_mode == MPT_PERF_MODE_DEFAULT) {
#if defined(CONFIG_X86)
/*
* Use global variable boot_cpu_data.x86_vendor to
* determine whether the architecture is Intel or not.
*/
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
ioc->high_iops_queues = 0;
return;
}
#else
ioc->high_iops_queues = 0;
return;
#endif
speed = pcie_get_speed_cap(ioc->pdev);
dev_info(&ioc->pdev->dev, "PCIe device speed is %s\n",
speed == PCIE_SPEED_2_5GT ? "2.5GHz" :
speed == PCIE_SPEED_5_0GT ? "5.0GHz" :
speed == PCIE_SPEED_8_0GT ? "8.0GHz" :
speed == PCIE_SPEED_16_0GT ? "16.0GHz" :
"Unknown");
if (speed < PCIE_SPEED_16_0GT) {
ioc->high_iops_queues = 0;
return;
}
}
if (!reset_devices && ioc->is_aero_ioc &&
hba_msix_vector_count == MPT3SAS_GEN35_MAX_MSIX_QUEUES &&
@ -3034,8 +3091,9 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
ioc_info(ioc, "MSI-X vectors supported: %d\n", ioc->msix_vector_count);
pr_info("\t no of cores: %d, max_msix_vectors: %d\n",
ioc->cpu_count, max_msix_vectors);
_base_check_and_enable_high_iops_queues(ioc, ioc->msix_vector_count);
if (ioc->is_aero_ioc)
_base_check_and_enable_high_iops_queues(ioc,
ioc->msix_vector_count);
ioc->reply_queue_count =
min_t(int, ioc->cpu_count + ioc->high_iops_queues,
ioc->msix_vector_count);
@ -4430,6 +4488,70 @@ mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc,
kfree(sas_iounit_pg1);
}
/**
* _base_update_ioc_page1_inlinewith_perf_mode - Update IOC Page1 fields
* according to performance mode.
* @ioc : per adapter object
*
* Return nothing.
*/
static void
_base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc)
{
Mpi2IOCPage1_t ioc_pg1;
Mpi2ConfigReply_t mpi_reply;
mpt3sas_config_get_ioc_pg1(ioc, &mpi_reply, &ioc->ioc_pg1_copy);
memcpy(&ioc_pg1, &ioc->ioc_pg1_copy, sizeof(Mpi2IOCPage1_t));
switch (perf_mode) {
case MPT_PERF_MODE_DEFAULT:
case MPT_PERF_MODE_BALANCED:
if (ioc->high_iops_queues) {
ioc_info(ioc,
"Enable interrupt coalescing only for first\t"
"%d reply queues\n",
MPT3SAS_HIGH_IOPS_REPLY_QUEUES);
/*
* If 31st bit is zero then interrupt coalescing is
* enabled for all reply descriptor post queues.
* If 31st bit is set to one then user can
* enable/disable interrupt coalescing on per reply
* descriptor post queue group(8) basis. So to enable
* interrupt coalescing only on first reply descriptor
* post queue group 31st bit and zero th bit is enabled.
*/
ioc_pg1.ProductSpecific = cpu_to_le32(0x80000000 |
((1 << MPT3SAS_HIGH_IOPS_REPLY_QUEUES/8) - 1));
mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1);
ioc_info(ioc, "performance mode: balanced\n");
return;
}
case MPT_PERF_MODE_LATENCY:
/*
* Enable interrupt coalescing on all reply queues
* with timeout value 0xA
*/
ioc_pg1.CoalescingTimeout = cpu_to_le32(0xa);
ioc_pg1.Flags |= cpu_to_le32(MPI2_IOCPAGE1_REPLY_COALESCING);
ioc_pg1.ProductSpecific = 0;
mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1);
ioc_info(ioc, "performance mode: latency\n");
break;
case MPT_PERF_MODE_IOPS:
/*
* Enable interrupt coalescing on all reply queues.
*/
ioc_info(ioc,
"performance mode: iops with coalescing timeout: 0x%x\n",
le32_to_cpu(ioc_pg1.CoalescingTimeout));
ioc_pg1.Flags |= cpu_to_le32(MPI2_IOCPAGE1_REPLY_COALESCING);
ioc_pg1.ProductSpecific = 0;
mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1);
break;
}
}
/**
* _base_static_config_pages - static start of day config pages
* @ioc: per adapter object
@ -4439,7 +4561,6 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
{
Mpi2ConfigReply_t mpi_reply;
u32 iounit_pg1_flags;
Mpi2IOCPage1_t ioc_pg1;
ioc->nvme_abort_timeout = 30;
mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
@ -4472,21 +4593,6 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
else
ioc->nvme_abort_timeout = ioc->manu_pg11.NVMeAbortTO;
}
if (ioc->high_iops_queues) {
mpt3sas_config_get_ioc_pg1(ioc, &mpi_reply, &ioc_pg1);
pr_info(
"%s Enable interrupt coalescing only for first reply queue group(8)\n",
ioc->name);
/* If 31st bit is zero then interrupt coalescing is enabled
* for all reply descriptor post queues. If 31st bit is set
* to one then user can enable/disable interrupt coalescing
* on per reply descriptor post queue group(8) basis. So to
* enable interrupt coalescing only on first reply descriptor
* post queue group 31st bit and zeroth bit is enabled.
*/
ioc_pg1.ProductSpecific = cpu_to_le32(0x80000001);
mpt3sas_config_set_ioc_pg1(ioc, &mpi_reply, &ioc_pg1);
}
mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
@ -4513,6 +4619,8 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
if (ioc->iounit_pg8.NumSensors)
ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors;
if (ioc->is_aero_ioc)
_base_update_ioc_page1_inlinewith_perf_mode(ioc);
}
/**