Skip to content

Commit

Permalink
Input: serio_raw - explicitly mark disconnected ports as dead
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dmitry Torokhov committed Oct 11, 2011
1 parent 15a564d commit 85f5b35
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions drivers/input/serio/serio_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct serio_raw {
wait_queue_head_t wait;
struct list_head client_list;
struct list_head node;
bool dead;
};

struct serio_raw_client {
Expand Down Expand Up @@ -91,7 +92,7 @@ static int serio_raw_open(struct inode *inode, struct file *file)
goto out;
}

if (!serio_raw->serio) {
if (serio_raw->dead) {
retval = -ENODEV;
goto out;
}
Expand Down Expand Up @@ -123,6 +124,8 @@ static void serio_raw_cleanup(struct kref *kref)

misc_deregister(&serio_raw->dev);
list_del_init(&serio_raw->node);

put_device(&serio_raw->serio->dev);
kfree(serio_raw);
}

Expand Down Expand Up @@ -164,19 +167,18 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,
char uninitialized_var(c);
ssize_t retval = 0;

if (!serio_raw->serio)
if (serio_raw->dead)
return -ENODEV;

if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
return -EAGAIN;

retval = wait_event_interruptible(serio_raw->wait,
serio_raw->head != serio_raw->tail ||
!serio_raw->serio);
serio_raw->head != serio_raw->tail || serio_raw->dead);
if (retval)
return retval;

if (!serio_raw->serio)
if (serio_raw->dead)
return -ENODEV;

while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
Expand All @@ -201,7 +203,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
if (retval)
return retval;

if (!serio_raw->serio) {
if (serio_raw->dead) {
retval = -ENODEV;
goto out;
}
Expand Down Expand Up @@ -291,10 +293,12 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
snprintf(serio_raw->name, sizeof(serio_raw->name),
"serio_raw%d", serio_raw_no++);
kref_init(&serio_raw->kref);
serio_raw->serio = serio;
INIT_LIST_HEAD(&serio_raw->client_list);
init_waitqueue_head(&serio_raw->wait);

serio_raw->serio = serio;
get_device(&serio->dev);

serio_set_drvdata(serio, serio_raw);

err = serio_open(serio, drv);
Expand Down Expand Up @@ -330,6 +334,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
list_del_init(&serio_raw->node);
out_free:
serio_set_drvdata(serio, NULL);
put_device(&serio->dev);
kfree(serio_raw);
out:
mutex_unlock(&serio_raw_mutex);
Expand Down Expand Up @@ -365,7 +370,7 @@ static void serio_raw_disconnect(struct serio *serio)
serio_close(serio);
serio_set_drvdata(serio, NULL);

serio_raw->serio = NULL;
serio_raw->dead = true;
wake_up_interruptible(&serio_raw->wait);
kref_put(&serio_raw->kref, serio_raw_cleanup);

Expand Down

0 comments on commit 85f5b35

Please sign in to comment.