aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-12-24 03:02:16 -0500
committerLen Brown <len.brown@intel.com>2009-12-24 14:45:50 -0500
commit9593bd07ec8eaaa30aba4281b2b3273282fc344f (patch)
tree1e92ba54182434dbeb4122c6bb5530dfb1a4c86e /drivers
parentfcb11235d3910c39afece52f6e106a9ca565d34b (diff)
sony-laptop - remove private workqueue, use keventd instead
If we reschedule work instead of having work function sleep for 10 msecs between reads from kfifo we can safely use the main workqueue (keventd) and not bother with creating driver-private one. Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/x86/sony-laptop.c71
1 files changed, 39 insertions, 32 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 5af53340da6f..c42d35ba73d6 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -145,7 +145,6 @@ struct sony_laptop_input_s {
145 struct input_dev *key_dev; 145 struct input_dev *key_dev;
146 struct kfifo fifo; 146 struct kfifo fifo;
147 spinlock_t fifo_lock; 147 spinlock_t fifo_lock;
148 struct workqueue_struct *wq;
149}; 148};
150 149
151static struct sony_laptop_input_s sony_laptop_input = { 150static struct sony_laptop_input_s sony_laptop_input = {
@@ -301,18 +300,28 @@ static int sony_laptop_input_keycode_map[] = {
301/* release buttons after a short delay if pressed */ 300/* release buttons after a short delay if pressed */
302static void do_sony_laptop_release_key(struct work_struct *work) 301static void do_sony_laptop_release_key(struct work_struct *work)
303{ 302{
303 struct delayed_work *dwork =
304 container_of(work, struct delayed_work, work);
304 struct sony_laptop_keypress kp; 305 struct sony_laptop_keypress kp;
306 unsigned long flags;
307
308 spin_lock_irqsave(&sony_laptop_input.fifo_lock, flags);
305 309
306 while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, 310 if (kfifo_out(&sony_laptop_input.fifo,
307 sizeof(kp), &sony_laptop_input.fifo_lock) 311 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
308 == sizeof(kp)) {
309 msleep(10);
310 input_report_key(kp.dev, kp.key, 0); 312 input_report_key(kp.dev, kp.key, 0);
311 input_sync(kp.dev); 313 input_sync(kp.dev);
312 } 314 }
315
316 /* If there is something in the fifo schedule next release. */
317 if (kfifo_len(&sony_laptop_input.fifo) != 0)
318 schedule_delayed_work(dwork, msecs_to_jiffies(10));
319
320 spin_unlock_irqrestore(&sony_laptop_input.fifo_lock, flags);
313} 321}
314static DECLARE_WORK(sony_laptop_release_key_work, 322
315 do_sony_laptop_release_key); 323static DECLARE_DELAYED_WORK(sony_laptop_release_key_work,
324 do_sony_laptop_release_key);
316 325
317/* forward event to the input subsystem */ 326/* forward event to the input subsystem */
318static void sony_laptop_report_input_event(u8 event) 327static void sony_laptop_report_input_event(u8 event)
@@ -366,13 +375,13 @@ static void sony_laptop_report_input_event(u8 event)
366 /* we emit the scancode so we can always remap the key */ 375 /* we emit the scancode so we can always remap the key */
367 input_event(kp.dev, EV_MSC, MSC_SCAN, event); 376 input_event(kp.dev, EV_MSC, MSC_SCAN, event);
368 input_sync(kp.dev); 377 input_sync(kp.dev);
369 kfifo_in_locked(&sony_laptop_input.fifo,
370 (unsigned char *)&kp, sizeof(kp),
371 &sony_laptop_input.fifo_lock);
372 378
373 if (!work_pending(&sony_laptop_release_key_work)) 379 /* schedule key release */
374 queue_work(sony_laptop_input.wq, 380 kfifo_in_locked(&sony_laptop_input.fifo,
375 &sony_laptop_release_key_work); 381 (unsigned char *)&kp, sizeof(kp),
382 &sony_laptop_input.fifo_lock);
383 schedule_delayed_work(&sony_laptop_release_key_work,
384 msecs_to_jiffies(10));
376 } else 385 } else
377 dprintk("unknown input event %.2x\n", event); 386 dprintk("unknown input event %.2x\n", event);
378} 387}
@@ -390,27 +399,18 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
390 399
391 /* kfifo */ 400 /* kfifo */
392 spin_lock_init(&sony_laptop_input.fifo_lock); 401 spin_lock_init(&sony_laptop_input.fifo_lock);
393 error = 402 error = kfifo_alloc(&sony_laptop_input.fifo,
394 kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); 403 SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
395 if (error) { 404 if (error) {
396 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); 405 printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
397 goto err_dec_users; 406 goto err_dec_users;
398 } 407 }
399 408
400 /* init workqueue */
401 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop");
402 if (!sony_laptop_input.wq) {
403 printk(KERN_ERR DRV_PFX
404 "Unable to create workqueue.\n");
405 error = -ENXIO;
406 goto err_free_kfifo;
407 }
408
409 /* input keys */ 409 /* input keys */
410 key_dev = input_allocate_device(); 410 key_dev = input_allocate_device();
411 if (!key_dev) { 411 if (!key_dev) {
412 error = -ENOMEM; 412 error = -ENOMEM;
413 goto err_destroy_wq; 413 goto err_free_kfifo;
414 } 414 }
415 415
416 key_dev->name = "Sony Vaio Keys"; 416 key_dev->name = "Sony Vaio Keys";
@@ -473,9 +473,6 @@ err_unregister_keydev:
473err_free_keydev: 473err_free_keydev:
474 input_free_device(key_dev); 474 input_free_device(key_dev);
475 475
476err_destroy_wq:
477 destroy_workqueue(sony_laptop_input.wq);
478
479err_free_kfifo: 476err_free_kfifo:
480 kfifo_free(&sony_laptop_input.fifo); 477 kfifo_free(&sony_laptop_input.fifo);
481 478
@@ -486,12 +483,23 @@ err_dec_users:
486 483
487static void sony_laptop_remove_input(void) 484static void sony_laptop_remove_input(void)
488{ 485{
489 /* cleanup only after the last user has gone */ 486 struct sony_laptop_keypress kp = { NULL };
487
488 /* Cleanup only after the last user has gone */
490 if (!atomic_dec_and_test(&sony_laptop_input.users)) 489 if (!atomic_dec_and_test(&sony_laptop_input.users))
491 return; 490 return;
492 491
493 /* flush workqueue first */ 492 cancel_delayed_work_sync(&sony_laptop_release_key_work);
494 flush_workqueue(sony_laptop_input.wq); 493
494 /*
495 * Generate key-up events for remaining keys. Note that we don't
496 * need locking since nobody is adding new events to the kfifo.
497 */
498 while (kfifo_out(&sony_laptop_input.fifo,
499 (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) {
500 input_report_key(kp.dev, kp.key, 0);
501 input_sync(kp.dev);
502 }
495 503
496 /* destroy input devs */ 504 /* destroy input devs */
497 input_unregister_device(sony_laptop_input.key_dev); 505 input_unregister_device(sony_laptop_input.key_dev);
@@ -502,7 +510,6 @@ static void sony_laptop_remove_input(void)
502 sony_laptop_input.jog_dev = NULL; 510 sony_laptop_input.jog_dev = NULL;
503 } 511 }
504 512
505 destroy_workqueue(sony_laptop_input.wq);
506 kfifo_free(&sony_laptop_input.fifo); 513 kfifo_free(&sony_laptop_input.fifo);
507} 514}
508 515