Commit 402723ad authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Thomas Gleixner

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: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Acked-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Acked-by: default avatarJens 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.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 61e1c590
...@@ -1179,11 +1179,12 @@ int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, ...@@ -1179,11 +1179,12 @@ int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
EXPORT_SYMBOL(pci_enable_msix_range); EXPORT_SYMBOL(pci_enable_msix_range);
/** /**
* pci_alloc_irq_vectors - allocate multiple IRQs for a device * pci_alloc_irq_vectors_affinity - allocate multiple IRQs for a device
* @dev: PCI device to operate on * @dev: PCI device to operate on
* @min_vecs: minimum number of vectors required (must be >= 1) * @min_vecs: minimum number of vectors required (must be >= 1)
* @max_vecs: maximum (desired) number of vectors * @max_vecs: maximum (desired) number of vectors
* @flags: flags or quirks for the allocation * @flags: flags or quirks for the allocation
* @affd: optional description of the affinity requirements
* *
* Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI * Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X or MSI
* vectors if available, and fall back to a single legacy vector * vectors if available, and fall back to a single legacy vector
...@@ -1195,15 +1196,20 @@ EXPORT_SYMBOL(pci_enable_msix_range); ...@@ -1195,15 +1196,20 @@ EXPORT_SYMBOL(pci_enable_msix_range);
* To get the Linux IRQ number used for a vector that can be passed to * To get the Linux IRQ number used for a vector that can be passed to
* request_irq() use the pci_irq_vector() helper. * request_irq() use the pci_irq_vector() helper.
*/ */
int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
unsigned int max_vecs, unsigned int flags) unsigned int max_vecs, unsigned int flags,
const struct irq_affinity *affd)
{ {
static const struct irq_affinity msi_default_affd; static const struct irq_affinity msi_default_affd;
const struct irq_affinity *affd = NULL;
int vecs = -ENOSPC; int vecs = -ENOSPC;
if (flags & PCI_IRQ_AFFINITY) if (flags & PCI_IRQ_AFFINITY) {
if (!affd)
affd = &msi_default_affd; affd = &msi_default_affd;
} else {
if (WARN_ON(affd))
affd = NULL;
}
if (flags & PCI_IRQ_MSIX) { if (flags & PCI_IRQ_MSIX) {
vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, 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,7 +1232,7 @@ int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
return vecs; return vecs;
} }
EXPORT_SYMBOL(pci_alloc_irq_vectors); EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);
/** /**
* pci_free_irq_vectors - free previously allocated IRQs for a device * pci_free_irq_vectors - free previously allocated IRQs for a device
......
...@@ -244,6 +244,7 @@ struct pci_cap_saved_state { ...@@ -244,6 +244,7 @@ struct pci_cap_saved_state {
struct pci_cap_saved_data cap; struct pci_cap_saved_data cap;
}; };
struct irq_affinity;
struct pcie_link_state; struct pcie_link_state;
struct pci_vpd; struct pci_vpd;
struct pci_sriov; struct pci_sriov;
...@@ -1310,8 +1311,10 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev, ...@@ -1310,8 +1311,10 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev,
return rc; return rc;
return 0; return 0;
} }
int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
unsigned int max_vecs, unsigned int flags); unsigned int max_vecs, unsigned int flags,
const struct irq_affinity *affd);
void pci_free_irq_vectors(struct pci_dev *dev); void pci_free_irq_vectors(struct pci_dev *dev);
int pci_irq_vector(struct pci_dev *dev, unsigned int nr); int pci_irq_vector(struct pci_dev *dev, unsigned int nr);
const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, int vec); const 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, ...@@ -1339,14 +1342,17 @@ static inline int pci_enable_msix_range(struct pci_dev *dev,
static inline int pci_enable_msix_exact(struct pci_dev *dev, static inline int pci_enable_msix_exact(struct pci_dev *dev,
struct msix_entry *entries, int nvec) struct msix_entry *entries, int nvec)
{ return -ENOSYS; } { return -ENOSYS; }
static inline int pci_alloc_irq_vectors(struct pci_dev *dev,
unsigned int min_vecs, unsigned int max_vecs, static inline int
unsigned int flags) pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
unsigned int max_vecs, unsigned int flags,
const struct irq_affinity *aff_desc)
{ {
if (min_vecs > 1) if (min_vecs > 1)
return -EINVAL; return -EINVAL;
return 1; return 1;
} }
static inline void pci_free_irq_vectors(struct pci_dev *dev) static inline void pci_free_irq_vectors(struct pci_dev *dev)
{ {
} }
...@@ -1364,6 +1370,14 @@ static inline const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, ...@@ -1364,6 +1370,14 @@ static inline const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev,
} }
#endif #endif
static inline int
pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
unsigned int max_vecs, unsigned int flags)
{
return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags,
NULL);
}
#ifdef CONFIG_PCIEPORTBUS #ifdef CONFIG_PCIEPORTBUS
extern bool pcie_ports_disabled; extern bool pcie_ports_disabled;
extern bool pcie_ports_auto; extern bool pcie_ports_auto;
......
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