diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 3f4cb52177f6..03e786981563 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2256,6 +2256,18 @@ enum MR_PD_TYPE { #define MR_DEVICE_HIGH_IOPS_DEPTH 8 #define MR_HIGH_IOPS_BATCH_COUNT 16 +enum MR_PERF_MODE { + MR_BALANCED_PERF_MODE = 0, + MR_IOPS_PERF_MODE = 1, + MR_LATENCY_PERF_MODE = 2, +}; + +#define MEGASAS_PERF_MODE_2STR(mode) \ + ((mode) == MR_BALANCED_PERF_MODE ? "Balanced" : \ + (mode) == MR_IOPS_PERF_MODE ? "IOPS" : \ + (mode) == MR_LATENCY_PERF_MODE ? "Latency" : \ + "Unknown") + struct megasas_instance { unsigned int *reply_map; @@ -2441,7 +2453,7 @@ struct megasas_instance { bool support_seqnum_jbod_fp; bool support_pci_lane_margining; u8 low_latency_index_start; - bool balanced_mode; + int perf_mode; }; struct MR_LD_VF_MAP { diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 33c57e773920..bd6da59c087f 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -105,6 +105,18 @@ unsigned int scmd_timeout = MEGASAS_DEFAULT_CMD_TIMEOUT; module_param(scmd_timeout, int, 0444); MODULE_PARM_DESC(scmd_timeout, "scsi command timeout (10-90s), default 90s. See megasas_reset_timer."); +int perf_mode = -1; +module_param(perf_mode, int, 0444); +MODULE_PARM_DESC(perf_mode, "Performance mode (only for Aero adapters), options:\n\t\t" + "0 - balanced: High iops and low latency queues are allocated &\n\t\t" + "interrupt coalescing is enabled only on high iops queues\n\t\t" + "1 - iops: High iops queues are not allocated &\n\t\t" + "interrupt coalescing is enabled on all queues\n\t\t" + "2 - latency: High iops queues are not allocated &\n\t\t" + "interrupt coalescing is disabled on all queues\n\t\t" + "default mode is 'balanced'" + ); + MODULE_LICENSE("GPL"); MODULE_VERSION(MEGASAS_VERSION); MODULE_AUTHOR("megaraidlinux.pdl@broadcom.com"); @@ -5472,7 +5484,7 @@ megasas_setup_irqs_ioapic(struct megasas_instance *instance) __func__, __LINE__); return -1; } - instance->balanced_mode = false; + instance->perf_mode = MR_LATENCY_PERF_MODE; instance->low_latency_index_start = 0; return 0; } @@ -5683,7 +5695,7 @@ megasas_set_high_iops_queue_affinity_hint(struct megasas_instance *instance) int i; int local_numa_node; - if (instance->balanced_mode) { + if (instance->perf_mode == MR_BALANCED_PERF_MODE) { local_numa_node = dev_to_node(&instance->pdev->dev); for (i = 0; i < instance->low_latency_index_start; i++) @@ -5726,11 +5738,12 @@ megasas_alloc_irq_vectors(struct megasas_instance *instance) i = __megasas_alloc_irq_vectors(instance); - if (instance->balanced_mode && (i != instance->msix_vectors)) { + if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && + (i != instance->msix_vectors)) { if (instance->msix_vectors) pci_free_irq_vectors(instance->pdev); /* Disable Balanced IOPS mode and try realloc vectors */ - instance->balanced_mode = false; + instance->perf_mode = MR_LATENCY_PERF_MODE; instance->low_latency_index_start = 1; num_msix_req = num_online_cpus() + instance->low_latency_index_start; @@ -5774,6 +5787,7 @@ static int megasas_init_fw(struct megasas_instance *instance) struct fusion_context *fusion; bool intr_coalescing; unsigned int num_msix_req; + u16 lnksta, speed; fusion = instance->ctrl_context; @@ -5983,11 +5997,43 @@ static int megasas_init_fw(struct megasas_instance *instance) if (intr_coalescing && (num_online_cpus() >= MR_HIGH_IOPS_QUEUE_COUNT) && (instance->msix_vectors == MEGASAS_MAX_MSIX_QUEUES)) - instance->balanced_mode = true; + instance->perf_mode = MR_BALANCED_PERF_MODE; else - instance->balanced_mode = false; + instance->perf_mode = MR_LATENCY_PERF_MODE; - if (instance->balanced_mode) + + if (instance->adapter_type == AERO_SERIES) { + pcie_capability_read_word(instance->pdev, PCI_EXP_LNKSTA, &lnksta); + speed = lnksta & PCI_EXP_LNKSTA_CLS; + + /* + * For Aero, if PCIe link speed is <16 GT/s, then driver should operate + * in latency perf mode and enable R1 PCI bandwidth algorithm + */ + if (speed < 0x4) { + instance->perf_mode = MR_LATENCY_PERF_MODE; + fusion->pcie_bw_limitation = true; + } + + /* + * Performance mode settings provided through module parameter-perf_mode will + * take affect only for: + * 1. Aero family of adapters. + * 2. When user sets module parameter- perf_mode in range of 0-2. + */ + if ((perf_mode >= MR_BALANCED_PERF_MODE) && + (perf_mode <= MR_LATENCY_PERF_MODE)) + instance->perf_mode = perf_mode; + /* + * If intr coalescing is not supported by controller FW, then IOPS + * and Balanced modes are not feasible. + */ + if (!intr_coalescing) + instance->perf_mode = MR_LATENCY_PERF_MODE; + + } + + if (instance->perf_mode == MR_BALANCED_PERF_MODE) instance->low_latency_index_start = MR_HIGH_IOPS_QUEUE_COUNT; else diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 90dced4290a2..8a3e2551a6e1 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -1097,10 +1097,10 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) if ((instance->low_latency_index_start == MR_HIGH_IOPS_QUEUE_COUNT) && cur_intr_coalescing) - instance->balanced_mode = true; + instance->perf_mode = MR_BALANCED_PERF_MODE; - dev_info(&instance->pdev->dev, "Balanced mode :%s\n", - instance->balanced_mode ? "Yes" : "No"); + dev_info(&instance->pdev->dev, "Performance mode :%s\n", + MEGASAS_PERF_MODE_2STR(instance->perf_mode)); instance->fw_sync_cache_support = (scratch_pad_1 & MR_CAN_HANDLE_SYNC_CACHE_OFFSET) ? 1 : 0; @@ -1190,9 +1190,17 @@ megasas_ioc_init_fusion(struct megasas_instance *instance) * Each bit in replyqueue_mask represents one group of MSI-x vectors * (each group has 8 vectors) */ - if (instance->balanced_mode) + switch (instance->perf_mode) { + case MR_BALANCED_PERF_MODE: init_frame->replyqueue_mask = - cpu_to_le16(~(~0 << instance->low_latency_index_start / 8)); + cpu_to_le16(~(~0 << instance->low_latency_index_start/8)); + break; + case MR_IOPS_PERF_MODE: + init_frame->replyqueue_mask = + cpu_to_le16(~(~0 << instance->msix_vectors/8)); + break; + } + req_desc.u.low = cpu_to_le32(lower_32_bits(cmd->frame_phys_addr)); req_desc.u.high = cpu_to_le32(upper_32_bits(cmd->frame_phys_addr)); @@ -2831,7 +2839,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance, fp_possible = (io_info.fpOkForIo > 0) ? true : false; } - if (instance->balanced_mode && + if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && atomic_read(&scp->device->device_busy) > (io_info.data_arms * MR_DEVICE_HIGH_IOPS_DEPTH)) cmd->request_desc->SCSIIO.MSIxIndex = @@ -3164,7 +3172,7 @@ megasas_build_syspd_fusion(struct megasas_instance *instance, cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle; - if (instance->balanced_mode && + if ((instance->perf_mode == MR_BALANCED_PERF_MODE) && atomic_read(&scmd->device->device_busy) > MR_DEVICE_HIGH_IOPS_DEPTH) cmd->request_desc->SCSIIO.MSIxIndex = mega_mod64((atomic64_add_return(1, &instance->high_iops_outstanding) /