aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/serio')
-rw-r--r--drivers/input/serio/serio_raw.c54
1 files changed, 29 insertions, 25 deletions
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 830e2fe70a66..4d4cd142bbbb 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -51,7 +51,6 @@ struct serio_raw_client {
51 51
52static DEFINE_MUTEX(serio_raw_mutex); 52static DEFINE_MUTEX(serio_raw_mutex);
53static LIST_HEAD(serio_raw_list); 53static LIST_HEAD(serio_raw_list);
54static unsigned int serio_raw_no;
55 54
56/********************************************************************* 55/*********************************************************************
57 * Interface with userspace (file operations) * 56 * Interface with userspace (file operations) *
@@ -117,14 +116,11 @@ out:
117 return retval; 116 return retval;
118} 117}
119 118
120static void serio_raw_cleanup(struct kref *kref) 119static void serio_raw_free(struct kref *kref)
121{ 120{
122 struct serio_raw *serio_raw = 121 struct serio_raw *serio_raw =
123 container_of(kref, struct serio_raw, kref); 122 container_of(kref, struct serio_raw, kref);
124 123
125 misc_deregister(&serio_raw->dev);
126 list_del_init(&serio_raw->node);
127
128 put_device(&serio_raw->serio->dev); 124 put_device(&serio_raw->serio->dev);
129 kfree(serio_raw); 125 kfree(serio_raw);
130} 126}
@@ -134,11 +130,14 @@ static int serio_raw_release(struct inode *inode, struct file *file)
134 struct serio_raw_client *client = file->private_data; 130 struct serio_raw_client *client = file->private_data;
135 struct serio_raw *serio_raw = client->serio_raw; 131 struct serio_raw *serio_raw = client->serio_raw;
136 132
137 mutex_lock(&serio_raw_mutex); 133 serio_pause_rx(serio_raw->serio);
134 list_del(&client->node);
135 serio_continue_rx(serio_raw->serio);
138 136
139 kref_put(&serio_raw->kref, serio_raw_cleanup); 137 kfree(client);
138
139 kref_put(&serio_raw->kref, serio_raw_free);
140 140
141 mutex_unlock(&serio_raw_mutex);
142 return 0; 141 return 0;
143} 142}
144 143
@@ -281,6 +280,7 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
281 280
282static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) 281static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
283{ 282{
283 static atomic_t serio_raw_no = ATOMIC_INIT(0);
284 struct serio_raw *serio_raw; 284 struct serio_raw *serio_raw;
285 int err; 285 int err;
286 286
@@ -290,10 +290,8 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
290 return -ENOMEM; 290 return -ENOMEM;
291 } 291 }
292 292
293 mutex_lock(&serio_raw_mutex);
294
295 snprintf(serio_raw->name, sizeof(serio_raw->name), 293 snprintf(serio_raw->name, sizeof(serio_raw->name),
296 "serio_raw%d", serio_raw_no++); 294 "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no) - 1);
297 kref_init(&serio_raw->kref); 295 kref_init(&serio_raw->kref);
298 INIT_LIST_HEAD(&serio_raw->client_list); 296 INIT_LIST_HEAD(&serio_raw->client_list);
299 init_waitqueue_head(&serio_raw->wait); 297 init_waitqueue_head(&serio_raw->wait);
@@ -305,9 +303,14 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
305 303
306 err = serio_open(serio, drv); 304 err = serio_open(serio, drv);
307 if (err) 305 if (err)
308 goto out_free; 306 goto err_free;
307
308 err = mutex_lock_killable(&serio_raw_mutex);
309 if (err)
310 goto err_close;
309 311
310 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);
311 314
312 serio_raw->dev.minor = PSMOUSE_MINOR; 315 serio_raw->dev.minor = PSMOUSE_MINOR;
313 serio_raw->dev.name = serio_raw->name; 316 serio_raw->dev.name = serio_raw->name;
@@ -324,22 +327,20 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
324 dev_err(&serio->dev, 327 dev_err(&serio->dev,
325 "failed to register raw access device for %s\n", 328 "failed to register raw access device for %s\n",
326 serio->phys); 329 serio->phys);
327 goto out_close; 330 goto err_unlink;
328 } 331 }
329 332
330 dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n", 333 dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n",
331 serio->phys, serio_raw->name, serio_raw->dev.minor); 334 serio->phys, serio_raw->name, serio_raw->dev.minor);
332 goto out; 335 return 0;
333 336
334out_close: 337err_unlink:
335 serio_close(serio);
336 list_del_init(&serio_raw->node); 338 list_del_init(&serio_raw->node);
337out_free: 339err_close:
340 serio_close(serio);
341err_free:
338 serio_set_drvdata(serio, NULL); 342 serio_set_drvdata(serio, NULL);
339 put_device(&serio->dev); 343 kref_put(&serio_raw->kref, serio_raw_free);
340 kfree(serio_raw);
341out:
342 mutex_unlock(&serio_raw_mutex);
343 return err; 344 return err;
344} 345}
345 346
@@ -382,14 +383,17 @@ static void serio_raw_disconnect(struct serio *serio)
382{ 383{
383 struct serio_raw *serio_raw = serio_get_drvdata(serio); 384 struct serio_raw *serio_raw = serio_get_drvdata(serio);
384 385
385 mutex_lock(&serio_raw_mutex); 386 misc_deregister(&serio_raw->dev);
386 387
387 serio_close(serio); 388 mutex_lock(&serio_raw_mutex);
388 serio_raw->dead = true; 389 serio_raw->dead = true;
390 list_del_init(&serio_raw->node);
391 mutex_unlock(&serio_raw_mutex);
392
389 serio_raw_hangup(serio_raw); 393 serio_raw_hangup(serio_raw);
390 kref_put(&serio_raw->kref, serio_raw_cleanup);
391 394
392 mutex_unlock(&serio_raw_mutex); 395 serio_close(serio);
396 kref_put(&serio_raw->kref, serio_raw_free);
393 397
394 serio_set_drvdata(serio, NULL); 398 serio_set_drvdata(serio, NULL);
395} 399}