diff options
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r-- | drivers/input/input.c | 36 |
1 files changed, 15 insertions, 21 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 3070c7aa1237..2f2b020cd629 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -65,16 +65,16 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) | |||
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Pass event through all open handles. This function is called with | 67 | * Pass event through all open handles. This function is called with |
68 | * dev->event_lock held and interrupts disabled. Because of that we | 68 | * dev->event_lock held and interrupts disabled. |
69 | * do not need to use rcu_read_lock() here although we are using RCU | ||
70 | * to access handle list. Note that because of that write-side uses | ||
71 | * synchronize_sched() instead of synchronize_ru(). | ||
72 | */ | 69 | */ |
73 | static void input_pass_event(struct input_dev *dev, | 70 | static void input_pass_event(struct input_dev *dev, |
74 | unsigned int type, unsigned int code, int value) | 71 | unsigned int type, unsigned int code, int value) |
75 | { | 72 | { |
76 | struct input_handle *handle = rcu_dereference(dev->grab); | 73 | struct input_handle *handle; |
74 | |||
75 | rcu_read_lock(); | ||
77 | 76 | ||
77 | handle = rcu_dereference(dev->grab); | ||
78 | if (handle) | 78 | if (handle) |
79 | handle->handler->event(handle, type, code, value); | 79 | handle->handler->event(handle, type, code, value); |
80 | else | 80 | else |
@@ -82,6 +82,7 @@ static void input_pass_event(struct input_dev *dev, | |||
82 | if (handle->open) | 82 | if (handle->open) |
83 | handle->handler->event(handle, | 83 | handle->handler->event(handle, |
84 | type, code, value); | 84 | type, code, value); |
85 | rcu_read_unlock(); | ||
85 | } | 86 | } |
86 | 87 | ||
87 | /* | 88 | /* |
@@ -293,9 +294,11 @@ void input_inject_event(struct input_handle *handle, | |||
293 | if (is_event_supported(type, dev->evbit, EV_MAX)) { | 294 | if (is_event_supported(type, dev->evbit, EV_MAX)) { |
294 | spin_lock_irqsave(&dev->event_lock, flags); | 295 | spin_lock_irqsave(&dev->event_lock, flags); |
295 | 296 | ||
297 | rcu_read_lock(); | ||
296 | grab = rcu_dereference(dev->grab); | 298 | grab = rcu_dereference(dev->grab); |
297 | if (!grab || grab == handle) | 299 | if (!grab || grab == handle) |
298 | input_handle_event(dev, type, code, value); | 300 | input_handle_event(dev, type, code, value); |
301 | rcu_read_unlock(); | ||
299 | 302 | ||
300 | spin_unlock_irqrestore(&dev->event_lock, flags); | 303 | spin_unlock_irqrestore(&dev->event_lock, flags); |
301 | } | 304 | } |
@@ -325,11 +328,7 @@ int input_grab_device(struct input_handle *handle) | |||
325 | } | 328 | } |
326 | 329 | ||
327 | rcu_assign_pointer(dev->grab, handle); | 330 | rcu_assign_pointer(dev->grab, handle); |
328 | /* | 331 | synchronize_rcu(); |
329 | * Not using synchronize_rcu() because read-side is protected | ||
330 | * by a spinlock with interrupts off instead of rcu_read_lock(). | ||
331 | */ | ||
332 | synchronize_sched(); | ||
333 | 332 | ||
334 | out: | 333 | out: |
335 | mutex_unlock(&dev->mutex); | 334 | mutex_unlock(&dev->mutex); |
@@ -344,7 +343,7 @@ static void __input_release_device(struct input_handle *handle) | |||
344 | if (dev->grab == handle) { | 343 | if (dev->grab == handle) { |
345 | rcu_assign_pointer(dev->grab, NULL); | 344 | rcu_assign_pointer(dev->grab, NULL); |
346 | /* Make sure input_pass_event() notices that grab is gone */ | 345 | /* Make sure input_pass_event() notices that grab is gone */ |
347 | synchronize_sched(); | 346 | synchronize_rcu(); |
348 | 347 | ||
349 | list_for_each_entry(handle, &dev->h_list, d_node) | 348 | list_for_each_entry(handle, &dev->h_list, d_node) |
350 | if (handle->open && handle->handler->start) | 349 | if (handle->open && handle->handler->start) |
@@ -404,7 +403,7 @@ int input_open_device(struct input_handle *handle) | |||
404 | * Make sure we are not delivering any more events | 403 | * Make sure we are not delivering any more events |
405 | * through this handle | 404 | * through this handle |
406 | */ | 405 | */ |
407 | synchronize_sched(); | 406 | synchronize_rcu(); |
408 | } | 407 | } |
409 | } | 408 | } |
410 | 409 | ||
@@ -451,11 +450,11 @@ void input_close_device(struct input_handle *handle) | |||
451 | 450 | ||
452 | if (!--handle->open) { | 451 | if (!--handle->open) { |
453 | /* | 452 | /* |
454 | * synchronize_sched() makes sure that input_pass_event() | 453 | * synchronize_rcu() makes sure that input_pass_event() |
455 | * completed and that no more input events are delivered | 454 | * completed and that no more input events are delivered |
456 | * through this handle | 455 | * through this handle |
457 | */ | 456 | */ |
458 | synchronize_sched(); | 457 | synchronize_rcu(); |
459 | } | 458 | } |
460 | 459 | ||
461 | mutex_unlock(&dev->mutex); | 460 | mutex_unlock(&dev->mutex); |
@@ -1477,12 +1476,7 @@ int input_register_handle(struct input_handle *handle) | |||
1477 | return error; | 1476 | return error; |
1478 | list_add_tail_rcu(&handle->d_node, &dev->h_list); | 1477 | list_add_tail_rcu(&handle->d_node, &dev->h_list); |
1479 | mutex_unlock(&dev->mutex); | 1478 | mutex_unlock(&dev->mutex); |
1480 | /* | 1479 | synchronize_rcu(); |
1481 | * We don't use synchronize_rcu() here because we rely | ||
1482 | * on dev->event_lock to protect read-side critical | ||
1483 | * section in input_pass_event(). | ||
1484 | */ | ||
1485 | synchronize_sched(); | ||
1486 | 1480 | ||
1487 | /* | 1481 | /* |
1488 | * Since we are supposed to be called from ->connect() | 1482 | * Since we are supposed to be called from ->connect() |
@@ -1521,7 +1515,7 @@ void input_unregister_handle(struct input_handle *handle) | |||
1521 | mutex_lock(&dev->mutex); | 1515 | mutex_lock(&dev->mutex); |
1522 | list_del_rcu(&handle->d_node); | 1516 | list_del_rcu(&handle->d_node); |
1523 | mutex_unlock(&dev->mutex); | 1517 | mutex_unlock(&dev->mutex); |
1524 | synchronize_sched(); | 1518 | synchronize_rcu(); |
1525 | } | 1519 | } |
1526 | EXPORT_SYMBOL(input_unregister_handle); | 1520 | EXPORT_SYMBOL(input_unregister_handle); |
1527 | 1521 | ||