aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/serio_raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/serio/serio_raw.c')
-rw-r--r--drivers/input/serio/serio_raw.c215
1 files changed, 125 insertions, 90 deletions
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index b7ba4597f7f0..4d4cd142bbbb 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -9,6 +9,7 @@
9 * the Free Software Foundation. 9 * the Free Software Foundation.
10 */ 10 */
11 11
12#include <linux/kref.h>
12#include <linux/sched.h> 13#include <linux/sched.h>
13#include <linux/slab.h> 14#include <linux/slab.h>
14#include <linux/poll.h> 15#include <linux/poll.h>
@@ -33,15 +34,16 @@ struct serio_raw {
33 unsigned int tail, head; 34 unsigned int tail, head;
34 35
35 char name[16]; 36 char name[16];
36 unsigned int refcnt; 37 struct kref kref;
37 struct serio *serio; 38 struct serio *serio;
38 struct miscdevice dev; 39 struct miscdevice dev;
39 wait_queue_head_t wait; 40 wait_queue_head_t wait;
40 struct list_head list; 41 struct list_head client_list;
41 struct list_head node; 42 struct list_head node;
43 bool dead;
42}; 44};
43 45
44struct serio_raw_list { 46struct serio_raw_client {
45 struct fasync_struct *fasync; 47 struct fasync_struct *fasync;
46 struct serio_raw *serio_raw; 48 struct serio_raw *serio_raw;
47 struct list_head node; 49 struct list_head node;
@@ -49,7 +51,6 @@ struct serio_raw_list {
49 51
50static DEFINE_MUTEX(serio_raw_mutex); 52static DEFINE_MUTEX(serio_raw_mutex);
51static LIST_HEAD(serio_raw_list); 53static LIST_HEAD(serio_raw_list);
52static unsigned int serio_raw_no;
53 54
54/********************************************************************* 55/*********************************************************************
55 * Interface with userspace (file operations) * 56 * Interface with userspace (file operations) *
@@ -57,9 +58,9 @@ static unsigned int serio_raw_no;
57 58
58static int serio_raw_fasync(int fd, struct file *file, int on) 59static int serio_raw_fasync(int fd, struct file *file, int on)
59{ 60{
60 struct serio_raw_list *list = file->private_data; 61 struct serio_raw_client *client = file->private_data;
61 62
62 return fasync_helper(fd, file, on, &list->fasync); 63 return fasync_helper(fd, file, on, &client->fasync);
63} 64}
64 65
65static struct serio_raw *serio_raw_locate(int minor) 66static struct serio_raw *serio_raw_locate(int minor)
@@ -77,8 +78,8 @@ static struct serio_raw *serio_raw_locate(int minor)
77static int serio_raw_open(struct inode *inode, struct file *file) 78static int serio_raw_open(struct inode *inode, struct file *file)
78{ 79{
79 struct serio_raw *serio_raw; 80 struct serio_raw *serio_raw;
80 struct serio_raw_list *list; 81 struct serio_raw_client *client;
81 int retval = 0; 82 int retval;
82 83
83 retval = mutex_lock_interruptible(&serio_raw_mutex); 84 retval = mutex_lock_interruptible(&serio_raw_mutex);
84 if (retval) 85 if (retval)
@@ -90,60 +91,61 @@ static int serio_raw_open(struct inode *inode, struct file *file)
90 goto out; 91 goto out;
91 } 92 }
92 93
93 if (!serio_raw->serio) { 94 if (serio_raw->dead) {
94 retval = -ENODEV; 95 retval = -ENODEV;
95 goto out; 96 goto out;
96 } 97 }
97 98
98 list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL); 99 client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL);
99 if (!list) { 100 if (!client) {
100 retval = -ENOMEM; 101 retval = -ENOMEM;
101 goto out; 102 goto out;
102 } 103 }
103 104
104 list->serio_raw = serio_raw; 105 client->serio_raw = serio_raw;
105 file->private_data = list; 106 file->private_data = client;
107
108 kref_get(&serio_raw->kref);
106 109
107 serio_raw->refcnt++; 110 serio_pause_rx(serio_raw->serio);
108 list_add_tail(&list->node, &serio_raw->list); 111 list_add_tail(&client->node, &serio_raw->client_list);
112 serio_continue_rx(serio_raw->serio);
109 113
110out: 114out:
111 mutex_unlock(&serio_raw_mutex); 115 mutex_unlock(&serio_raw_mutex);
112 return retval; 116 return retval;
113} 117}
114 118
115static int serio_raw_cleanup(struct serio_raw *serio_raw) 119static void serio_raw_free(struct kref *kref)
116{ 120{
117 if (--serio_raw->refcnt == 0) { 121 struct serio_raw *serio_raw =
118 misc_deregister(&serio_raw->dev); 122 container_of(kref, struct serio_raw, kref);
119 list_del_init(&serio_raw->node);
120 kfree(serio_raw);
121 123
122 return 1; 124 put_device(&serio_raw->serio->dev);
123 } 125 kfree(serio_raw);
124
125 return 0;
126} 126}
127 127
128static int serio_raw_release(struct inode *inode, struct file *file) 128static int serio_raw_release(struct inode *inode, struct file *file)
129{ 129{
130 struct serio_raw_list *list = file->private_data; 130 struct serio_raw_client *client = file->private_data;
131 struct serio_raw *serio_raw = list->serio_raw; 131 struct serio_raw *serio_raw = client->serio_raw;
132 132
133 mutex_lock(&serio_raw_mutex); 133 serio_pause_rx(serio_raw->serio);
134 list_del(&client->node);
135 serio_continue_rx(serio_raw->serio);
134 136
135 serio_raw_cleanup(serio_raw); 137 kfree(client);
138
139 kref_put(&serio_raw->kref, serio_raw_free);
136 140
137 mutex_unlock(&serio_raw_mutex);
138 return 0; 141 return 0;
139} 142}
140 143
141static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) 144static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
142{ 145{
143 unsigned long flags; 146 bool empty;
144 int empty;
145 147
146 spin_lock_irqsave(&serio_raw->serio->lock, flags); 148 serio_pause_rx(serio_raw->serio);
147 149
148 empty = serio_raw->head == serio_raw->tail; 150 empty = serio_raw->head == serio_raw->tail;
149 if (!empty) { 151 if (!empty) {
@@ -151,30 +153,31 @@ static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
151 serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; 153 serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
152 } 154 }
153 155
154 spin_unlock_irqrestore(&serio_raw->serio->lock, flags); 156 serio_continue_rx(serio_raw->serio);
155 157
156 return !empty; 158 return !empty;
157} 159}
158 160
159static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 161static ssize_t serio_raw_read(struct file *file, char __user *buffer,
162 size_t count, loff_t *ppos)
160{ 163{
161 struct serio_raw_list *list = file->private_data; 164 struct serio_raw_client *client = file->private_data;
162 struct serio_raw *serio_raw = list->serio_raw; 165 struct serio_raw *serio_raw = client->serio_raw;
163 char uninitialized_var(c); 166 char uninitialized_var(c);
164 ssize_t retval = 0; 167 ssize_t retval = 0;
165 168
166 if (!serio_raw->serio) 169 if (serio_raw->dead)
167 return -ENODEV; 170 return -ENODEV;
168 171
169 if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK)) 172 if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
170 return -EAGAIN; 173 return -EAGAIN;
171 174
172 retval = wait_event_interruptible(list->serio_raw->wait, 175 retval = wait_event_interruptible(serio_raw->wait,
173 serio_raw->head != serio_raw->tail || !serio_raw->serio); 176 serio_raw->head != serio_raw->tail || serio_raw->dead);
174 if (retval) 177 if (retval)
175 return retval; 178 return retval;
176 179
177 if (!serio_raw->serio) 180 if (serio_raw->dead)
178 return -ENODEV; 181 return -ENODEV;
179 182
180 while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) { 183 while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
@@ -186,9 +189,11 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t cou
186 return retval; 189 return retval;
187} 190}
188 191
189static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) 192static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
193 size_t count, loff_t *ppos)
190{ 194{
191 struct serio_raw_list *list = file->private_data; 195 struct serio_raw_client *client = file->private_data;
196 struct serio_raw *serio_raw = client->serio_raw;
192 ssize_t written = 0; 197 ssize_t written = 0;
193 int retval; 198 int retval;
194 unsigned char c; 199 unsigned char c;
@@ -197,7 +202,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
197 if (retval) 202 if (retval)
198 return retval; 203 return retval;
199 204
200 if (!list->serio_raw->serio) { 205 if (serio_raw->dead) {
201 retval = -ENODEV; 206 retval = -ENODEV;
202 goto out; 207 goto out;
203 } 208 }
@@ -210,7 +215,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz
210 retval = -EFAULT; 215 retval = -EFAULT;
211 goto out; 216 goto out;
212 } 217 }
213 if (serio_write(list->serio_raw->serio, c)) { 218 if (serio_write(serio_raw->serio, c)) {
214 retval = -EIO; 219 retval = -EIO;
215 goto out; 220 goto out;
216 } 221 }
@@ -224,46 +229,49 @@ out:
224 229
225static unsigned int serio_raw_poll(struct file *file, poll_table *wait) 230static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
226{ 231{
227 struct serio_raw_list *list = file->private_data; 232 struct serio_raw_client *client = file->private_data;
233 struct serio_raw *serio_raw = client->serio_raw;
234 unsigned int mask;
228 235
229 poll_wait(file, &list->serio_raw->wait, wait); 236 poll_wait(file, &serio_raw->wait, wait);
230 237
231 if (list->serio_raw->head != list->serio_raw->tail) 238 mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM;
239 if (serio_raw->head != serio_raw->tail)
232 return POLLIN | POLLRDNORM; 240 return POLLIN | POLLRDNORM;
233 241
234 return 0; 242 return 0;
235} 243}
236 244
237static const struct file_operations serio_raw_fops = { 245static const struct file_operations serio_raw_fops = {
238 .owner = THIS_MODULE, 246 .owner = THIS_MODULE,
239 .open = serio_raw_open, 247 .open = serio_raw_open,
240 .release = serio_raw_release, 248 .release = serio_raw_release,
241 .read = serio_raw_read, 249 .read = serio_raw_read,
242 .write = serio_raw_write, 250 .write = serio_raw_write,
243 .poll = serio_raw_poll, 251 .poll = serio_raw_poll,
244 .fasync = serio_raw_fasync, 252 .fasync = serio_raw_fasync,
245 .llseek = noop_llseek, 253 .llseek = noop_llseek,
246}; 254};
247 255
248 256
249/********************************************************************* 257/*********************************************************************
250 * Interface with serio port * 258 * Interface with serio port *
251 *********************************************************************/ 259 *********************************************************************/
252 260
253static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data, 261static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
254 unsigned int dfl) 262 unsigned int dfl)
255{ 263{
256 struct serio_raw *serio_raw = serio_get_drvdata(serio); 264 struct serio_raw *serio_raw = serio_get_drvdata(serio);
257 struct serio_raw_list *list; 265 struct serio_raw_client *client;
258 unsigned int head = serio_raw->head; 266 unsigned int head = serio_raw->head;
259 267
260 /* we are holding serio->lock here so we are prootected */ 268 /* we are holding serio->lock here so we are protected */
261 serio_raw->queue[head] = data; 269 serio_raw->queue[head] = data;
262 head = (head + 1) % SERIO_RAW_QUEUE_LEN; 270 head = (head + 1) % SERIO_RAW_QUEUE_LEN;
263 if (likely(head != serio_raw->tail)) { 271 if (likely(head != serio_raw->tail)) {
264 serio_raw->head = head; 272 serio_raw->head = head;
265 list_for_each_entry(list, &serio_raw->list, node) 273 list_for_each_entry(client, &serio_raw->client_list, node)
266 kill_fasync(&list->fasync, SIGIO, POLL_IN); 274 kill_fasync(&client->fasync, SIGIO, POLL_IN);
267 wake_up_interruptible(&serio_raw->wait); 275 wake_up_interruptible(&serio_raw->wait);
268 } 276 }
269 277
@@ -272,29 +280,37 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
272 280
273static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) 281static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
274{ 282{
283 static atomic_t serio_raw_no = ATOMIC_INIT(0);
275 struct serio_raw *serio_raw; 284 struct serio_raw *serio_raw;
276 int err; 285 int err;
277 286
278 if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) { 287 serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL);
279 printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n"); 288 if (!serio_raw) {
289 dev_dbg(&serio->dev, "can't allocate memory for a device\n");
280 return -ENOMEM; 290 return -ENOMEM;
281 } 291 }
282 292
283 mutex_lock(&serio_raw_mutex); 293 snprintf(serio_raw->name, sizeof(serio_raw->name),
294 "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1);
295 kref_init(&serio_raw->kref);
296 INIT_LIST_HEAD(&serio_raw->client_list);
297 init_waitqueue_head(&serio_raw->wait);
284 298
285 snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
286 serio_raw->refcnt = 1;
287 serio_raw->serio = serio; 299 serio_raw->serio = serio;
288 INIT_LIST_HEAD(&serio_raw->list); 300 get_device(&serio->dev);
289 init_waitqueue_head(&serio_raw->wait);
290 301
291 serio_set_drvdata(serio, serio_raw); 302 serio_set_drvdata(serio, serio_raw);
292 303
293 err = serio_open(serio, drv); 304 err = serio_open(serio, drv);
294 if (err) 305 if (err)
295 goto out_free; 306 goto err_free;
307
308 err = mutex_lock_killable(&serio_raw_mutex);
309 if (err)
310 goto err_close;
296 311
297 list_add_tail(&serio_raw->node, &serio_raw_list); 312 list_add_tail(&serio_raw->node, &serio_raw_list);
313 mutex_unlock(&serio_raw_mutex);
298 314
299 serio_raw->dev.minor = PSMOUSE_MINOR; 315 serio_raw->dev.minor = PSMOUSE_MINOR;
300 serio_raw->dev.name = serio_raw->name; 316 serio_raw->dev.name = serio_raw->name;
@@ -308,23 +324,23 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
308 } 324 }
309 325
310 if (err) { 326 if (err) {
311 printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n", 327 dev_err(&serio->dev,
328 "failed to register raw access device for %s\n",
312 serio->phys); 329 serio->phys);
313 goto out_close; 330 goto err_unlink;
314 } 331 }
315 332
316 printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n", 333 dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n",
317 serio->phys, serio_raw->name, serio_raw->dev.minor); 334 serio->phys, serio_raw->name, serio_raw->dev.minor);
318 goto out; 335 return 0;
319 336
320out_close: 337err_unlink:
321 serio_close(serio);
322 list_del_init(&serio_raw->node); 338 list_del_init(&serio_raw->node);
323out_free: 339err_close:
340 serio_close(serio);
341err_free:
324 serio_set_drvdata(serio, NULL); 342 serio_set_drvdata(serio, NULL);
325 kfree(serio_raw); 343 kref_put(&serio_raw->kref, serio_raw_free);
326out:
327 mutex_unlock(&serio_raw_mutex);
328 return err; 344 return err;
329} 345}
330 346
@@ -334,7 +350,8 @@ static int serio_raw_reconnect(struct serio *serio)
334 struct serio_driver *drv = serio->drv; 350 struct serio_driver *drv = serio->drv;
335 351
336 if (!drv || !serio_raw) { 352 if (!drv || !serio_raw) {
337 printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n"); 353 dev_dbg(&serio->dev,
354 "reconnect request, but serio is disconnected, ignoring...\n");
338 return -1; 355 return -1;
339 } 356 }
340 357
@@ -345,22 +362,40 @@ static int serio_raw_reconnect(struct serio *serio)
345 return 0; 362 return 0;
346} 363}
347 364
365/*
366 * Wake up users waiting for IO so they can disconnect from
367 * dead device.
368 */
369static void serio_raw_hangup(struct serio_raw *serio_raw)
370{
371 struct serio_raw_client *client;
372
373 serio_pause_rx(serio_raw->serio);
374 list_for_each_entry(client, &serio_raw->client_list, node)
375 kill_fasync(&client->fasync, SIGIO, POLL_HUP);
376 serio_continue_rx(serio_raw->serio);
377
378 wake_up_interruptible(&serio_raw->wait);
379}
380
381
348static void serio_raw_disconnect(struct serio *serio) 382static void serio_raw_disconnect(struct serio *serio)
349{ 383{
350 struct serio_raw *serio_raw; 384 struct serio_raw *serio_raw = serio_get_drvdata(serio);
385
386 misc_deregister(&serio_raw->dev);
351 387
352 mutex_lock(&serio_raw_mutex); 388 mutex_lock(&serio_raw_mutex);
389 serio_raw->dead = true;
390 list_del_init(&serio_raw->node);
391 mutex_unlock(&serio_raw_mutex);
353 392
354 serio_raw = serio_get_drvdata(serio); 393 serio_raw_hangup(serio_raw);
355 394
356 serio_close(serio); 395 serio_close(serio);
357 serio_set_drvdata(serio, NULL); 396 kref_put(&serio_raw->kref, serio_raw_free);
358
359 serio_raw->serio = NULL;
360 if (!serio_raw_cleanup(serio_raw))
361 wake_up_interruptible(&serio_raw->wait);
362 397
363 mutex_unlock(&serio_raw_mutex); 398 serio_set_drvdata(serio, NULL);
364} 399}
365 400
366static struct serio_device_id serio_raw_serio_ids[] = { 401static struct serio_device_id serio_raw_serio_ids[] = {
@@ -391,7 +426,7 @@ static struct serio_driver serio_raw_drv = {
391 .connect = serio_raw_connect, 426 .connect = serio_raw_connect,
392 .reconnect = serio_raw_reconnect, 427 .reconnect = serio_raw_reconnect,
393 .disconnect = serio_raw_disconnect, 428 .disconnect = serio_raw_disconnect,
394 .manual_bind = 1, 429 .manual_bind = true,
395}; 430};
396 431
397static int __init serio_raw_init(void) 432static int __init serio_raw_init(void)