Commit a7097ff89c3204737a07eecbc83f9ae6002cc534
1 parent
399f486286
Exists in
master
and in
39 other branches
Input: make sure input interfaces pin parent input devices
Recent driver core change causes references to parent devices being dropped early, at device_del() time, as opposed to when all children are freed. This causes oops in evdev with grabbed devices. Take the reference to the parent input device ourselves to ensure that it stays around long enough. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Showing 4 changed files with 9 additions and 8 deletions Side-by-side Diff
drivers/input/evdev.c
... | ... | @@ -124,6 +124,7 @@ |
124 | 124 | { |
125 | 125 | struct evdev *evdev = container_of(dev, struct evdev, dev); |
126 | 126 | |
127 | + input_put_device(evdev->handle.dev); | |
127 | 128 | kfree(evdev); |
128 | 129 | } |
129 | 130 | |
... | ... | @@ -853,9 +854,6 @@ |
853 | 854 | evdev_hangup(evdev); |
854 | 855 | evdev_remove_chrdev(evdev); |
855 | 856 | |
856 | - if (evdev->grab) | |
857 | - evdev_ungrab(evdev, evdev->grab); | |
858 | - | |
859 | 857 | /* evdev is marked dead so no one else accesses evdev->open */ |
860 | 858 | if (evdev->open) { |
861 | 859 | input_flush_device(handle, NULL); |
... | ... | @@ -896,7 +894,7 @@ |
896 | 894 | evdev->exist = 1; |
897 | 895 | evdev->minor = minor; |
898 | 896 | |
899 | - evdev->handle.dev = dev; | |
897 | + evdev->handle.dev = input_get_device(dev); | |
900 | 898 | evdev->handle.name = evdev->name; |
901 | 899 | evdev->handle.handler = handler; |
902 | 900 | evdev->handle.private = evdev; |
drivers/input/joydev.c
... | ... | @@ -171,6 +171,7 @@ |
171 | 171 | { |
172 | 172 | struct joydev *joydev = container_of(dev, struct joydev, dev); |
173 | 173 | |
174 | + input_put_device(joydev->handle.dev); | |
174 | 175 | kfree(joydev); |
175 | 176 | } |
176 | 177 | |
... | ... | @@ -750,7 +751,7 @@ |
750 | 751 | joydev->minor = minor; |
751 | 752 | |
752 | 753 | joydev->exist = 1; |
753 | - joydev->handle.dev = dev; | |
754 | + joydev->handle.dev = input_get_device(dev); | |
754 | 755 | joydev->handle.name = joydev->name; |
755 | 756 | joydev->handle.handler = handler; |
756 | 757 | joydev->handle.private = joydev; |
drivers/input/mousedev.c
... | ... | @@ -414,6 +414,7 @@ |
414 | 414 | { |
415 | 415 | struct mousedev *mousedev = container_of(dev, struct mousedev, dev); |
416 | 416 | |
417 | + input_put_device(mousedev->handle.dev); | |
417 | 418 | kfree(mousedev); |
418 | 419 | } |
419 | 420 | |
... | ... | @@ -865,7 +866,7 @@ |
865 | 866 | |
866 | 867 | mousedev->minor = minor; |
867 | 868 | mousedev->exist = 1; |
868 | - mousedev->handle.dev = dev; | |
869 | + mousedev->handle.dev = input_get_device(dev); | |
869 | 870 | mousedev->handle.name = mousedev->name; |
870 | 871 | mousedev->handle.handler = handler; |
871 | 872 | mousedev->handle.private = mousedev; |
include/linux/input.h
... | ... | @@ -1227,12 +1227,13 @@ |
1227 | 1227 | |
1228 | 1228 | static inline struct input_dev *input_get_device(struct input_dev *dev) |
1229 | 1229 | { |
1230 | - return to_input_dev(get_device(&dev->dev)); | |
1230 | + return dev ? to_input_dev(get_device(&dev->dev)) : NULL; | |
1231 | 1231 | } |
1232 | 1232 | |
1233 | 1233 | static inline void input_put_device(struct input_dev *dev) |
1234 | 1234 | { |
1235 | - put_device(&dev->dev); | |
1235 | + if (dev) | |
1236 | + put_device(&dev->dev); | |
1236 | 1237 | } |
1237 | 1238 | |
1238 | 1239 | static inline void *input_get_drvdata(struct input_dev *dev) |