summaryrefslogtreecommitdiffstats
path: root/drivers/input/evdev.c
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 /drivers/input/evdev.c
parent70093178b6eda34e4a4fb18cc4a48a9eacc01d98 (diff)
downloadlinux-82ba56c273911f7eda79849cfa0fc2d2e5a3b75b.tar.bz2
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>
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r--drivers/input/evdev.c22
1 files changed, 9 insertions, 13 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,
}
/*
- * Pass incoming event to all connected clients. Note that we are
- * caleld under a spinlock with interrupts off so we don't need
- * to use rcu_read_lock() here. Writers will be using syncronize_sched()
- * instead of synchrnoize_rcu().
+ * Pass incoming event to all connected clients.
*/
static void evdev_event(struct input_handle *handle,
unsigned int type, unsigned int code, int value)
@@ -80,6 +77,8 @@ static void evdev_event(struct input_handle *handle,
event.code = code;
event.value = value;
+ rcu_read_lock();
+
client = rcu_dereference(evdev->grab);
if (client)
evdev_pass_event(client, &event);
@@ -87,6 +86,8 @@ static void evdev_event(struct input_handle *handle,
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_event(client, &event);
+ rcu_read_unlock();
+
wake_up_interruptible(&evdev->wait);
}
@@ -142,12 +143,7 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
return error;
rcu_assign_pointer(evdev->grab, client);
- /*
- * We don't use synchronize_rcu() here because read-side
- * critical section is protected by a spinlock instead
- * of rcu_read_lock().
- */
- synchronize_sched();
+ synchronize_rcu();
return 0;
}
@@ -158,7 +154,7 @@ static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client)
return -EINVAL;
rcu_assign_pointer(evdev->grab, NULL);
- synchronize_sched();
+ synchronize_rcu();
input_release_device(&evdev->handle);
return 0;
@@ -170,7 +166,7 @@ static void evdev_attach_client(struct evdev *evdev,
spin_lock(&evdev->client_lock);
list_add_tail_rcu(&client->node, &evdev->client_list);
spin_unlock(&evdev->client_lock);
- synchronize_sched();
+ synchronize_rcu();
}
static void evdev_detach_client(struct evdev *evdev,
@@ -179,7 +175,7 @@ static void evdev_detach_client(struct evdev *evdev,
spin_lock(&evdev->client_lock);
list_del_rcu(&client->node);
spin_unlock(&evdev->client_lock);
- synchronize_sched();
+ synchronize_rcu();
}
static int evdev_open_device(struct evdev *evdev)