diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2009-03-05 09:44:26 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-03-11 02:11:33 -0400 |
commit | 94afa5a5f54235c4612198768b6a2fa2e2366f44 (patch) | |
tree | 392eea5363e4655f3cfd0cfc05a611dbd258a278 /arch/powerpc/platforms/pseries | |
parent | e7943fbbfdb6eef03c003b374de1f802cc14f02a (diff) |
powerpc/pseries: Reject discontiguous/non-zero based MSI-X requests
There's no way for us to express to firmware that we want a
discontiguous, or non-zero based, range of MSI-X entries. So we
must reject such requests.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/msi.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 3e0d6ef3eca..bf2e1ac4130 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c | |||
@@ -356,6 +356,27 @@ static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type) | |||
356 | return 0; | 356 | return 0; |
357 | } | 357 | } |
358 | 358 | ||
359 | static int check_msix_entries(struct pci_dev *pdev) | ||
360 | { | ||
361 | struct msi_desc *entry; | ||
362 | int expected; | ||
363 | |||
364 | /* There's no way for us to express to firmware that we want | ||
365 | * a discontiguous, or non-zero based, range of MSI-X entries. | ||
366 | * So we must reject such requests. */ | ||
367 | |||
368 | expected = 0; | ||
369 | list_for_each_entry(entry, &pdev->msi_list, list) { | ||
370 | if (entry->msi_attrib.entry_nr != expected) { | ||
371 | pr_debug("rtas_msi: bad MSI-X entries.\n"); | ||
372 | return -EINVAL; | ||
373 | } | ||
374 | expected++; | ||
375 | } | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
359 | static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 380 | static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
360 | { | 381 | { |
361 | struct pci_dn *pdn; | 382 | struct pci_dn *pdn; |
@@ -367,6 +388,9 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
367 | if (!pdn) | 388 | if (!pdn) |
368 | return -ENODEV; | 389 | return -ENODEV; |
369 | 390 | ||
391 | if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev)) | ||
392 | return -EINVAL; | ||
393 | |||
370 | /* | 394 | /* |
371 | * Try the new more explicit firmware interface, if that fails fall | 395 | * Try the new more explicit firmware interface, if that fails fall |
372 | * back to the old interface. The old interface is known to never | 396 | * back to the old interface. The old interface is known to never |