aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-03-30 20:20:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-03-30 20:20:40 -0400
commit915ac4e26ef9c39a0f831e935509243732abedc0 (patch)
tree68ac39fbf077217583f9936eada2c072301becb6
parentaa4af831bb4f3168f2f574b2620124699c09c4a3 (diff)
parente4dbedc7eac7da9db363a36f2bd4366962eeefcc (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: "Some more updates for the input subsystem. You will get a fix for race in mousedev that has been causing quite a few oopses lately and a small fixup for force feedback support in evdev" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: mousedev - fix race when creating mixed device Input: don't modify the id of ioctl-provided ff effect on upload failure
-rw-r--r--drivers/input/evdev.c4
-rw-r--r--drivers/input/mousedev.c73
2 files changed, 45 insertions, 32 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a06e12552886..ce953d895f5b 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -954,11 +954,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
954 return -EFAULT; 954 return -EFAULT;
955 955
956 error = input_ff_upload(dev, &effect, file); 956 error = input_ff_upload(dev, &effect, file);
957 if (error)
958 return error;
957 959
958 if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) 960 if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
959 return -EFAULT; 961 return -EFAULT;
960 962
961 return error; 963 return 0;
962 } 964 }
963 965
964 /* Multi-number variable-length handlers */ 966 /* Multi-number variable-length handlers */
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 4c842c320c2e..b604564dec5c 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -67,7 +67,6 @@ struct mousedev {
67 struct device dev; 67 struct device dev;
68 struct cdev cdev; 68 struct cdev cdev;
69 bool exist; 69 bool exist;
70 bool is_mixdev;
71 70
72 struct list_head mixdev_node; 71 struct list_head mixdev_node;
73 bool opened_by_mixdev; 72 bool opened_by_mixdev;
@@ -77,6 +76,9 @@ struct mousedev {
77 int old_x[4], old_y[4]; 76 int old_x[4], old_y[4];
78 int frac_dx, frac_dy; 77 int frac_dx, frac_dy;
79 unsigned long touch; 78 unsigned long touch;
79
80 int (*open_device)(struct mousedev *mousedev);
81 void (*close_device)(struct mousedev *mousedev);
80}; 82};
81 83
82enum mousedev_emul { 84enum mousedev_emul {
@@ -116,9 +118,6 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
116static struct mousedev *mousedev_mix; 118static struct mousedev *mousedev_mix;
117static LIST_HEAD(mousedev_mix_list); 119static LIST_HEAD(mousedev_mix_list);
118 120
119static void mixdev_open_devices(void);
120static void mixdev_close_devices(void);
121
122#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) 121#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
123#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) 122#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
124 123
@@ -428,9 +427,7 @@ static int mousedev_open_device(struct mousedev *mousedev)
428 if (retval) 427 if (retval)
429 return retval; 428 return retval;
430 429
431 if (mousedev->is_mixdev) 430 if (!mousedev->exist)
432 mixdev_open_devices();
433 else if (!mousedev->exist)
434 retval = -ENODEV; 431 retval = -ENODEV;
435 else if (!mousedev->open++) { 432 else if (!mousedev->open++) {
436 retval = input_open_device(&mousedev->handle); 433 retval = input_open_device(&mousedev->handle);
@@ -446,9 +443,7 @@ static void mousedev_close_device(struct mousedev *mousedev)
446{ 443{
447 mutex_lock(&mousedev->mutex); 444 mutex_lock(&mousedev->mutex);
448 445
449 if (mousedev->is_mixdev) 446 if (mousedev->exist && !--mousedev->open)
450 mixdev_close_devices();
451 else if (mousedev->exist && !--mousedev->open)
452 input_close_device(&mousedev->handle); 447 input_close_device(&mousedev->handle);
453 448
454 mutex_unlock(&mousedev->mutex); 449 mutex_unlock(&mousedev->mutex);
@@ -459,21 +454,29 @@ static void mousedev_close_device(struct mousedev *mousedev)
459 * stream. Note that this function is called with mousedev_mix->mutex 454 * stream. Note that this function is called with mousedev_mix->mutex
460 * held. 455 * held.
461 */ 456 */
462static void mixdev_open_devices(void) 457static int mixdev_open_devices(struct mousedev *mixdev)
463{ 458{
464 struct mousedev *mousedev; 459 int error;
460
461 error = mutex_lock_interruptible(&mixdev->mutex);
462 if (error)
463 return error;
465 464
466 if (mousedev_mix->open++) 465 if (!mixdev->open++) {
467 return; 466 struct mousedev *mousedev;
468 467
469 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { 468 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
470 if (!mousedev->opened_by_mixdev) { 469 if (!mousedev->opened_by_mixdev) {
471 if (mousedev_open_device(mousedev)) 470 if (mousedev_open_device(mousedev))
472 continue; 471 continue;
473 472
474 mousedev->opened_by_mixdev = true; 473 mousedev->opened_by_mixdev = true;
474 }
475 } 475 }
476 } 476 }
477
478 mutex_unlock(&mixdev->mutex);
479 return 0;
477} 480}
478 481
479/* 482/*
@@ -481,19 +484,22 @@ static void mixdev_open_devices(void)
481 * device. Note that this function is called with mousedev_mix->mutex 484 * device. Note that this function is called with mousedev_mix->mutex
482 * held. 485 * held.
483 */ 486 */
484static void mixdev_close_devices(void) 487static void mixdev_close_devices(struct mousedev *mixdev)
485{ 488{
486 struct mousedev *mousedev; 489 mutex_lock(&mixdev->mutex);
487 490
488 if (--mousedev_mix->open) 491 if (!--mixdev->open) {
489 return; 492 struct mousedev *mousedev;
490 493
491 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { 494 list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
492 if (mousedev->opened_by_mixdev) { 495 if (mousedev->opened_by_mixdev) {
493 mousedev->opened_by_mixdev = false; 496 mousedev->opened_by_mixdev = false;
494 mousedev_close_device(mousedev); 497 mousedev_close_device(mousedev);
498 }
495 } 499 }
496 } 500 }
501
502 mutex_unlock(&mixdev->mutex);
497} 503}
498 504
499 505
@@ -522,7 +528,7 @@ static int mousedev_release(struct inode *inode, struct file *file)
522 mousedev_detach_client(mousedev, client); 528 mousedev_detach_client(mousedev, client);
523 kfree(client); 529 kfree(client);
524 530
525 mousedev_close_device(mousedev); 531 mousedev->close_device(mousedev);
526 532
527 return 0; 533 return 0;
528} 534}
@@ -550,7 +556,7 @@ static int mousedev_open(struct inode *inode, struct file *file)
550 client->mousedev = mousedev; 556 client->mousedev = mousedev;
551 mousedev_attach_client(mousedev, client); 557 mousedev_attach_client(mousedev, client);
552 558
553 error = mousedev_open_device(mousedev); 559 error = mousedev->open_device(mousedev);
554 if (error) 560 if (error)
555 goto err_free_client; 561 goto err_free_client;
556 562
@@ -861,16 +867,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
861 867
862 if (mixdev) { 868 if (mixdev) {
863 dev_set_name(&mousedev->dev, "mice"); 869 dev_set_name(&mousedev->dev, "mice");
870
871 mousedev->open_device = mixdev_open_devices;
872 mousedev->close_device = mixdev_close_devices;
864 } else { 873 } else {
865 int dev_no = minor; 874 int dev_no = minor;
866 /* Normalize device number if it falls into legacy range */ 875 /* Normalize device number if it falls into legacy range */
867 if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS) 876 if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
868 dev_no -= MOUSEDEV_MINOR_BASE; 877 dev_no -= MOUSEDEV_MINOR_BASE;
869 dev_set_name(&mousedev->dev, "mouse%d", dev_no); 878 dev_set_name(&mousedev->dev, "mouse%d", dev_no);
879
880 mousedev->open_device = mousedev_open_device;
881 mousedev->close_device = mousedev_close_device;
870 } 882 }
871 883
872 mousedev->exist = true; 884 mousedev->exist = true;
873 mousedev->is_mixdev = mixdev;
874 mousedev->handle.dev = input_get_device(dev); 885 mousedev->handle.dev = input_get_device(dev);
875 mousedev->handle.name = dev_name(&mousedev->dev); 886 mousedev->handle.name = dev_name(&mousedev->dev);
876 mousedev->handle.handler = handler; 887 mousedev->handle.handler = handler;
@@ -919,7 +930,7 @@ static void mousedev_destroy(struct mousedev *mousedev)
919 device_del(&mousedev->dev); 930 device_del(&mousedev->dev);
920 mousedev_cleanup(mousedev); 931 mousedev_cleanup(mousedev);
921 input_free_minor(MINOR(mousedev->dev.devt)); 932 input_free_minor(MINOR(mousedev->dev.devt));
922 if (!mousedev->is_mixdev) 933 if (mousedev != mousedev_mix)
923 input_unregister_handle(&mousedev->handle); 934 input_unregister_handle(&mousedev->handle);
924 put_device(&mousedev->dev); 935 put_device(&mousedev->dev);
925} 936}