Commit a7097ff89c3204737a07eecbc83f9ae6002cc534

Authored by Dmitry Torokhov
1 parent 399f486286

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)