aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi.c
diff options
context:
space:
mode:
authorAlexander Gordeev <agordeev@redhat.com>2012-11-19 10:02:10 -0500
committerIngo Molnar <mingo@kernel.org>2013-01-24 11:25:13 -0500
commit08261d87f7d1b6253ab3223756625a5c74532293 (patch)
treec0025a8e4593564bf356f1f185c21a137a96cb8a /drivers/pci/msi.c
parent51906e779f2b13b38f8153774c4c7163d412ffd9 (diff)
PCI/MSI: Enable multiple MSIs with pci_enable_msi_block_auto()
The new function pci_enable_msi_block_auto() tries to allocate maximum possible number of MSIs up to the number the device supports. It generalizes a pattern when pci_enable_msi_block() is contiguously called until it succeeds or fails. Opposite to pci_enable_msi_block() which takes the number of MSIs to allocate as a input parameter, pci_enable_msi_block_auto() could be used by device drivers to obtain the number of assigned MSIs and the number of MSIs the device supports. Signed-off-by: Alexander Gordeev <agordeev@redhat.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Cc: Suresh Siddha <suresh.b.siddha@intel.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Matthew Wilcox <willy@linux.intel.com> Cc: Jeff Garzik <jgarzik@pobox.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/c3de2419df94a0f95ca1a6f755afc421486455e6.1353324359.git.agordeev@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r--drivers/pci/msi.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 5099636a6e5f..00cc78c7aa04 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -845,6 +845,32 @@ int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
845} 845}
846EXPORT_SYMBOL(pci_enable_msi_block); 846EXPORT_SYMBOL(pci_enable_msi_block);
847 847
848int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
849{
850 int ret, pos, nvec;
851 u16 msgctl;
852
853 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
854 if (!pos)
855 return -EINVAL;
856
857 pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
858 ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
859
860 if (maxvec)
861 *maxvec = ret;
862
863 do {
864 nvec = ret;
865 ret = pci_enable_msi_block(dev, nvec);
866 } while (ret > 0);
867
868 if (ret < 0)
869 return ret;
870 return nvec;
871}
872EXPORT_SYMBOL(pci_enable_msi_block_auto);
873
848void pci_msi_shutdown(struct pci_dev *dev) 874void pci_msi_shutdown(struct pci_dev *dev)
849{ 875{
850 struct msi_desc *desc; 876 struct msi_desc *desc;