diff options
-rw-r--r-- | arch/i386/pci/irq.c | 30 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 9 | ||||
-rw-r--r-- | drivers/pci/msi.c | 53 | ||||
-rw-r--r-- | drivers/pci/msi.h | 11 |
4 files changed, 8 insertions, 95 deletions
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 4a8995c9c76..960f364cab6 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c | |||
@@ -1169,33 +1169,3 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
1169 | } | 1169 | } |
1170 | return 0; | 1170 | return 0; |
1171 | } | 1171 | } |
1172 | |||
1173 | int pci_vector_resources(int last, int nr_released) | ||
1174 | { | ||
1175 | int count = nr_released; | ||
1176 | |||
1177 | int next = last; | ||
1178 | int offset = (last % 8); | ||
1179 | |||
1180 | while (next < FIRST_SYSTEM_VECTOR) { | ||
1181 | next += 8; | ||
1182 | #ifdef CONFIG_X86_64 | ||
1183 | if (next == IA32_SYSCALL_VECTOR) | ||
1184 | continue; | ||
1185 | #else | ||
1186 | if (next == SYSCALL_VECTOR) | ||
1187 | continue; | ||
1188 | #endif | ||
1189 | count++; | ||
1190 | if (next >= FIRST_SYSTEM_VECTOR) { | ||
1191 | if (offset%8) { | ||
1192 | next = FIRST_DEVICE_VECTOR + offset; | ||
1193 | offset++; | ||
1194 | continue; | ||
1195 | } | ||
1196 | count--; | ||
1197 | } | ||
1198 | } | ||
1199 | |||
1200 | return count; | ||
1201 | } | ||
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 15c7c670da3..b30be7c48ba 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -810,12 +810,3 @@ pcibios_prep_mwi (struct pci_dev *dev) | |||
810 | } | 810 | } |
811 | return rc; | 811 | return rc; |
812 | } | 812 | } |
813 | |||
814 | int pci_vector_resources(int last, int nr_released) | ||
815 | { | ||
816 | int count = nr_released; | ||
817 | |||
818 | count += (IA64_LAST_DEVICE_VECTOR - last); | ||
819 | |||
820 | return count; | ||
821 | } | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 6d9de026e14..a32e75a4417 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -29,8 +29,6 @@ static kmem_cache_t* msi_cachep; | |||
29 | static int pci_msi_enable = 1; | 29 | static int pci_msi_enable = 1; |
30 | static int last_alloc_vector; | 30 | static int last_alloc_vector; |
31 | static int nr_released_vectors; | 31 | static int nr_released_vectors; |
32 | static int nr_reserved_vectors = NR_HP_RESERVED_VECTORS; | ||
33 | static int nr_msix_devices; | ||
34 | 32 | ||
35 | #ifndef CONFIG_X86_IO_APIC | 33 | #ifndef CONFIG_X86_IO_APIC |
36 | int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; | 34 | int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; |
@@ -534,11 +532,6 @@ void pci_scan_msi_device(struct pci_dev *dev) | |||
534 | { | 532 | { |
535 | if (!dev) | 533 | if (!dev) |
536 | return; | 534 | return; |
537 | |||
538 | if (pci_find_capability(dev, PCI_CAP_ID_MSIX) > 0) | ||
539 | nr_msix_devices++; | ||
540 | else if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0) | ||
541 | nr_reserved_vectors++; | ||
542 | } | 535 | } |
543 | 536 | ||
544 | #ifdef CONFIG_PM | 537 | #ifdef CONFIG_PM |
@@ -869,13 +862,19 @@ static int msix_capability_init(struct pci_dev *dev, | |||
869 | attach_msi_entry(entry, vector); | 862 | attach_msi_entry(entry, vector); |
870 | } | 863 | } |
871 | if (i != nvec) { | 864 | if (i != nvec) { |
865 | int avail = i - 1; | ||
872 | i--; | 866 | i--; |
873 | for (; i >= 0; i--) { | 867 | for (; i >= 0; i--) { |
874 | vector = (entries + i)->vector; | 868 | vector = (entries + i)->vector; |
875 | msi_free_vector(dev, vector, 0); | 869 | msi_free_vector(dev, vector, 0); |
876 | (entries + i)->vector = 0; | 870 | (entries + i)->vector = 0; |
877 | } | 871 | } |
878 | return -EBUSY; | 872 | /* If we had some success report the number of irqs |
873 | * we succeeded in setting up. | ||
874 | */ | ||
875 | if (avail <= 0) | ||
876 | avail = -EBUSY; | ||
877 | return avail; | ||
879 | } | 878 | } |
880 | /* Set MSI-X enabled bits */ | 879 | /* Set MSI-X enabled bits */ |
881 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | 880 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
@@ -954,14 +953,6 @@ int pci_enable_msi(struct pci_dev* dev) | |||
954 | return -EINVAL; | 953 | return -EINVAL; |
955 | } | 954 | } |
956 | status = msi_capability_init(dev); | 955 | status = msi_capability_init(dev); |
957 | if (!status) { | ||
958 | if (!pos) | ||
959 | nr_reserved_vectors--; /* Only MSI capable */ | ||
960 | else if (nr_msix_devices > 0) | ||
961 | nr_msix_devices--; /* Both MSI and MSI-X capable, | ||
962 | but choose enabling MSI */ | ||
963 | } | ||
964 | |||
965 | return status; | 956 | return status; |
966 | } | 957 | } |
967 | 958 | ||
@@ -1070,10 +1061,9 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) | |||
1070 | **/ | 1061 | **/ |
1071 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | 1062 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) |
1072 | { | 1063 | { |
1073 | int status, pos, nr_entries, free_vectors; | 1064 | int status, pos, nr_entries; |
1074 | int i, j, temp; | 1065 | int i, j, temp; |
1075 | u16 control; | 1066 | u16 control; |
1076 | unsigned long flags; | ||
1077 | 1067 | ||
1078 | if (!entries || pci_msi_supported(dev) < 0) | 1068 | if (!entries || pci_msi_supported(dev) < 0) |
1079 | return -EINVAL; | 1069 | return -EINVAL; |
@@ -1112,34 +1102,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
1112 | dev->irq = temp; | 1102 | dev->irq = temp; |
1113 | return -EINVAL; | 1103 | return -EINVAL; |
1114 | } | 1104 | } |
1115 | |||
1116 | spin_lock_irqsave(&msi_lock, flags); | ||
1117 | /* | ||
1118 | * msi_lock is provided to ensure that enough vectors resources are | ||
1119 | * available before granting. | ||
1120 | */ | ||
1121 | free_vectors = pci_vector_resources(last_alloc_vector, | ||
1122 | nr_released_vectors); | ||
1123 | /* Ensure that each MSI/MSI-X device has one vector reserved by | ||
1124 | default to avoid any MSI-X driver to take all available | ||
1125 | resources */ | ||
1126 | free_vectors -= nr_reserved_vectors; | ||
1127 | /* Find the average of free vectors among MSI-X devices */ | ||
1128 | if (nr_msix_devices > 0) | ||
1129 | free_vectors /= nr_msix_devices; | ||
1130 | spin_unlock_irqrestore(&msi_lock, flags); | ||
1131 | |||
1132 | if (nvec > free_vectors) { | ||
1133 | if (free_vectors > 0) | ||
1134 | return free_vectors; | ||
1135 | else | ||
1136 | return -EBUSY; | ||
1137 | } | ||
1138 | |||
1139 | status = msix_capability_init(dev, entries, nvec); | 1105 | status = msix_capability_init(dev, entries, nvec); |
1140 | if (!status && nr_msix_devices > 0) | ||
1141 | nr_msix_devices--; | ||
1142 | |||
1143 | return status; | 1106 | return status; |
1144 | } | 1107 | } |
1145 | 1108 | ||
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 3519eca50d8..6793241f388 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
@@ -8,19 +8,8 @@ | |||
8 | 8 | ||
9 | #include <asm/msi.h> | 9 | #include <asm/msi.h> |
10 | 10 | ||
11 | /* | ||
12 | * Assume the maximum number of hot plug slots supported by the system is about | ||
13 | * ten. The worstcase is that each of these slots is hot-added with a device, | ||
14 | * which has two MSI/MSI-X capable functions. To avoid any MSI-X driver, which | ||
15 | * attempts to request all available vectors, NR_HP_RESERVED_VECTORS is defined | ||
16 | * as below to ensure at least one message is assigned to each detected MSI/ | ||
17 | * MSI-X device function. | ||
18 | */ | ||
19 | #define NR_HP_RESERVED_VECTORS 20 | ||
20 | |||
21 | extern int vector_irq[NR_VECTORS]; | 11 | extern int vector_irq[NR_VECTORS]; |
22 | extern void (*interrupt[NR_IRQS])(void); | 12 | extern void (*interrupt[NR_IRQS])(void); |
23 | extern int pci_vector_resources(int last, int nr_released); | ||
24 | 13 | ||
25 | /* | 14 | /* |
26 | * MSI-X Address Register | 15 | * MSI-X Address Register |