aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2013-04-17 20:19:16 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-02 16:10:25 -0400
commit7bb03bbf1e8c0cb17309ac8a6dae6a54ebdfe66e (patch)
tree1fb2d70836583981000105a6b6884a746fcfea03 /drivers/scsi/lpfc
parent6a485eb9a921cd1276fc63b4967e6b713fffb6f3 (diff)
[SCSI] lpfc 8.3.39: Fixed driver vector mapping to CPU affinity
Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c137
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c322
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c22
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h16
6 files changed, 488 insertions, 15 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 2d2261f4eab0..bcc56cac4fd8 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -709,6 +709,7 @@ struct lpfc_hba {
709 uint32_t cfg_poll_tmo; 709 uint32_t cfg_poll_tmo;
710 uint32_t cfg_use_msi; 710 uint32_t cfg_use_msi;
711 uint32_t cfg_fcp_imax; 711 uint32_t cfg_fcp_imax;
712 uint32_t cfg_fcp_cpu_map;
712 uint32_t cfg_fcp_wq_count; 713 uint32_t cfg_fcp_wq_count;
713 uint32_t cfg_fcp_eq_count; 714 uint32_t cfg_fcp_eq_count;
714 uint32_t cfg_fcp_io_channel; 715 uint32_t cfg_fcp_io_channel;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 57f1ad848edc..3c5625b8b1f4 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3799,6 +3799,141 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val)
3799static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR, 3799static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR,
3800 lpfc_fcp_imax_show, lpfc_fcp_imax_store); 3800 lpfc_fcp_imax_show, lpfc_fcp_imax_store);
3801 3801
3802/**
3803 * lpfc_state_show - Display current driver CPU affinity
3804 * @dev: class converted to a Scsi_host structure.
3805 * @attr: device attribute, not used.
3806 * @buf: on return contains text describing the state of the link.
3807 *
3808 * Returns: size of formatted string.
3809 **/
3810static ssize_t
3811lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr,
3812 char *buf)
3813{
3814 struct Scsi_Host *shost = class_to_shost(dev);
3815 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
3816 struct lpfc_hba *phba = vport->phba;
3817 struct lpfc_vector_map_info *cpup;
3818 int idx, len = 0;
3819
3820 if ((phba->sli_rev != LPFC_SLI_REV4) ||
3821 (phba->intr_type != MSIX))
3822 return len;
3823
3824 switch (phba->cfg_fcp_cpu_map) {
3825 case 0:
3826 len += snprintf(buf + len, PAGE_SIZE-len,
3827 "fcp_cpu_map: No mapping (%d)\n",
3828 phba->cfg_fcp_cpu_map);
3829 return len;
3830 case 1:
3831 len += snprintf(buf + len, PAGE_SIZE-len,
3832 "fcp_cpu_map: HBA centric mapping (%d): "
3833 "%d online CPUs\n",
3834 phba->cfg_fcp_cpu_map,
3835 phba->sli4_hba.num_online_cpu);
3836 break;
3837 case 2:
3838 len += snprintf(buf + len, PAGE_SIZE-len,
3839 "fcp_cpu_map: Driver centric mapping (%d): "
3840 "%d online CPUs\n",
3841 phba->cfg_fcp_cpu_map,
3842 phba->sli4_hba.num_online_cpu);
3843 break;
3844 }
3845
3846 cpup = phba->sli4_hba.cpu_map;
3847 for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) {
3848 if (cpup->irq == LPFC_VECTOR_MAP_EMPTY)
3849 len += snprintf(buf + len, PAGE_SIZE-len,
3850 "CPU %02d io_chan %02d "
3851 "physid %d coreid %d\n",
3852 idx, cpup->channel_id, cpup->phys_id,
3853 cpup->core_id);
3854 else
3855 len += snprintf(buf + len, PAGE_SIZE-len,
3856 "CPU %02d io_chan %02d "
3857 "physid %d coreid %d IRQ %d\n",
3858 idx, cpup->channel_id, cpup->phys_id,
3859 cpup->core_id, cpup->irq);
3860
3861 cpup++;
3862 }
3863 return len;
3864}
3865
3866/**
3867 * lpfc_fcp_cpu_map_store - Change CPU affinity of driver vectors
3868 * @dev: class device that is converted into a Scsi_host.
3869 * @attr: device attribute, not used.
3870 * @buf: one or more lpfc_polling_flags values.
3871 * @count: not used.
3872 *
3873 * Returns:
3874 * -EINVAL - Not implemented yet.
3875 **/
3876static ssize_t
3877lpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr,
3878 const char *buf, size_t count)
3879{
3880 int status = -EINVAL;
3881 return status;
3882}
3883
3884/*
3885# lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors
3886# for the HBA.
3887#
3888# Value range is [0 to 2]. Default value is LPFC_DRIVER_CPU_MAP (2).
3889# 0 - Do not affinitze IRQ vectors
3890# 1 - Affintize HBA vectors with respect to each HBA
3891# (start with CPU0 for each HBA)
3892# 2 - Affintize HBA vectors with respect to the entire driver
3893# (round robin thru all CPUs across all HBAs)
3894*/
3895static int lpfc_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
3896module_param(lpfc_fcp_cpu_map, int, S_IRUGO|S_IWUSR);
3897MODULE_PARM_DESC(lpfc_fcp_cpu_map,
3898 "Defines how to map CPUs to IRQ vectors per HBA");
3899
3900/**
3901 * lpfc_fcp_cpu_map_init - Set the initial sr-iov virtual function enable
3902 * @phba: lpfc_hba pointer.
3903 * @val: link speed value.
3904 *
3905 * Description:
3906 * If val is in a valid range [0-2], then affinitze the adapter's
3907 * MSIX vectors.
3908 *
3909 * Returns:
3910 * zero if val saved.
3911 * -EINVAL val out of range
3912 **/
3913static int
3914lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val)
3915{
3916 if (phba->sli_rev != LPFC_SLI_REV4) {
3917 phba->cfg_fcp_cpu_map = 0;
3918 return 0;
3919 }
3920
3921 if (val >= LPFC_MIN_CPU_MAP && val <= LPFC_MAX_CPU_MAP) {
3922 phba->cfg_fcp_cpu_map = val;
3923 return 0;
3924 }
3925
3926 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
3927 "3326 fcp_cpu_map: %d out of range, using default\n",
3928 val);
3929 phba->cfg_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
3930
3931 return 0;
3932}
3933
3934static DEVICE_ATTR(lpfc_fcp_cpu_map, S_IRUGO | S_IWUSR,
3935 lpfc_fcp_cpu_map_show, lpfc_fcp_cpu_map_store);
3936
3802/* 3937/*
3803# lpfc_fcp_class: Determines FC class to use for the FCP protocol. 3938# lpfc_fcp_class: Determines FC class to use for the FCP protocol.
3804# Value range is [2,3]. Default value is 3. 3939# Value range is [2,3]. Default value is 3.
@@ -4154,6 +4289,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
4154 &dev_attr_lpfc_poll_tmo, 4289 &dev_attr_lpfc_poll_tmo,
4155 &dev_attr_lpfc_use_msi, 4290 &dev_attr_lpfc_use_msi,
4156 &dev_attr_lpfc_fcp_imax, 4291 &dev_attr_lpfc_fcp_imax,
4292 &dev_attr_lpfc_fcp_cpu_map,
4157 &dev_attr_lpfc_fcp_wq_count, 4293 &dev_attr_lpfc_fcp_wq_count,
4158 &dev_attr_lpfc_fcp_eq_count, 4294 &dev_attr_lpfc_fcp_eq_count,
4159 &dev_attr_lpfc_fcp_io_channel, 4295 &dev_attr_lpfc_fcp_io_channel,
@@ -5136,6 +5272,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
5136 lpfc_enable_rrq_init(phba, lpfc_enable_rrq); 5272 lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
5137 lpfc_use_msi_init(phba, lpfc_use_msi); 5273 lpfc_use_msi_init(phba, lpfc_use_msi);
5138 lpfc_fcp_imax_init(phba, lpfc_fcp_imax); 5274 lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
5275 lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map);
5139 lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count); 5276 lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count);
5140 lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count); 5277 lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count);
5141 lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel); 5278 lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel);
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 42660c97119e..713a4613ec3a 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -200,6 +200,11 @@ struct lpfc_sli_intf {
200#define LPFC_MAX_IMAX 5000000 200#define LPFC_MAX_IMAX 5000000
201#define LPFC_DEF_IMAX 50000 201#define LPFC_DEF_IMAX 50000
202 202
203#define LPFC_MIN_CPU_MAP 0
204#define LPFC_MAX_CPU_MAP 2
205#define LPFC_HBA_CPU_MAP 1
206#define LPFC_DRIVER_CPU_MAP 2 /* Default */
207
203/* PORT_CAPABILITIES constants. */ 208/* PORT_CAPABILITIES constants. */
204#define LPFC_MAX_SUPPORTED_PAGES 8 209#define LPFC_MAX_SUPPORTED_PAGES 8
205 210
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 7af1eabf5ebc..3b574a0698d9 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -33,6 +33,7 @@
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/firmware.h> 34#include <linux/firmware.h>
35#include <linux/miscdevice.h> 35#include <linux/miscdevice.h>
36#include <linux/percpu.h>
36 37
37#include <scsi/scsi.h> 38#include <scsi/scsi.h>
38#include <scsi/scsi_device.h> 39#include <scsi/scsi_device.h>
@@ -58,6 +59,9 @@ char *_dump_buf_dif;
58unsigned long _dump_buf_dif_order; 59unsigned long _dump_buf_dif_order;
59spinlock_t _dump_buf_lock; 60spinlock_t _dump_buf_lock;
60 61
62/* Used when mapping IRQ vectors in a driver centric manner */
63uint16_t lpfc_used_cpu[LPFC_MAX_CPU];
64
61static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); 65static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *);
62static int lpfc_post_rcv_buf(struct lpfc_hba *); 66static int lpfc_post_rcv_buf(struct lpfc_hba *);
63static int lpfc_sli4_queue_verify(struct lpfc_hba *); 67static int lpfc_sli4_queue_verify(struct lpfc_hba *);
@@ -4861,6 +4865,7 @@ lpfc_sli_driver_resource_unset(struct lpfc_hba *phba)
4861static int 4865static int
4862lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) 4866lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
4863{ 4867{
4868 struct lpfc_vector_map_info *cpup;
4864 struct lpfc_sli *psli; 4869 struct lpfc_sli *psli;
4865 LPFC_MBOXQ_t *mboxq; 4870 LPFC_MBOXQ_t *mboxq;
4866 int rc, i, hbq_count, max_buf_size; 4871 int rc, i, hbq_count, max_buf_size;
@@ -5198,6 +5203,26 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
5198 goto out_free_fcp_eq_hdl; 5203 goto out_free_fcp_eq_hdl;
5199 } 5204 }
5200 5205
5206 phba->sli4_hba.cpu_map = kzalloc((sizeof(struct lpfc_vector_map_info) *
5207 phba->sli4_hba.num_present_cpu),
5208 GFP_KERNEL);
5209 if (!phba->sli4_hba.cpu_map) {
5210 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
5211 "3327 Failed allocate memory for msi-x "
5212 "interrupt vector mapping\n");
5213 rc = -ENOMEM;
5214 goto out_free_msix;
5215 }
5216 /* Initialize io channels for round robin */
5217 cpup = phba->sli4_hba.cpu_map;
5218 rc = 0;
5219 for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
5220 cpup->channel_id = rc;
5221 rc++;
5222 if (rc >= phba->cfg_fcp_io_channel)
5223 rc = 0;
5224 }
5225
5201 /* 5226 /*
5202 * Enable sr-iov virtual functions if supported and configured 5227 * Enable sr-iov virtual functions if supported and configured
5203 * through the module parameter. 5228 * through the module parameter.
@@ -5217,6 +5242,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
5217 5242
5218 return 0; 5243 return 0;
5219 5244
5245out_free_msix:
5246 kfree(phba->sli4_hba.msix_entries);
5220out_free_fcp_eq_hdl: 5247out_free_fcp_eq_hdl:
5221 kfree(phba->sli4_hba.fcp_eq_hdl); 5248 kfree(phba->sli4_hba.fcp_eq_hdl);
5222out_free_fcf_rr_bmask: 5249out_free_fcf_rr_bmask:
@@ -5246,6 +5273,11 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
5246{ 5273{
5247 struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry; 5274 struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry;
5248 5275
5276 /* Free memory allocated for msi-x interrupt vector to CPU mapping */
5277 kfree(phba->sli4_hba.cpu_map);
5278 phba->sli4_hba.num_present_cpu = 0;
5279 phba->sli4_hba.num_online_cpu = 0;
5280
5249 /* Free memory allocated for msi-x interrupt vector entries */ 5281 /* Free memory allocated for msi-x interrupt vector entries */
5250 kfree(phba->sli4_hba.msix_entries); 5282 kfree(phba->sli4_hba.msix_entries);
5251 5283
@@ -6792,6 +6824,7 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
6792 int cfg_fcp_io_channel; 6824 int cfg_fcp_io_channel;
6793 uint32_t cpu; 6825 uint32_t cpu;
6794 uint32_t i = 0; 6826 uint32_t i = 0;
6827 uint32_t j = 0;
6795 6828
6796 6829
6797 /* 6830 /*
@@ -6802,15 +6835,21 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
6802 /* Sanity check on HBA EQ parameters */ 6835 /* Sanity check on HBA EQ parameters */
6803 cfg_fcp_io_channel = phba->cfg_fcp_io_channel; 6836 cfg_fcp_io_channel = phba->cfg_fcp_io_channel;
6804 6837
6805 /* It doesn't make sense to have more io channels then CPUs */ 6838 /* It doesn't make sense to have more io channels then online CPUs */
6806 for_each_online_cpu(cpu) { 6839 for_each_present_cpu(cpu) {
6807 i++; 6840 if (cpu_online(cpu))
6841 i++;
6842 j++;
6808 } 6843 }
6844 phba->sli4_hba.num_online_cpu = i;
6845 phba->sli4_hba.num_present_cpu = j;
6846
6809 if (i < cfg_fcp_io_channel) { 6847 if (i < cfg_fcp_io_channel) {
6810 lpfc_printf_log(phba, 6848 lpfc_printf_log(phba,
6811 KERN_ERR, LOG_INIT, 6849 KERN_ERR, LOG_INIT,
6812 "3188 Reducing IO channels to match number of " 6850 "3188 Reducing IO channels to match number of "
6813 "CPUs: from %d to %d\n", cfg_fcp_io_channel, i); 6851 "online CPUs: from %d to %d\n",
6852 cfg_fcp_io_channel, i);
6814 cfg_fcp_io_channel = i; 6853 cfg_fcp_io_channel = i;
6815 } 6854 }
6816 6855
@@ -8310,6 +8349,269 @@ lpfc_sli_disable_intr(struct lpfc_hba *phba)
8310} 8349}
8311 8350
8312/** 8351/**
8352 * lpfc_find_next_cpu - Find next available CPU that matches the phys_id
8353 * @phba: pointer to lpfc hba data structure.
8354 *
8355 * Find next available CPU to use for IRQ to CPU affinity.
8356 */
8357static int
8358lpfc_find_next_cpu(struct lpfc_hba *phba, uint32_t phys_id)
8359{
8360 struct lpfc_vector_map_info *cpup;
8361 int cpu;
8362
8363 cpup = phba->sli4_hba.cpu_map;
8364 for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
8365 /* CPU must be online */
8366 if (cpu_online(cpu)) {
8367 if ((cpup->irq == LPFC_VECTOR_MAP_EMPTY) &&
8368 (lpfc_used_cpu[cpu] == LPFC_VECTOR_MAP_EMPTY) &&
8369 (cpup->phys_id == phys_id)) {
8370 return cpu;
8371 }
8372 }
8373 cpup++;
8374 }
8375
8376 /*
8377 * If we get here, we have used ALL CPUs for the specific
8378 * phys_id. Now we need to clear out lpfc_used_cpu and start
8379 * reusing CPUs.
8380 */
8381
8382 for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
8383 if (lpfc_used_cpu[cpu] == phys_id)
8384 lpfc_used_cpu[cpu] = LPFC_VECTOR_MAP_EMPTY;
8385 }
8386
8387 cpup = phba->sli4_hba.cpu_map;
8388 for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
8389 /* CPU must be online */
8390 if (cpu_online(cpu)) {
8391 if ((cpup->irq == LPFC_VECTOR_MAP_EMPTY) &&
8392 (cpup->phys_id == phys_id)) {
8393 return cpu;
8394 }
8395 }
8396 cpup++;
8397 }
8398 return LPFC_VECTOR_MAP_EMPTY;
8399}
8400
8401/**
8402 * lpfc_sli4_set_affinity - Set affinity for HBA IRQ vectors
8403 * @phba: pointer to lpfc hba data structure.
8404 * @vectors: number of HBA vectors
8405 *
8406 * Affinitize MSIX IRQ vectors to CPUs. Try to equally spread vector
8407 * affinization across multple physical CPUs (numa nodes).
8408 * In addition, this routine will assign an IO channel for each CPU
8409 * to use when issuing I/Os.
8410 */
8411static int
8412lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors)
8413{
8414 int i, idx, saved_chann, used_chann, cpu, phys_id;
8415 int max_phys_id, num_io_channel, first_cpu;
8416 struct lpfc_vector_map_info *cpup;
8417#ifdef CONFIG_X86
8418 struct cpuinfo_x86 *cpuinfo;
8419#endif
8420 struct cpumask *mask;
8421 uint8_t chann[LPFC_FCP_IO_CHAN_MAX+1];
8422
8423 /* If there is no mapping, just return */
8424 if (!phba->cfg_fcp_cpu_map)
8425 return 1;
8426
8427 /* Init cpu_map array */
8428 memset(phba->sli4_hba.cpu_map, 0xff,
8429 (sizeof(struct lpfc_vector_map_info) *
8430 phba->sli4_hba.num_present_cpu));
8431
8432 max_phys_id = 0;
8433 phys_id = 0;
8434 num_io_channel = 0;
8435 first_cpu = LPFC_VECTOR_MAP_EMPTY;
8436
8437 /* Update CPU map with physical id and core id of each CPU */
8438 cpup = phba->sli4_hba.cpu_map;
8439 for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) {
8440#ifdef CONFIG_X86
8441 cpuinfo = &cpu_data(cpu);
8442 cpup->phys_id = cpuinfo->phys_proc_id;
8443 cpup->core_id = cpuinfo->cpu_core_id;
8444#else
8445 /* No distinction between CPUs for other platforms */
8446 cpup->phys_id = 0;
8447 cpup->core_id = 0;
8448#endif
8449
8450 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
8451 "3328 CPU physid %d coreid %d\n",
8452 cpup->phys_id, cpup->core_id);
8453
8454 if (cpup->phys_id > max_phys_id)
8455 max_phys_id = cpup->phys_id;
8456 cpup++;
8457 }
8458
8459 /* Now associate the HBA vectors with specific CPUs */
8460 for (idx = 0; idx < vectors; idx++) {
8461 cpup = phba->sli4_hba.cpu_map;
8462 cpu = lpfc_find_next_cpu(phba, phys_id);
8463 if (cpu == LPFC_VECTOR_MAP_EMPTY) {
8464
8465 /* Try for all phys_id's */
8466 for (i = 1; i < max_phys_id; i++) {
8467 phys_id++;
8468 if (phys_id > max_phys_id)
8469 phys_id = 0;
8470 cpu = lpfc_find_next_cpu(phba, phys_id);
8471 if (cpu == LPFC_VECTOR_MAP_EMPTY)
8472 continue;
8473 goto found;
8474 }
8475
8476 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8477 "3329 Cannot set affinity:"
8478 "Error mapping vector %d (%d)\n",
8479 idx, vectors);
8480 return 0;
8481 }
8482found:
8483 cpup += cpu;
8484 if (phba->cfg_fcp_cpu_map == LPFC_DRIVER_CPU_MAP)
8485 lpfc_used_cpu[cpu] = phys_id;
8486
8487 /* Associate vector with selected CPU */
8488 cpup->irq = phba->sli4_hba.msix_entries[idx].vector;
8489
8490 /* Associate IO channel with selected CPU */
8491 cpup->channel_id = idx;
8492 num_io_channel++;
8493
8494 if (first_cpu == LPFC_VECTOR_MAP_EMPTY)
8495 first_cpu = cpu;
8496
8497 /* Now affinitize to the selected CPU */
8498 mask = &cpup->maskbits;
8499 cpumask_clear(mask);
8500 cpumask_set_cpu(cpu, mask);
8501 i = irq_set_affinity_hint(phba->sli4_hba.msix_entries[idx].
8502 vector, mask);
8503
8504 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
8505 "3330 Set Affinity: CPU %d channel %d "
8506 "irq %d (%x)\n",
8507 cpu, cpup->channel_id,
8508 phba->sli4_hba.msix_entries[idx].vector, i);
8509
8510 /* Spread vector mapping across multple physical CPU nodes */
8511 phys_id++;
8512 if (phys_id > max_phys_id)
8513 phys_id = 0;
8514 }
8515
8516 /*
8517 * Finally fill in the IO channel for any remaining CPUs.
8518 * At this point, all IO channels have been assigned to a specific
8519 * MSIx vector, mapped to a specific CPU.
8520 * Base the remaining IO channel assigned, to IO channels already
8521 * assigned to other CPUs on the same phys_id.
8522 */
8523 for (i = 0; i <= max_phys_id; i++) {
8524 /*
8525 * If there are no io channels already mapped to
8526 * this phys_id, just round robin thru the io_channels.
8527 * Setup chann[] for round robin.
8528 */
8529 for (idx = 0; idx < phba->cfg_fcp_io_channel; idx++)
8530 chann[idx] = idx;
8531
8532 saved_chann = 0;
8533 used_chann = 0;
8534
8535 /*
8536 * First build a list of IO channels already assigned
8537 * to this phys_id before reassigning the same IO
8538 * channels to the remaining CPUs.
8539 */
8540 cpup = phba->sli4_hba.cpu_map;
8541 cpu = first_cpu;
8542 cpup += cpu;
8543 for (idx = 0; idx < phba->sli4_hba.num_present_cpu;
8544 idx++) {
8545 if (cpup->phys_id == i) {
8546 /*
8547 * Save any IO channels that are
8548 * already mapped to this phys_id.
8549 */
8550 if (cpup->irq != LPFC_VECTOR_MAP_EMPTY) {
8551 chann[saved_chann] =
8552 cpup->channel_id;
8553 saved_chann++;
8554 goto out;
8555 }
8556
8557 /* See if we are using round-robin */
8558 if (saved_chann == 0)
8559 saved_chann =
8560 phba->cfg_fcp_io_channel;
8561
8562 /* Associate next IO channel with CPU */
8563 cpup->channel_id = chann[used_chann];
8564 num_io_channel++;
8565 used_chann++;
8566 if (used_chann == saved_chann)
8567 used_chann = 0;
8568
8569 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
8570 "3331 Set IO_CHANN "
8571 "CPU %d channel %d\n",
8572 idx, cpup->channel_id);
8573 }
8574out:
8575 cpu++;
8576 if (cpu >= phba->sli4_hba.num_present_cpu) {
8577 cpup = phba->sli4_hba.cpu_map;
8578 cpu = 0;
8579 } else {
8580 cpup++;
8581 }
8582 }
8583 }
8584
8585 if (phba->sli4_hba.num_online_cpu != phba->sli4_hba.num_present_cpu) {
8586 cpup = phba->sli4_hba.cpu_map;
8587 for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) {
8588 if (cpup->channel_id == LPFC_VECTOR_MAP_EMPTY) {
8589 cpup->channel_id = 0;
8590 num_io_channel++;
8591
8592 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
8593 "3332 Assign IO_CHANN "
8594 "CPU %d channel %d\n",
8595 idx, cpup->channel_id);
8596 }
8597 cpup++;
8598 }
8599 }
8600
8601 /* Sanity check */
8602 if (num_io_channel != phba->sli4_hba.num_present_cpu)
8603 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8604 "3333 Set affinity mismatch:"
8605 "%d chann != %d cpus: %d vactors\n",
8606 num_io_channel, phba->sli4_hba.num_present_cpu,
8607 vectors);
8608
8609 phba->cfg_fcp_io_sched = LPFC_FCP_SCHED_BY_CPU;
8610 return 1;
8611}
8612
8613
8614/**
8313 * lpfc_sli4_enable_msix - Enable MSI-X interrupt mode to SLI-4 device 8615 * lpfc_sli4_enable_msix - Enable MSI-X interrupt mode to SLI-4 device
8314 * @phba: pointer to lpfc hba data structure. 8616 * @phba: pointer to lpfc hba data structure.
8315 * 8617 *
@@ -8360,9 +8662,7 @@ enable_msix_vectors:
8360 phba->sli4_hba.msix_entries[index].vector, 8662 phba->sli4_hba.msix_entries[index].vector,
8361 phba->sli4_hba.msix_entries[index].entry); 8663 phba->sli4_hba.msix_entries[index].entry);
8362 8664
8363 /* 8665 /* Assign MSI-X vectors to interrupt handlers */
8364 * Assign MSI-X vectors to interrupt handlers
8365 */
8366 for (index = 0; index < vectors; index++) { 8666 for (index = 0; index < vectors; index++) {
8367 memset(&phba->sli4_hba.handler_name[index], 0, 16); 8667 memset(&phba->sli4_hba.handler_name[index], 0, 16);
8368 sprintf((char *)&phba->sli4_hba.handler_name[index], 8668 sprintf((char *)&phba->sli4_hba.handler_name[index],
@@ -8390,6 +8690,8 @@ enable_msix_vectors:
8390 phba->cfg_fcp_io_channel, vectors); 8690 phba->cfg_fcp_io_channel, vectors);
8391 phba->cfg_fcp_io_channel = vectors; 8691 phba->cfg_fcp_io_channel = vectors;
8392 } 8692 }
8693
8694 lpfc_sli4_set_affinity(phba, vectors);
8393 return rc; 8695 return rc;
8394 8696
8395cfg_fail_out: 8697cfg_fail_out:
@@ -10667,6 +10969,7 @@ static struct miscdevice lpfc_mgmt_dev = {
10667static int __init 10969static int __init
10668lpfc_init(void) 10970lpfc_init(void)
10669{ 10971{
10972 int cpu;
10670 int error = 0; 10973 int error = 0;
10671 10974
10672 printk(LPFC_MODULE_DESC "\n"); 10975 printk(LPFC_MODULE_DESC "\n");
@@ -10693,6 +10996,11 @@ lpfc_init(void)
10693 return -ENOMEM; 10996 return -ENOMEM;
10694 } 10997 }
10695 } 10998 }
10999
11000 /* Initialize in case vector mapping is needed */
11001 for (cpu = 0; cpu < LPFC_MAX_CPU; cpu++)
11002 lpfc_used_cpu[cpu] = LPFC_VECTOR_MAP_EMPTY;
11003
10696 error = pci_register_driver(&lpfc_driver); 11004 error = pci_register_driver(&lpfc_driver);
10697 if (error) { 11005 if (error) {
10698 fc_release_transport(lpfc_transport_template); 11006 fc_release_transport(lpfc_transport_template);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index c13ab4fd36b9..94b017ee9aa3 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -7923,15 +7923,21 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
7923static inline uint32_t 7923static inline uint32_t
7924lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba) 7924lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba)
7925{ 7925{
7926 int i; 7926 struct lpfc_vector_map_info *cpup;
7927 7927 int chann, cpu;
7928 if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU)
7929 i = smp_processor_id();
7930 else
7931 i = atomic_add_return(1, &phba->fcp_qidx);
7932 7928
7933 i = (i % phba->cfg_fcp_io_channel); 7929 if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU) {
7934 return i; 7930 cpu = smp_processor_id();
7931 if (cpu < phba->sli4_hba.num_present_cpu) {
7932 cpup = phba->sli4_hba.cpu_map;
7933 cpup += cpu;
7934 return cpup->channel_id;
7935 }
7936 chann = cpu;
7937 }
7938 chann = atomic_add_return(1, &phba->fcp_qidx);
7939 chann = (chann % phba->cfg_fcp_io_channel);
7940 return chann;
7935} 7941}
7936 7942
7937/** 7943/**
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 347e22c527b1..67af460184ba 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -435,6 +435,17 @@ struct lpfc_sli4_lnk_info {
435 435
436#define LPFC_SLI4_HANDLER_NAME_SZ 16 436#define LPFC_SLI4_HANDLER_NAME_SZ 16
437 437
438/* Used for IRQ vector to CPU mapping */
439struct lpfc_vector_map_info {
440 uint16_t phys_id;
441 uint16_t core_id;
442 uint16_t irq;
443 uint16_t channel_id;
444 struct cpumask maskbits;
445};
446#define LPFC_VECTOR_MAP_EMPTY 0xffff
447#define LPFC_MAX_CPU 256
448
438/* SLI4 HBA data structure entries */ 449/* SLI4 HBA data structure entries */
439struct lpfc_sli4_hba { 450struct lpfc_sli4_hba {
440 void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for 451 void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
@@ -568,6 +579,11 @@ struct lpfc_sli4_hba {
568 struct lpfc_iov iov; 579 struct lpfc_iov iov;
569 spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ 580 spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
570 spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ 581 spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */
582
583 /* CPU to vector mapping information */
584 struct lpfc_vector_map_info *cpu_map;
585 uint16_t num_online_cpu;
586 uint16_t num_present_cpu;
571}; 587};
572 588
573enum lpfc_sge_type { 589enum lpfc_sge_type {