diff options
| -rw-r--r-- | Documentation/DocBook/genericirq.tmpl | 82 | ||||
| -rw-r--r-- | arch/arm/mach-davinci/irq.c | 93 | ||||
| -rw-r--r-- | include/linux/irq.h | 179 | ||||
| -rw-r--r-- | include/linux/irqdesc.h | 6 | ||||
| -rw-r--r-- | kernel/irq/Makefile | 1 | ||||
| -rw-r--r-- | kernel/irq/chip.c | 1 | ||||
| -rw-r--r-- | kernel/irq/debug.h | 1 | ||||
| -rw-r--r-- | kernel/irq/generic-chip.c | 354 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 3 | ||||
| -rw-r--r-- | kernel/irq/settings.h | 17 |
10 files changed, 607 insertions, 130 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/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c index e6269a6e0014..bfe68ec4e1a6 100644 --- a/arch/arm/mach-davinci/irq.c +++ b/arch/arm/mach-davinci/irq.c | |||
| @@ -29,8 +29,6 @@ | |||
| 29 | #include <mach/common.h> | 29 | #include <mach/common.h> |
| 30 | #include <asm/mach/irq.h> | 30 | #include <asm/mach/irq.h> |
| 31 | 31 | ||
| 32 | #define IRQ_BIT(irq) ((irq) & 0x1f) | ||
| 33 | |||
| 34 | #define FIQ_REG0_OFFSET 0x0000 | 32 | #define FIQ_REG0_OFFSET 0x0000 |
| 35 | #define FIQ_REG1_OFFSET 0x0004 | 33 | #define FIQ_REG1_OFFSET 0x0004 |
| 36 | #define IRQ_REG0_OFFSET 0x0008 | 34 | #define IRQ_REG0_OFFSET 0x0008 |
| @@ -42,78 +40,33 @@ | |||
| 42 | #define IRQ_INTPRI0_REG_OFFSET 0x0030 | 40 | #define IRQ_INTPRI0_REG_OFFSET 0x0030 |
| 43 | #define IRQ_INTPRI7_REG_OFFSET 0x004C | 41 | #define IRQ_INTPRI7_REG_OFFSET 0x004C |
| 44 | 42 | ||
| 45 | static inline unsigned int davinci_irq_readl(int offset) | ||
| 46 | { | ||
| 47 | return __raw_readl(davinci_intc_base + offset); | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline void davinci_irq_writel(unsigned long value, int offset) | 43 | static inline void davinci_irq_writel(unsigned long value, int offset) |
| 51 | { | 44 | { |
| 52 | __raw_writel(value, davinci_intc_base + offset); | 45 | __raw_writel(value, davinci_intc_base + offset); |
| 53 | } | 46 | } |
| 54 | 47 | ||
| 55 | /* Disable interrupt */ | 48 | static __init void |
| 56 | static void davinci_mask_irq(struct irq_data *d) | 49 | davinci_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) |
| 57 | { | 50 | { |
| 58 | unsigned int mask; | 51 | struct irq_chip_generic *gc; |
| 59 | u32 l; | 52 | struct irq_chip_type *ct; |
| 60 | 53 | ||
| 61 | mask = 1 << IRQ_BIT(d->irq); | 54 | gc = irq_alloc_generic_chip("AINTC", 1, irq_start, base, handle_edge_irq); |
| 62 | 55 | ct = gc->chip_types; | |
| 63 | if (d->irq > 31) { | 56 | ct->chip.irq_ack = irq_gc_ack; |
| 64 | l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET); | 57 | ct->chip.irq_mask = irq_gc_mask_clr_bit; |
| 65 | l &= ~mask; | 58 | ct->chip.irq_unmask = irq_gc_mask_set_bit; |
| 66 | davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET); | 59 | |
| 67 | } else { | 60 | ct->regs.ack = IRQ_REG0_OFFSET; |
| 68 | l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET); | 61 | ct->regs.mask = IRQ_ENT_REG0_OFFSET; |
| 69 | l &= ~mask; | 62 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, |
| 70 | davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET); | 63 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); |
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | /* Enable interrupt */ | ||
| 75 | static void davinci_unmask_irq(struct irq_data *d) | ||
| 76 | { | ||
| 77 | unsigned int mask; | ||
| 78 | u32 l; | ||
| 79 | |||
| 80 | mask = 1 << IRQ_BIT(d->irq); | ||
| 81 | |||
| 82 | if (d->irq > 31) { | ||
| 83 | l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET); | ||
| 84 | l |= mask; | ||
| 85 | davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET); | ||
| 86 | } else { | ||
| 87 | l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET); | ||
| 88 | l |= mask; | ||
| 89 | davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET); | ||
| 90 | } | ||
| 91 | } | 64 | } |
| 92 | 65 | ||
| 93 | /* EOI interrupt */ | ||
| 94 | static void davinci_ack_irq(struct irq_data *d) | ||
| 95 | { | ||
| 96 | unsigned int mask; | ||
| 97 | |||
| 98 | mask = 1 << IRQ_BIT(d->irq); | ||
| 99 | |||
| 100 | if (d->irq > 31) | ||
| 101 | davinci_irq_writel(mask, IRQ_REG1_OFFSET); | ||
| 102 | else | ||
| 103 | davinci_irq_writel(mask, IRQ_REG0_OFFSET); | ||
| 104 | } | ||
| 105 | |||
| 106 | static struct irq_chip davinci_irq_chip_0 = { | ||
| 107 | .name = "AINTC", | ||
| 108 | .irq_ack = davinci_ack_irq, | ||
| 109 | .irq_mask = davinci_mask_irq, | ||
| 110 | .irq_unmask = davinci_unmask_irq, | ||
| 111 | }; | ||
| 112 | |||
| 113 | /* ARM Interrupt Controller Initialization */ | 66 | /* ARM Interrupt Controller Initialization */ |
| 114 | void __init davinci_irq_init(void) | 67 | void __init davinci_irq_init(void) |
| 115 | { | 68 | { |
| 116 | unsigned i; | 69 | unsigned i, j; |
| 117 | const u8 *davinci_def_priorities = davinci_soc_info.intc_irq_prios; | 70 | const u8 *davinci_def_priorities = davinci_soc_info.intc_irq_prios; |
| 118 | 71 | ||
| 119 | davinci_intc_type = DAVINCI_INTC_TYPE_AINTC; | 72 | davinci_intc_type = DAVINCI_INTC_TYPE_AINTC; |
| @@ -144,7 +97,6 @@ void __init davinci_irq_init(void) | |||
| 144 | davinci_irq_writel(~0x0, IRQ_REG1_OFFSET); | 97 | davinci_irq_writel(~0x0, IRQ_REG1_OFFSET); |
| 145 | 98 | ||
| 146 | for (i = IRQ_INTPRI0_REG_OFFSET; i <= IRQ_INTPRI7_REG_OFFSET; i += 4) { | 99 | for (i = IRQ_INTPRI0_REG_OFFSET; i <= IRQ_INTPRI7_REG_OFFSET; i += 4) { |
| 147 | unsigned j; | ||
| 148 | u32 pri; | 100 | u32 pri; |
| 149 | 101 | ||
| 150 | for (j = 0, pri = 0; j < 32; j += 4, davinci_def_priorities++) | 102 | for (j = 0, pri = 0; j < 32; j += 4, davinci_def_priorities++) |
| @@ -152,13 +104,8 @@ void __init davinci_irq_init(void) | |||
| 152 | davinci_irq_writel(pri, i); | 104 | davinci_irq_writel(pri, i); |
| 153 | } | 105 | } |
| 154 | 106 | ||
| 155 | /* set up genirq dispatch for ARM INTC */ | 107 | for (i = 0, j = 0; i < davinci_soc_info.intc_irq_num; i += 32, j += 0x04) |
| 156 | for (i = 0; i < davinci_soc_info.intc_irq_num; i++) { | 108 | davinci_alloc_gc(davinci_intc_base + j, i, 32); |
| 157 | irq_set_chip(i, &davinci_irq_chip_0); | 109 | |
| 158 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); | 110 | irq_set_handler(IRQ_TINT1_TINT34, handle_level_irq); |
| 159 | if (i != IRQ_TINT1_TINT34) | ||
| 160 | irq_set_handler(i, handle_edge_irq); | ||
| 161 | else | ||
| 162 | irq_set_handler(i, handle_level_irq); | ||
| 163 | } | ||
| 164 | } | 111 | } |
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..c70b1aa4b93a 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 |
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile index 54329cd7b3ee..e7a13bd3316a 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-y += 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..52d856d513ff 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -573,6 +573,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
| 573 | if (handle != handle_bad_irq && is_chained) { | 573 | if (handle != handle_bad_irq && is_chained) { |
| 574 | irq_settings_set_noprobe(desc); | 574 | irq_settings_set_noprobe(desc); |
| 575 | irq_settings_set_norequest(desc); | 575 | irq_settings_set_norequest(desc); |
| 576 | irq_settings_set_nothread(desc); | ||
| 576 | irq_startup(desc); | 577 | irq_startup(desc); |
| 577 | } | 578 | } |
| 578 | out: | 579 | out: |
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/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); |
