aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:35 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:27 -0400
commit92db6d10bc1bc43330a4c540fa5b64c83d9d865f (patch)
treed889ea4ba6d2e55a33d89f05d2b2222bed7788e7
parent38bc0361303535c86f6b67b151a541728d7bdae6 (diff)
[PATCH] genirq: msi: simplify the msi irq limit policy
Currently we attempt to predict how many irqs we will be able to allocate with msi using pci_vector_resources and some complicated accounting, and then we only allow each device as many irqs as we think are available on average. Only the s2io driver even takes advantage of this feature all other drivers have a fixed number of irqs they need and bail if they can't get them. pci_vector_resources is inaccurate if anyone ever frees an irq. The whole implmentation is racy. The current irq limit policy does not appear to make sense with current drivers. So I have simplified things. We can revisit this we we need a more sophisticated policy. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rajesh Shah <rajesh.shah@intel.com> Cc: Andi Kleen <ak@muc.de> Cc: "Protasevich, Natalie" <Natalie.Protasevich@UNISYS.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-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 4a8995c9c762..960f364cab6b 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 15c7c670da39..b30be7c48ba8 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 6d9de026e141..a32e75a4417e 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 3519eca50d8a..6793241f3884 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