Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: ucb1400_ts - convert to threaded IRQ

Instead of manually create and handler kernel thread switch to threaded
IRQ and let kernel IRQ core manage thread for us.

Acked-by: Marek Vasut <marek.vasut@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

+115 -126
+113 -122
drivers/input/touchscreen/ucb1400_ts.c
··· 20 20 21 21 #include <linux/module.h> 22 22 #include <linux/init.h> 23 - #include <linux/completion.h> 24 23 #include <linux/delay.h> 24 + #include <linux/sched.h> 25 + #include <linux/wait.h> 25 26 #include <linux/input.h> 26 27 #include <linux/device.h> 27 28 #include <linux/interrupt.h> 28 - #include <linux/suspend.h> 29 - #include <linux/kthread.h> 30 - #include <linux/freezer.h> 31 29 #include <linux/ucb1400.h> 30 + 31 + #define UCB1400_TS_POLL_PERIOD 10 /* ms */ 32 32 33 33 static int adcsync; 34 34 static int ts_delay = 55; /* us */ 35 35 static int ts_delay_pressure; /* us */ 36 36 37 37 /* Switch to interrupt mode. */ 38 - static void ucb1400_ts_mode_int(struct snd_ac97 *ac97) 38 + static void ucb1400_ts_mode_int(struct ucb1400_ts *ucb) 39 39 { 40 - ucb1400_reg_write(ac97, UCB_TS_CR, 40 + ucb1400_reg_write(ucb->ac97, UCB_TS_CR, 41 41 UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | 42 42 UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | 43 43 UCB_TS_CR_MODE_INT); ··· 53 53 UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | 54 54 UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | 55 55 UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); 56 + 56 57 udelay(ts_delay_pressure); 58 + 57 59 return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPY, adcsync); 58 60 } 59 61 ··· 129 127 return ucb1400_adc_read(ucb->ac97, 0, adcsync); 130 128 } 131 129 132 - static int ucb1400_ts_pen_up(struct snd_ac97 *ac97) 130 + static int ucb1400_ts_pen_up(struct ucb1400_ts *ucb) 133 131 { 134 - unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); 132 + unsigned short val = ucb1400_reg_read(ucb->ac97, UCB_TS_CR); 135 133 136 134 return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); 137 135 } 138 136 139 - static void ucb1400_ts_irq_enable(struct snd_ac97 *ac97) 137 + static void ucb1400_ts_irq_enable(struct ucb1400_ts *ucb) 140 138 { 141 - ucb1400_reg_write(ac97, UCB_IE_CLEAR, UCB_IE_TSPX); 142 - ucb1400_reg_write(ac97, UCB_IE_CLEAR, 0); 143 - ucb1400_reg_write(ac97, UCB_IE_FAL, UCB_IE_TSPX); 139 + ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, UCB_IE_TSPX); 140 + ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); 141 + ucb1400_reg_write(ucb->ac97, UCB_IE_FAL, UCB_IE_TSPX); 144 142 } 145 143 146 - static void ucb1400_ts_irq_disable(struct snd_ac97 *ac97) 144 + static void ucb1400_ts_irq_disable(struct ucb1400_ts *ucb) 147 145 { 148 - ucb1400_reg_write(ac97, UCB_IE_FAL, 0); 146 + ucb1400_reg_write(ucb->ac97, UCB_IE_FAL, 0); 149 147 } 150 148 151 - static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 y) 149 + static void ucb1400_ts_report_event(struct input_dev *idev, u16 pressure, u16 x, u16 y) 152 150 { 153 151 input_report_abs(idev, ABS_X, x); 154 152 input_report_abs(idev, ABS_Y, y); ··· 164 162 input_sync(idev); 165 163 } 166 164 167 - static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb) 165 + static void ucb1400_clear_pending_irq(struct ucb1400_ts *ucb) 168 166 { 169 167 unsigned int isr; 170 168 ··· 173 171 ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); 174 172 175 173 if (isr & UCB_IE_TSPX) 176 - ucb1400_ts_irq_disable(ucb->ac97); 174 + ucb1400_ts_irq_disable(ucb); 177 175 else 178 - dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr); 179 - enable_irq(ucb->irq); 176 + dev_dbg(&ucb->ts_idev->dev, 177 + "ucb1400: unexpected IE_STATUS = %#x\n", isr); 180 178 } 181 179 182 - static int ucb1400_ts_thread(void *_ucb) 180 + /* 181 + * A restriction with interrupts exists when using the ucb1400, as 182 + * the codec read/write routines may sleep while waiting for codec 183 + * access completion and uses semaphores for access control to the 184 + * AC97 bus. Therefore the driver is forced to use threaded interrupt 185 + * handler. 186 + */ 187 + static irqreturn_t ucb1400_irq(int irqnr, void *devid) 183 188 { 184 - struct ucb1400_ts *ucb = _ucb; 185 - struct task_struct *tsk = current; 186 - int valid = 0; 187 - struct sched_param param = { .sched_priority = 1 }; 189 + struct ucb1400_ts *ucb = devid; 190 + unsigned int x, y, p; 191 + bool penup; 188 192 189 - sched_setscheduler(tsk, SCHED_FIFO, &param); 193 + if (unlikely(irqnr != ucb->irq)) 194 + return IRQ_NONE; 190 195 191 - set_freezable(); 192 - while (!kthread_should_stop()) { 193 - unsigned int x, y, p; 194 - long timeout; 196 + ucb1400_clear_pending_irq(ucb); 195 197 196 - ucb->ts_restart = 0; 198 + /* Start with a small delay before checking pendown state */ 199 + msleep(UCB1400_TS_POLL_PERIOD); 197 200 198 - if (ucb->irq_pending) { 199 - ucb->irq_pending = 0; 200 - ucb1400_handle_pending_irq(ucb); 201 - } 201 + while (!ucb->stopped && !(penup = ucb1400_ts_pen_up(ucb))) { 202 202 203 203 ucb1400_adc_enable(ucb->ac97); 204 204 x = ucb1400_ts_read_xpos(ucb); ··· 208 204 p = ucb1400_ts_read_pressure(ucb); 209 205 ucb1400_adc_disable(ucb->ac97); 210 206 211 - /* Switch back to interrupt mode. */ 212 - ucb1400_ts_mode_int(ucb->ac97); 207 + ucb1400_ts_report_event(ucb->ts_idev, p, x, y); 213 208 214 - msleep(10); 215 - 216 - if (ucb1400_ts_pen_up(ucb->ac97)) { 217 - ucb1400_ts_irq_enable(ucb->ac97); 218 - 219 - /* 220 - * If we spat out a valid sample set last time, 221 - * spit out a "pen off" sample here. 222 - */ 223 - if (valid) { 224 - ucb1400_ts_event_release(ucb->ts_idev); 225 - valid = 0; 226 - } 227 - 228 - timeout = MAX_SCHEDULE_TIMEOUT; 229 - } else { 230 - valid = 1; 231 - ucb1400_ts_evt_add(ucb->ts_idev, p, x, y); 232 - timeout = msecs_to_jiffies(10); 233 - } 234 - 235 - wait_event_freezable_timeout(ucb->ts_wait, 236 - ucb->irq_pending || ucb->ts_restart || 237 - kthread_should_stop(), timeout); 209 + wait_event_timeout(ucb->ts_wait, ucb->stopped, 210 + msecs_to_jiffies(UCB1400_TS_POLL_PERIOD)); 238 211 } 239 212 240 - /* Send the "pen off" if we are stopping with the pen still active */ 241 - if (valid) 242 - ucb1400_ts_event_release(ucb->ts_idev); 213 + ucb1400_ts_event_release(ucb->ts_idev); 243 214 244 - ucb->ts_task = NULL; 245 - return 0; 215 + if (!ucb->stopped) { 216 + /* Switch back to interrupt mode. */ 217 + ucb1400_ts_mode_int(ucb); 218 + ucb1400_ts_irq_enable(ucb); 219 + } 220 + 221 + return IRQ_HANDLED; 246 222 } 247 223 248 - /* 249 - * A restriction with interrupts exists when using the ucb1400, as 250 - * the codec read/write routines may sleep while waiting for codec 251 - * access completion and uses semaphores for access control to the 252 - * AC97 bus. A complete codec read cycle could take anywhere from 253 - * 60 to 100uSec so we *definitely* don't want to spin inside the 254 - * interrupt handler waiting for codec access. So, we handle the 255 - * interrupt by scheduling a RT kernel thread to run in process 256 - * context instead of interrupt context. 257 - */ 258 - static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid) 224 + static void ucb1400_ts_stop(struct ucb1400_ts *ucb) 259 225 { 260 - struct ucb1400_ts *ucb = devid; 226 + /* Signal IRQ thread to stop polling and disable the handler. */ 227 + ucb->stopped = true; 228 + mb(); 229 + wake_up(&ucb->ts_wait); 230 + disable_irq(ucb->irq); 261 231 262 - if (irqnr == ucb->irq) { 263 - disable_irq_nosync(ucb->irq); 264 - ucb->irq_pending = 1; 265 - wake_up(&ucb->ts_wait); 266 - return IRQ_HANDLED; 267 - } 268 - return IRQ_NONE; 232 + ucb1400_ts_irq_disable(ucb); 233 + ucb1400_reg_write(ucb->ac97, UCB_TS_CR, 0); 234 + } 235 + 236 + /* Must be called with ts->lock held */ 237 + static void ucb1400_ts_start(struct ucb1400_ts *ucb) 238 + { 239 + /* Tell IRQ thread that it may poll the device. */ 240 + ucb->stopped = false; 241 + mb(); 242 + 243 + ucb1400_ts_mode_int(ucb); 244 + ucb1400_ts_irq_enable(ucb); 245 + 246 + enable_irq(ucb->irq); 269 247 } 270 248 271 249 static int ucb1400_ts_open(struct input_dev *idev) 272 250 { 273 251 struct ucb1400_ts *ucb = input_get_drvdata(idev); 274 - int ret = 0; 275 252 276 - BUG_ON(ucb->ts_task); 253 + ucb1400_ts_start(ucb); 277 254 278 - ucb->ts_task = kthread_run(ucb1400_ts_thread, ucb, "UCB1400_ts"); 279 - if (IS_ERR(ucb->ts_task)) { 280 - ret = PTR_ERR(ucb->ts_task); 281 - ucb->ts_task = NULL; 282 - } 283 - 284 - return ret; 255 + return 0; 285 256 } 286 257 287 258 static void ucb1400_ts_close(struct input_dev *idev) 288 259 { 289 260 struct ucb1400_ts *ucb = input_get_drvdata(idev); 290 261 291 - if (ucb->ts_task) 292 - kthread_stop(ucb->ts_task); 293 - 294 - ucb1400_ts_irq_disable(ucb->ac97); 295 - ucb1400_reg_write(ucb->ac97, UCB_TS_CR, 0); 262 + ucb1400_ts_stop(ucb); 296 263 } 297 264 298 265 #ifndef NO_IRQ ··· 317 342 return 0; 318 343 } 319 344 320 - static int __devinit ucb1400_ts_probe(struct platform_device *dev) 345 + static int __devinit ucb1400_ts_probe(struct platform_device *pdev) 321 346 { 347 + struct ucb1400_ts *ucb = pdev->dev.platform_data; 322 348 int error, x_res, y_res; 323 349 u16 fcsr; 324 - struct ucb1400_ts *ucb = dev->dev.platform_data; 325 350 326 351 ucb->ts_idev = input_allocate_device(); 327 352 if (!ucb->ts_idev) { ··· 337 362 goto err_free_devs; 338 363 } 339 364 } 365 + printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq); 340 366 341 367 init_waitqueue_head(&ucb->ts_wait); 342 368 343 - error = request_irq(ucb->irq, ucb1400_hard_irq, IRQF_TRIGGER_RISING, 344 - "UCB1400", ucb); 345 - if (error) { 346 - printk(KERN_ERR "ucb1400: unable to grab irq%d: %d\n", 347 - ucb->irq, error); 348 - goto err_free_devs; 349 - } 350 - printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq); 351 - 352 369 input_set_drvdata(ucb->ts_idev, ucb); 353 370 354 - ucb->ts_idev->dev.parent = &dev->dev; 371 + ucb->ts_idev->dev.parent = &pdev->dev; 355 372 ucb->ts_idev->name = "UCB1400 touchscreen interface"; 356 373 ucb->ts_idev->id.vendor = ucb1400_reg_read(ucb->ac97, 357 374 AC97_VENDOR_ID1); ··· 371 404 input_set_abs_params(ucb->ts_idev, ABS_Y, 0, y_res, 0, 0); 372 405 input_set_abs_params(ucb->ts_idev, ABS_PRESSURE, 0, 0, 0, 0); 373 406 407 + ucb1400_ts_stop(ucb); 408 + 409 + error = request_threaded_irq(ucb->irq, NULL, ucb1400_irq, 410 + IRQF_TRIGGER_RISING | IRQF_ONESHOT, 411 + "UCB1400", ucb); 412 + if (error) { 413 + printk(KERN_ERR "ucb1400: unable to grab irq%d: %d\n", 414 + ucb->irq, error); 415 + goto err_free_devs; 416 + } 417 + 374 418 error = input_register_device(ucb->ts_idev); 375 419 if (error) 376 420 goto err_free_irq; ··· 396 418 return error; 397 419 } 398 420 399 - static int __devexit ucb1400_ts_remove(struct platform_device *dev) 421 + static int __devexit ucb1400_ts_remove(struct platform_device *pdev) 400 422 { 401 - struct ucb1400_ts *ucb = dev->dev.platform_data; 423 + struct ucb1400_ts *ucb = pdev->dev.platform_data; 402 424 403 425 free_irq(ucb->irq, ucb); 404 426 input_unregister_device(ucb->ts_idev); ··· 407 429 } 408 430 409 431 #ifdef CONFIG_PM_SLEEP 432 + static int ucb1400_ts_suspend(struct device *dev) 433 + { 434 + struct ucb1400_ts *ucb = dev->platform_data; 435 + struct input_dev *idev = ucb->ts_idev; 436 + 437 + mutex_lock(&idev->mutex); 438 + 439 + if (idev->users) 440 + ucb1400_ts_start(ucb); 441 + 442 + mutex_unlock(&idev->mutex); 443 + return 0; 444 + } 445 + 410 446 static int ucb1400_ts_resume(struct device *dev) 411 447 { 412 448 struct ucb1400_ts *ucb = dev->platform_data; 449 + struct input_dev *idev = ucb->ts_idev; 413 450 414 - if (ucb->ts_task) { 415 - /* 416 - * Restart the TS thread to ensure the 417 - * TS interrupt mode is set up again 418 - * after sleep. 419 - */ 420 - ucb->ts_restart = 1; 421 - wake_up(&ucb->ts_wait); 422 - } 451 + mutex_lock(&idev->mutex); 452 + 453 + if (idev->users) 454 + ucb1400_ts_stop(ucb); 455 + 456 + mutex_unlock(&idev->mutex); 423 457 return 0; 424 458 } 425 459 #endif 426 460 427 - static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops, NULL, ucb1400_ts_resume); 461 + static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops, 462 + ucb1400_ts_suspend, ucb1400_ts_resume); 428 463 429 464 static struct platform_driver ucb1400_ts_driver = { 430 465 .probe = ucb1400_ts_probe,
+2 -4
include/linux/ucb1400.h
··· 96 96 97 97 struct ucb1400_ts { 98 98 struct input_dev *ts_idev; 99 - struct task_struct *ts_task; 100 99 int id; 101 - wait_queue_head_t ts_wait; 102 - unsigned int ts_restart:1; 103 100 int irq; 104 - unsigned int irq_pending; /* not bit field shared */ 105 101 struct snd_ac97 *ac97; 102 + wait_queue_head_t ts_wait; 103 + bool stopped; 106 104 }; 107 105 108 106 struct ucb1400 {