--- y/drivers/input/input.c +++ n/drivers/input/input.c @@ -604,22 +604,24 @@ int input_grab_device(struct input_handl } EXPORT_SYMBOL(input_grab_device); -static void __input_release_device(struct input_handle *handle) +static int __input_release_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; struct input_handle *grabber; + int sync = 0; grabber = rcu_dereference_protected(dev->grab, lockdep_is_held(&dev->mutex)); if (grabber == handle) { rcu_assign_pointer(dev->grab, NULL); /* Make sure input_pass_event() notices that grab is gone */ - synchronize_rcu(); + sync = 1; list_for_each_entry(handle, &dev->h_list, d_node) if (handle->open && handle->handler->start) handle->handler->start(handle); } + return sync; } /** @@ -634,10 +636,13 @@ static void __input_release_device(struc void input_release_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; + int sync; mutex_lock(&dev->mutex); - __input_release_device(handle); + sync = __input_release_device(handle); mutex_unlock(&dev->mutex); + if (sync) + synchronize_rcu(); } EXPORT_SYMBOL(input_release_device); @@ -677,12 +682,13 @@ int input_open_device(struct input_handl if (retval) { dev->users--; handle->open--; + mutex_unlock(&dev->mutex); /* * Make sure we are not delivering any more events * through this handle */ synchronize_rcu(); - goto out; + return retval; } } @@ -722,10 +728,11 @@ EXPORT_SYMBOL(input_flush_device); void input_close_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; + int sync = 0; mutex_lock(&dev->mutex); - __input_release_device(handle); + sync = __input_release_device(handle); if (!dev->inhibited && !--dev->users) { if (dev->poller) @@ -740,10 +747,12 @@ void input_close_device(struct input_han * completed and that no more input events are delivered * through this handle */ - synchronize_rcu(); + sync = 1; } mutex_unlock(&dev->mutex); + if (sync) + synchronize_rcu(); } EXPORT_SYMBOL(input_close_device);