aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/evdev.c
diff options
context:
space:
mode:
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,
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)