Commit 7bb03bbf authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.39: Fixed driver vector mapping to CPU affinity

Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 6a485eb9
...@@ -709,6 +709,7 @@ struct lpfc_hba { ...@@ -709,6 +709,7 @@ struct lpfc_hba {
uint32_t cfg_poll_tmo; uint32_t cfg_poll_tmo;
uint32_t cfg_use_msi; uint32_t cfg_use_msi;
uint32_t cfg_fcp_imax; uint32_t cfg_fcp_imax;
uint32_t cfg_fcp_cpu_map;
uint32_t cfg_fcp_wq_count; uint32_t cfg_fcp_wq_count;
uint32_t cfg_fcp_eq_count; uint32_t cfg_fcp_eq_count;
uint32_t cfg_fcp_io_channel; uint32_t cfg_fcp_io_channel;
......
...@@ -3799,6 +3799,141 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val) ...@@ -3799,6 +3799,141 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val)
static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR, static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR,
lpfc_fcp_imax_show, lpfc_fcp_imax_store); lpfc_fcp_imax_show, lpfc_fcp_imax_store);
/**
* lpfc_state_show - Display current driver CPU affinity
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains text describing the state of the link.
*
* Returns: size of formatted string.
**/
static ssize_t
lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
struct lpfc_hba *phba = vport->phba;
struct lpfc_vector_map_info *cpup;
int idx, len = 0;
if ((phba->sli_rev != LPFC_SLI_REV4) ||
(phba->intr_type != MSIX))
return len;
switch (phba->cfg_fcp_cpu_map) {
case 0:
len += snprintf(buf + len, PAGE_SIZE-len,
"fcp_cpu_map: No mapping (%d)\n",
phba->cfg_fcp_cpu_map);
return len;
case 1:
len += snprintf(buf + len, PAGE_SIZE-len,
"fcp_cpu_map: HBA centric mapping (%d): "
"%d online CPUs\n",
phba->cfg_fcp_cpu_map,
phba->sli4_hba.num_online_cpu);
break;
case 2:
len += snprintf(buf + len, PAGE_SIZE-len,
"fcp_cpu_map: Driver centric mapping (%d): "
"%d online CPUs\n",
phba->cfg_fcp_cpu_map,
phba->sli4_hba.num_online_cpu);
break;
}
cpup = phba->sli4_hba.cpu_map;
for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) {
if (cpup->irq == LPFC_VECTOR_MAP_EMPTY)
len += snprintf(buf + len, PAGE_SIZE-len,
"CPU %02d io_chan %02d "
"physid %d coreid %d\n",
idx, cpup->channel_id, cpup->phys_id,
cpup->core_id);
else
len += snprintf(buf + len, PAGE_SIZE-len,
"CPU %02d io_chan %02d "
"physid %d coreid %d IRQ %d\n",
idx, cpup->channel_id, cpup->phys_id,
cpup->core_id, cpup->irq);
cpup++;
}
return len;
}
/**
* lpfc_fcp_cpu_map_store - Change CPU affinity of driver vectors
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: one or more lpfc_polling_flags values.
* @count: not used.
*
* Returns:
* -EINVAL - Not implemented yet.
**/
static ssize_t
lpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int status = -EINVAL;
return status;
}
/*
# lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors
# for the HBA.
#
# Value range is [0 to 2]. Default value is LPFC_DRIVER_CPU_MAP (2).
# 0 - Do not affinitze IRQ vectors
# 1 - Affintize HBA vectors with respect to each HBA
# (start with CPU0 for each HBA)
# 2 - Affintize HBA vectors with respect to the entire driver
# (round robin thru all CPUs across all HBAs)
*/
static int lpfc_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
module_param(lpfc_fcp_cpu_map, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(lpfc_fcp_cpu_map,
"Defines how to map CPUs to IRQ vectors per HBA");
/**
* lpfc_fcp_cpu_map_init - Set the initial sr-iov virtual function enable
* @phba: lpfc_hba pointer.
* @val: link speed value.
*
* Description:
* If val is in a valid range [0-2], then affinitze the adapter's
* MSIX vectors.
*
* Returns:
* zero if val saved.
* -EINVAL val out of range
**/
static int
lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val)
{
if (phba->sli_rev != LPFC_SLI_REV4) {
phba->cfg_fcp_cpu_map = 0;
return 0;
}
if (val >= LPFC_MIN_CPU_MAP && val <= LPFC_MAX_CPU_MAP) {
phba->cfg_fcp_cpu_map = val;
return 0;
}
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3326 fcp_cpu_map: %d out of range, using default\n",
val);
phba->cfg_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
return 0;
}
static DEVICE_ATTR(lpfc_fcp_cpu_map, S_IRUGO | S_IWUSR,
lpfc_fcp_cpu_map_show, lpfc_fcp_cpu_map_store);
/* /*
# lpfc_fcp_class: Determines FC class to use for the FCP protocol. # lpfc_fcp_class: Determines FC class to use for the FCP protocol.
# Value range is [2,3]. Default value is 3. # Value range is [2,3]. Default value is 3.
...@@ -4154,6 +4289,7 @@ struct device_attribute *lpfc_hba_attrs[] = { ...@@ -4154,6 +4289,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_poll_tmo, &dev_attr_lpfc_poll_tmo,
&dev_attr_lpfc_use_msi, &dev_attr_lpfc_use_msi,
&dev_attr_lpfc_fcp_imax, &dev_attr_lpfc_fcp_imax,
&dev_attr_lpfc_fcp_cpu_map,
&dev_attr_lpfc_fcp_wq_count, &dev_attr_lpfc_fcp_wq_count,
&dev_attr_lpfc_fcp_eq_count, &dev_attr_lpfc_fcp_eq_count,
&dev_attr_lpfc_fcp_io_channel, &dev_attr_lpfc_fcp_io_channel,
...@@ -5136,6 +5272,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) ...@@ -5136,6 +5272,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_rrq_init(phba, lpfc_enable_rrq); lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
lpfc_use_msi_init(phba, lpfc_use_msi); lpfc_use_msi_init(phba, lpfc_use_msi);
lpfc_fcp_imax_init(phba, lpfc_fcp_imax); lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map);
lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count); lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count);
lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count); lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count);
lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel); lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel);
......
...@@ -200,6 +200,11 @@ struct lpfc_sli_intf { ...@@ -200,6 +200,11 @@ struct lpfc_sli_intf {
#define LPFC_MAX_IMAX 5000000 #define LPFC_MAX_IMAX 5000000
#define LPFC_DEF_IMAX 50000 #define LPFC_DEF_IMAX 50000
#define LPFC_MIN_CPU_MAP 0
#define LPFC_MAX_CPU_MAP 2
#define LPFC_HBA_CPU_MAP 1
#define LPFC_DRIVER_CPU_MAP 2 /* Default */
/* PORT_CAPABILITIES constants. */ /* PORT_CAPABILITIES constants. */
#define LPFC_MAX_SUPPORTED_PAGES 8 #define LPFC_MAX_SUPPORTED_PAGES 8
......
This diff is collapsed.
...@@ -7923,15 +7923,21 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, ...@@ -7923,15 +7923,21 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
static inline uint32_t static inline uint32_t
lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba) lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba)
{ {
int i; struct lpfc_vector_map_info *cpup;
int chann, cpu;
if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU)
i = smp_processor_id();
else
i = atomic_add_return(1, &phba->fcp_qidx);
i = (i % phba->cfg_fcp_io_channel); if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU) {
return i; cpu = smp_processor_id();
if (cpu < phba->sli4_hba.num_present_cpu) {
cpup = phba->sli4_hba.cpu_map;
cpup += cpu;
return cpup->channel_id;
}
chann = cpu;
}
chann = atomic_add_return(1, &phba->fcp_qidx);
chann = (chann % phba->cfg_fcp_io_channel);
return chann;
} }
/** /**
......
...@@ -435,6 +435,17 @@ struct lpfc_sli4_lnk_info { ...@@ -435,6 +435,17 @@ struct lpfc_sli4_lnk_info {
#define LPFC_SLI4_HANDLER_NAME_SZ 16 #define LPFC_SLI4_HANDLER_NAME_SZ 16
/* Used for IRQ vector to CPU mapping */
struct lpfc_vector_map_info {
uint16_t phys_id;
uint16_t core_id;
uint16_t irq;
uint16_t channel_id;
struct cpumask maskbits;
};
#define LPFC_VECTOR_MAP_EMPTY 0xffff
#define LPFC_MAX_CPU 256
/* SLI4 HBA data structure entries */ /* SLI4 HBA data structure entries */
struct lpfc_sli4_hba { struct lpfc_sli4_hba {
void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
...@@ -568,6 +579,11 @@ struct lpfc_sli4_hba { ...@@ -568,6 +579,11 @@ struct lpfc_sli4_hba {
struct lpfc_iov iov; struct lpfc_iov iov;
spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */
/* CPU to vector mapping information */
struct lpfc_vector_map_info *cpu_map;
uint16_t num_online_cpu;
uint16_t num_present_cpu;
}; };
enum lpfc_sge_type { enum lpfc_sge_type {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment