Input: wm831x-ts - fix races with IRQ management

If the WM831x pen down and data IRQs run in parallel it is possible for the
data and pen down IRQs to deadlock themselves as one is part way through
disabling its operation while the other is part way through enabling. Fix
this by always disabling the pen down interrupt while data is active and
vice versa. When a changeover is required we disable the IRQ that is to
be stopped then schedule work that will enable the new IRQ.

We need to handle the data flow in the data IRQ as the readback from the
device needs to be ordered correctly with the IRQ for robust operation.

This also fixes an issue when using the built in IRQs due to enable_irq()
not being valid from interrupt context on an interrupt controller with bus
operations like the built in IRQ controller - this issue may also have
affected other interrupt controllers. We can't rely on having the data
and pen down IRQs available via GPIOs on the CPU on every system.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by Mark Brown and committed by Dmitry Torokhov f5346668 c36b58e8

+49 -5
+49 -5
drivers/input/touchscreen/wm831x-ts.c
··· 68 unsigned int pd_irq; 69 bool pressure; 70 bool pen_down; 71 }; 72 73 static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data) 74 { ··· 125 } 126 127 if (!wm831x_ts->pen_down) { 128 disable_irq_nosync(wm831x_ts->data_irq); 129 130 /* Don't need data any more */ ··· 146 ABS_PRESSURE, 0); 147 148 input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0); 149 } 150 151 input_sync(wm831x_ts->input_dev); ··· 160 struct wm831x_ts *wm831x_ts = irq_data; 161 struct wm831x *wm831x = wm831x_ts->wm831x; 162 int ena = 0; 163 164 /* Start collecting data */ 165 if (wm831x_ts->pressure) ··· 181 WM831X_TCHPD_EINT, WM831X_TCHPD_EINT); 182 183 wm831x_ts->pen_down = true; 184 - enable_irq(wm831x_ts->data_irq); 185 186 return IRQ_HANDLED; 187 } ··· 210 struct wm831x_ts *wm831x_ts = input_get_drvdata(idev); 211 struct wm831x *wm831x = wm831x_ts->wm831x; 212 213 wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, 214 - WM831X_TCH_ENA | WM831X_TCH_CVT_ENA | 215 - WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | 216 - WM831X_TCH_Z_ENA, 0); 217 218 - if (wm831x_ts->pen_down) 219 disable_irq(wm831x_ts->data_irq); 220 } 221 222 static __devinit int wm831x_ts_probe(struct platform_device *pdev) ··· 255 256 wm831x_ts->wm831x = wm831x; 257 wm831x_ts->input_dev = input_dev; 258 259 /* 260 * If we have a direct IRQ use it, otherwise use the interrupt
··· 68 unsigned int pd_irq; 69 bool pressure; 70 bool pen_down; 71 + struct work_struct pd_data_work; 72 }; 73 + 74 + static void wm831x_pd_data_work(struct work_struct *work) 75 + { 76 + struct wm831x_ts *wm831x_ts = 77 + container_of(work, struct wm831x_ts, pd_data_work); 78 + 79 + if (wm831x_ts->pen_down) { 80 + enable_irq(wm831x_ts->data_irq); 81 + dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n"); 82 + } else { 83 + enable_irq(wm831x_ts->pd_irq); 84 + dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n"); 85 + } 86 + } 87 88 static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data) 89 { ··· 110 } 111 112 if (!wm831x_ts->pen_down) { 113 + /* Switch from data to pen down */ 114 + dev_dbg(wm831x->dev, "IRQ DATA->PD\n"); 115 + 116 disable_irq_nosync(wm831x_ts->data_irq); 117 118 /* Don't need data any more */ ··· 128 ABS_PRESSURE, 0); 129 130 input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0); 131 + 132 + schedule_work(&wm831x_ts->pd_data_work); 133 } 134 135 input_sync(wm831x_ts->input_dev); ··· 140 struct wm831x_ts *wm831x_ts = irq_data; 141 struct wm831x *wm831x = wm831x_ts->wm831x; 142 int ena = 0; 143 + 144 + if (wm831x_ts->pen_down) 145 + return IRQ_HANDLED; 146 + 147 + disable_irq_nosync(wm831x_ts->pd_irq); 148 149 /* Start collecting data */ 150 if (wm831x_ts->pressure) ··· 156 WM831X_TCHPD_EINT, WM831X_TCHPD_EINT); 157 158 wm831x_ts->pen_down = true; 159 + 160 + /* Switch from pen down to data */ 161 + dev_dbg(wm831x->dev, "IRQ PD->DATA\n"); 162 + schedule_work(&wm831x_ts->pd_data_work); 163 164 return IRQ_HANDLED; 165 } ··· 182 struct wm831x_ts *wm831x_ts = input_get_drvdata(idev); 183 struct wm831x *wm831x = wm831x_ts->wm831x; 184 185 + /* Shut the controller down, disabling all other functionality too */ 186 wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1, 187 + WM831X_TCH_ENA | WM831X_TCH_X_ENA | 188 + WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0); 189 190 + /* Make sure any pending IRQs are done, the above will prevent 191 + * new ones firing. 192 + */ 193 + synchronize_irq(wm831x_ts->data_irq); 194 + synchronize_irq(wm831x_ts->pd_irq); 195 + 196 + /* Make sure the IRQ completion work is quiesced */ 197 + flush_work_sync(&wm831x_ts->pd_data_work); 198 + 199 + /* If we ended up with the pen down then make sure we revert back 200 + * to pen detection state for the next time we start up. 201 + */ 202 + if (wm831x_ts->pen_down) { 203 disable_irq(wm831x_ts->data_irq); 204 + enable_irq(wm831x_ts->pd_irq); 205 + wm831x_ts->pen_down = false; 206 + } 207 } 208 209 static __devinit int wm831x_ts_probe(struct platform_device *pdev) ··· 212 213 wm831x_ts->wm831x = wm831x; 214 wm831x_ts->input_dev = input_dev; 215 + INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work); 216 217 /* 218 * If we have a direct IRQ use it, otherwise use the interrupt