aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2011-10-10 21:31:04 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-10-10 21:35:13 -0400
commit85f5b35da86bcd63dd27f0976176169727f96da4 (patch)
tree0e486981ec3f8b9783c06bb3955476012538e268 /drivers/input
parent15a564d8dbfc9429540c2d9b38a64d1909de8b24 (diff)
Input: serio_raw - explicitly mark disconnected ports as dead
Instead of relying on setting serio_raw->serio to NULL upon disconnecting ports mark them explicitly as "dead". Also take and carry reference to underlying serio port to make sure it does not go away until we are done with it. Reviewed-by: Wanlong Gao <gaowanlong@cn.fujitsu.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/serio/serio_raw.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 64fcefb50fb..30ff9638819 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -40,6 +40,7 @@ struct serio_raw {
40 wait_queue_head_t wait; 40 wait_queue_head_t wait;
41 struct list_head client_list; 41 struct list_head client_list;
42 struct list_head node; 42 struct list_head node;
43 bool dead;
43}; 44};
44 45
45struct serio_raw_client { 46struct serio_raw_client {
@@ -91,7 +92,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
91 goto out; 92 goto out;
92 } 93 }
93 94
94 if (!serio_raw->serio) { 95 if (serio_raw->dead) {
95 retval = -ENODEV; 96 retval = -ENODEV;
96 goto out; 97 goto out;
97 } 98 }
@@ -123,6 +124,8 @@ static void serio_raw_cleanup(struct kref *kref)
123 124
124 misc_deregister(&serio_raw->dev); 125 misc_deregister(&serio_raw->dev);
125 list_del_init(&serio_raw->node); 126 list_del_init(&serio_raw->node);
127
128 put_device(&serio_raw->serio->dev);
126 kfree(serio_raw); 129 kfree(serio_raw);
127} 130}
128 131
@@ -164,19 +167,18 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
164 char uninitialized_var(c); 167 char uninitialized_var(c);
165 ssize_t retval = 0; 168 ssize_t retval = 0;
166 169
167 if (!serio_raw->serio) 170 if (serio_raw->dead)
168 return -ENODEV; 171 return -ENODEV;
169 172
170 if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK)) 173 if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
171 return -EAGAIN; 174 return -EAGAIN;
172 175
173 retval = wait_event_interruptible(serio_raw->wait, 176 retval = wait_event_interruptible(serio_raw->wait,
174 serio_raw->head != serio_raw->tail || 177 serio_raw->head != serio_raw->tail || serio_raw->dead);
175 !serio_raw->serio);
176 if (retval) 178 if (retval)
177 return retval; 179 return retval;
178 180
179 if (!serio_raw->serio) 181 if (serio_raw->dead)
180 return -ENODEV; 182 return -ENODEV;
181 183
182 while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) { 184 while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
@@ -201,7 +203,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
201 if (retval) 203 if (retval)
202 return retval; 204 return retval;
203 205
204 if (!serio_raw->serio) { 206 if (serio_raw->dead) {
205 retval = -ENODEV; 207 retval = -ENODEV;
206 goto out; 208 goto out;
207 } 209 }
@@ -291,10 +293,12 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
291 snprintf(serio_raw->name, sizeof(serio_raw->name), 293 snprintf(serio_raw->name, sizeof(serio_raw->name),
292 "serio_raw%d", serio_raw_no++); 294 "serio_raw%d", serio_raw_no++);
293 kref_init(&serio_raw->kref); 295 kref_init(&serio_raw->kref);
294 serio_raw->serio = serio;
295 INIT_LIST_HEAD(&serio_raw->client_list); 296 INIT_LIST_HEAD(&serio_raw->client_list);
296 init_waitqueue_head(&serio_raw->wait); 297 init_waitqueue_head(&serio_raw->wait);
297 298
299 serio_raw->serio = serio;
300 get_device(&serio->dev);
301
298 serio_set_drvdata(serio, serio_raw); 302 serio_set_drvdata(serio, serio_raw);
299 303
300 err = serio_open(serio, drv); 304 err = serio_open(serio, drv);
@@ -330,6 +334,7 @@ out_close:
330 list_del_init(&serio_raw->node); 334 list_del_init(&serio_raw->node);
331out_free: 335out_free:
332 serio_set_drvdata(serio, NULL); 336 serio_set_drvdata(serio, NULL);
337 put_device(&serio->dev);
333 kfree(serio_raw); 338 kfree(serio_raw);
334out: 339out:
335 mutex_unlock(&serio_raw_mutex); 340 mutex_unlock(&serio_raw_mutex);
@@ -365,7 +370,7 @@ static void serio_raw_disconnect(struct serio *serio)
365 serio_close(serio); 370 serio_close(serio);
366 serio_set_drvdata(serio, NULL); 371 serio_set_drvdata(serio, NULL);
367 372
368 serio_raw->serio = NULL; 373 serio_raw->dead = true;
369 wake_up_interruptible(&serio_raw->wait); 374 wake_up_interruptible(&serio_raw->wait);
370 kref_put(&serio_raw->kref, serio_raw_cleanup); 375 kref_put(&serio_raw->kref, serio_raw_cleanup);
371 376