aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi.c
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 /drivers/pci/msi.c
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>
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r--drivers/pci/msi.c53
1 files changed, 8 insertions, 45 deletions
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