aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 23:33:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 23:33:19 -0400
commit471368557a734c6c486ee757952c902b36e7fd01 (patch)
treef192a77d2cb70b1d135e7be62418806e8c590a3e
parentcb60e3e65c1b96a4d6444a7a13dc7dd48bc15a2b (diff)
parente0d8ffd1df44518cb9ac9b1807d1f13cc100fc2f (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/Kconfig2
-rw-r--r--arch/hexagon/Kconfig2
-rw-r--r--include/linux/interrupt.h8
-rw-r--r--kernel/irq/chip.c4
-rw-r--r--kernel/irq/manage.c46
-rw-r--r--kernel/irq/pm.c7
-rw-r--r--kernel/irq/resend.c7
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 */
108struct irqaction { 108struct 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
1117mismatch: 1134mismatch:
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
1128out_mask: 1144out_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) {