diff options
author | Ingo Molnar <mingo@elte.hu> | 2012-03-05 03:20:08 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2012-03-05 03:20:08 -0500 |
commit | 737f24bda723fdf89ecaacb99fa2bf5683c32799 (patch) | |
tree | 35495fff3e9956679cb5468e74e6814c8e44ee66 /kernel/irq | |
parent | 8eedce996556d7d06522cd3a0e6069141c8dffe0 (diff) | |
parent | b7c924274c456499264d1cfa3d44063bb11eb5db (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.c | 4 | ||||
-rw-r--r-- | kernel/irq/chip.c | 42 | ||||
-rw-r--r-- | kernel/irq/internals.h | 2 | ||||
-rw-r--r-- | kernel/irq/manage.c | 2 |
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 | ||
162 | int irq_startup(struct irq_desc *desc) | 162 | int 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 | ||
177 | void irq_shutdown(struct irq_desc *desc) | 180 | void irq_shutdown(struct irq_desc *desc) |
@@ -332,6 +335,24 @@ out_unlock: | |||
332 | } | 335 | } |
333 | EXPORT_SYMBOL_GPL(handle_simple_irq); | 336 | EXPORT_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 | */ | ||
342 | static 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 | |
369 | out_unlock: | 390 | out_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 | |||
422 | out_eoi: | 446 | out_eoi: |
423 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | 447 | desc->irq_data.chip->irq_eoi(&desc->irq_data); |
424 | out_unlock: | 448 | out_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 | } |
632 | out: | 656 | out: |
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, | |||
67 | extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); | 67 | extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); |
68 | extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); | 68 | extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); |
69 | 69 | ||
70 | extern int irq_startup(struct irq_desc *desc); | 70 | extern int irq_startup(struct irq_desc *desc, bool resend); |
71 | extern void irq_shutdown(struct irq_desc *desc); | 71 | extern void irq_shutdown(struct irq_desc *desc); |
72 | extern void irq_enable(struct irq_desc *desc); | 72 | extern void irq_enable(struct irq_desc *desc); |
73 | extern void irq_disable(struct irq_desc *desc); | 73 | extern 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; |