]>
Commit | Line | Data |
---|---|---|
f232e200 GKH |
1 | From a09b659cd68c10ec6a30cb91ebd2c327fcd5bfe5 Mon Sep 17 00:00:00 2001 |
2 | From: Russell King <linux@arm.linux.org.uk> | |
3 | Date: Mon, 5 Mar 2012 15:07:25 -0800 | |
4 | Subject: genirq: Fix long-term regression in genirq irq_set_irq_type() handling | |
5 | ||
6 | From: Russell King <linux@arm.linux.org.uk> | |
7 | ||
8 | commit a09b659cd68c10ec6a30cb91ebd2c327fcd5bfe5 upstream. | |
9 | ||
10 | In 2008, commit 0c5d1eb77a8be ("genirq: record trigger type") modified the | |
11 | way set_irq_type() handles the 'no trigger' condition. However, this has | |
12 | an adverse effect on PCMCIA support on Intel StrongARM and probably PXA | |
13 | platforms. | |
14 | ||
15 | PCMCIA has several status signals on the socket which can trigger | |
16 | interrupts; some of these status signals depend on the card's mode | |
17 | (whether it is configured in memory or IO mode). For example, cards have | |
18 | a 'Ready/IRQ' signal: in memory mode, this provides an indication to | |
19 | PCMCIA that the card has finished its power up initialization. In IO | |
20 | mode, it provides the device interrupt signal. Other status signals | |
21 | switch between on-board battery status and loud speaker output. | |
22 | ||
23 | In classical PCMCIA implementations, where you have a specific socket | |
24 | controller, the controller provides a method to mask interrupts from the | |
25 | socket, and importantly ignore any state transitions on the pins which | |
26 | correspond with interrupts once masked. This masking prevents unwanted | |
27 | events caused by the removal and application of socket power being | |
28 | forwarded. | |
29 | ||
30 | However, on platforms where there is no socket controller, the PCMCIA | |
31 | status and interrupt signals are routed to standard edge-triggered GPIOs. | |
32 | These GPIOs can be configured to interrupt on rising edge, falling edge, | |
33 | or never. This is where the problems start. | |
34 | ||
35 | Edge triggered interrupts are required to record events while disabled via | |
36 | the usual methods of {free,request,disable,enable}_irq() to prevent | |
37 | problems with dropped interrupts (eg, the 8390 driver uses disable_irq() | |
38 | to defer the delivery of interrupts). As a result, these interfaces can | |
39 | not be used to implement the desired behaviour. | |
40 | ||
41 | The side effect of this is that if the 'Ready/IRQ' GPIO is disabled via | |
42 | disable_irq() on suspend, and enabled via enable_irq() after resume, we | |
43 | will record the state transitions caused by powering events as valid | |
44 | interrupts, and foward them to the card driver, which may attempt to | |
45 | access a card which is not powered up. | |
46 | ||
47 | This leads delays resume while drivers spin in their interrupt handlers, | |
48 | and complaints from drivers before they realize what's happened. | |
49 | ||
50 | Moreover, in the case of the 'Ready/IRQ' signal, this is requested and | |
51 | freed by the card driver itself; the PCMCIA core has no idea whether the | |
52 | interrupt is requested, and, therefore, whether a call to disable_irq() | |
53 | would be valid. (We tried this around 2.4.17 / 2.5.1 kernel era, and | |
54 | ended up throwing it out because of this problem.) | |
55 | ||
56 | Therefore, it was decided back in around 2002 to disable the edge | |
57 | triggering instead, resulting in all state transitions on the GPIO being | |
58 | ignored. That's what we actually need the hardware to do. | |
59 | ||
60 | The commit above changes this behaviour; it explicitly prevents the 'no | |
61 | trigger' state being selected. | |
62 | ||
63 | The reason that request_irq() does not accept the 'no trigger' state is | |
64 | for compatibility with existing drivers which do not provide their desired | |
65 | triggering configuration. The set_irq_type() function is 'new' and not | |
66 | used by non-trigger aware drivers. | |
67 | ||
68 | Therefore, revert this change, and restore previously working platforms | |
69 | back to their former state. | |
70 | ||
71 | Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | |
72 | Cc: linux@arm.linux.org.uk | |
73 | Cc: Ingo Molnar <mingo@elte.hu> | |
74 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
75 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
76 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
77 | ||
78 | --- | |
79 | kernel/irq/chip.c | 3 +-- | |
80 | 1 file changed, 1 insertion(+), 2 deletions(-) | |
81 | ||
82 | --- a/kernel/irq/chip.c | |
83 | +++ b/kernel/irq/chip.c | |
84 | @@ -61,8 +61,7 @@ int irq_set_irq_type(unsigned int irq, u | |
85 | return -EINVAL; | |
86 | ||
87 | type &= IRQ_TYPE_SENSE_MASK; | |
88 | - if (type != IRQ_TYPE_NONE) | |
89 | - ret = __irq_set_trigger(desc, irq, type); | |
90 | + ret = __irq_set_trigger(desc, irq, type); | |
91 | irq_put_desc_busunlock(desc, flags); | |
92 | return ret; | |
93 | } |