diff options
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r-- | drivers/pci/msi.c | 64 |
1 files changed, 34 insertions, 30 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a83c1f5735d6..27a057409eca 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -45,16 +45,10 @@ msi_register(struct msi_ops *ops) | |||
45 | return 0; | 45 | return 0; |
46 | } | 46 | } |
47 | 47 | ||
48 | static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags) | ||
49 | { | ||
50 | memset(p, 0, sizeof(struct msi_desc)); | ||
51 | } | ||
52 | |||
53 | static int msi_cache_init(void) | 48 | static int msi_cache_init(void) |
54 | { | 49 | { |
55 | msi_cachep = kmem_cache_create("msi_cache", | 50 | msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc), |
56 | sizeof(struct msi_desc), | 51 | 0, SLAB_HWCACHE_ALIGN, NULL, NULL); |
57 | 0, SLAB_HWCACHE_ALIGN, msi_cache_ctor, NULL); | ||
58 | if (!msi_cachep) | 52 | if (!msi_cachep) |
59 | return -ENOMEM; | 53 | return -ENOMEM; |
60 | 54 | ||
@@ -402,11 +396,10 @@ static struct msi_desc* alloc_msi_entry(void) | |||
402 | { | 396 | { |
403 | struct msi_desc *entry; | 397 | struct msi_desc *entry; |
404 | 398 | ||
405 | entry = kmem_cache_alloc(msi_cachep, SLAB_KERNEL); | 399 | entry = kmem_cache_zalloc(msi_cachep, GFP_KERNEL); |
406 | if (!entry) | 400 | if (!entry) |
407 | return NULL; | 401 | return NULL; |
408 | 402 | ||
409 | memset(entry, 0, sizeof(struct msi_desc)); | ||
410 | entry->link.tail = entry->link.head = 0; /* single message */ | 403 | entry->link.tail = entry->link.head = 0; /* single message */ |
411 | entry->dev = NULL; | 404 | entry->dev = NULL; |
412 | 405 | ||
@@ -901,6 +894,33 @@ static int msix_capability_init(struct pci_dev *dev, | |||
901 | } | 894 | } |
902 | 895 | ||
903 | /** | 896 | /** |
897 | * pci_msi_supported - check whether MSI may be enabled on device | ||
898 | * @dev: pointer to the pci_dev data structure of MSI device function | ||
899 | * | ||
900 | * MSI must be globally enabled and supported by the device and its root | ||
901 | * bus. But, the root bus is not easy to find since some architectures | ||
902 | * have virtual busses on top of the PCI hierarchy (for instance the | ||
903 | * hypertransport bus), while the actual bus where MSI must be supported | ||
904 | * is below. So we test the MSI flag on all parent busses and assume | ||
905 | * that no quirk will ever set the NO_MSI flag on a non-root bus. | ||
906 | **/ | ||
907 | static | ||
908 | int pci_msi_supported(struct pci_dev * dev) | ||
909 | { | ||
910 | struct pci_bus *bus; | ||
911 | |||
912 | if (!pci_msi_enable || !dev || dev->no_msi) | ||
913 | return -EINVAL; | ||
914 | |||
915 | /* check MSI flags of all parent busses */ | ||
916 | for (bus = dev->bus; bus; bus = bus->parent) | ||
917 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) | ||
918 | return -EINVAL; | ||
919 | |||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | /** | ||
904 | * pci_enable_msi - configure device's MSI capability structure | 924 | * pci_enable_msi - configure device's MSI capability structure |
905 | * @dev: pointer to the pci_dev data structure of MSI device function | 925 | * @dev: pointer to the pci_dev data structure of MSI device function |
906 | * | 926 | * |
@@ -912,19 +932,11 @@ static int msix_capability_init(struct pci_dev *dev, | |||
912 | **/ | 932 | **/ |
913 | int pci_enable_msi(struct pci_dev* dev) | 933 | int pci_enable_msi(struct pci_dev* dev) |
914 | { | 934 | { |
915 | struct pci_bus *bus; | 935 | int pos, temp, status; |
916 | int pos, temp, status = -EINVAL; | ||
917 | u16 control; | 936 | u16 control; |
918 | 937 | ||
919 | if (!pci_msi_enable || !dev) | 938 | if (pci_msi_supported(dev) < 0) |
920 | return status; | 939 | 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 | 940 | ||
929 | temp = dev->irq; | 941 | temp = dev->irq; |
930 | 942 | ||
@@ -1134,22 +1146,14 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec) | |||
1134 | **/ | 1146 | **/ |
1135 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | 1147 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) |
1136 | { | 1148 | { |
1137 | struct pci_bus *bus; | ||
1138 | int status, pos, nr_entries, free_vectors; | 1149 | int status, pos, nr_entries, free_vectors; |
1139 | int i, j, temp; | 1150 | int i, j, temp; |
1140 | u16 control; | 1151 | u16 control; |
1141 | unsigned long flags; | 1152 | unsigned long flags; |
1142 | 1153 | ||
1143 | if (!pci_msi_enable || !dev || !entries) | 1154 | if (!entries || pci_msi_supported(dev) < 0) |
1144 | return -EINVAL; | 1155 | return -EINVAL; |
1145 | 1156 | ||
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(); | 1157 | status = msi_init(); |
1154 | if (status < 0) | 1158 | if (status < 0) |
1155 | return status; | 1159 | return status; |