aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/pci/irq.c30
-rw-r--r--arch/ia64/pci/pci.c9
-rw-r--r--drivers/pci/msi.c53
-rw-r--r--drivers/pci/msi.h11
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
1173int 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
814int 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;
29static int pci_msi_enable = 1; 29static int pci_msi_enable = 1;
30static int last_alloc_vector; 30static int last_alloc_vector;
31static int nr_released_vectors; 31static int nr_released_vectors;
32static int nr_reserved_vectors = NR_HP_RESERVED_VECTORS;
33static int nr_msix_devices;
34 32
35#ifndef CONFIG_X86_IO_APIC 33#ifndef CONFIG_X86_IO_APIC
36int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; 34int 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 **/
1071int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) 1062int 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
21extern int vector_irq[NR_VECTORS]; 11extern int vector_irq[NR_VECTORS];
22extern void (*interrupt[NR_IRQS])(void); 12extern void (*interrupt[NR_IRQS])(void);
23extern int pci_vector_resources(int last, int nr_released);
24 13
25/* 14/*
26 * MSI-X Address Register 15 * MSI-X Address Register