aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-11-08 20:15:05 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-11-09 02:25:10 -0500
commit402723ad5c625ee052432698ae5e56b02d38d4ec (patch)
treeac5eab5d6638f13c289287aef2016bdacb1bba21
parent61e1c5905290efe48bacda5e342d4af4cb1b923b (diff)
PCI/MSI: Provide pci_alloc_irq_vectors_affinity()
This is a variant of pci_alloc_irq_vectors() that allows passing a struct irq_affinity to provide fine-grained IRQ affinity control. For now this means being able to exclude vectors at the beginning or end of the MSI vector space, but it could also be used for any other quirks needed in the future (e.g. more vectors than CPUs, or excluding CPUs from the spreading). Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Jens Axboe <axboe@kernel.dk> Cc: linux-block@vger.kernel.org Cc: linux-pci@vger.kernel.org Link: http://lkml.kernel.org/r/1478654107-7384-6-git-send-email-hch@lst.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/pci/msi.c20
-rw-r--r--include/linux/pci.h24
2 files changed, 32 insertions, 12 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 512f388a74f2..dd27f73a45fc 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1179,11 +1179,12 @@ int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
1179EXPORT_SYMBOL(pci_enable_msix_range); 1179EXPORT_SYMBOL(pci_enable_msix_range);
1180 1180
1181/** 1181/**
1182 * pci_alloc_irq_vectors - allocate multiple IRQs for a device 1182 * pci_alloc_irq_vectors_affinity - allocate multiple IRQs for a device
1183 * @dev: PCI device to operate on 1183 * @dev: PCI device to operate on
1184 * @min_vecs: minimum number of vectors required (must be >= 1) 1184 * @min_vecs: minimum number of vectors required (must be >= 1)
1185 * @max_vecs: maximum (desired) number of vectors 1185 * @max_vecs: maximum (desired) number of vectors
1186 * @flags: flags or quirks for the allocation 1186 * @flags: flags or quirks for the allocation
1187 * @affd: optional description of the affinity requirements
1187 * 1188 *
1188 * Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI 1189 * Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI
1189 * vectors if available, and fall back to a single legacy vector 1190 * vectors if available, and fall back to a single legacy vector
@@ -1195,15 +1196,20 @@ EXPORT_SYMBOL(pci_enable_msix_range);
1195 * To get the Linux IRQ number used for a vector that can be passed to 1196 * To get the Linux IRQ number used for a vector that can be passed to
1196 * request_irq() use the pci_irq_vector() helper. 1197 * request_irq() use the pci_irq_vector() helper.
1197 */ 1198 */
1198int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, 1199int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
1199 unsigned int max_vecs, unsigned int flags) 1200 unsigned int max_vecs, unsigned int flags,
1201 const struct irq_affinity *affd)
1200{ 1202{
1201 static const struct irq_affinity msi_default_affd; 1203 static const struct irq_affinity msi_default_affd;
1202 const struct irq_affinity *affd = NULL;
1203 int vecs = -ENOSPC; 1204 int vecs = -ENOSPC;
1204 1205
1205 if (flags & PCI_IRQ_AFFINITY) 1206 if (flags & PCI_IRQ_AFFINITY) {
1206 affd = &msi_default_affd; 1207 if (!affd)
1208 affd = &msi_default_affd;
1209 } else {
1210 if (WARN_ON(affd))
1211 affd = NULL;
1212 }
1207 1213
1208 if (flags & PCI_IRQ_MSIX) { 1214 if (flags & PCI_IRQ_MSIX) {
1209 vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, 1215 vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,
@@ -1226,7 +1232,7 @@ int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
1226 1232
1227 return vecs; 1233 return vecs;
1228} 1234}
1229EXPORT_SYMBOL(pci_alloc_irq_vectors); 1235EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);
1230 1236
1231/** 1237/**
1232 * pci_free_irq_vectors - free previously allocated IRQs for a device 1238 * pci_free_irq_vectors - free previously allocated IRQs for a device
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0e49f70dbd9b..7090f5ff7252 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -244,6 +244,7 @@ struct pci_cap_saved_state {
244 struct pci_cap_saved_data cap; 244 struct pci_cap_saved_data cap;
245}; 245};
246 246
247struct irq_affinity;
247struct pcie_link_state; 248struct pcie_link_state;
248struct pci_vpd; 249struct pci_vpd;
249struct pci_sriov; 250struct pci_sriov;
@@ -1310,8 +1311,10 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev,
1310 return rc; 1311 return rc;
1311 return 0; 1312 return 0;
1312} 1313}
1313int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, 1314int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
1314 unsigned int max_vecs, unsigned int flags); 1315 unsigned int max_vecs, unsigned int flags,
1316 const struct irq_affinity *affd);
1317
1315void pci_free_irq_vectors(struct pci_dev *dev); 1318void pci_free_irq_vectors(struct pci_dev *dev);
1316int pci_irq_vector(struct pci_dev *dev, unsigned int nr); 1319int pci_irq_vector(struct pci_dev *dev, unsigned int nr);
1317const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, int vec); 1320const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, int vec);
@@ -1339,14 +1342,17 @@ static inline int pci_enable_msix_range(struct pci_dev *dev,
1339static inline int pci_enable_msix_exact(struct pci_dev *dev, 1342static inline int pci_enable_msix_exact(struct pci_dev *dev,
1340 struct msix_entry *entries, int nvec) 1343 struct msix_entry *entries, int nvec)
1341{ return -ENOSYS; } 1344{ return -ENOSYS; }
1342static inline int pci_alloc_irq_vectors(struct pci_dev *dev, 1345
1343 unsigned int min_vecs, unsigned int max_vecs, 1346static inline int
1344 unsigned int flags) 1347pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
1348 unsigned int max_vecs, unsigned int flags,
1349 const struct irq_affinity *aff_desc)
1345{ 1350{
1346 if (min_vecs > 1) 1351 if (min_vecs > 1)
1347 return -EINVAL; 1352 return -EINVAL;
1348 return 1; 1353 return 1;
1349} 1354}
1355
1350static inline void pci_free_irq_vectors(struct pci_dev *dev) 1356static inline void pci_free_irq_vectors(struct pci_dev *dev)
1351{ 1357{
1352} 1358}
@@ -1364,6 +1370,14 @@ static inline const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev,
1364} 1370}
1365#endif 1371#endif
1366 1372
1373static inline int
1374pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
1375 unsigned int max_vecs, unsigned int flags)
1376{
1377 return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags,
1378 NULL);
1379}
1380
1367#ifdef CONFIG_PCIEPORTBUS 1381#ifdef CONFIG_PCIEPORTBUS
1368extern bool pcie_ports_disabled; 1382extern bool pcie_ports_disabled;
1369extern bool pcie_ports_auto; 1383extern bool pcie_ports_auto;