aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2012-03-05 03:20:08 -0500
committerIngo Molnar <mingo@elte.hu>2012-03-05 03:20:08 -0500
commit737f24bda723fdf89ecaacb99fa2bf5683c32799 (patch)
tree35495fff3e9956679cb5468e74e6814c8e44ee66 /kernel/irq
parent8eedce996556d7d06522cd3a0e6069141c8dffe0 (diff)
parentb7c924274c456499264d1cfa3d44063bb11eb5db (diff)
Merge branch 'perf/urgent' into perf/core
Conflicts: tools/perf/builtin-record.c tools/perf/builtin-top.c tools/perf/perf.h tools/perf/util/top.h Merge reason: resolve these cherry-picking conflicts. Signed-off-by: Ingo Molnar <mingo@elte.hu>
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.c2
4 files changed, 37 insertions, 13 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 fc418249f01f..838687ed802a 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -159,19 +159,22 @@ static void irq_state_set_masked(struct irq_desc *desc)
159 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); 159 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
160} 160}
161 161
162int irq_startup(struct irq_desc *desc) 162int irq_startup(struct irq_desc *desc, bool resend)
163{ 163{
164 int ret = 0;
165
164 irq_state_clr_disabled(desc); 166 irq_state_clr_disabled(desc);
165 desc->depth = 0; 167 desc->depth = 0;
166 168
167 if (desc->irq_data.chip->irq_startup) { 169 if (desc->irq_data.chip->irq_startup) {
168 int ret = desc->irq_data.chip->irq_startup(&desc->irq_data); 170 ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
169 irq_state_clr_masked(desc); 171 irq_state_clr_masked(desc);
170 return ret; 172 } else {
173 irq_enable(desc);
171 } 174 }
172 175 if (resend)
173 irq_enable(desc); 176 check_irq_resend(desc, desc->irq_data.irq);
174 return 0; 177 return ret;
175} 178}
176 179
177void irq_shutdown(struct irq_desc *desc) 180void irq_shutdown(struct irq_desc *desc)
@@ -332,6 +335,24 @@ out_unlock:
332} 335}
333EXPORT_SYMBOL_GPL(handle_simple_irq); 336EXPORT_SYMBOL_GPL(handle_simple_irq);
334 337
338/*
339 * Called unconditionally from handle_level_irq() and only for oneshot
340 * interrupts from handle_fasteoi_irq()
341 */
342static void cond_unmask_irq(struct irq_desc *desc)
343{
344 /*
345 * We need to unmask in the following cases:
346 * - Standard level irq (IRQF_ONESHOT is not set)
347 * - Oneshot irq which did not wake the thread (caused by a
348 * spurious interrupt or a primary handler handling it
349 * completely).
350 */
351 if (!irqd_irq_disabled(&desc->irq_data) &&
352 irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot)
353 unmask_irq(desc);
354}
355
335/** 356/**
336 * handle_level_irq - Level type irq handler 357 * handle_level_irq - Level type irq handler
337 * @irq: the interrupt number 358 * @irq: the interrupt number
@@ -364,8 +385,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
364 385
365 handle_irq_event(desc); 386 handle_irq_event(desc);
366 387
367 if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT)) 388 cond_unmask_irq(desc);
368 unmask_irq(desc); 389
369out_unlock: 390out_unlock:
370 raw_spin_unlock(&desc->lock); 391 raw_spin_unlock(&desc->lock);
371} 392}
@@ -419,6 +440,9 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
419 preflow_handler(desc); 440 preflow_handler(desc);
420 handle_irq_event(desc); 441 handle_irq_event(desc);
421 442
443 if (desc->istate & IRQS_ONESHOT)
444 cond_unmask_irq(desc);
445
422out_eoi: 446out_eoi:
423 desc->irq_data.chip->irq_eoi(&desc->irq_data); 447 desc->irq_data.chip->irq_eoi(&desc->irq_data);
424out_unlock: 448out_unlock:
@@ -627,7 +651,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
627 irq_settings_set_noprobe(desc); 651 irq_settings_set_noprobe(desc);
628 irq_settings_set_norequest(desc); 652 irq_settings_set_norequest(desc);
629 irq_settings_set_nothread(desc); 653 irq_settings_set_nothread(desc);
630 irq_startup(desc); 654 irq_startup(desc, true);
631 } 655 }
632out: 656out:
633 irq_put_desc_busunlock(desc, flags); 657 irq_put_desc_busunlock(desc, flags);
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index b7952316016a..40378ff877e7 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -67,7 +67,7 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
67extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); 67extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
68extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); 68extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
69 69
70extern int irq_startup(struct irq_desc *desc); 70extern int irq_startup(struct irq_desc *desc, bool resend);
71extern void irq_shutdown(struct irq_desc *desc); 71extern void irq_shutdown(struct irq_desc *desc);
72extern void irq_enable(struct irq_desc *desc); 72extern void irq_enable(struct irq_desc *desc);
73extern void irq_disable(struct irq_desc *desc); 73extern void irq_disable(struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a9a9dbe49fea..32313c084442 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1027,7 +1027,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
1027 desc->istate |= IRQS_ONESHOT; 1027 desc->istate |= IRQS_ONESHOT;
1028 1028
1029 if (irq_settings_can_autoenable(desc)) 1029 if (irq_settings_can_autoenable(desc))
1030 irq_startup(desc); 1030 irq_startup(desc, true);
1031 else 1031 else
1032 /* Undo nested disables: */ 1032 /* Undo nested disables: */
1033 desc->depth = 1; 1033 desc->depth = 1;