diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 23:33:19 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 23:33:19 -0400 |
| commit | 471368557a734c6c486ee757952c902b36e7fd01 (patch) | |
| tree | f192a77d2cb70b1d135e7be62418806e8c590a3e | |
| parent | cb60e3e65c1b96a4d6444a7a13dc7dd48bc15a2b (diff) | |
| parent | e0d8ffd1df44518cb9ac9b1807d1f13cc100fc2f (diff) | |
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core irq changes from Ingo Molnar:
"A collection of small fixes."
By Thomas Gleixner
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
hexagon: Remove select of not longer existing Kconfig switches
arm: Select core options instead of redefining them
genirq: Do not consider disabled wakeup irqs
genirq: Allow check_wakeup_irqs to notice level-triggered interrupts
genirq: Be more informative on irq type mismatch
genirq: Reject bogus threaded irq requests
genirq: Streamline irq_action
| -rw-r--r-- | arch/arm/Kconfig | 2 | ||||
| -rw-r--r-- | arch/hexagon/Kconfig | 2 | ||||
| -rw-r--r-- | include/linux/interrupt.h | 8 | ||||
| -rw-r--r-- | kernel/irq/chip.c | 4 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 46 | ||||
| -rw-r--r-- | kernel/irq/pm.c | 7 | ||||
| -rw-r--r-- | kernel/irq/resend.c | 7 |
7 files changed, 51 insertions, 25 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4305ae25652b..002b1c8da225 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -34,6 +34,8 @@ config ARM | |||
| 34 | select HARDIRQS_SW_RESEND | 34 | select HARDIRQS_SW_RESEND |
| 35 | select GENERIC_IRQ_PROBE | 35 | select GENERIC_IRQ_PROBE |
| 36 | select GENERIC_IRQ_SHOW | 36 | select GENERIC_IRQ_SHOW |
| 37 | select GENERIC_IRQ_PROBE | ||
| 38 | select HARDIRQS_SW_RESEND | ||
| 37 | select CPU_PM if (SUSPEND || CPU_IDLE) | 39 | select CPU_PM if (SUSPEND || CPU_IDLE) |
| 38 | select GENERIC_PCI_IOMAP | 40 | select GENERIC_PCI_IOMAP |
| 39 | select HAVE_BPF_JIT | 41 | select HAVE_BPF_JIT |
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index d2e4a3330336..22615dd02219 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig | |||
| @@ -18,8 +18,6 @@ config HEXAGON | |||
| 18 | select GENERIC_ATOMIC64 | 18 | select GENERIC_ATOMIC64 |
| 19 | select HAVE_PERF_EVENTS | 19 | select HAVE_PERF_EVENTS |
| 20 | select HAVE_GENERIC_HARDIRQS | 20 | select HAVE_GENERIC_HARDIRQS |
| 21 | select GENERIC_HARDIRQS_NO__DO_IRQ | ||
| 22 | select GENERIC_HARDIRQS_NO_DEPRECATED | ||
| 23 | # GENERIC_ALLOCATOR is used by dma_alloc_coherent() | 21 | # GENERIC_ALLOCATOR is used by dma_alloc_coherent() |
| 24 | select GENERIC_ALLOCATOR | 22 | select GENERIC_ALLOCATOR |
| 25 | select GENERIC_IRQ_SHOW | 23 | select GENERIC_IRQ_SHOW |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 2aea5d22db07..c91171599cb6 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
| @@ -93,27 +93,27 @@ typedef irqreturn_t (*irq_handler_t)(int, void *); | |||
| 93 | /** | 93 | /** |
| 94 | * struct irqaction - per interrupt action descriptor | 94 | * struct irqaction - per interrupt action descriptor |
| 95 | * @handler: interrupt handler function | 95 | * @handler: interrupt handler function |
| 96 | * @flags: flags (see IRQF_* above) | ||
| 97 | * @name: name of the device | 96 | * @name: name of the device |
| 98 | * @dev_id: cookie to identify the device | 97 | * @dev_id: cookie to identify the device |
| 99 | * @percpu_dev_id: cookie to identify the device | 98 | * @percpu_dev_id: cookie to identify the device |
| 100 | * @next: pointer to the next irqaction for shared interrupts | 99 | * @next: pointer to the next irqaction for shared interrupts |
| 101 | * @irq: interrupt number | 100 | * @irq: interrupt number |
| 102 | * @dir: pointer to the proc/irq/NN/name entry | 101 | * @flags: flags (see IRQF_* above) |
| 103 | * @thread_fn: interrupt handler function for threaded interrupts | 102 | * @thread_fn: interrupt handler function for threaded interrupts |
| 104 | * @thread: thread pointer for threaded interrupts | 103 | * @thread: thread pointer for threaded interrupts |
| 105 | * @thread_flags: flags related to @thread | 104 | * @thread_flags: flags related to @thread |
| 106 | * @thread_mask: bitmask for keeping track of @thread activity | 105 | * @thread_mask: bitmask for keeping track of @thread activity |
| 106 | * @dir: pointer to the proc/irq/NN/name entry | ||
| 107 | */ | 107 | */ |
| 108 | struct irqaction { | 108 | struct irqaction { |
| 109 | irq_handler_t handler; | 109 | irq_handler_t handler; |
| 110 | unsigned long flags; | ||
| 111 | void *dev_id; | 110 | void *dev_id; |
| 112 | void __percpu *percpu_dev_id; | 111 | void __percpu *percpu_dev_id; |
| 113 | struct irqaction *next; | 112 | struct irqaction *next; |
| 114 | int irq; | ||
| 115 | irq_handler_t thread_fn; | 113 | irq_handler_t thread_fn; |
| 116 | struct task_struct *thread; | 114 | struct task_struct *thread; |
| 115 | unsigned int irq; | ||
| 116 | unsigned int flags; | ||
| 117 | unsigned long thread_flags; | 117 | unsigned long thread_flags; |
| 118 | unsigned long thread_mask; | 118 | unsigned long thread_mask; |
| 119 | const char *name; | 119 | const char *name; |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 3914c1e03cff..fc275e4f629b 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -379,8 +379,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 379 | * If its disabled or no action available | 379 | * If its disabled or no action available |
| 380 | * keep it masked and get out of here | 380 | * keep it masked and get out of here |
| 381 | */ | 381 | */ |
| 382 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) | 382 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { |
| 383 | desc->istate |= IRQS_PENDING; | ||
| 383 | goto out_unlock; | 384 | goto out_unlock; |
| 385 | } | ||
| 384 | 386 | ||
| 385 | handle_irq_event(desc); | 387 | handle_irq_event(desc); |
| 386 | 388 | ||
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 89a3ea82569b..585f6381f8e4 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -565,8 +565,8 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
| 565 | * IRQF_TRIGGER_* but the PIC does not support multiple | 565 | * IRQF_TRIGGER_* but the PIC does not support multiple |
| 566 | * flow-types? | 566 | * flow-types? |
| 567 | */ | 567 | */ |
| 568 | pr_debug("No set_type function for IRQ %d (%s)\n", irq, | 568 | pr_debug("genirq: No set_type function for IRQ %d (%s)\n", irq, |
| 569 | chip ? (chip->name ? : "unknown") : "unknown"); | 569 | chip ? (chip->name ? : "unknown") : "unknown"); |
| 570 | return 0; | 570 | return 0; |
| 571 | } | 571 | } |
| 572 | 572 | ||
| @@ -600,7 +600,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
| 600 | ret = 0; | 600 | ret = 0; |
| 601 | break; | 601 | break; |
| 602 | default: | 602 | default: |
| 603 | pr_err("setting trigger mode %lu for irq %u failed (%pF)\n", | 603 | pr_err("genirq: Setting trigger mode %lu for irq %u failed (%pF)\n", |
| 604 | flags, irq, chip->irq_set_type); | 604 | flags, irq, chip->irq_set_type); |
| 605 | } | 605 | } |
| 606 | if (unmask) | 606 | if (unmask) |
| @@ -837,8 +837,7 @@ void exit_irq_thread(void) | |||
| 837 | 837 | ||
| 838 | action = kthread_data(tsk); | 838 | action = kthread_data(tsk); |
| 839 | 839 | ||
| 840 | printk(KERN_ERR | 840 | pr_err("genirq: exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n", |
| 841 | "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n", | ||
| 842 | tsk->comm ? tsk->comm : "", tsk->pid, action->irq); | 841 | tsk->comm ? tsk->comm : "", tsk->pid, action->irq); |
| 843 | 842 | ||
| 844 | desc = irq_to_desc(action->irq); | 843 | desc = irq_to_desc(action->irq); |
| @@ -878,7 +877,6 @@ static int | |||
| 878 | __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | 877 | __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) |
| 879 | { | 878 | { |
| 880 | struct irqaction *old, **old_ptr; | 879 | struct irqaction *old, **old_ptr; |
| 881 | const char *old_name = NULL; | ||
| 882 | unsigned long flags, thread_mask = 0; | 880 | unsigned long flags, thread_mask = 0; |
| 883 | int ret, nested, shared = 0; | 881 | int ret, nested, shared = 0; |
| 884 | cpumask_var_t mask; | 882 | cpumask_var_t mask; |
| @@ -972,10 +970,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 972 | */ | 970 | */ |
| 973 | if (!((old->flags & new->flags) & IRQF_SHARED) || | 971 | if (!((old->flags & new->flags) & IRQF_SHARED) || |
| 974 | ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) || | 972 | ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) || |
| 975 | ((old->flags ^ new->flags) & IRQF_ONESHOT)) { | 973 | ((old->flags ^ new->flags) & IRQF_ONESHOT)) |
| 976 | old_name = old->name; | ||
| 977 | goto mismatch; | 974 | goto mismatch; |
| 978 | } | ||
| 979 | 975 | ||
| 980 | /* All handlers must agree on per-cpuness */ | 976 | /* All handlers must agree on per-cpuness */ |
| 981 | if ((old->flags & IRQF_PERCPU) != | 977 | if ((old->flags & IRQF_PERCPU) != |
| @@ -1031,6 +1027,27 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 1031 | * all existing action->thread_mask bits. | 1027 | * all existing action->thread_mask bits. |
| 1032 | */ | 1028 | */ |
| 1033 | new->thread_mask = 1 << ffz(thread_mask); | 1029 | new->thread_mask = 1 << ffz(thread_mask); |
| 1030 | |||
| 1031 | } else if (new->handler == irq_default_primary_handler) { | ||
| 1032 | /* | ||
| 1033 | * The interrupt was requested with handler = NULL, so | ||
| 1034 | * we use the default primary handler for it. But it | ||
| 1035 | * does not have the oneshot flag set. In combination | ||
| 1036 | * with level interrupts this is deadly, because the | ||
| 1037 | * default primary handler just wakes the thread, then | ||
| 1038 | * the irq lines is reenabled, but the device still | ||
| 1039 | * has the level irq asserted. Rinse and repeat.... | ||
| 1040 | * | ||
| 1041 | * While this works for edge type interrupts, we play | ||
| 1042 | * it safe and reject unconditionally because we can't | ||
| 1043 | * say for sure which type this interrupt really | ||
| 1044 | * has. The type flags are unreliable as the | ||
| 1045 | * underlying chip implementation can override them. | ||
| 1046 | */ | ||
| 1047 | pr_err("genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq %d\n", | ||
| 1048 | irq); | ||
| 1049 | ret = -EINVAL; | ||
| 1050 | goto out_mask; | ||
| 1034 | } | 1051 | } |
| 1035 | 1052 | ||
| 1036 | if (!shared) { | 1053 | if (!shared) { |
| @@ -1078,7 +1095,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 1078 | 1095 | ||
| 1079 | if (nmsk != omsk) | 1096 | if (nmsk != omsk) |
| 1080 | /* hope the handler works with current trigger mode */ | 1097 | /* hope the handler works with current trigger mode */ |
| 1081 | pr_warning("IRQ %d uses trigger mode %u; requested %u\n", | 1098 | pr_warning("genirq: irq %d uses trigger mode %u; requested %u\n", |
| 1082 | irq, nmsk, omsk); | 1099 | irq, nmsk, omsk); |
| 1083 | } | 1100 | } |
| 1084 | 1101 | ||
| @@ -1115,14 +1132,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 1115 | return 0; | 1132 | return 0; |
| 1116 | 1133 | ||
| 1117 | mismatch: | 1134 | mismatch: |
| 1118 | #ifdef CONFIG_DEBUG_SHIRQ | ||
| 1119 | if (!(new->flags & IRQF_PROBE_SHARED)) { | 1135 | if (!(new->flags & IRQF_PROBE_SHARED)) { |
| 1120 | printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq); | 1136 | pr_err("genirq: Flags mismatch irq %d. %08x (%s) vs. %08x (%s)\n", |
| 1121 | if (old_name) | 1137 | irq, new->flags, new->name, old->flags, old->name); |
| 1122 | printk(KERN_ERR "current handler: %s\n", old_name); | 1138 | #ifdef CONFIG_DEBUG_SHIRQ |
| 1123 | dump_stack(); | 1139 | dump_stack(); |
| 1124 | } | ||
| 1125 | #endif | 1140 | #endif |
| 1141 | } | ||
| 1126 | ret = -EBUSY; | 1142 | ret = -EBUSY; |
| 1127 | 1143 | ||
| 1128 | out_mask: | 1144 | out_mask: |
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 15e53b1766a6..cb228bf21760 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c | |||
| @@ -103,8 +103,13 @@ int check_wakeup_irqs(void) | |||
| 103 | int irq; | 103 | int irq; |
| 104 | 104 | ||
| 105 | for_each_irq_desc(irq, desc) { | 105 | for_each_irq_desc(irq, desc) { |
| 106 | /* | ||
| 107 | * Only interrupts which are marked as wakeup source | ||
| 108 | * and have not been disabled before the suspend check | ||
| 109 | * can abort suspend. | ||
| 110 | */ | ||
| 106 | if (irqd_is_wakeup_set(&desc->irq_data)) { | 111 | if (irqd_is_wakeup_set(&desc->irq_data)) { |
| 107 | if (desc->istate & IRQS_PENDING) | 112 | if (desc->depth == 1 && desc->istate & IRQS_PENDING) |
| 108 | return -EBUSY; | 113 | return -EBUSY; |
| 109 | continue; | 114 | continue; |
| 110 | } | 115 | } |
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c index 14dd5761e8c9..6454db7b6a4d 100644 --- a/kernel/irq/resend.c +++ b/kernel/irq/resend.c | |||
| @@ -58,10 +58,13 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq) | |||
| 58 | /* | 58 | /* |
| 59 | * We do not resend level type interrupts. Level type | 59 | * We do not resend level type interrupts. Level type |
| 60 | * interrupts are resent by hardware when they are still | 60 | * interrupts are resent by hardware when they are still |
| 61 | * active. | 61 | * active. Clear the pending bit so suspend/resume does not |
| 62 | * get confused. | ||
| 62 | */ | 63 | */ |
| 63 | if (irq_settings_is_level(desc)) | 64 | if (irq_settings_is_level(desc)) { |
| 65 | desc->istate &= ~IRQS_PENDING; | ||
| 64 | return; | 66 | return; |
| 67 | } | ||
| 65 | if (desc->istate & IRQS_REPLAY) | 68 | if (desc->istate & IRQS_REPLAY) |
| 66 | return; | 69 | return; |
| 67 | if (desc->istate & IRQS_PENDING) { | 70 | if (desc->istate & IRQS_PENDING) { |
