aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r--drivers/input/input.c36
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 */
73static void input_pass_event(struct input_dev *dev, 70static 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}
1526EXPORT_SYMBOL(input_unregister_handle); 1520EXPORT_SYMBOL(input_unregister_handle);
1527 1521