diff options
author | Michael Hernandez <michael.hernandez@cavium.com> | 2017-05-18 13:47:47 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-05-22 16:06:05 -0400 |
commit | 6f9a22bc5775d231ab8fbe2c2f3c88e45e3e7c28 (patch) | |
tree | 1c783fb19be43cd07b3a1f7a32af66e64dba2958 | |
parent | 2ea659a9ef488125eb46da6eb571de5eae5c43f6 (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.c | 14 | ||||
-rw-r--r-- | include/linux/interrupt.h | 4 | ||||
-rw-r--r-- | kernel/irq/affinity.c | 13 |
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 | |||
291 | irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); | 291 | irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); |
292 | 292 | ||
293 | struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd); | 293 | struct cpumask *irq_create_affinity_masks(int nvec, const struct irq_affinity *affd); |
294 | int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd); | 294 | int 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 | ||
333 | static inline int | 333 | static inline int |
334 | irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd) | 334 | irq_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 | */ |
146 | int irq_calc_affinity_vectors(int maxvec, const struct irq_affinity *affd) | 154 | int 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); |