aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/msi.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index a83c1f5735d6..008235947aa4 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -901,6 +901,33 @@ static int msix_capability_init(struct pci_dev *dev,
901} 901}
902 902
903/** 903/**
904 * pci_msi_supported - check whether MSI may be enabled on device
905 * @dev: pointer to the pci_dev data structure of MSI device function
906 *
907 * MSI must be globally enabled and supported by the device and its root
908 * bus. But, the root bus is not easy to find since some architectures
909 * have virtual busses on top of the PCI hierarchy (for instance the
910 * hypertransport bus), while the actual bus where MSI must be supported
911 * is below. So we test the MSI flag on all parent busses and assume
912 * that no quirk will ever set the NO_MSI flag on a non-root bus.
913 **/
914static
915int pci_msi_supported(struct pci_dev * dev)
916{
917 struct pci_bus *bus;
918
919 if (!pci_msi_enable || !dev || dev->no_msi)
920 return -EINVAL;
921
922 /* check MSI flags of all parent busses */
923 for (bus = dev->bus; bus; bus = bus->parent)
924 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
925 return -EINVAL;
926
927 return 0;
928}
929
930/**
904 * pci_enable_msi - configure device's MSI capability structure 931 * pci_enable_msi - configure device's MSI capability structure
905 * @dev: pointer to the pci_dev data structure of MSI device function 932 * @dev: pointer to the pci_dev data structure of MSI device function
906 * 933 *
@@ -912,19 +939,11 @@ static int msix_capability_init(struct pci_dev *dev,
912 **/ 939 **/
913int pci_enable_msi(struct pci_dev* dev) 940int pci_enable_msi(struct pci_dev* dev)
914{ 941{
915 struct pci_bus *bus; 942 int pos, temp, status;
916 int pos, temp, status = -EINVAL;
917 u16 control; 943 u16 control;
918 944
919 if (!pci_msi_enable || !dev) 945 if (pci_msi_supported(dev) < 0)
920 return status; 946 return -EINVAL;
921
922 if (dev->no_msi)
923 return status;
924
925 for (bus = dev->bus; bus; bus = bus->parent)
926 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
927 return -EINVAL;
928 947
929 temp = dev->irq; 948 temp = dev->irq;
930 949
@@ -1134,22 +1153,14 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
1134 **/ 1153 **/
1135int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) 1154int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
1136{ 1155{
1137 struct pci_bus *bus;
1138 int status, pos, nr_entries, free_vectors; 1156 int status, pos, nr_entries, free_vectors;
1139 int i, j, temp; 1157 int i, j, temp;
1140 u16 control; 1158 u16 control;
1141 unsigned long flags; 1159 unsigned long flags;
1142 1160
1143 if (!pci_msi_enable || !dev || !entries) 1161 if (!entries || pci_msi_supported(dev) < 0)
1144 return -EINVAL; 1162 return -EINVAL;
1145 1163
1146 if (dev->no_msi)
1147 return -EINVAL;
1148
1149 for (bus = dev->bus; bus; bus = bus->parent)
1150 if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
1151 return -EINVAL;
1152
1153 status = msi_init(); 1164 status = msi_init();
1154 if (status < 0) 1165 if (status < 0)
1155 return status; 1166 return status;