@@ -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
@@ -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
@@ -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;
}
@@ -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) {
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@linux.vnet.ibm.com> --- 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(-)