From 9fe725f84ae31681628d853d3a9fd4c2df8dfdf8 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 5 Apr 2007 17:19:08 +1000 Subject: [PATCH] --- yaml --- r: 53348 b: refs/heads/master c: c9953a73e92df11edd812d863ff741877ea9e58c h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/pci/msi.c | 29 +++++++++++++++++++++++++---- trunk/include/linux/msi.h | 1 + 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/[refs] b/[refs] index daa85ec794b0..deccdb88b9e2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 17bbc12acdb23ffb9613e12ca974fafd31bfcb56 +refs/heads/master: c9953a73e92df11edd812d863ff741877ea9e58c diff --git a/trunk/drivers/pci/msi.c b/trunk/drivers/pci/msi.c index 34087af68833..5902c00f4fce 100644 --- a/trunk/drivers/pci/msi.c +++ b/trunk/drivers/pci/msi.c @@ -459,15 +459,17 @@ static int msix_capability_init(struct pci_dev *dev, /** * pci_msi_check_device - check whether MSI may be enabled on a device * @dev: pointer to the pci_dev data structure of MSI device function + * @nvec: how many MSIs have been requested ? * @type: are we checking for MSI or MSI-X ? * * Look at global flags, the device itself, and its parent busses * to determine if MSI/-X are supported for the device. If MSI/-X is * supported return 0, else return an error code. **/ -static int pci_msi_check_device(struct pci_dev * dev, int type) +static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type) { struct pci_bus *bus; + int ret; /* MSI must be globally enabled and supported by the device */ if (!pci_msi_enable || !dev || dev->no_msi) @@ -483,6 +485,10 @@ static int pci_msi_check_device(struct pci_dev * dev, int type) if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) return -EINVAL; + ret = arch_msi_check_device(dev, nvec, type); + if (ret) + return ret; + if (!pci_find_capability(dev, type)) return -EINVAL; @@ -503,8 +509,9 @@ int pci_enable_msi(struct pci_dev* dev) { int status; - if (pci_msi_check_device(dev, PCI_CAP_ID_MSI)) - return -EINVAL; + status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI); + if (status) + return status; WARN_ON(!!dev->msi_enabled); @@ -601,9 +608,13 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) int i, j; u16 control; - if (!entries || pci_msi_check_device(dev, PCI_CAP_ID_MSIX)) + if (!entries) return -EINVAL; + status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX); + if (status) + return status; + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); pci_read_config_word(dev, msi_control_reg(pos), &control); nr_entries = multi_msix_capable(control); @@ -687,3 +698,13 @@ void pci_no_msi(void) { pci_msi_enable = 0; } + + +/* Arch hooks */ + +int __attribute__ ((weak)) +arch_msi_check_device(struct pci_dev* dev, int nvec, int type) +{ + return 0; +} + diff --git a/trunk/include/linux/msi.h b/trunk/include/linux/msi.h index e38fe6822cb4..d2a200048b22 100644 --- a/trunk/include/linux/msi.h +++ b/trunk/include/linux/msi.h @@ -41,6 +41,7 @@ struct msi_desc { */ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); void arch_teardown_msi_irq(unsigned int irq); +extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); #endif /* LINUX_MSI_H */