aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2007-10-13 15:46:55 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2007-10-13 15:46:55 -0400
commit82ba56c273911f7eda79849cfa0fc2d2e5a3b75b (patch)
tree1b169cbda51caed72440e1ff034780df5a4dda33
parent70093178b6eda34e4a4fb18cc4a48a9eacc01d98 (diff)
Input: use full RCU API
RT guys alerted me to the fact that in their tree spinlocks are preemptible and it is better to use full RCU API (rcu_read_lock()/rcu_read_unlock()) to be safe. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/input/evdev.c22
-rw-r--r--drivers/input/input.c36
-rw-r--r--drivers/input/joydev.c11
-rw-r--r--drivers/input/mousedev.c11
4 files changed, 32 insertions, 48 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 27026f7d3c03..1d62c8b88e12 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -63,10 +63,7 @@ static void evdev_pass_event(struct evdev_client *client,
63} 63}
64 64
65/* 65/*
66 * Pass incoming event to all connected clients. Note that we are 66 * Pass incoming event to all connected clients.
67 * caleld under a spinlock with interrupts off so we don't need
68 * to use rcu_read_lock() here. Writers will be using syncronize_sched()
69 * instead of synchrnoize_rcu().
70 */ 67 */
71static void evdev_event(struct input_handle *handle, 68static void evdev_event(struct input_handle *handle,
72 unsigned int type, unsigned int code, int value) 69 unsigned int type, unsigned int code, int value)
@@ -80,6 +77,8 @@ static void evdev_event(struct input_handle *handle,
80 event.code = code; 77 event.code = code;
81 event.value = value; 78 event.value = value;
82 79
80 rcu_read_lock();
81
83 client = rcu_dereference(evdev->grab); 82 client = rcu_dereference(evdev->grab);
84 if (client) 83 if (client)
85 evdev_pass_event(client, &event); 84 evdev_pass_event(client, &event);
@@ -87,6 +86,8 @@ static void evdev_event(struct input_handle *handle,
87 list_for_each_entry_rcu(client, &evdev->client_list, node) 86 list_for_each_entry_rcu(client, &evdev->client_list, node)
88 evdev_pass_event(client, &event); 87 evdev_pass_event(client, &event);
89 88
89 rcu_read_unlock();
90
90 wake_up_interruptible(&evdev->wait); 91 wake_up_interruptible(&evdev->wait);
91} 92}
92 93
@@ -142,12 +143,7 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
142 return error; 143 return error;
143 144
144 rcu_assign_pointer(evdev->grab, client); 145 rcu_assign_pointer(evdev->grab, client);
145 /* 146 synchronize_rcu();
146 * We don't use synchronize_rcu() here because read-side
147 * critical section is protected by a spinlock instead
148 * of rcu_read_lock().
149 */
150 synchronize_sched();
151 147
152 return 0; 148 return 0;
153} 149}
@@ -158,7 +154,7 @@ static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client)
158 return -EINVAL; 154 return -EINVAL;
159 155
160 rcu_assign_pointer(evdev->grab, NULL); 156 rcu_assign_pointer(evdev->grab, NULL);
161 synchronize_sched(); 157 synchronize_rcu();
162 input_release_device(&evdev->handle); 158 input_release_device(&evdev->handle);
163 159
164 return 0; 160 return 0;
@@ -170,7 +166,7 @@ static void evdev_attach_client(struct evdev *evdev,
170 spin_lock(&evdev->client_lock); 166 spin_lock(&evdev->client_lock);
171 list_add_tail_rcu(&client->node, &evdev->client_list); 167 list_add_tail_rcu(&client->node, &evdev->client_list);
172 spin_unlock(&evdev->client_lock); 168 spin_unlock(&evdev->client_lock);
173 synchronize_sched(); 169 synchronize_rcu();
174} 170}
175 171
176static void evdev_detach_client(struct evdev *evdev, 172static void evdev_detach_client(struct evdev *evdev,
@@ -179,7 +175,7 @@ static void evdev_detach_client(struct evdev *evdev,
179 spin_lock(&evdev->client_lock); 175 spin_lock(&evdev->client_lock);
180 list_del_rcu(&client->node); 176 list_del_rcu(&client->node);
181 spin_unlock(&evdev->client_lock); 177 spin_unlock(&evdev->client_lock);
182 synchronize_sched(); 178 synchronize_rcu();
183} 179}
184 180
185static int evdev_open_device(struct evdev *evdev) 181static int evdev_open_device(struct evdev *evdev)
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
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index f306c97f556d..2b201f9aa024 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -149,8 +149,10 @@ static void joydev_event(struct input_handle *handle,
149 149
150 event.time = jiffies_to_msecs(jiffies); 150 event.time = jiffies_to_msecs(jiffies);
151 151
152 rcu_read_lock();
152 list_for_each_entry_rcu(client, &joydev->client_list, node) 153 list_for_each_entry_rcu(client, &joydev->client_list, node)
153 joydev_pass_event(client, &event); 154 joydev_pass_event(client, &event);
155 rcu_read_unlock();
154 156
155 wake_up_interruptible(&joydev->wait); 157 wake_up_interruptible(&joydev->wait);
156} 158}
@@ -178,12 +180,7 @@ static void joydev_attach_client(struct joydev *joydev,
178 spin_lock(&joydev->client_lock); 180 spin_lock(&joydev->client_lock);
179 list_add_tail_rcu(&client->node, &joydev->client_list); 181 list_add_tail_rcu(&client->node, &joydev->client_list);
180 spin_unlock(&joydev->client_lock); 182 spin_unlock(&joydev->client_lock);
181 /* 183 synchronize_rcu();
182 * We don't use synchronize_rcu() here because read-side
183 * critical section is protected by a spinlock (dev->event_lock)
184 * instead of rcu_read_lock().
185 */
186 synchronize_sched();
187} 184}
188 185
189static void joydev_detach_client(struct joydev *joydev, 186static void joydev_detach_client(struct joydev *joydev,
@@ -192,7 +189,7 @@ static void joydev_detach_client(struct joydev *joydev,
192 spin_lock(&joydev->client_lock); 189 spin_lock(&joydev->client_lock);
193 list_del_rcu(&client->node); 190 list_del_rcu(&client->node);
194 spin_unlock(&joydev->client_lock); 191 spin_unlock(&joydev->client_lock);
195 synchronize_sched(); 192 synchronize_rcu();
196} 193}
197 194
198static int joydev_open_device(struct joydev *joydev) 195static int joydev_open_device(struct joydev *joydev)
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index cc36edbb912f..79146d6ed2ab 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -265,6 +265,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev,
265 unsigned int new_head; 265 unsigned int new_head;
266 int wake_readers = 0; 266 int wake_readers = 0;
267 267
268 rcu_read_lock();
268 list_for_each_entry_rcu(client, &mousedev->client_list, node) { 269 list_for_each_entry_rcu(client, &mousedev->client_list, node) {
269 270
270 /* Just acquire the lock, interrupts already disabled */ 271 /* Just acquire the lock, interrupts already disabled */
@@ -309,6 +310,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev,
309 wake_readers = 1; 310 wake_readers = 1;
310 } 311 }
311 } 312 }
313 rcu_read_unlock();
312 314
313 if (wake_readers) 315 if (wake_readers)
314 wake_up_interruptible(&mousedev->wait); 316 wake_up_interruptible(&mousedev->wait);
@@ -499,12 +501,7 @@ static void mousedev_attach_client(struct mousedev *mousedev,
499 spin_lock(&mousedev->client_lock); 501 spin_lock(&mousedev->client_lock);
500 list_add_tail_rcu(&client->node, &mousedev->client_list); 502 list_add_tail_rcu(&client->node, &mousedev->client_list);
501 spin_unlock(&mousedev->client_lock); 503 spin_unlock(&mousedev->client_lock);
502 /* 504 synchronize_rcu();
503 * We don't use synchronize_rcu() here because read-side
504 * critical section is protected by a spinlock (dev->event_lock)
505 * instead of rcu_read_lock().
506 */
507 synchronize_sched();
508} 505}
509 506
510static void mousedev_detach_client(struct mousedev *mousedev, 507static void mousedev_detach_client(struct mousedev *mousedev,
@@ -513,7 +510,7 @@ static void mousedev_detach_client(struct mousedev *mousedev,
513 spin_lock(&mousedev->client_lock); 510 spin_lock(&mousedev->client_lock);
514 list_del_rcu(&client->node); 511 list_del_rcu(&client->node);
515 spin_unlock(&mousedev->client_lock); 512 spin_unlock(&mousedev->client_lock);
516 synchronize_sched(); 513 synchronize_rcu();
517} 514}
518 515
519static int mousedev_release(struct inode *inode, struct file *file) 516static int mousedev_release(struct inode *inode, struct file *file)