diff options
| -rw-r--r-- | drivers/pci/msi.c | 43 | ||||
| -rw-r--r-- | drivers/pci/msi.h | 2 | ||||
| -rw-r--r-- | include/linux/irq.h | 7 | ||||
| -rw-r--r-- | kernel/irq/chip.c | 7 |
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 | ||
| 189 | static unsigned int startup_msi_irq_wo_maskbit(unsigned int irq) | 189 | static 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 | ||
| 213 | static void shutdown_msi_irq(unsigned int irq) | 201 | static 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 | ||
| 225 | static void end_msi_irq_wo_maskbit(unsigned int irq) | 205 | static 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 | **/ |
| 1073 | void msi_remove_pci_irq_vectors(struct pci_dev* dev) | 1050 | void 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, | |||
| 372 | extern int create_irq(void); | 372 | extern int create_irq(void); |
| 373 | extern void destroy_irq(unsigned int irq); | 373 | extern void destroy_irq(unsigned int irq); |
| 374 | 374 | ||
| 375 | /* Test to see if a driver has successfully requested an irq */ | ||
| 376 | static 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 */ |
| 376 | extern void dynamic_irq_init(unsigned int irq); | 383 | extern void dynamic_irq_init(unsigned int irq); |
| 377 | extern void dynamic_irq_cleanup(unsigned int irq); | 384 | extern 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); |
