diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-19 20:30:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-19 20:30:15 -0400 |
commit | acd30250d7d0f495685d1c7c6184636a22fcdf7f (patch) | |
tree | 40f4e7e092de434c49a5f67f27ff1d3bf71000f9 | |
parent | 6595b4a940c4c447b619ab5268378ed03e632694 (diff) | |
parent | edf76f8307c350bcb81f0c760118a991b3e62956 (diff) |
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
irq: Export functions to allow modular irq drivers
genirq: Uninline and sanity check generic_handle_irq()
genirq: Remove pointless ifdefs
genirq: Make generic irq chip depend on CONFIG_GENERIC_IRQ_CHIP
genirq: Add chip suspend and resume callbacks
genirq: Implement a generic interrupt chip
genirq: Support per-IRQ thread disabling.
genirq: irq_desc: Document preflow_handler and affinity_hint
genirq: Update DocBook comments
genirq: Forgotten updates/deletions after removal of compat code
-rw-r--r-- | Documentation/DocBook/genericirq.tmpl | 82 | ||||
-rw-r--r-- | include/linux/irq.h | 179 | ||||
-rw-r--r-- | include/linux/irqdesc.h | 11 | ||||
-rw-r--r-- | kernel/irq/Kconfig | 4 | ||||
-rw-r--r-- | kernel/irq/Makefile | 1 | ||||
-rw-r--r-- | kernel/irq/chip.c | 3 | ||||
-rw-r--r-- | kernel/irq/debug.h | 1 | ||||
-rw-r--r-- | kernel/irq/generic-chip.c | 354 | ||||
-rw-r--r-- | kernel/irq/irqdesc.c | 22 | ||||
-rw-r--r-- | kernel/irq/manage.c | 3 | ||||
-rw-r--r-- | kernel/irq/settings.h | 17 |
11 files changed, 613 insertions, 64 deletions
diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl index fb10fd08c05c..b3422341d65c 100644 --- a/Documentation/DocBook/genericirq.tmpl +++ b/Documentation/DocBook/genericirq.tmpl | |||
@@ -191,8 +191,8 @@ | |||
191 | <para> | 191 | <para> |
192 | Whenever an interrupt triggers, the lowlevel arch code calls into | 192 | Whenever an interrupt triggers, the lowlevel arch code calls into |
193 | the generic interrupt code by calling desc->handle_irq(). | 193 | the generic interrupt code by calling desc->handle_irq(). |
194 | This highlevel IRQ handling function only uses desc->chip primitives | 194 | This highlevel IRQ handling function only uses desc->irq_data.chip |
195 | referenced by the assigned chip descriptor structure. | 195 | primitives referenced by the assigned chip descriptor structure. |
196 | </para> | 196 | </para> |
197 | </sect1> | 197 | </sect1> |
198 | <sect1 id="Highlevel_Driver_API"> | 198 | <sect1 id="Highlevel_Driver_API"> |
@@ -206,11 +206,11 @@ | |||
206 | <listitem><para>enable_irq()</para></listitem> | 206 | <listitem><para>enable_irq()</para></listitem> |
207 | <listitem><para>disable_irq_nosync() (SMP only)</para></listitem> | 207 | <listitem><para>disable_irq_nosync() (SMP only)</para></listitem> |
208 | <listitem><para>synchronize_irq() (SMP only)</para></listitem> | 208 | <listitem><para>synchronize_irq() (SMP only)</para></listitem> |
209 | <listitem><para>set_irq_type()</para></listitem> | 209 | <listitem><para>irq_set_irq_type()</para></listitem> |
210 | <listitem><para>set_irq_wake()</para></listitem> | 210 | <listitem><para>irq_set_irq_wake()</para></listitem> |
211 | <listitem><para>set_irq_data()</para></listitem> | 211 | <listitem><para>irq_set_handler_data()</para></listitem> |
212 | <listitem><para>set_irq_chip()</para></listitem> | 212 | <listitem><para>irq_set_chip()</para></listitem> |
213 | <listitem><para>set_irq_chip_data()</para></listitem> | 213 | <listitem><para>irq_set_chip_data()</para></listitem> |
214 | </itemizedlist> | 214 | </itemizedlist> |
215 | See the autogenerated function documentation for details. | 215 | See the autogenerated function documentation for details. |
216 | </para> | 216 | </para> |
@@ -225,6 +225,8 @@ | |||
225 | <listitem><para>handle_fasteoi_irq</para></listitem> | 225 | <listitem><para>handle_fasteoi_irq</para></listitem> |
226 | <listitem><para>handle_simple_irq</para></listitem> | 226 | <listitem><para>handle_simple_irq</para></listitem> |
227 | <listitem><para>handle_percpu_irq</para></listitem> | 227 | <listitem><para>handle_percpu_irq</para></listitem> |
228 | <listitem><para>handle_edge_eoi_irq</para></listitem> | ||
229 | <listitem><para>handle_bad_irq</para></listitem> | ||
228 | </itemizedlist> | 230 | </itemizedlist> |
229 | The interrupt flow handlers (either predefined or architecture | 231 | The interrupt flow handlers (either predefined or architecture |
230 | specific) are assigned to specific interrupts by the architecture | 232 | specific) are assigned to specific interrupts by the architecture |
@@ -241,13 +243,13 @@ | |||
241 | <programlisting> | 243 | <programlisting> |
242 | default_enable(struct irq_data *data) | 244 | default_enable(struct irq_data *data) |
243 | { | 245 | { |
244 | desc->chip->irq_unmask(data); | 246 | desc->irq_data.chip->irq_unmask(data); |
245 | } | 247 | } |
246 | 248 | ||
247 | default_disable(struct irq_data *data) | 249 | default_disable(struct irq_data *data) |
248 | { | 250 | { |
249 | if (!delay_disable(data)) | 251 | if (!delay_disable(data)) |
250 | desc->chip->irq_mask(data); | 252 | desc->irq_data.chip->irq_mask(data); |
251 | } | 253 | } |
252 | 254 | ||
253 | default_ack(struct irq_data *data) | 255 | default_ack(struct irq_data *data) |
@@ -284,9 +286,9 @@ noop(struct irq_data *data)) | |||
284 | <para> | 286 | <para> |
285 | The following control flow is implemented (simplified excerpt): | 287 | The following control flow is implemented (simplified excerpt): |
286 | <programlisting> | 288 | <programlisting> |
287 | desc->chip->irq_mask(); | 289 | desc->irq_data.chip->irq_mask_ack(); |
288 | handle_IRQ_event(desc->action); | 290 | handle_irq_event(desc->action); |
289 | desc->chip->irq_unmask(); | 291 | desc->irq_data.chip->irq_unmask(); |
290 | </programlisting> | 292 | </programlisting> |
291 | </para> | 293 | </para> |
292 | </sect3> | 294 | </sect3> |
@@ -300,8 +302,8 @@ desc->chip->irq_unmask(); | |||
300 | <para> | 302 | <para> |
301 | The following control flow is implemented (simplified excerpt): | 303 | The following control flow is implemented (simplified excerpt): |
302 | <programlisting> | 304 | <programlisting> |
303 | handle_IRQ_event(desc->action); | 305 | handle_irq_event(desc->action); |
304 | desc->chip->irq_eoi(); | 306 | desc->irq_data.chip->irq_eoi(); |
305 | </programlisting> | 307 | </programlisting> |
306 | </para> | 308 | </para> |
307 | </sect3> | 309 | </sect3> |
@@ -315,17 +317,17 @@ desc->chip->irq_eoi(); | |||
315 | The following control flow is implemented (simplified excerpt): | 317 | The following control flow is implemented (simplified excerpt): |
316 | <programlisting> | 318 | <programlisting> |
317 | if (desc->status & running) { | 319 | if (desc->status & running) { |
318 | desc->chip->irq_mask(); | 320 | desc->irq_data.chip->irq_mask_ack(); |
319 | desc->status |= pending | masked; | 321 | desc->status |= pending | masked; |
320 | return; | 322 | return; |
321 | } | 323 | } |
322 | desc->chip->irq_ack(); | 324 | desc->irq_data.chip->irq_ack(); |
323 | desc->status |= running; | 325 | desc->status |= running; |
324 | do { | 326 | do { |
325 | if (desc->status & masked) | 327 | if (desc->status & masked) |
326 | desc->chip->irq_unmask(); | 328 | desc->irq_data.chip->irq_unmask(); |
327 | desc->status &= ~pending; | 329 | desc->status &= ~pending; |
328 | handle_IRQ_event(desc->action); | 330 | handle_irq_event(desc->action); |
329 | } while (status & pending); | 331 | } while (status & pending); |
330 | desc->status &= ~running; | 332 | desc->status &= ~running; |
331 | </programlisting> | 333 | </programlisting> |
@@ -344,7 +346,7 @@ desc->status &= ~running; | |||
344 | <para> | 346 | <para> |
345 | The following control flow is implemented (simplified excerpt): | 347 | The following control flow is implemented (simplified excerpt): |
346 | <programlisting> | 348 | <programlisting> |
347 | handle_IRQ_event(desc->action); | 349 | handle_irq_event(desc->action); |
348 | </programlisting> | 350 | </programlisting> |
349 | </para> | 351 | </para> |
350 | </sect3> | 352 | </sect3> |
@@ -362,12 +364,29 @@ handle_IRQ_event(desc->action); | |||
362 | <para> | 364 | <para> |
363 | The following control flow is implemented (simplified excerpt): | 365 | The following control flow is implemented (simplified excerpt): |
364 | <programlisting> | 366 | <programlisting> |
365 | handle_IRQ_event(desc->action); | 367 | if (desc->irq_data.chip->irq_ack) |
366 | if (desc->chip->irq_eoi) | 368 | desc->irq_data.chip->irq_ack(); |
367 | desc->chip->irq_eoi(); | 369 | handle_irq_event(desc->action); |
370 | if (desc->irq_data.chip->irq_eoi) | ||
371 | desc->irq_data.chip->irq_eoi(); | ||
368 | </programlisting> | 372 | </programlisting> |
369 | </para> | 373 | </para> |
370 | </sect3> | 374 | </sect3> |
375 | <sect3 id="EOI_Edge_IRQ_flow_handler"> | ||
376 | <title>EOI Edge IRQ flow handler</title> | ||
377 | <para> | ||
378 | handle_edge_eoi_irq provides an abnomination of the edge | ||
379 | handler which is solely used to tame a badly wreckaged | ||
380 | irq controller on powerpc/cell. | ||
381 | </para> | ||
382 | </sect3> | ||
383 | <sect3 id="BAD_IRQ_flow_handler"> | ||
384 | <title>Bad IRQ flow handler</title> | ||
385 | <para> | ||
386 | handle_bad_irq is used for spurious interrupts which | ||
387 | have no real handler assigned.. | ||
388 | </para> | ||
389 | </sect3> | ||
371 | </sect2> | 390 | </sect2> |
372 | <sect2 id="Quirks_and_optimizations"> | 391 | <sect2 id="Quirks_and_optimizations"> |
373 | <title>Quirks and optimizations</title> | 392 | <title>Quirks and optimizations</title> |
@@ -410,6 +429,7 @@ if (desc->chip->irq_eoi) | |||
410 | <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem> | 429 | <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem> |
411 | <listitem><para>irq_mask()</para></listitem> | 430 | <listitem><para>irq_mask()</para></listitem> |
412 | <listitem><para>irq_unmask()</para></listitem> | 431 | <listitem><para>irq_unmask()</para></listitem> |
432 | <listitem><para>irq_eoi() - Optional, required for eoi flow handlers</para></listitem> | ||
413 | <listitem><para>irq_retrigger() - Optional</para></listitem> | 433 | <listitem><para>irq_retrigger() - Optional</para></listitem> |
414 | <listitem><para>irq_set_type() - Optional</para></listitem> | 434 | <listitem><para>irq_set_type() - Optional</para></listitem> |
415 | <listitem><para>irq_set_wake() - Optional</para></listitem> | 435 | <listitem><para>irq_set_wake() - Optional</para></listitem> |
@@ -424,32 +444,24 @@ if (desc->chip->irq_eoi) | |||
424 | <chapter id="doirq"> | 444 | <chapter id="doirq"> |
425 | <title>__do_IRQ entry point</title> | 445 | <title>__do_IRQ entry point</title> |
426 | <para> | 446 | <para> |
427 | The original implementation __do_IRQ() is an alternative entry | 447 | The original implementation __do_IRQ() was an alternative entry |
428 | point for all types of interrupts. | 448 | point for all types of interrupts. It not longer exists. |
429 | </para> | 449 | </para> |
430 | <para> | 450 | <para> |
431 | This handler turned out to be not suitable for all | 451 | This handler turned out to be not suitable for all |
432 | interrupt hardware and was therefore reimplemented with split | 452 | interrupt hardware and was therefore reimplemented with split |
433 | functionality for egde/level/simple/percpu interrupts. This is not | 453 | functionality for edge/level/simple/percpu interrupts. This is not |
434 | only a functional optimization. It also shortens code paths for | 454 | only a functional optimization. It also shortens code paths for |
435 | interrupts. | 455 | interrupts. |
436 | </para> | 456 | </para> |
437 | <para> | ||
438 | To make use of the split implementation, replace the call to | ||
439 | __do_IRQ by a call to desc->handle_irq() and associate | ||
440 | the appropriate handler function to desc->handle_irq(). | ||
441 | In most cases the generic handler implementations should | ||
442 | be sufficient. | ||
443 | </para> | ||
444 | </chapter> | 457 | </chapter> |
445 | 458 | ||
446 | <chapter id="locking"> | 459 | <chapter id="locking"> |
447 | <title>Locking on SMP</title> | 460 | <title>Locking on SMP</title> |
448 | <para> | 461 | <para> |
449 | The locking of chip registers is up to the architecture that | 462 | The locking of chip registers is up to the architecture that |
450 | defines the chip primitives. There is a chip->lock field that can be used | 463 | defines the chip primitives. The per-irq structure is |
451 | for serialization, but the generic layer does not touch it. The per-irq | 464 | protected via desc->lock, by the generic layer. |
452 | structure is protected via desc->lock, by the generic layer. | ||
453 | </para> | 465 | </para> |
454 | </chapter> | 466 | </chapter> |
455 | <chapter id="structs"> | 467 | <chapter id="structs"> |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 09a308072f56..8b4538446636 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -53,12 +53,13 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data); | |||
53 | * Bits which can be modified via irq_set/clear/modify_status_flags() | 53 | * Bits which can be modified via irq_set/clear/modify_status_flags() |
54 | * IRQ_LEVEL - Interrupt is level type. Will be also | 54 | * IRQ_LEVEL - Interrupt is level type. Will be also |
55 | * updated in the code when the above trigger | 55 | * updated in the code when the above trigger |
56 | * bits are modified via set_irq_type() | 56 | * bits are modified via irq_set_irq_type() |
57 | * IRQ_PER_CPU - Mark an interrupt PER_CPU. Will protect | 57 | * IRQ_PER_CPU - Mark an interrupt PER_CPU. Will protect |
58 | * it from affinity setting | 58 | * it from affinity setting |
59 | * IRQ_NOPROBE - Interrupt cannot be probed by autoprobing | 59 | * IRQ_NOPROBE - Interrupt cannot be probed by autoprobing |
60 | * IRQ_NOREQUEST - Interrupt cannot be requested via | 60 | * IRQ_NOREQUEST - Interrupt cannot be requested via |
61 | * request_irq() | 61 | * request_irq() |
62 | * IRQ_NOTHREAD - Interrupt cannot be threaded | ||
62 | * IRQ_NOAUTOEN - Interrupt is not automatically enabled in | 63 | * IRQ_NOAUTOEN - Interrupt is not automatically enabled in |
63 | * request/setup_irq() | 64 | * request/setup_irq() |
64 | * IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set) | 65 | * IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set) |
@@ -85,6 +86,7 @@ enum { | |||
85 | IRQ_NO_BALANCING = (1 << 13), | 86 | IRQ_NO_BALANCING = (1 << 13), |
86 | IRQ_MOVE_PCNTXT = (1 << 14), | 87 | IRQ_MOVE_PCNTXT = (1 << 14), |
87 | IRQ_NESTED_THREAD = (1 << 15), | 88 | IRQ_NESTED_THREAD = (1 << 15), |
89 | IRQ_NOTHREAD = (1 << 16), | ||
88 | }; | 90 | }; |
89 | 91 | ||
90 | #define IRQF_MODIFY_MASK \ | 92 | #define IRQF_MODIFY_MASK \ |
@@ -261,23 +263,6 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d) | |||
261 | * struct irq_chip - hardware interrupt chip descriptor | 263 | * struct irq_chip - hardware interrupt chip descriptor |
262 | * | 264 | * |
263 | * @name: name for /proc/interrupts | 265 | * @name: name for /proc/interrupts |
264 | * @startup: deprecated, replaced by irq_startup | ||
265 | * @shutdown: deprecated, replaced by irq_shutdown | ||
266 | * @enable: deprecated, replaced by irq_enable | ||
267 | * @disable: deprecated, replaced by irq_disable | ||
268 | * @ack: deprecated, replaced by irq_ack | ||
269 | * @mask: deprecated, replaced by irq_mask | ||
270 | * @mask_ack: deprecated, replaced by irq_mask_ack | ||
271 | * @unmask: deprecated, replaced by irq_unmask | ||
272 | * @eoi: deprecated, replaced by irq_eoi | ||
273 | * @end: deprecated, will go away with __do_IRQ() | ||
274 | * @set_affinity: deprecated, replaced by irq_set_affinity | ||
275 | * @retrigger: deprecated, replaced by irq_retrigger | ||
276 | * @set_type: deprecated, replaced by irq_set_type | ||
277 | * @set_wake: deprecated, replaced by irq_wake | ||
278 | * @bus_lock: deprecated, replaced by irq_bus_lock | ||
279 | * @bus_sync_unlock: deprecated, replaced by irq_bus_sync_unlock | ||
280 | * | ||
281 | * @irq_startup: start up the interrupt (defaults to ->enable if NULL) | 266 | * @irq_startup: start up the interrupt (defaults to ->enable if NULL) |
282 | * @irq_shutdown: shut down the interrupt (defaults to ->disable if NULL) | 267 | * @irq_shutdown: shut down the interrupt (defaults to ->disable if NULL) |
283 | * @irq_enable: enable the interrupt (defaults to chip->unmask if NULL) | 268 | * @irq_enable: enable the interrupt (defaults to chip->unmask if NULL) |
@@ -295,6 +280,9 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d) | |||
295 | * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips | 280 | * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips |
296 | * @irq_cpu_online: configure an interrupt source for a secondary CPU | 281 | * @irq_cpu_online: configure an interrupt source for a secondary CPU |
297 | * @irq_cpu_offline: un-configure an interrupt source for a secondary CPU | 282 | * @irq_cpu_offline: un-configure an interrupt source for a secondary CPU |
283 | * @irq_suspend: function called from core code on suspend once per chip | ||
284 | * @irq_resume: function called from core code on resume once per chip | ||
285 | * @irq_pm_shutdown: function called from core code on shutdown once per chip | ||
298 | * @irq_print_chip: optional to print special chip info in show_interrupts | 286 | * @irq_print_chip: optional to print special chip info in show_interrupts |
299 | * @flags: chip specific flags | 287 | * @flags: chip specific flags |
300 | * | 288 | * |
@@ -324,6 +312,10 @@ struct irq_chip { | |||
324 | void (*irq_cpu_online)(struct irq_data *data); | 312 | void (*irq_cpu_online)(struct irq_data *data); |
325 | void (*irq_cpu_offline)(struct irq_data *data); | 313 | void (*irq_cpu_offline)(struct irq_data *data); |
326 | 314 | ||
315 | void (*irq_suspend)(struct irq_data *data); | ||
316 | void (*irq_resume)(struct irq_data *data); | ||
317 | void (*irq_pm_shutdown)(struct irq_data *data); | ||
318 | |||
327 | void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); | 319 | void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); |
328 | 320 | ||
329 | unsigned long flags; | 321 | unsigned long flags; |
@@ -439,7 +431,7 @@ irq_set_handler(unsigned int irq, irq_flow_handler_t handle) | |||
439 | /* | 431 | /* |
440 | * Set a highlevel chained flow handler for a given IRQ. | 432 | * Set a highlevel chained flow handler for a given IRQ. |
441 | * (a chained handler is automatically enabled and set to | 433 | * (a chained handler is automatically enabled and set to |
442 | * IRQ_NOREQUEST and IRQ_NOPROBE) | 434 | * IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD) |
443 | */ | 435 | */ |
444 | static inline void | 436 | static inline void |
445 | irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle) | 437 | irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle) |
@@ -469,6 +461,16 @@ static inline void irq_set_probe(unsigned int irq) | |||
469 | irq_modify_status(irq, IRQ_NOPROBE, 0); | 461 | irq_modify_status(irq, IRQ_NOPROBE, 0); |
470 | } | 462 | } |
471 | 463 | ||
464 | static inline void irq_set_nothread(unsigned int irq) | ||
465 | { | ||
466 | irq_modify_status(irq, 0, IRQ_NOTHREAD); | ||
467 | } | ||
468 | |||
469 | static inline void irq_set_thread(unsigned int irq) | ||
470 | { | ||
471 | irq_modify_status(irq, IRQ_NOTHREAD, 0); | ||
472 | } | ||
473 | |||
472 | static inline void irq_set_nested_thread(unsigned int irq, bool nest) | 474 | static inline void irq_set_nested_thread(unsigned int irq, bool nest) |
473 | { | 475 | { |
474 | if (nest) | 476 | if (nest) |
@@ -573,6 +575,145 @@ static inline int irq_reserve_irq(unsigned int irq) | |||
573 | return irq_reserve_irqs(irq, 1); | 575 | return irq_reserve_irqs(irq, 1); |
574 | } | 576 | } |
575 | 577 | ||
578 | #ifndef irq_reg_writel | ||
579 | # define irq_reg_writel(val, addr) writel(val, addr) | ||
580 | #endif | ||
581 | #ifndef irq_reg_readl | ||
582 | # define irq_reg_readl(addr) readl(addr) | ||
583 | #endif | ||
584 | |||
585 | /** | ||
586 | * struct irq_chip_regs - register offsets for struct irq_gci | ||
587 | * @enable: Enable register offset to reg_base | ||
588 | * @disable: Disable register offset to reg_base | ||
589 | * @mask: Mask register offset to reg_base | ||
590 | * @ack: Ack register offset to reg_base | ||
591 | * @eoi: Eoi register offset to reg_base | ||
592 | * @type: Type configuration register offset to reg_base | ||
593 | * @polarity: Polarity configuration register offset to reg_base | ||
594 | */ | ||
595 | struct irq_chip_regs { | ||
596 | unsigned long enable; | ||
597 | unsigned long disable; | ||
598 | unsigned long mask; | ||
599 | unsigned long ack; | ||
600 | unsigned long eoi; | ||
601 | unsigned long type; | ||
602 | unsigned long polarity; | ||
603 | }; | ||
604 | |||
605 | /** | ||
606 | * struct irq_chip_type - Generic interrupt chip instance for a flow type | ||
607 | * @chip: The real interrupt chip which provides the callbacks | ||
608 | * @regs: Register offsets for this chip | ||
609 | * @handler: Flow handler associated with this chip | ||
610 | * @type: Chip can handle these flow types | ||
611 | * | ||
612 | * A irq_generic_chip can have several instances of irq_chip_type when | ||
613 | * it requires different functions and register offsets for different | ||
614 | * flow types. | ||
615 | */ | ||
616 | struct irq_chip_type { | ||
617 | struct irq_chip chip; | ||
618 | struct irq_chip_regs regs; | ||
619 | irq_flow_handler_t handler; | ||
620 | u32 type; | ||
621 | }; | ||
622 | |||
623 | /** | ||
624 | * struct irq_chip_generic - Generic irq chip data structure | ||
625 | * @lock: Lock to protect register and cache data access | ||
626 | * @reg_base: Register base address (virtual) | ||
627 | * @irq_base: Interrupt base nr for this chip | ||
628 | * @irq_cnt: Number of interrupts handled by this chip | ||
629 | * @mask_cache: Cached mask register | ||
630 | * @type_cache: Cached type register | ||
631 | * @polarity_cache: Cached polarity register | ||
632 | * @wake_enabled: Interrupt can wakeup from suspend | ||
633 | * @wake_active: Interrupt is marked as an wakeup from suspend source | ||
634 | * @num_ct: Number of available irq_chip_type instances (usually 1) | ||
635 | * @private: Private data for non generic chip callbacks | ||
636 | * @list: List head for keeping track of instances | ||
637 | * @chip_types: Array of interrupt irq_chip_types | ||
638 | * | ||
639 | * Note, that irq_chip_generic can have multiple irq_chip_type | ||
640 | * implementations which can be associated to a particular irq line of | ||
641 | * an irq_chip_generic instance. That allows to share and protect | ||
642 | * state in an irq_chip_generic instance when we need to implement | ||
643 | * different flow mechanisms (level/edge) for it. | ||
644 | */ | ||
645 | struct irq_chip_generic { | ||
646 | raw_spinlock_t lock; | ||
647 | void __iomem *reg_base; | ||
648 | unsigned int irq_base; | ||
649 | unsigned int irq_cnt; | ||
650 | u32 mask_cache; | ||
651 | u32 type_cache; | ||
652 | u32 polarity_cache; | ||
653 | u32 wake_enabled; | ||
654 | u32 wake_active; | ||
655 | unsigned int num_ct; | ||
656 | void *private; | ||
657 | struct list_head list; | ||
658 | struct irq_chip_type chip_types[0]; | ||
659 | }; | ||
660 | |||
661 | /** | ||
662 | * enum irq_gc_flags - Initialization flags for generic irq chips | ||
663 | * @IRQ_GC_INIT_MASK_CACHE: Initialize the mask_cache by reading mask reg | ||
664 | * @IRQ_GC_INIT_NESTED_LOCK: Set the lock class of the irqs to nested for | ||
665 | * irq chips which need to call irq_set_wake() on | ||
666 | * the parent irq. Usually GPIO implementations | ||
667 | */ | ||
668 | enum irq_gc_flags { | ||
669 | IRQ_GC_INIT_MASK_CACHE = 1 << 0, | ||
670 | IRQ_GC_INIT_NESTED_LOCK = 1 << 1, | ||
671 | }; | ||
672 | |||
673 | /* Generic chip callback functions */ | ||
674 | void irq_gc_noop(struct irq_data *d); | ||
675 | void irq_gc_mask_disable_reg(struct irq_data *d); | ||
676 | void irq_gc_mask_set_bit(struct irq_data *d); | ||
677 | void irq_gc_mask_clr_bit(struct irq_data *d); | ||
678 | void irq_gc_unmask_enable_reg(struct irq_data *d); | ||
679 | void irq_gc_ack(struct irq_data *d); | ||
680 | void irq_gc_mask_disable_reg_and_ack(struct irq_data *d); | ||
681 | void irq_gc_eoi(struct irq_data *d); | ||
682 | int irq_gc_set_wake(struct irq_data *d, unsigned int on); | ||
683 | |||
684 | /* Setup functions for irq_chip_generic */ | ||
685 | struct irq_chip_generic * | ||
686 | irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base, | ||
687 | void __iomem *reg_base, irq_flow_handler_t handler); | ||
688 | void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | ||
689 | enum irq_gc_flags flags, unsigned int clr, | ||
690 | unsigned int set); | ||
691 | int irq_setup_alt_chip(struct irq_data *d, unsigned int type); | ||
692 | void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk, | ||
693 | unsigned int clr, unsigned int set); | ||
694 | |||
695 | static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d) | ||
696 | { | ||
697 | return container_of(d->chip, struct irq_chip_type, chip); | ||
698 | } | ||
699 | |||
700 | #define IRQ_MSK(n) (u32)((n) < 32 ? ((1 << (n)) - 1) : UINT_MAX) | ||
701 | |||
702 | #ifdef CONFIG_SMP | ||
703 | static inline void irq_gc_lock(struct irq_chip_generic *gc) | ||
704 | { | ||
705 | raw_spin_lock(&gc->lock); | ||
706 | } | ||
707 | |||
708 | static inline void irq_gc_unlock(struct irq_chip_generic *gc) | ||
709 | { | ||
710 | raw_spin_unlock(&gc->lock); | ||
711 | } | ||
712 | #else | ||
713 | static inline void irq_gc_lock(struct irq_chip_generic *gc) { } | ||
714 | static inline void irq_gc_unlock(struct irq_chip_generic *gc) { } | ||
715 | #endif | ||
716 | |||
576 | #endif /* CONFIG_GENERIC_HARDIRQS */ | 717 | #endif /* CONFIG_GENERIC_HARDIRQS */ |
577 | 718 | ||
578 | #endif /* !CONFIG_S390 */ | 719 | #endif /* !CONFIG_S390 */ |
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index a082905b5ebe..2d921b35212c 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h | |||
@@ -16,16 +16,18 @@ struct timer_rand_state; | |||
16 | * @irq_data: per irq and chip data passed down to chip functions | 16 | * @irq_data: per irq and chip data passed down to chip functions |
17 | * @timer_rand_state: pointer to timer rand state struct | 17 | * @timer_rand_state: pointer to timer rand state struct |
18 | * @kstat_irqs: irq stats per cpu | 18 | * @kstat_irqs: irq stats per cpu |
19 | * @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()] | 19 | * @handle_irq: highlevel irq-events handler |
20 | * @preflow_handler: handler called before the flow handler (currently used by sparc) | ||
20 | * @action: the irq action chain | 21 | * @action: the irq action chain |
21 | * @status: status information | 22 | * @status: status information |
22 | * @core_internal_state__do_not_mess_with_it: core internal status information | 23 | * @core_internal_state__do_not_mess_with_it: core internal status information |
23 | * @depth: disable-depth, for nested irq_disable() calls | 24 | * @depth: disable-depth, for nested irq_disable() calls |
24 | * @wake_depth: enable depth, for multiple set_irq_wake() callers | 25 | * @wake_depth: enable depth, for multiple irq_set_irq_wake() callers |
25 | * @irq_count: stats field to detect stalled irqs | 26 | * @irq_count: stats field to detect stalled irqs |
26 | * @last_unhandled: aging timer for unhandled count | 27 | * @last_unhandled: aging timer for unhandled count |
27 | * @irqs_unhandled: stats field for spurious unhandled interrupts | 28 | * @irqs_unhandled: stats field for spurious unhandled interrupts |
28 | * @lock: locking for SMP | 29 | * @lock: locking for SMP |
30 | * @affinity_hint: hint to user space for preferred irq affinity | ||
29 | * @affinity_notify: context for notification of affinity changes | 31 | * @affinity_notify: context for notification of affinity changes |
30 | * @pending_mask: pending rebalanced interrupts | 32 | * @pending_mask: pending rebalanced interrupts |
31 | * @threads_oneshot: bitfield to handle shared oneshot threads | 33 | * @threads_oneshot: bitfield to handle shared oneshot threads |
@@ -109,10 +111,7 @@ static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *de | |||
109 | desc->handle_irq(irq, desc); | 111 | desc->handle_irq(irq, desc); |
110 | } | 112 | } |
111 | 113 | ||
112 | static inline void generic_handle_irq(unsigned int irq) | 114 | int generic_handle_irq(unsigned int irq); |
113 | { | ||
114 | generic_handle_irq_desc(irq, irq_to_desc(irq)); | ||
115 | } | ||
116 | 115 | ||
117 | /* Test to see if a driver has successfully requested an irq */ | 116 | /* Test to see if a driver has successfully requested an irq */ |
118 | static inline int irq_has_action(unsigned int irq) | 117 | static inline int irq_has_action(unsigned int irq) |
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index c574f9a12c48..d1d051b38e0b 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
@@ -48,6 +48,10 @@ config IRQ_PREFLOW_FASTEOI | |||
48 | config IRQ_EDGE_EOI_HANDLER | 48 | config IRQ_EDGE_EOI_HANDLER |
49 | bool | 49 | bool |
50 | 50 | ||
51 | # Generic configurable interrupt chip implementation | ||
52 | config GENERIC_IRQ_CHIP | ||
53 | bool | ||
54 | |||
51 | # Support forced irq threading | 55 | # Support forced irq threading |
52 | config IRQ_FORCED_THREADING | 56 | config IRQ_FORCED_THREADING |
53 | bool | 57 | bool |
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile index 54329cd7b3ee..73290056cfb6 100644 --- a/kernel/irq/Makefile +++ b/kernel/irq/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | 1 | ||
2 | obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o | 2 | obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o |
3 | obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o | ||
3 | obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o | 4 | obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o |
4 | obj-$(CONFIG_PROC_FS) += proc.o | 5 | obj-$(CONFIG_PROC_FS) += proc.o |
5 | obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o | 6 | obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 4af1e2b244cb..d5a3009da71a 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -310,6 +310,7 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) | |||
310 | out_unlock: | 310 | out_unlock: |
311 | raw_spin_unlock(&desc->lock); | 311 | raw_spin_unlock(&desc->lock); |
312 | } | 312 | } |
313 | EXPORT_SYMBOL_GPL(handle_simple_irq); | ||
313 | 314 | ||
314 | /** | 315 | /** |
315 | * handle_level_irq - Level type irq handler | 316 | * handle_level_irq - Level type irq handler |
@@ -573,6 +574,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
573 | if (handle != handle_bad_irq && is_chained) { | 574 | if (handle != handle_bad_irq && is_chained) { |
574 | irq_settings_set_noprobe(desc); | 575 | irq_settings_set_noprobe(desc); |
575 | irq_settings_set_norequest(desc); | 576 | irq_settings_set_norequest(desc); |
577 | irq_settings_set_nothread(desc); | ||
576 | irq_startup(desc); | 578 | irq_startup(desc); |
577 | } | 579 | } |
578 | out: | 580 | out: |
@@ -612,6 +614,7 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) | |||
612 | 614 | ||
613 | irq_put_desc_unlock(desc, flags); | 615 | irq_put_desc_unlock(desc, flags); |
614 | } | 616 | } |
617 | EXPORT_SYMBOL_GPL(irq_modify_status); | ||
615 | 618 | ||
616 | /** | 619 | /** |
617 | * irq_cpu_online - Invoke all irq_cpu_online functions. | 620 | * irq_cpu_online - Invoke all irq_cpu_online functions. |
diff --git a/kernel/irq/debug.h b/kernel/irq/debug.h index 306cba37e9a5..97a8bfadc88a 100644 --- a/kernel/irq/debug.h +++ b/kernel/irq/debug.h | |||
@@ -27,6 +27,7 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) | |||
27 | P(IRQ_PER_CPU); | 27 | P(IRQ_PER_CPU); |
28 | P(IRQ_NOPROBE); | 28 | P(IRQ_NOPROBE); |
29 | P(IRQ_NOREQUEST); | 29 | P(IRQ_NOREQUEST); |
30 | P(IRQ_NOTHREAD); | ||
30 | P(IRQ_NOAUTOEN); | 31 | P(IRQ_NOAUTOEN); |
31 | 32 | ||
32 | PS(IRQS_AUTODETECT); | 33 | PS(IRQS_AUTODETECT); |
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c new file mode 100644 index 000000000000..31a9db711906 --- /dev/null +++ b/kernel/irq/generic-chip.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * Library implementing the most common irq chip callback functions | ||
3 | * | ||
4 | * Copyright (C) 2011, Thomas Gleixner | ||
5 | */ | ||
6 | #include <linux/io.h> | ||
7 | #include <linux/irq.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/kernel_stat.h> | ||
11 | #include <linux/syscore_ops.h> | ||
12 | |||
13 | #include "internals.h" | ||
14 | |||
15 | static LIST_HEAD(gc_list); | ||
16 | static DEFINE_RAW_SPINLOCK(gc_lock); | ||
17 | |||
18 | static inline struct irq_chip_regs *cur_regs(struct irq_data *d) | ||
19 | { | ||
20 | return &container_of(d->chip, struct irq_chip_type, chip)->regs; | ||
21 | } | ||
22 | |||
23 | /** | ||
24 | * irq_gc_noop - NOOP function | ||
25 | * @d: irq_data | ||
26 | */ | ||
27 | void irq_gc_noop(struct irq_data *d) | ||
28 | { | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * irq_gc_mask_disable_reg - Mask chip via disable register | ||
33 | * @d: irq_data | ||
34 | * | ||
35 | * Chip has separate enable/disable registers instead of a single mask | ||
36 | * register. | ||
37 | */ | ||
38 | void irq_gc_mask_disable_reg(struct irq_data *d) | ||
39 | { | ||
40 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
41 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
42 | |||
43 | irq_gc_lock(gc); | ||
44 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->disable); | ||
45 | gc->mask_cache &= ~mask; | ||
46 | irq_gc_unlock(gc); | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * irq_gc_mask_set_mask_bit - Mask chip via setting bit in mask register | ||
51 | * @d: irq_data | ||
52 | * | ||
53 | * Chip has a single mask register. Values of this register are cached | ||
54 | * and protected by gc->lock | ||
55 | */ | ||
56 | void irq_gc_mask_set_bit(struct irq_data *d) | ||
57 | { | ||
58 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
59 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
60 | |||
61 | irq_gc_lock(gc); | ||
62 | gc->mask_cache |= mask; | ||
63 | irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask); | ||
64 | irq_gc_unlock(gc); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * irq_gc_mask_set_mask_bit - Mask chip via clearing bit in mask register | ||
69 | * @d: irq_data | ||
70 | * | ||
71 | * Chip has a single mask register. Values of this register are cached | ||
72 | * and protected by gc->lock | ||
73 | */ | ||
74 | void irq_gc_mask_clr_bit(struct irq_data *d) | ||
75 | { | ||
76 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
77 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
78 | |||
79 | irq_gc_lock(gc); | ||
80 | gc->mask_cache &= ~mask; | ||
81 | irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask); | ||
82 | irq_gc_unlock(gc); | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * irq_gc_unmask_enable_reg - Unmask chip via enable register | ||
87 | * @d: irq_data | ||
88 | * | ||
89 | * Chip has separate enable/disable registers instead of a single mask | ||
90 | * register. | ||
91 | */ | ||
92 | void irq_gc_unmask_enable_reg(struct irq_data *d) | ||
93 | { | ||
94 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
95 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
96 | |||
97 | irq_gc_lock(gc); | ||
98 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->enable); | ||
99 | gc->mask_cache |= mask; | ||
100 | irq_gc_unlock(gc); | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * irq_gc_ack - Ack pending interrupt | ||
105 | * @d: irq_data | ||
106 | */ | ||
107 | void irq_gc_ack(struct irq_data *d) | ||
108 | { | ||
109 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
110 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
111 | |||
112 | irq_gc_lock(gc); | ||
113 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); | ||
114 | irq_gc_unlock(gc); | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * irq_gc_mask_disable_reg_and_ack- Mask and ack pending interrupt | ||
119 | * @d: irq_data | ||
120 | */ | ||
121 | void irq_gc_mask_disable_reg_and_ack(struct irq_data *d) | ||
122 | { | ||
123 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
124 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
125 | |||
126 | irq_gc_lock(gc); | ||
127 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->mask); | ||
128 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); | ||
129 | irq_gc_unlock(gc); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * irq_gc_eoi - EOI interrupt | ||
134 | * @d: irq_data | ||
135 | */ | ||
136 | void irq_gc_eoi(struct irq_data *d) | ||
137 | { | ||
138 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
139 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
140 | |||
141 | irq_gc_lock(gc); | ||
142 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->eoi); | ||
143 | irq_gc_unlock(gc); | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * irq_gc_set_wake - Set/clr wake bit for an interrupt | ||
148 | * @d: irq_data | ||
149 | * | ||
150 | * For chips where the wake from suspend functionality is not | ||
151 | * configured in a separate register and the wakeup active state is | ||
152 | * just stored in a bitmask. | ||
153 | */ | ||
154 | int irq_gc_set_wake(struct irq_data *d, unsigned int on) | ||
155 | { | ||
156 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
157 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
158 | |||
159 | if (!(mask & gc->wake_enabled)) | ||
160 | return -EINVAL; | ||
161 | |||
162 | irq_gc_lock(gc); | ||
163 | if (on) | ||
164 | gc->wake_active |= mask; | ||
165 | else | ||
166 | gc->wake_active &= ~mask; | ||
167 | irq_gc_unlock(gc); | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * irq_alloc_generic_chip - Allocate a generic chip and initialize it | ||
173 | * @name: Name of the irq chip | ||
174 | * @num_ct: Number of irq_chip_type instances associated with this | ||
175 | * @irq_base: Interrupt base nr for this chip | ||
176 | * @reg_base: Register base address (virtual) | ||
177 | * @handler: Default flow handler associated with this chip | ||
178 | * | ||
179 | * Returns an initialized irq_chip_generic structure. The chip defaults | ||
180 | * to the primary (index 0) irq_chip_type and @handler | ||
181 | */ | ||
182 | struct irq_chip_generic * | ||
183 | irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base, | ||
184 | void __iomem *reg_base, irq_flow_handler_t handler) | ||
185 | { | ||
186 | struct irq_chip_generic *gc; | ||
187 | unsigned long sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type); | ||
188 | |||
189 | gc = kzalloc(sz, GFP_KERNEL); | ||
190 | if (gc) { | ||
191 | raw_spin_lock_init(&gc->lock); | ||
192 | gc->num_ct = num_ct; | ||
193 | gc->irq_base = irq_base; | ||
194 | gc->reg_base = reg_base; | ||
195 | gc->chip_types->chip.name = name; | ||
196 | gc->chip_types->handler = handler; | ||
197 | } | ||
198 | return gc; | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Separate lockdep class for interrupt chip which can nest irq_desc | ||
203 | * lock. | ||
204 | */ | ||
205 | static struct lock_class_key irq_nested_lock_class; | ||
206 | |||
207 | /** | ||
208 | * irq_setup_generic_chip - Setup a range of interrupts with a generic chip | ||
209 | * @gc: Generic irq chip holding all data | ||
210 | * @msk: Bitmask holding the irqs to initialize relative to gc->irq_base | ||
211 | * @flags: Flags for initialization | ||
212 | * @clr: IRQ_* bits to clear | ||
213 | * @set: IRQ_* bits to set | ||
214 | * | ||
215 | * Set up max. 32 interrupts starting from gc->irq_base. Note, this | ||
216 | * initializes all interrupts to the primary irq_chip_type and its | ||
217 | * associated handler. | ||
218 | */ | ||
219 | void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | ||
220 | enum irq_gc_flags flags, unsigned int clr, | ||
221 | unsigned int set) | ||
222 | { | ||
223 | struct irq_chip_type *ct = gc->chip_types; | ||
224 | unsigned int i; | ||
225 | |||
226 | raw_spin_lock(&gc_lock); | ||
227 | list_add_tail(&gc->list, &gc_list); | ||
228 | raw_spin_unlock(&gc_lock); | ||
229 | |||
230 | /* Init mask cache ? */ | ||
231 | if (flags & IRQ_GC_INIT_MASK_CACHE) | ||
232 | gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask); | ||
233 | |||
234 | for (i = gc->irq_base; msk; msk >>= 1, i++) { | ||
235 | if (!msk & 0x01) | ||
236 | continue; | ||
237 | |||
238 | if (flags & IRQ_GC_INIT_NESTED_LOCK) | ||
239 | irq_set_lockdep_class(i, &irq_nested_lock_class); | ||
240 | |||
241 | irq_set_chip_and_handler(i, &ct->chip, ct->handler); | ||
242 | irq_set_chip_data(i, gc); | ||
243 | irq_modify_status(i, clr, set); | ||
244 | } | ||
245 | gc->irq_cnt = i - gc->irq_base; | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * irq_setup_alt_chip - Switch to alternative chip | ||
250 | * @d: irq_data for this interrupt | ||
251 | * @type Flow type to be initialized | ||
252 | * | ||
253 | * Only to be called from chip->irq_set_type() callbacks. | ||
254 | */ | ||
255 | int irq_setup_alt_chip(struct irq_data *d, unsigned int type) | ||
256 | { | ||
257 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
258 | struct irq_chip_type *ct = gc->chip_types; | ||
259 | unsigned int i; | ||
260 | |||
261 | for (i = 0; i < gc->num_ct; i++, ct++) { | ||
262 | if (ct->type & type) { | ||
263 | d->chip = &ct->chip; | ||
264 | irq_data_to_desc(d)->handle_irq = ct->handler; | ||
265 | return 0; | ||
266 | } | ||
267 | } | ||
268 | return -EINVAL; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * irq_remove_generic_chip - Remove a chip | ||
273 | * @gc: Generic irq chip holding all data | ||
274 | * @msk: Bitmask holding the irqs to initialize relative to gc->irq_base | ||
275 | * @clr: IRQ_* bits to clear | ||
276 | * @set: IRQ_* bits to set | ||
277 | * | ||
278 | * Remove up to 32 interrupts starting from gc->irq_base. | ||
279 | */ | ||
280 | void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk, | ||
281 | unsigned int clr, unsigned int set) | ||
282 | { | ||
283 | unsigned int i = gc->irq_base; | ||
284 | |||
285 | raw_spin_lock(&gc_lock); | ||
286 | list_del(&gc->list); | ||
287 | raw_spin_unlock(&gc_lock); | ||
288 | |||
289 | for (; msk; msk >>= 1, i++) { | ||
290 | if (!msk & 0x01) | ||
291 | continue; | ||
292 | |||
293 | /* Remove handler first. That will mask the irq line */ | ||
294 | irq_set_handler(i, NULL); | ||
295 | irq_set_chip(i, &no_irq_chip); | ||
296 | irq_set_chip_data(i, NULL); | ||
297 | irq_modify_status(i, clr, set); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | #ifdef CONFIG_PM | ||
302 | static int irq_gc_suspend(void) | ||
303 | { | ||
304 | struct irq_chip_generic *gc; | ||
305 | |||
306 | list_for_each_entry(gc, &gc_list, list) { | ||
307 | struct irq_chip_type *ct = gc->chip_types; | ||
308 | |||
309 | if (ct->chip.irq_suspend) | ||
310 | ct->chip.irq_suspend(irq_get_irq_data(gc->irq_base)); | ||
311 | } | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static void irq_gc_resume(void) | ||
316 | { | ||
317 | struct irq_chip_generic *gc; | ||
318 | |||
319 | list_for_each_entry(gc, &gc_list, list) { | ||
320 | struct irq_chip_type *ct = gc->chip_types; | ||
321 | |||
322 | if (ct->chip.irq_resume) | ||
323 | ct->chip.irq_resume(irq_get_irq_data(gc->irq_base)); | ||
324 | } | ||
325 | } | ||
326 | #else | ||
327 | #define irq_gc_suspend NULL | ||
328 | #define irq_gc_resume NULL | ||
329 | #endif | ||
330 | |||
331 | static void irq_gc_shutdown(void) | ||
332 | { | ||
333 | struct irq_chip_generic *gc; | ||
334 | |||
335 | list_for_each_entry(gc, &gc_list, list) { | ||
336 | struct irq_chip_type *ct = gc->chip_types; | ||
337 | |||
338 | if (ct->chip.irq_pm_shutdown) | ||
339 | ct->chip.irq_pm_shutdown(irq_get_irq_data(gc->irq_base)); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | static struct syscore_ops irq_gc_syscore_ops = { | ||
344 | .suspend = irq_gc_suspend, | ||
345 | .resume = irq_gc_resume, | ||
346 | .shutdown = irq_gc_shutdown, | ||
347 | }; | ||
348 | |||
349 | static int __init irq_gc_init_ops(void) | ||
350 | { | ||
351 | register_syscore_ops(&irq_gc_syscore_ops); | ||
352 | return 0; | ||
353 | } | ||
354 | device_initcall(irq_gc_init_ops); | ||
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 2c039c9b9383..886e80347b32 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
@@ -22,7 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | static struct lock_class_key irq_desc_lock_class; | 23 | static struct lock_class_key irq_desc_lock_class; |
24 | 24 | ||
25 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS) | 25 | #if defined(CONFIG_SMP) |
26 | static void __init init_irq_default_affinity(void) | 26 | static void __init init_irq_default_affinity(void) |
27 | { | 27 | { |
28 | alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); | 28 | alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); |
@@ -290,6 +290,22 @@ static int irq_expand_nr_irqs(unsigned int nr) | |||
290 | 290 | ||
291 | #endif /* !CONFIG_SPARSE_IRQ */ | 291 | #endif /* !CONFIG_SPARSE_IRQ */ |
292 | 292 | ||
293 | /** | ||
294 | * generic_handle_irq - Invoke the handler for a particular irq | ||
295 | * @irq: The irq number to handle | ||
296 | * | ||
297 | */ | ||
298 | int generic_handle_irq(unsigned int irq) | ||
299 | { | ||
300 | struct irq_desc *desc = irq_to_desc(irq); | ||
301 | |||
302 | if (!desc) | ||
303 | return -EINVAL; | ||
304 | generic_handle_irq_desc(irq, desc); | ||
305 | return 0; | ||
306 | } | ||
307 | EXPORT_SYMBOL_GPL(generic_handle_irq); | ||
308 | |||
293 | /* Dynamic interrupt handling */ | 309 | /* Dynamic interrupt handling */ |
294 | 310 | ||
295 | /** | 311 | /** |
@@ -311,6 +327,7 @@ void irq_free_descs(unsigned int from, unsigned int cnt) | |||
311 | bitmap_clear(allocated_irqs, from, cnt); | 327 | bitmap_clear(allocated_irqs, from, cnt); |
312 | mutex_unlock(&sparse_irq_lock); | 328 | mutex_unlock(&sparse_irq_lock); |
313 | } | 329 | } |
330 | EXPORT_SYMBOL_GPL(irq_free_descs); | ||
314 | 331 | ||
315 | /** | 332 | /** |
316 | * irq_alloc_descs - allocate and initialize a range of irq descriptors | 333 | * irq_alloc_descs - allocate and initialize a range of irq descriptors |
@@ -351,6 +368,7 @@ err: | |||
351 | mutex_unlock(&sparse_irq_lock); | 368 | mutex_unlock(&sparse_irq_lock); |
352 | return ret; | 369 | return ret; |
353 | } | 370 | } |
371 | EXPORT_SYMBOL_GPL(irq_alloc_descs); | ||
354 | 372 | ||
355 | /** | 373 | /** |
356 | * irq_reserve_irqs - mark irqs allocated | 374 | * irq_reserve_irqs - mark irqs allocated |
@@ -430,7 +448,6 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) | |||
430 | *per_cpu_ptr(desc->kstat_irqs, cpu) : 0; | 448 | *per_cpu_ptr(desc->kstat_irqs, cpu) : 0; |
431 | } | 449 | } |
432 | 450 | ||
433 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
434 | unsigned int kstat_irqs(unsigned int irq) | 451 | unsigned int kstat_irqs(unsigned int irq) |
435 | { | 452 | { |
436 | struct irq_desc *desc = irq_to_desc(irq); | 453 | struct irq_desc *desc = irq_to_desc(irq); |
@@ -443,4 +460,3 @@ unsigned int kstat_irqs(unsigned int irq) | |||
443 | sum += *per_cpu_ptr(desc->kstat_irqs, cpu); | 460 | sum += *per_cpu_ptr(desc->kstat_irqs, cpu); |
444 | return sum; | 461 | return sum; |
445 | } | 462 | } |
446 | #endif /* CONFIG_GENERIC_HARDIRQS */ | ||
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 07c1611f3899..f7ce0021e1c4 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -900,7 +900,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
900 | */ | 900 | */ |
901 | new->handler = irq_nested_primary_handler; | 901 | new->handler = irq_nested_primary_handler; |
902 | } else { | 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 | /* |
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h index 0d91730b6330..f1667833d444 100644 --- a/kernel/irq/settings.h +++ b/kernel/irq/settings.h | |||
@@ -8,6 +8,7 @@ enum { | |||
8 | _IRQ_LEVEL = IRQ_LEVEL, | 8 | _IRQ_LEVEL = IRQ_LEVEL, |
9 | _IRQ_NOPROBE = IRQ_NOPROBE, | 9 | _IRQ_NOPROBE = IRQ_NOPROBE, |
10 | _IRQ_NOREQUEST = IRQ_NOREQUEST, | 10 | _IRQ_NOREQUEST = IRQ_NOREQUEST, |
11 | _IRQ_NOTHREAD = IRQ_NOTHREAD, | ||
11 | _IRQ_NOAUTOEN = IRQ_NOAUTOEN, | 12 | _IRQ_NOAUTOEN = IRQ_NOAUTOEN, |
12 | _IRQ_MOVE_PCNTXT = IRQ_MOVE_PCNTXT, | 13 | _IRQ_MOVE_PCNTXT = IRQ_MOVE_PCNTXT, |
13 | _IRQ_NO_BALANCING = IRQ_NO_BALANCING, | 14 | _IRQ_NO_BALANCING = IRQ_NO_BALANCING, |
@@ -20,6 +21,7 @@ enum { | |||
20 | #define IRQ_LEVEL GOT_YOU_MORON | 21 | #define IRQ_LEVEL GOT_YOU_MORON |
21 | #define IRQ_NOPROBE GOT_YOU_MORON | 22 | #define IRQ_NOPROBE GOT_YOU_MORON |
22 | #define IRQ_NOREQUEST GOT_YOU_MORON | 23 | #define IRQ_NOREQUEST GOT_YOU_MORON |
24 | #define IRQ_NOTHREAD GOT_YOU_MORON | ||
23 | #define IRQ_NOAUTOEN GOT_YOU_MORON | 25 | #define IRQ_NOAUTOEN GOT_YOU_MORON |
24 | #define IRQ_NESTED_THREAD GOT_YOU_MORON | 26 | #define IRQ_NESTED_THREAD GOT_YOU_MORON |
25 | #undef IRQF_MODIFY_MASK | 27 | #undef IRQF_MODIFY_MASK |
@@ -94,6 +96,21 @@ static inline void irq_settings_set_norequest(struct irq_desc *desc) | |||
94 | desc->status_use_accessors |= _IRQ_NOREQUEST; | 96 | desc->status_use_accessors |= _IRQ_NOREQUEST; |
95 | } | 97 | } |
96 | 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; | ||
112 | } | ||
113 | |||
97 | static inline bool irq_settings_can_probe(struct irq_desc *desc) | 114 | static inline bool irq_settings_can_probe(struct irq_desc *desc) |
98 | { | 115 | { |
99 | return !(desc->status_use_accessors & _IRQ_NOPROBE); | 116 | return !(desc->status_use_accessors & _IRQ_NOPROBE); |