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; |
