Skip to content

Commit

Permalink
Input: make sure input interfaces pin parent input devices
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dmitry Torokhov committed Apr 1, 2008
1 parent 399f486 commit a7097ff
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 8 deletions.
6 changes: 2 additions & 4 deletions drivers/input/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ static void evdev_free(struct device *dev)
{
struct evdev *evdev = container_of(dev, struct evdev, dev);

input_put_device(evdev->handle.dev);
kfree(evdev);
}

Expand Down Expand Up @@ -853,9 +854,6 @@ static void evdev_cleanup(struct evdev *evdev)
evdev_hangup(evdev);
evdev_remove_chrdev(evdev);

if (evdev->grab)
evdev_ungrab(evdev, evdev->grab);

/* evdev is marked dead so no one else accesses evdev->open */
if (evdev->open) {
input_flush_device(handle, NULL);
Expand Down Expand Up @@ -896,7 +894,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
evdev->exist = 1;
evdev->minor = minor;

evdev->handle.dev = dev;
evdev->handle.dev = input_get_device(dev);
evdev->handle.name = evdev->name;
evdev->handle.handler = handler;
evdev->handle.private = evdev;
Expand Down
3 changes: 2 additions & 1 deletion drivers/input/joydev.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ static void joydev_free(struct device *dev)
{
struct joydev *joydev = container_of(dev, struct joydev, dev);

input_put_device(joydev->handle.dev);
kfree(joydev);
}

Expand Down Expand Up @@ -750,7 +751,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->minor = minor;

joydev->exist = 1;
joydev->handle.dev = dev;
joydev->handle.dev = input_get_device(dev);
joydev->handle.name = joydev->name;
joydev->handle.handler = handler;
joydev->handle.private = joydev;
Expand Down
3 changes: 2 additions & 1 deletion drivers/input/mousedev.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ static void mousedev_free(struct device *dev)
{
struct mousedev *mousedev = container_of(dev, struct mousedev, dev);

input_put_device(mousedev->handle.dev);
kfree(mousedev);
}

Expand Down Expand Up @@ -865,7 +866,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,

mousedev->minor = minor;
mousedev->exist = 1;
mousedev->handle.dev = dev;
mousedev->handle.dev = input_get_device(dev);
mousedev->handle.name = mousedev->name;
mousedev->handle.handler = handler;
mousedev->handle.private = mousedev;
Expand Down
5 changes: 3 additions & 2 deletions include/linux/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -1227,12 +1227,13 @@ void input_free_device(struct input_dev *dev);

static inline struct input_dev *input_get_device(struct input_dev *dev)
{
return to_input_dev(get_device(&dev->dev));
return dev ? to_input_dev(get_device(&dev->dev)) : NULL;
}

static inline void input_put_device(struct input_dev *dev)
{
put_device(&dev->dev);
if (dev)
put_device(&dev->dev);
}

static inline void *input_get_drvdata(struct input_dev *dev)
Expand Down

0 comments on commit a7097ff

Please sign in to comment.