This commit introduces the new value 2 for parameter 'lpfc_fcp_io_sched', which associates work queues (or IO channels) by core, that is, all CPUs (or threads) of a particular core are assigned the same IO channel. The IO channels are assigned to each core in a round-robin fashion. Tested on next-20160601. Signed-off-by: Mauricio Faria de Oliveira <mauricfo@xxxxxxxxxxxxxxxxxx> --- drivers/scsi/lpfc/lpfc_attr.c | 8 +++++-- drivers/scsi/lpfc/lpfc_hw4.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 54 ++++++++++++++++++++++++++++++++++++++++++- drivers/scsi/lpfc/lpfc_scsi.c | 3 ++- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index cfec2ec..f8db2ad 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -4517,12 +4517,16 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support"); # For [0], FCP commands are issued to Work Queues ina round robin fashion. # For [1], FCP commands are issued to a Work Queue associated with the # current CPU. +# For [2], FCP commands are issued to a Work Queue associated with the +# current CPU core (same Work Queue for all CPUs of a core). # It would be set to 1 by the driver if it's able to set up cpu affinity # for FCP I/Os through Work Queue associated with the current CPU. Otherwise, # roundrobin scheduling of FCP I/Os through WQs will be used. +# It would remain set to 2 by the driver, likewise, if 2 was requested. */ -LPFC_ATTR_RW(fcp_io_sched, 0, 0, 1, "Determine scheduling algorithm for " - "issuing commands [0] - Round Robin, [1] - Current CPU"); +LPFC_ATTR_RW(fcp_io_sched, 0, 0, 2, "Determine scheduling algorithm for " + "issuing commands [0] - Round Robin, [1] - Current CPU, " + "[2] - Current CPU core"); /* # lpfc_fcp2_no_tgt_reset: Determine bus reset behavior diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 0c7070b..3c63063 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -191,6 +191,7 @@ struct lpfc_sli_intf { /* Algrithmns for scheduling FCP commands to WQs */ #define LPFC_FCP_SCHED_ROUND_ROBIN 0 #define LPFC_FCP_SCHED_BY_CPU 1 +#define LPFC_FCP_SCHED_BY_CPU_CORE 2 /* Delay Multiplier constant */ #define LPFC_DMULT_CONST 651042 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 03d1946..917351c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8703,6 +8703,7 @@ lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors) { int i, idx, saved_chann, used_chann, cpu, phys_id; int max_phys_id, min_phys_id; + int max_core_id, min_core_id, core_id, prev_core_id; int num_io_channel, first_cpu, chan; struct lpfc_vector_map_info *cpup; #ifdef CONFIG_X86 @@ -8722,6 +8723,9 @@ lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors) max_phys_id = 0; min_phys_id = INT_MAX; phys_id = 0; + max_core_id = 0; + min_core_id = INT_MAX; + core_id = 0; num_io_channel = 0; first_cpu = LPFC_VECTOR_MAP_EMPTY; @@ -8749,6 +8753,12 @@ lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors) max_phys_id = cpup->phys_id; if (cpup->phys_id < min_phys_id) min_phys_id = cpup->phys_id; + + if (cpup->core_id > max_core_id) + max_core_id = cpup->core_id; + if (cpup->core_id < min_core_id) + min_core_id = cpup->core_id; + cpup++; } @@ -8820,6 +8830,46 @@ found: } /* + * With lpfc_fcp_io_sched per core, associate IO channels with CPUs + * based only on the core numbers instead of individual CPU numbers, + * and ignore/overwrite already assigned values (from MSI-x vectors). + */ + if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU_CORE) { + + /* The IO channel used by a core */ + chan = -1; + + /* For each core, assign its (sequential) CPUs the same IO channel */ + prev_core_id = -1; + for (core_id = min_core_id; core_id <= max_core_id; core_id++) { + + cpup = phba->sli4_hba.cpu_map; + for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++, cpup++) { + + if (cpup->core_id != core_id) + continue; + + /* Round-robin on different cores */ + if (core_id != prev_core_id) { + prev_core_id = core_id; + chan = (chan + 1) % phba->cfg_fcp_io_channel; + } + + cpup->channel_id = chan; + + /* Don't count CPUs w/ IRQ affinity hint (already counted) */ + if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) + num_io_channel++; + + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "3336 Set IO_CHANN CPU %d channel %d coreid %d\n", + cpu, cpup->channel_id, cpup->core_id); + } + } + goto out_fcp_io_sched_per_core; + } + + /* * Finally fill in the IO channel for any remaining CPUs. * At this point, all IO channels have been assigned to a specific * MSIx vector, mapped to a specific CPU. @@ -8891,6 +8941,7 @@ out: } } +out_fcp_io_sched_per_core: if (phba->sli4_hba.num_online_cpu != phba->sli4_hba.num_present_cpu) { cpup = phba->sli4_hba.cpu_map; for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) { @@ -8916,7 +8967,8 @@ out: vectors); /* Enable using cpu affinity for scheduling */ - phba->cfg_fcp_io_sched = LPFC_FCP_SCHED_BY_CPU; + if (phba->cfg_fcp_io_sched != LPFC_FCP_SCHED_BY_CPU_CORE) + phba->cfg_fcp_io_sched = LPFC_FCP_SCHED_BY_CPU; return 1; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 3bd0be6..b34276e 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -3881,7 +3881,8 @@ int lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba, return hwq; } - if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU + if ((phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU || + phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU_CORE) && phba->cfg_fcp_io_channel > 1) { cpu = smp_processor_id(); if (cpu < phba->sli4_hba.num_present_cpu) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html