aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:56 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:29 -0400
commit1f80025e624bb14fefadfef7e80fbfb9740d4714 (patch)
tree1d6f18ebd2855e882213922036d8df8cd7e88db4
parent8b955b0dddb35e398b07e217a81f8bd49400796f (diff)
[PATCH] msi: simplify msi sanity checks by adding with generic irq code
Currently msi.c is doing sanity checks that make certain before an irq is destroyed it has no more users. By adding irq_has_action I can perform the test is a generic way, instead of relying on a msi specific data structure. By performing the core check in dynamic_irq_cleanup I ensure every user of dynamic irqs has a test present and we don't free resources that are in use. In msi.c this allows me to kill the attrib.state member of msi_desc and all of the assciated code to maintain it. To keep from freeing data structures when irq cleanup code is called to soon changing dyanamic_irq_cleanup is insufficient because there are msi specific data structures that are also not safe to free. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Tony Luck <tony.luck@intel.com> Cc: Andi Kleen <ak@suse.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Greg KH <greg@kroah.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/pci/msi.c43
-rw-r--r--drivers/pci/msi.h2
-rw-r--r--include/linux/irq.h7
-rw-r--r--kernel/irq/chip.c7
4 files changed, 23 insertions, 36 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index da2c6c2b6b11..e3ba3963988c 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -188,18 +188,6 @@ static void unmask_MSI_irq(unsigned int irq)
188 188
189static unsigned int startup_msi_irq_wo_maskbit(unsigned int irq) 189static unsigned int startup_msi_irq_wo_maskbit(unsigned int irq)
190{ 190{
191 struct msi_desc *entry;
192 unsigned long flags;
193
194 spin_lock_irqsave(&msi_lock, flags);
195 entry = msi_desc[irq];
196 if (!entry || !entry->dev) {
197 spin_unlock_irqrestore(&msi_lock, flags);
198 return 0;
199 }
200 entry->msi_attrib.state = 1; /* Mark it active */
201 spin_unlock_irqrestore(&msi_lock, flags);
202
203 return 0; /* never anything pending */ 191 return 0; /* never anything pending */
204} 192}
205 193
@@ -212,14 +200,6 @@ static unsigned int startup_msi_irq_w_maskbit(unsigned int irq)
212 200
213static void shutdown_msi_irq(unsigned int irq) 201static void shutdown_msi_irq(unsigned int irq)
214{ 202{
215 struct msi_desc *entry;
216 unsigned long flags;
217
218 spin_lock_irqsave(&msi_lock, flags);
219 entry = msi_desc[irq];
220 if (entry && entry->dev)
221 entry->msi_attrib.state = 0; /* Mark it not active */
222 spin_unlock_irqrestore(&msi_lock, flags);
223} 203}
224 204
225static void end_msi_irq_wo_maskbit(unsigned int irq) 205static void end_msi_irq_wo_maskbit(unsigned int irq)
@@ -671,7 +651,6 @@ static int msi_capability_init(struct pci_dev *dev)
671 entry->link.head = irq; 651 entry->link.head = irq;
672 entry->link.tail = irq; 652 entry->link.tail = irq;
673 entry->msi_attrib.type = PCI_CAP_ID_MSI; 653 entry->msi_attrib.type = PCI_CAP_ID_MSI;
674 entry->msi_attrib.state = 0; /* Mark it not active */
675 entry->msi_attrib.is_64 = is_64bit_address(control); 654 entry->msi_attrib.is_64 = is_64bit_address(control);
676 entry->msi_attrib.entry_nr = 0; 655 entry->msi_attrib.entry_nr = 0;
677 entry->msi_attrib.maskbit = is_mask_bit_support(control); 656 entry->msi_attrib.maskbit = is_mask_bit_support(control);
@@ -744,7 +723,6 @@ static int msix_capability_init(struct pci_dev *dev,
744 j = entries[i].entry; 723 j = entries[i].entry;
745 entries[i].vector = irq; 724 entries[i].vector = irq;
746 entry->msi_attrib.type = PCI_CAP_ID_MSIX; 725 entry->msi_attrib.type = PCI_CAP_ID_MSIX;
747 entry->msi_attrib.state = 0; /* Mark it not active */
748 entry->msi_attrib.is_64 = 1; 726 entry->msi_attrib.is_64 = 1;
749 entry->msi_attrib.entry_nr = j; 727 entry->msi_attrib.entry_nr = j;
750 entry->msi_attrib.maskbit = 1; 728 entry->msi_attrib.maskbit = 1;
@@ -897,12 +875,12 @@ void pci_disable_msi(struct pci_dev* dev)
897 spin_unlock_irqrestore(&msi_lock, flags); 875 spin_unlock_irqrestore(&msi_lock, flags);
898 return; 876 return;
899 } 877 }
900 if (entry->msi_attrib.state) { 878 if (irq_has_action(dev->irq)) {
901 spin_unlock_irqrestore(&msi_lock, flags); 879 spin_unlock_irqrestore(&msi_lock, flags);
902 printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " 880 printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without "
903 "free_irq() on MSI irq %d\n", 881 "free_irq() on MSI irq %d\n",
904 pci_name(dev), dev->irq); 882 pci_name(dev), dev->irq);
905 BUG_ON(entry->msi_attrib.state > 0); 883 BUG_ON(irq_has_action(dev->irq));
906 } else { 884 } else {
907 default_irq = entry->msi_attrib.default_irq; 885 default_irq = entry->msi_attrib.default_irq;
908 spin_unlock_irqrestore(&msi_lock, flags); 886 spin_unlock_irqrestore(&msi_lock, flags);
@@ -1035,17 +1013,16 @@ void pci_disable_msix(struct pci_dev* dev)
1035 1013
1036 temp = dev->irq; 1014 temp = dev->irq;
1037 if (!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { 1015 if (!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) {
1038 int state, irq, head, tail = 0, warning = 0; 1016 int irq, head, tail = 0, warning = 0;
1039 unsigned long flags; 1017 unsigned long flags;
1040 1018
1041 irq = head = dev->irq; 1019 irq = head = dev->irq;
1042 dev->irq = temp; /* Restore pin IRQ */ 1020 dev->irq = temp; /* Restore pin IRQ */
1043 while (head != tail) { 1021 while (head != tail) {
1044 spin_lock_irqsave(&msi_lock, flags); 1022 spin_lock_irqsave(&msi_lock, flags);
1045 state = msi_desc[irq]->msi_attrib.state;
1046 tail = msi_desc[irq]->link.tail; 1023 tail = msi_desc[irq]->link.tail;
1047 spin_unlock_irqrestore(&msi_lock, flags); 1024 spin_unlock_irqrestore(&msi_lock, flags);
1048 if (state) 1025 if (irq_has_action(irq))
1049 warning = 1; 1026 warning = 1;
1050 else if (irq != head) /* Release MSI-X irq */ 1027 else if (irq != head) /* Release MSI-X irq */
1051 msi_free_irq(dev, irq); 1028 msi_free_irq(dev, irq);
@@ -1072,7 +1049,7 @@ void pci_disable_msix(struct pci_dev* dev)
1072 **/ 1049 **/
1073void msi_remove_pci_irq_vectors(struct pci_dev* dev) 1050void msi_remove_pci_irq_vectors(struct pci_dev* dev)
1074{ 1051{
1075 int state, pos, temp; 1052 int pos, temp;
1076 unsigned long flags; 1053 unsigned long flags;
1077 1054
1078 if (!pci_msi_enable || !dev) 1055 if (!pci_msi_enable || !dev)
@@ -1081,14 +1058,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
1081 temp = dev->irq; /* Save IOAPIC IRQ */ 1058 temp = dev->irq; /* Save IOAPIC IRQ */
1082 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 1059 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
1083 if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) { 1060 if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) {
1084 spin_lock_irqsave(&msi_lock, flags); 1061 if (irq_has_action(dev->irq)) {
1085 state = msi_desc[dev->irq]->msi_attrib.state;
1086 spin_unlock_irqrestore(&msi_lock, flags);
1087 if (state) {
1088 printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " 1062 printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
1089 "called without free_irq() on MSI irq %d\n", 1063 "called without free_irq() on MSI irq %d\n",
1090 pci_name(dev), dev->irq); 1064 pci_name(dev), dev->irq);
1091 BUG_ON(state > 0); 1065 BUG_ON(irq_has_action(dev->irq));
1092 } else /* Release MSI irq assigned to this device */ 1066 } else /* Release MSI irq assigned to this device */
1093 msi_free_irq(dev, dev->irq); 1067 msi_free_irq(dev, dev->irq);
1094 dev->irq = temp; /* Restore IOAPIC IRQ */ 1068 dev->irq = temp; /* Restore IOAPIC IRQ */
@@ -1101,11 +1075,10 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
1101 irq = head = dev->irq; 1075 irq = head = dev->irq;
1102 while (head != tail) { 1076 while (head != tail) {
1103 spin_lock_irqsave(&msi_lock, flags); 1077 spin_lock_irqsave(&msi_lock, flags);
1104 state = msi_desc[irq]->msi_attrib.state;
1105 tail = msi_desc[irq]->link.tail; 1078 tail = msi_desc[irq]->link.tail;
1106 base = msi_desc[irq]->mask_base; 1079 base = msi_desc[irq]->mask_base;
1107 spin_unlock_irqrestore(&msi_lock, flags); 1080 spin_unlock_irqrestore(&msi_lock, flags);
1108 if (state) 1081 if (irq_has_action(irq))
1109 warning = 1; 1082 warning = 1;
1110 else if (irq != head) /* Release MSI-X irq */ 1083 else if (irq != head) /* Release MSI-X irq */
1111 msi_free_irq(dev, irq); 1084 msi_free_irq(dev, irq);
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 435d05aae4ba..77823bfed5c1 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -53,7 +53,7 @@ struct msi_desc {
53 struct { 53 struct {
54 __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ 54 __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
55 __u8 maskbit : 1; /* mask-pending bit supported ? */ 55 __u8 maskbit : 1; /* mask-pending bit supported ? */
56 __u8 state : 1; /* {0: free, 1: busy} */ 56 __u8 unused : 1;
57 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */ 57 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
58 __u8 pos; /* Location of the msi capability */ 58 __u8 pos; /* Location of the msi capability */
59 __u16 entry_nr; /* specific enabled entry */ 59 __u16 entry_nr; /* specific enabled entry */
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 69855b23dff9..6f463606c318 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -372,6 +372,13 @@ set_irq_chained_handler(unsigned int irq,
372extern int create_irq(void); 372extern int create_irq(void);
373extern void destroy_irq(unsigned int irq); 373extern void destroy_irq(unsigned int irq);
374 374
375/* Test to see if a driver has successfully requested an irq */
376static inline int irq_has_action(unsigned int irq)
377{
378 struct irq_desc *desc = irq_desc + irq;
379 return desc->action != NULL;
380}
381
375/* Dynamic irq helper functions */ 382/* Dynamic irq helper functions */
376extern void dynamic_irq_init(unsigned int irq); 383extern void dynamic_irq_init(unsigned int irq);
377extern void dynamic_irq_cleanup(unsigned int irq); 384extern void dynamic_irq_cleanup(unsigned int irq);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 0dc24386dd99..4cf65f5c6a74 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -67,6 +67,13 @@ void dynamic_irq_cleanup(unsigned int irq)
67 67
68 desc = irq_desc + irq; 68 desc = irq_desc + irq;
69 spin_lock_irqsave(&desc->lock, flags); 69 spin_lock_irqsave(&desc->lock, flags);
70 if (desc->action) {
71 spin_unlock_irqrestore(&desc->lock, flags);
72 printk(KERN_ERR "Destroying IRQ%d without calling free_irq\n",
73 irq);
74 WARN_ON(1);
75 return;
76 }
70 desc->handle_irq = handle_bad_irq; 77 desc->handle_irq = handle_bad_irq;
71 desc->chip = &no_irq_chip; 78 desc->chip = &no_irq_chip;
72 spin_unlock_irqrestore(&desc->lock, flags); 79 spin_unlock_irqrestore(&desc->lock, flags);