Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Mar 31, 2014
2 parents aa4af83 + e4dbedc commit 915ac4e
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 32 deletions.
4 changes: 3 additions & 1 deletion drivers/input/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -954,11 +954,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
return -EFAULT;

error = input_ff_upload(dev, &effect, file);
if (error)
return error;

if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
return -EFAULT;

return error;
return 0;
}

/* Multi-number variable-length handlers */
Expand Down
73 changes: 42 additions & 31 deletions drivers/input/mousedev.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ struct mousedev {
struct device dev;
struct cdev cdev;
bool exist;
bool is_mixdev;

struct list_head mixdev_node;
bool opened_by_mixdev;
Expand All @@ -77,6 +76,9 @@ struct mousedev {
int old_x[4], old_y[4];
int frac_dx, frac_dy;
unsigned long touch;

int (*open_device)(struct mousedev *mousedev);
void (*close_device)(struct mousedev *mousedev);
};

enum mousedev_emul {
Expand Down Expand Up @@ -116,9 +118,6 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
static struct mousedev *mousedev_mix;
static LIST_HEAD(mousedev_mix_list);

static void mixdev_open_devices(void);
static void mixdev_close_devices(void);

#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])

Expand Down Expand Up @@ -428,9 +427,7 @@ static int mousedev_open_device(struct mousedev *mousedev)
if (retval)
return retval;

if (mousedev->is_mixdev)
mixdev_open_devices();
else if (!mousedev->exist)
if (!mousedev->exist)
retval = -ENODEV;
else if (!mousedev->open++) {
retval = input_open_device(&mousedev->handle);
Expand All @@ -446,9 +443,7 @@ static void mousedev_close_device(struct mousedev *mousedev)
{
mutex_lock(&mousedev->mutex);

if (mousedev->is_mixdev)
mixdev_close_devices();
else if (mousedev->exist && !--mousedev->open)
if (mousedev->exist && !--mousedev->open)
input_close_device(&mousedev->handle);

mutex_unlock(&mousedev->mutex);
Expand All @@ -459,41 +454,52 @@ static void mousedev_close_device(struct mousedev *mousedev)
* stream. Note that this function is called with mousedev_mix->mutex
* held.
*/
static void mixdev_open_devices(void)
static int mixdev_open_devices(struct mousedev *mixdev)
{
struct mousedev *mousedev;
int error;

error = mutex_lock_interruptible(&mixdev->mutex);
if (error)
return error;

if (mousedev_mix->open++)
return;
if (!mixdev->open++) {
struct mousedev *mousedev;

list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (!mousedev->opened_by_mixdev) {
if (mousedev_open_device(mousedev))
continue;
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (!mousedev->opened_by_mixdev) {
if (mousedev_open_device(mousedev))
continue;

mousedev->opened_by_mixdev = true;
mousedev->opened_by_mixdev = true;
}
}
}

mutex_unlock(&mixdev->mutex);
return 0;
}

/*
* Close all devices that were opened as part of multiplexed
* device. Note that this function is called with mousedev_mix->mutex
* held.
*/
static void mixdev_close_devices(void)
static void mixdev_close_devices(struct mousedev *mixdev)
{
struct mousedev *mousedev;
mutex_lock(&mixdev->mutex);

if (--mousedev_mix->open)
return;
if (!--mixdev->open) {
struct mousedev *mousedev;

list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (mousedev->opened_by_mixdev) {
mousedev->opened_by_mixdev = false;
mousedev_close_device(mousedev);
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (mousedev->opened_by_mixdev) {
mousedev->opened_by_mixdev = false;
mousedev_close_device(mousedev);
}
}
}

mutex_unlock(&mixdev->mutex);
}


Expand Down Expand Up @@ -522,7 +528,7 @@ static int mousedev_release(struct inode *inode, struct file *file)
mousedev_detach_client(mousedev, client);
kfree(client);

mousedev_close_device(mousedev);
mousedev->close_device(mousedev);

return 0;
}
Expand Down Expand Up @@ -550,7 +556,7 @@ static int mousedev_open(struct inode *inode, struct file *file)
client->mousedev = mousedev;
mousedev_attach_client(mousedev, client);

error = mousedev_open_device(mousedev);
error = mousedev->open_device(mousedev);
if (error)
goto err_free_client;

Expand Down Expand Up @@ -861,16 +867,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev,

if (mixdev) {
dev_set_name(&mousedev->dev, "mice");

mousedev->open_device = mixdev_open_devices;
mousedev->close_device = mixdev_close_devices;
} else {
int dev_no = minor;
/* Normalize device number if it falls into legacy range */
if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
dev_no -= MOUSEDEV_MINOR_BASE;
dev_set_name(&mousedev->dev, "mouse%d", dev_no);

mousedev->open_device = mousedev_open_device;
mousedev->close_device = mousedev_close_device;
}

mousedev->exist = true;
mousedev->is_mixdev = mixdev;
mousedev->handle.dev = input_get_device(dev);
mousedev->handle.name = dev_name(&mousedev->dev);
mousedev->handle.handler = handler;
Expand Down Expand Up @@ -919,7 +930,7 @@ static void mousedev_destroy(struct mousedev *mousedev)
device_del(&mousedev->dev);
mousedev_cleanup(mousedev);
input_free_minor(MINOR(mousedev->dev.devt));
if (!mousedev->is_mixdev)
if (mousedev != mousedev_mix)
input_unregister_handle(&mousedev->handle);
put_device(&mousedev->dev);
}
Expand Down

0 comments on commit 915ac4e

Please sign in to comment.