diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-30 20:20:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-30 20:20:40 -0400 |
commit | 915ac4e26ef9c39a0f831e935509243732abedc0 (patch) | |
tree | 68ac39fbf077217583f9936eada2c072301becb6 | |
parent | aa4af831bb4f3168f2f574b2620124699c09c4a3 (diff) | |
parent | e4dbedc7eac7da9db363a36f2bd4366962eeefcc (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.c | 4 | ||||
-rw-r--r-- | drivers/input/mousedev.c | 73 |
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 | ||
82 | enum mousedev_emul { | 84 | enum mousedev_emul { |
@@ -116,9 +118,6 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; | |||
116 | static struct mousedev *mousedev_mix; | 118 | static struct mousedev *mousedev_mix; |
117 | static LIST_HEAD(mousedev_mix_list); | 119 | static LIST_HEAD(mousedev_mix_list); |
118 | 120 | ||
119 | static void mixdev_open_devices(void); | ||
120 | static 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 | */ |
462 | static void mixdev_open_devices(void) | 457 | static 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 | */ |
484 | static void mixdev_close_devices(void) | 487 | static 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 | } |