aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorBrice Goglin <brice@myri.com>2006-08-31 01:55:07 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-26 20:43:52 -0400
commit24334a12533e9ac70dcb467ccd629f190afc5361 (patch)
treebf771331e8b657fd4f4e7170a4ad3dc437b8d514 /drivers/pci
parent3f79e107f72e8efa86cd2f21356692b712713b5c (diff)
MSI: Factorize common code in pci_msi_supported()
pci_enable_msi() and pci_enable_msix() use the same code to detect whether MSI might be enabled on this device. Factorize this code in pci_msi_supported(). And improve the documentation about the fact that only the root chipset must support MSI, but it is hard to find the root bus so we check all parent busses MSI flags. Signed-off-by: Brice Goglin <brice@myri.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci')
-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;