aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/msi.c29
-rw-r--r--include/linux/msi.h1
2 files changed, 26 insertions, 4 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 34087af68833..5902c00f4fce 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -459,15 +459,17 @@ static int msix_capability_init(struct pci_dev *dev,
459/** 459/**
460 * pci_msi_check_device - check whether MSI may be enabled on a device 460 * pci_msi_check_device - check whether MSI may be enabled on a device
461 * @dev: pointer to the pci_dev data structure of MSI device function 461 * @dev: pointer to the pci_dev data structure of MSI device function
462 * @nvec: how many MSIs have been requested ?
462 * @type: are we checking for MSI or MSI-X ? 463 * @type: are we checking for MSI or MSI-X ?
463 * 464 *
464 * Look at global flags, the device itself, and its parent busses 465 * Look at global flags, the device itself, and its parent busses
465 * to determine if MSI/-X are supported for the device. If MSI/-X is 466 * to determine if MSI/-X are supported for the device. If MSI/-X is
466 * supported return 0, else return an error code. 467 * supported return 0, else return an error code.
467 **/ 468 **/
468static int pci_msi_check_device(struct pci_dev * dev, int type) 469static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type)
469{ 470{
470 struct pci_bus *bus; 471 struct pci_bus *bus;
472 int ret;
471 473
472 /* MSI must be globally enabled and supported by the device */ 474 /* MSI must be globally enabled and supported by the device */
473 if (!pci_msi_enable || !dev || dev->no_msi) 475 if (!pci_msi_enable || !dev || dev->no_msi)
@@ -483,6 +485,10 @@ static int pci_msi_check_device(struct pci_dev * dev, int type)
483 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) 485 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
484 return -EINVAL; 486 return -EINVAL;
485 487
488 ret = arch_msi_check_device(dev, nvec, type);
489 if (ret)
490 return ret;
491
486 if (!pci_find_capability(dev, type)) 492 if (!pci_find_capability(dev, type))
487 return -EINVAL; 493 return -EINVAL;
488 494
@@ -503,8 +509,9 @@ int pci_enable_msi(struct pci_dev* dev)
503{ 509{
504 int status; 510 int status;
505 511
506 if (pci_msi_check_device(dev, PCI_CAP_ID_MSI)) 512 status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
507 return -EINVAL; 513 if (status)
514 return status;
508 515
509 WARN_ON(!!dev->msi_enabled); 516 WARN_ON(!!dev->msi_enabled);
510 517
@@ -601,9 +608,13 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
601 int i, j; 608 int i, j;
602 u16 control; 609 u16 control;
603 610
604 if (!entries || pci_msi_check_device(dev, PCI_CAP_ID_MSIX)) 611 if (!entries)
605 return -EINVAL; 612 return -EINVAL;
606 613
614 status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
615 if (status)
616 return status;
617
607 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 618 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
608 pci_read_config_word(dev, msi_control_reg(pos), &control); 619 pci_read_config_word(dev, msi_control_reg(pos), &control);
609 nr_entries = multi_msix_capable(control); 620 nr_entries = multi_msix_capable(control);
@@ -687,3 +698,13 @@ void pci_no_msi(void)
687{ 698{
688 pci_msi_enable = 0; 699 pci_msi_enable = 0;
689} 700}
701
702
703/* Arch hooks */
704
705int __attribute__ ((weak))
706arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
707{
708 return 0;
709}
710
diff --git a/include/linux/msi.h b/include/linux/msi.h
index e38fe6822cb4..d2a200048b22 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -41,6 +41,7 @@ struct msi_desc {
41 */ 41 */
42int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); 42int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
43void arch_teardown_msi_irq(unsigned int irq); 43void arch_teardown_msi_irq(unsigned int irq);
44extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
44 45
45 46
46#endif /* LINUX_MSI_H */ 47#endif /* LINUX_MSI_H */