diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2009-02-11 06:27:02 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@hobbes.lan> | 2009-03-19 22:29:34 -0400 |
commit | b5fbf53324f65646154e172af350674d5a2a1629 (patch) | |
tree | 6310f1629c3112e240b151862b7f0b357045649e /drivers/pci/msi.c | |
parent | 35e1801ea637810830e653ffe7ff62c7048ae03a (diff) |
PCI/MSI: Allow arch code to return the number of MSI-X available
There is code in msix_capability_init() which, when the requested number
of MSI-X couldn't be allocated, calculates how many MSI-X /could/ be
allocated and returns that to the driver. That allows the driver to then
make a second request, with a number of MSIs that should succeed.
The current code requires the arch code to setup as many msi_descs as it
can, and then return to the generic code. On some platforms the arch
code may already know how many MSI-X it can allocate, before it sets up
any of the msi_descs.
So change the logic such that if the arch code returns a positive error
code, that is taken to be the number of MSI-X that could be allocated.
If the error code is negative we still calculate the number available
using the old method.
Because it's a little subtle, make sure the error return code from
arch_setup_msi_irq() is always negative. That way only implementations
of arch_setup_msi_irqs() need to be careful about returning a positive
error code.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r-- | drivers/pci/msi.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 33adf323f06..dceea56f734 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -42,8 +42,10 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
42 | 42 | ||
43 | list_for_each_entry(entry, &dev->msi_list, list) { | 43 | list_for_each_entry(entry, &dev->msi_list, list) { |
44 | ret = arch_setup_msi_irq(dev, entry); | 44 | ret = arch_setup_msi_irq(dev, entry); |
45 | if (ret) | 45 | if (ret < 0) |
46 | return ret; | 46 | return ret; |
47 | if (ret > 0) | ||
48 | return -ENOSPC; | ||
47 | } | 49 | } |
48 | 50 | ||
49 | return 0; | 51 | return 0; |
@@ -487,7 +489,9 @@ static int msix_capability_init(struct pci_dev *dev, | |||
487 | } | 489 | } |
488 | 490 | ||
489 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); | 491 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); |
490 | if (ret) { | 492 | if (ret < 0) { |
493 | /* If we had some success report the number of irqs | ||
494 | * we succeeded in setting up. */ | ||
491 | int avail = 0; | 495 | int avail = 0; |
492 | list_for_each_entry(entry, &dev->msi_list, list) { | 496 | list_for_each_entry(entry, &dev->msi_list, list) { |
493 | if (entry->irq != 0) { | 497 | if (entry->irq != 0) { |
@@ -495,14 +499,13 @@ static int msix_capability_init(struct pci_dev *dev, | |||
495 | } | 499 | } |
496 | } | 500 | } |
497 | 501 | ||
498 | msi_free_irqs(dev); | 502 | if (avail != 0) |
503 | ret = avail; | ||
504 | } | ||
499 | 505 | ||
500 | /* If we had some success report the number of irqs | 506 | if (ret) { |
501 | * we succeeded in setting up. | 507 | msi_free_irqs(dev); |
502 | */ | 508 | return ret; |
503 | if (avail == 0) | ||
504 | avail = ret; | ||
505 | return avail; | ||
506 | } | 509 | } |
507 | 510 | ||
508 | i = 0; | 511 | i = 0; |