Commit 7f1b1244e159a8490d7fb13667c6cb7e1e75046b

Authored by Paul Mundt
Committed by Thomas Gleixner
1 parent 770767787c

genirq: Support per-IRQ thread disabling.

This adds support for disabling threading on a per-IRQ basis via the IRQ
status instead of the IRQ flow, which is necessary for interrupts that
don't follow the natural IRQ flow channels, such as those that are
virtually created.

The new APIs added are simply:

	irq_set_thread()
	irq_set_nothread()

which follow the rest of the IRQ status routines.

Chained handlers also have IRQ_NOTHREAD set on them automatically, making
the lack of threading explicit rather than implicit. Subsequently, the
nothread flag can be viewed through the standard genirq debugging
facilities.

[ tglx: Fixed cleanup fallout ]

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Link: http://lkml.kernel.org/r/%3C20110406210135.GF18426%40linux-sh.org%3E
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Showing 5 changed files with 34 additions and 2 deletions Side-by-side Diff

... ... @@ -59,6 +59,7 @@
59 59 * IRQ_NOPROBE - Interrupt cannot be probed by autoprobing
60 60 * IRQ_NOREQUEST - Interrupt cannot be requested via
61 61 * request_irq()
  62 + * IRQ_NOTHREAD - Interrupt cannot be threaded
62 63 * IRQ_NOAUTOEN - Interrupt is not automatically enabled in
63 64 * request/setup_irq()
64 65 * IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set)
... ... @@ -85,6 +86,7 @@
85 86 IRQ_NO_BALANCING = (1 << 13),
86 87 IRQ_MOVE_PCNTXT = (1 << 14),
87 88 IRQ_NESTED_THREAD = (1 << 15),
  89 + IRQ_NOTHREAD = (1 << 16),
88 90 };
89 91  
90 92 #define IRQF_MODIFY_MASK \
... ... @@ -422,7 +424,7 @@
422 424 /*
423 425 * Set a highlevel chained flow handler for a given IRQ.
424 426 * (a chained handler is automatically enabled and set to
425   - * IRQ_NOREQUEST and IRQ_NOPROBE)
  427 + * IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
426 428 */
427 429 static inline void
428 430 irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
... ... @@ -450,6 +452,16 @@
450 452 static inline void irq_set_probe(unsigned int irq)
451 453 {
452 454 irq_modify_status(irq, IRQ_NOPROBE, 0);
  455 +}
  456 +
  457 +static inline void irq_set_nothread(unsigned int irq)
  458 +{
  459 + irq_modify_status(irq, 0, IRQ_NOTHREAD);
  460 +}
  461 +
  462 +static inline void irq_set_thread(unsigned int irq)
  463 +{
  464 + irq_modify_status(irq, IRQ_NOTHREAD, 0);
453 465 }
454 466  
455 467 static inline void irq_set_nested_thread(unsigned int irq, bool nest)
... ... @@ -573,6 +573,7 @@
573 573 if (handle != handle_bad_irq && is_chained) {
574 574 irq_settings_set_noprobe(desc);
575 575 irq_settings_set_norequest(desc);
  576 + irq_settings_set_nothread(desc);
576 577 irq_startup(desc);
577 578 }
578 579 out:
... ... @@ -27,6 +27,7 @@
27 27 P(IRQ_PER_CPU);
28 28 P(IRQ_NOPROBE);
29 29 P(IRQ_NOREQUEST);
  30 + P(IRQ_NOTHREAD);
30 31 P(IRQ_NOAUTOEN);
31 32  
32 33 PS(IRQS_AUTODETECT);
... ... @@ -900,7 +900,8 @@
900 900 */
901 901 new->handler = irq_nested_primary_handler;
902 902 } else {
903   - irq_setup_forced_threading(new);
  903 + if (irq_settings_can_thread(desc))
  904 + irq_setup_forced_threading(new);
904 905 }
905 906  
906 907 /*
kernel/irq/settings.h
... ... @@ -8,6 +8,7 @@
8 8 _IRQ_LEVEL = IRQ_LEVEL,
9 9 _IRQ_NOPROBE = IRQ_NOPROBE,
10 10 _IRQ_NOREQUEST = IRQ_NOREQUEST,
  11 + _IRQ_NOTHREAD = IRQ_NOTHREAD,
11 12 _IRQ_NOAUTOEN = IRQ_NOAUTOEN,
12 13 _IRQ_MOVE_PCNTXT = IRQ_MOVE_PCNTXT,
13 14 _IRQ_NO_BALANCING = IRQ_NO_BALANCING,
... ... @@ -20,6 +21,7 @@
20 21 #define IRQ_LEVEL GOT_YOU_MORON
21 22 #define IRQ_NOPROBE GOT_YOU_MORON
22 23 #define IRQ_NOREQUEST GOT_YOU_MORON
  24 +#define IRQ_NOTHREAD GOT_YOU_MORON
23 25 #define IRQ_NOAUTOEN GOT_YOU_MORON
24 26 #define IRQ_NESTED_THREAD GOT_YOU_MORON
25 27 #undef IRQF_MODIFY_MASK
... ... @@ -92,6 +94,21 @@
92 94 static inline void irq_settings_set_norequest(struct irq_desc *desc)
93 95 {
94 96 desc->status_use_accessors |= _IRQ_NOREQUEST;
  97 +}
  98 +
  99 +static inline bool irq_settings_can_thread(struct irq_desc *desc)
  100 +{
  101 + return !(desc->status_use_accessors & _IRQ_NOTHREAD);
  102 +}
  103 +
  104 +static inline void irq_settings_clr_nothread(struct irq_desc *desc)
  105 +{
  106 + desc->status_use_accessors &= ~_IRQ_NOTHREAD;
  107 +}
  108 +
  109 +static inline void irq_settings_set_nothread(struct irq_desc *desc)
  110 +{
  111 + desc->status_use_accessors |= _IRQ_NOTHREAD;
95 112 }
96 113  
97 114 static inline bool irq_settings_can_probe(struct irq_desc *desc)