aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2012-03-13 11:34:48 -0400
committerThomas Gleixner <tglx@linutronix.de>2012-03-13 11:35:16 -0400
commitdf8d291f28aa1e8437c8f7816328a6516379c71b (patch)
tree26ae585aa259584ddd0d9088933547c065c37086 /kernel/irq
parent5234ffb9f74cfa8993d174782bc861dd9b7b5bfb (diff)
parentfde7d9049e55ab85a390be7f415d74c9f62dd0f9 (diff)
Merge branch 'linus' into irq/core
Reason: Get upstream fixes integrated before further modifications. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/autoprobe.c4
-rw-r--r--kernel/irq/chip.c42
-rw-r--r--kernel/irq/internals.h2
-rw-r--r--kernel/irq/manage.c46
4 files changed, 75 insertions, 19 deletions
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c
index 342d8f44e401..0119b9d467ae 100644
--- a/kernel/irq/autoprobe.c
+++ b/kernel/irq/autoprobe.c
@@ -53,7 +53,7 @@ unsigned long probe_irq_on(void)
53 if (desc->irq_data.chip->irq_set_type) 53 if (desc->irq_data.chip->irq_set_type)
54 desc->irq_data.chip->irq_set_type(&desc->irq_data, 54 desc->irq_data.chip->irq_set_type(&desc->irq_data,
55 IRQ_TYPE_PROBE); 55 IRQ_TYPE_PROBE);
56 irq_startup(desc); 56 irq_startup(desc, false);
57 } 57 }
58 raw_spin_unlock_irq(&desc->lock); 58 raw_spin_unlock_irq(&desc->lock);
59 } 59 }
@@ -70,7 +70,7 @@ unsigned long probe_irq_on(void)
70 raw_spin_lock_irq(&desc->lock); 70 raw_spin_lock_irq(&desc->lock);
71 if (!desc->action && irq_settings_can_probe(desc)) { 71 if (!desc->action && irq_settings_can_probe(desc)) {
72 desc->istate |= IRQS_AUTODETECT | IRQS_WAITING; 72 desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
73 if (irq_startup(desc)) 73 if (irq_startup(desc, false))
74 desc->istate |= IRQS_PENDING; 74 desc->istate |= IRQS_PENDING;
75 } 75 }
76 raw_spin_unlock_irq(&desc->lock); 76 raw_spin_unlock_irq(&desc->lock);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 4dbc9c9d641b..25784d630a12 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -156,19 +156,22 @@ static void irq_state_set_masked(struct irq_desc *desc)
156 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); 156 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
157} 157}
158 158
159int irq_startup(struct irq_desc *desc) 159int irq_startup(struct irq_desc *desc, bool resend)
160{ 160{
161 int ret = 0;
162
161 irq_state_clr_disabled(desc); 163 irq_state_clr_disabled(desc);
162 desc->depth = 0; 164 desc->depth = 0;
163 165
164 if (desc->irq_data.chip->irq_startup) { 166 if (desc->irq_data.chip->irq_startup) {
165 int ret = desc->irq_data.chip->irq_startup(&desc->irq_data); 167 ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
166 irq_state_clr_masked(desc); 168 irq_state_clr_masked(desc);
167 return ret; 169 } else {
170 irq_enable(desc);
168 } 171 }
169 172 if (resend)
170 irq_enable(desc); 173 check_irq_resend(desc, desc->irq_data.irq);
171 return 0; 174 return ret;
172} 175}
173 176
174void irq_shutdown(struct irq_desc *desc) 177void irq_shutdown(struct irq_desc *desc)
@@ -329,6 +332,24 @@ out_unlock:
329} 332}
330EXPORT_SYMBOL_GPL(handle_simple_irq); 333EXPORT_SYMBOL_GPL(handle_simple_irq);
331 334
335/*
336 * Called unconditionally from handle_level_irq() and only for oneshot
337 * interrupts from handle_fasteoi_irq()
338 */
339static void cond_unmask_irq(struct irq_desc *desc)
340{
341 /*
342 * We need to unmask in the following cases:
343 * - Standard level irq (IRQF_ONESHOT is not set)
344 * - Oneshot irq which did not wake the thread (caused by a
345 * spurious interrupt or a primary handler handling it
346 * completely).
347 */
348 if (!irqd_irq_disabled(&desc->irq_data) &&
349 irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot)
350 unmask_irq(desc);
351}
352
332/** 353/**
333 * handle_level_irq - Level type irq handler 354 * handle_level_irq - Level type irq handler
334 * @irq: the interrupt number 355 * @irq: the interrupt number
@@ -361,8 +382,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
361 382
362 handle_irq_event(desc); 383 handle_irq_event(desc);
363 384
364 if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT)) 385 cond_unmask_irq(desc);
365 unmask_irq(desc); 386
366out_unlock: 387out_unlock:
367 raw_spin_unlock(&desc->lock); 388 raw_spin_unlock(&desc->lock);
368} 389}
@@ -416,6 +437,9 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
416 preflow_handler(desc); 437 preflow_handler(desc);
417 handle_irq_event(desc); 438 handle_irq_event(desc);
418 439
440 if (desc->istate & IRQS_ONESHOT)
441 cond_unmask_irq(desc);
442
419out_eoi: 443out_eoi:
420 desc->irq_data.chip->irq_eoi(&desc->irq_data); 444 desc->irq_data.chip->irq_eoi(&desc->irq_data);
421out_unlock: 445out_unlock:
@@ -624,7 +648,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
624 irq_settings_set_noprobe(desc); 648 irq_settings_set_noprobe(desc);
625 irq_settings_set_norequest(desc); 649 irq_settings_set_norequest(desc);
626 irq_settings_set_nothread(desc); 650 irq_settings_set_nothread(desc);
627 irq_startup(desc); 651 irq_startup(desc, true);
628 } 652 }
629out: 653out:
630 irq_put_desc_busunlock(desc, flags); 654 irq_put_desc_busunlock(desc, flags);
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 5c233e0ea2c3..8e5c56b3b7d9 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -65,7 +65,7 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
65extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); 65extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
66extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); 66extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
67 67
68extern int irq_startup(struct irq_desc *desc); 68extern int irq_startup(struct irq_desc *desc, bool resend);
69extern void irq_shutdown(struct irq_desc *desc); 69extern void irq_shutdown(struct irq_desc *desc);
70extern void irq_enable(struct irq_desc *desc); 70extern void irq_enable(struct irq_desc *desc);
71extern void irq_disable(struct irq_desc *desc); 71extern void irq_disable(struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a94466db73b2..1786cf7dac54 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -979,6 +979,11 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
979 979
980 /* add new interrupt at end of irq queue */ 980 /* add new interrupt at end of irq queue */
981 do { 981 do {
982 /*
983 * Or all existing action->thread_mask bits,
984 * so we can find the next zero bit for this
985 * new action.
986 */
982 thread_mask |= old->thread_mask; 987 thread_mask |= old->thread_mask;
983 old_ptr = &old->next; 988 old_ptr = &old->next;
984 old = *old_ptr; 989 old = *old_ptr;
@@ -987,14 +992,41 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
987 } 992 }
988 993
989 /* 994 /*
990 * Setup the thread mask for this irqaction. Unlikely to have 995 * Setup the thread mask for this irqaction for ONESHOT. For
991 * 32 resp 64 irqs sharing one line, but who knows. 996 * !ONESHOT irqs the thread mask is 0 so we can avoid a
997 * conditional in irq_wake_thread().
992 */ 998 */
993 if (new->flags & IRQF_ONESHOT && thread_mask == ~0UL) { 999 if (new->flags & IRQF_ONESHOT) {
994 ret = -EBUSY; 1000 /*
995 goto out_mask; 1001 * Unlikely to have 32 resp 64 irqs sharing one line,
1002 * but who knows.
1003 */
1004 if (thread_mask == ~0UL) {
1005 ret = -EBUSY;
1006 goto out_mask;
1007 }
1008 /*
1009 * The thread_mask for the action is or'ed to
1010 * desc->thread_active to indicate that the
1011 * IRQF_ONESHOT thread handler has been woken, but not
1012 * yet finished. The bit is cleared when a thread
1013 * completes. When all threads of a shared interrupt
1014 * line have completed desc->threads_active becomes
1015 * zero and the interrupt line is unmasked. See
1016 * handle.c:irq_wake_thread() for further information.
1017 *
1018 * If no thread is woken by primary (hard irq context)
1019 * interrupt handlers, then desc->threads_active is
1020 * also checked for zero to unmask the irq line in the
1021 * affected hard irq flow handlers
1022 * (handle_[fasteoi|level]_irq).
1023 *
1024 * The new action gets the first zero bit of
1025 * thread_mask assigned. See the loop above which or's
1026 * all existing action->thread_mask bits.
1027 */
1028 new->thread_mask = 1 << ffz(thread_mask);
996 } 1029 }
997 new->thread_mask = 1 << ffz(thread_mask);
998 1030
999 if (!shared) { 1031 if (!shared) {
1000 init_waitqueue_head(&desc->wait_for_threads); 1032 init_waitqueue_head(&desc->wait_for_threads);
@@ -1021,7 +1053,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
1021 desc->istate |= IRQS_ONESHOT; 1053 desc->istate |= IRQS_ONESHOT;
1022 1054
1023 if (irq_settings_can_autoenable(desc)) 1055 if (irq_settings_can_autoenable(desc))
1024 irq_startup(desc); 1056 irq_startup(desc, true);
1025 else 1057 else
1026 /* Undo nested disables: */ 1058 /* Undo nested disables: */
1027 desc->depth = 1; 1059 desc->depth = 1;