aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Hernandez <michael.hernandez@cavium.com>2017-05-18 13:47:47 -0400
committerBjorn Helgaas <bhelgaas@google.com>2017-05-22 16:06:05 -0400
commit6f9a22bc5775d231ab8fbe2c2f3c88e45e3e7c28 (patch)
tree1c783fb19be43cd07b3a1f7a32af66e64dba2958
parent2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff)
PCI/MSI: Ignore affinity if pre/post vector count is more than min_vecs
min_vecs is the minimum amount of vectors needed to operate in MSI-X mode which may just include the vectors that don't need affinity. Disabling affinity settings causes the qla2xxx driver scsi_add_host() to fail when blk_mq is enabled as the blk_mq_pci_map_queues() expects affinity masks on each vector. Fixes: dfef358bd1be ("PCI/MSI: Don't apply affinity if there aren't enough vectors left") Signed-off-by: Michael Hernandez <michael.hernandez@cavium.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Cc: stable@vger.kernel.org # v4.10+
-rw-r--r--drivers/pci/msi.c14
-rw-r--r--include/linux/interrupt.h4
-rw-r--r--kernel/irq/affinity.c13
3 files changed, 16 insertions, 15 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index ba44fdfda66b..9e1569107cd6 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1058,7 +1058,7 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
1058 1058
1059 for (;;) { 1059 for (;;) {
1060 if (affd) { 1060 if (affd) {
1061 nvec = irq_calc_affinity_vectors(nvec, affd); 1061 nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
1062 if (nvec < minvec) 1062 if (nvec < minvec)
1063 return -ENOSPC; 1063 return -ENOSPC;
1064 } 1064 }
@@ -1097,7 +1097,7 @@ static int __pci_enable_msix_range(struct pci_dev *dev,
1097 1097
1098 for (;;) { 1098 for (;;) {
1099 if (affd) { 1099 if (affd) {
1100 nvec = irq_calc_affinity_vectors(nvec, affd); 1100 nvec = irq_calc_affinity_vectors(minvec, nvec, affd);
1101 if (nvec < minvec) 1101 if (nvec < minvec)
1102 return -ENOSPC; 1102 return -ENOSPC;
1103 } 1103 }
@@ -1165,16 +1165,6 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
1165 if (flags & PCI_IRQ_AFFINITY) { 1165 if (flags & PCI_IRQ_AFFINITY) {
1166 if (!affd) 1166 if (!affd)
1167 affd = &msi_default_affd; 1167 affd = &msi_default_affd;
1168
1169 if (affd->pre_vectors + affd->post_vectors > min_vecs)
1170 return -EINVAL;
1171
1172 /*
1173 * If there aren't any vectors left after applying the pre/post
1174 * vectors don't bother with assigning affinity.
1175 */
1176 if (affd->pre_vectors + affd->post_vectors == min_vecs)
1177 affd = NULL;
1178 } else { 1168 } else {
1179 if (WARN_ON(affd)) 1169 if (WARN_ON(affd))
1180 affd = NULL; 1170 affd = NULL;
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index a6fba4804672..0991f973f8ca 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -291,7 +291,7 @@ extern int
291irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); 291irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);
292 292
293struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd); 293struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd);
294int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd); 294int irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity *affd);
295 295
296#else /* CONFIG_SMP */ 296#else /* CONFIG_SMP */
297 297
@@ -331,7 +331,7 @@ irq_create_affinity_masks(int nvec, const struct irq_affinity *affd)
331} 331}
332 332
333static inline int 333static inline int
334irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd) 334irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity *affd)
335{ 335{
336 return maxvec; 336 return maxvec;
337} 337}
diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
index e2d356dd7581..9b71406d2eec 100644
--- a/kernel/irq/affinity.c
+++ b/kernel/irq/affinity.c
@@ -66,6 +66,13 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
66 struct cpumask *masks; 66 struct cpumask *masks;
67 cpumask_var_t nmsk; 67 cpumask_var_t nmsk;
68 68
69 /*
70 * If there aren't any vectors left after applying the pre/post
71 * vectors don't bother with assigning affinity.
72 */
73 if (!affv)
74 return NULL;
75
69 if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL)) 76 if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
70 return NULL; 77 return NULL;
71 78
@@ -140,15 +147,19 @@ out:
140 147
141/** 148/**
142 * irq_calc_affinity_vectors - Calculate the optimal number of vectors 149 * irq_calc_affinity_vectors - Calculate the optimal number of vectors
150 * @minvec: The minimum number of vectors available
143 * @maxvec: The maximum number of vectors available 151 * @maxvec: The maximum number of vectors available
144 * @affd: Description of the affinity requirements 152 * @affd: Description of the affinity requirements
145 */ 153 */
146int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd) 154int irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity *affd)
147{ 155{
148 int resv = affd->pre_vectors + affd->post_vectors; 156 int resv = affd->pre_vectors + affd->post_vectors;
149 int vecs = maxvec - resv; 157 int vecs = maxvec - resv;
150 int cpus; 158 int cpus;
151 159
160 if (resv > minvec)
161 return 0;
162
152 /* Stabilize the cpumasks */ 163 /* Stabilize the cpumasks */
153 get_online_cpus(); 164 get_online_cpus();
154 cpus = cpumask_weight(cpu_online_mask); 165 cpus = cpumask_weight(cpu_online_mask);