From 13da601c64e56f244d0b4876a0e68ab106eac821 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 10 Oct 2011 18:31:30 -0700 Subject: [PATCH] --- yaml --- r: 269507 b: refs/heads/master c: 8c1c10d5706bbb3b41cb4a5578339d67d3eeffc2 h: refs/heads/master i: 269505: 5dcc6c087cde23c89355c57dfe19f5987e036b35 269503: 0bf35c5b0aa0eb334dbf505f44a99feadc86dbb0 v: v3 --- [refs] | 2 +- trunk/drivers/input/serio/serio_raw.c | 29 +++++++++++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index e1e5117fae29..9b711a433524 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 85f5b35da86bcd63dd27f0976176169727f96da4 +refs/heads/master: 8c1c10d5706bbb3b41cb4a5578339d67d3eeffc2 diff --git a/trunk/drivers/input/serio/serio_raw.c b/trunk/drivers/input/serio/serio_raw.c index 30ff96388198..830e2fe70a66 100644 --- a/trunk/drivers/input/serio/serio_raw.c +++ b/trunk/drivers/input/serio/serio_raw.c @@ -232,9 +232,11 @@ static unsigned int serio_raw_poll(struct file *file, poll_table *wait) { struct serio_raw_client *client = file->private_data; struct serio_raw *serio_raw = client->serio_raw; + unsigned int mask; poll_wait(file, &serio_raw->wait, wait); + mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM; if (serio_raw->head != serio_raw->tail) return POLLIN | POLLRDNORM; @@ -359,22 +361,37 @@ static int serio_raw_reconnect(struct serio *serio) return 0; } +/* + * Wake up users waiting for IO so they can disconnect from + * dead device. + */ +static void serio_raw_hangup(struct serio_raw *serio_raw) +{ + struct serio_raw_client *client; + + serio_pause_rx(serio_raw->serio); + list_for_each_entry(client, &serio_raw->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); + serio_continue_rx(serio_raw->serio); + + wake_up_interruptible(&serio_raw->wait); +} + + static void serio_raw_disconnect(struct serio *serio) { - struct serio_raw *serio_raw; + struct serio_raw *serio_raw = serio_get_drvdata(serio); mutex_lock(&serio_raw_mutex); - serio_raw = serio_get_drvdata(serio); - serio_close(serio); - serio_set_drvdata(serio, NULL); - serio_raw->dead = true; - wake_up_interruptible(&serio_raw->wait); + serio_raw_hangup(serio_raw); kref_put(&serio_raw->kref, serio_raw_cleanup); mutex_unlock(&serio_raw_mutex); + + serio_set_drvdata(serio, NULL); } static struct serio_device_id serio_raw_serio_ids[] = {