On Tue, 26 Sep 2006 23:37:29 -0700
Andrew Morton <[EMAIL PROTECTED]> wrote:
> With git-input.patch applied, my wireless USB mouse doesn't work.
OK, I did a round of restesting. I haven't seen the oopses again,
but I didn't try terribly hard.
The mouse-dies-after-one-second bug is still there. Bisection shows
that it's caused by this:
commit 0bfb22b4308bea5e7afd9434ac7e937b12fc5915
Author: Dmitry Torokhov <[EMAIL PROTECTED]>
Date: Sun Oct 1 23:50:26 2006 -0400
Input: make input_{open|close}_device() more robust
- add "dead" flag to input_dev structure and check the flag when
opening, closing or trying to flush input device
- fix error handling in input_open_device (was leaving device "used")
- allow input_close_device() to be safely called for already closed
devices
Signed-off-by: Dmitry Torokhov <[EMAIL PROTECTED]>
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 7f87c4b..b71e2f3 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -23,8 +23,7 @@ #include <linux/device.h>
#include <linux/compat.h>
struct evdev {
- int exist;
- int open;
+ int dead;
int minor;
char name[16];
struct input_handle handle;
@@ -90,9 +89,6 @@ static int evdev_flush(struct file *file
{
struct evdev_list *list = file->private_data;
- if (!list->evdev->exist)
- return -ENODEV;
-
return input_flush_device(&list->evdev->handle, file);
}
@@ -119,9 +115,7 @@ static int evdev_release(struct inode *i
list_del(&list->node);
kfree(list);
- if (!--evdev->open && evdev->exist)
- input_close_device(&evdev->handle);
-
+ input_close_device(&evdev->handle);
kref_put(&evdev->kref, evdev_free);
return 0;
@@ -131,13 +125,14 @@ static int evdev_open(struct inode *inod
{
struct evdev_list *list;
struct evdev *evdev;
+ int error;
int i = iminor(inode) - EVDEV_MINOR_BASE;
if (i >= EVDEV_MINORS)
return -ENODEV;
evdev = evdev_table[i];
- if (!evdev || !evdev->exist)
+ if (!evdev || evdev->dead)
return -ENODEV;
list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL);
@@ -150,10 +145,16 @@ static int evdev_open(struct inode *inod
list_add_tail(&list->node, &evdev->list);
file->private_data = list;
- if (!evdev->open++ && evdev->exist)
- input_open_device(&evdev->handle);
+ error = input_open_device(&evdev->handle);
+ if (error)
+ goto fail;
return 0;
+
+ fail: list_del(&list->node);
+ kfree(list);
+ kref_put(&evdev->kref, evdev_free);
+ return error;
}
#ifdef CONFIG_COMPAT
@@ -254,44 +255,46 @@ static int evdev_event_to_user(char __us
#endif /* CONFIG_COMPAT */
-static ssize_t evdev_write(struct file * file, const char __user * buffer,
size_t count, loff_t *ppos)
+static ssize_t evdev_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
+ struct evdev *evdev = list->evdev;
struct input_event event;
int retval = 0;
- if (!list->evdev->exist)
+ if (evdev->dead)
return -ENODEV;
while (retval < count) {
if (evdev_event_from_user(buffer + retval, &event))
return -EFAULT;
- input_inject_event(&list->evdev->handle, event.type,
event.code, event.value);
+ input_inject_event(&evdev->handle, event.type, event.code,
event.value);
retval += evdev_event_size();
}
return retval;
}
-static ssize_t evdev_read(struct file * file, char __user * buffer, size_t
count, loff_t *ppos)
+static ssize_t evdev_read(struct file *file, char __user *buffer, size_t
count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
+ struct evdev *evdev = list->evdev;
int retval;
if (count < evdev_event_size())
return -EINVAL;
- if (list->head == list->tail && list->evdev->exist && (file->f_flags &
O_NONBLOCK))
+ if (list->head == list->tail && !evdev->dead && (file->f_flags &
O_NONBLOCK))
return -EAGAIN;
- retval = wait_event_interruptible(list->evdev->wait,
- list->head != list->tail || (!list->evdev->exist));
+ retval = wait_event_interruptible(evdev->wait,
+ list->head != list->tail || evdev->dead);
if (retval)
return retval;
- if (!list->evdev->exist)
+ if (evdev->dead)
return -ENODEV;
while (list->head != list->tail && retval + evdev_event_size() <=
count) {
@@ -312,10 +315,11 @@ static ssize_t evdev_read(struct file *
static unsigned int evdev_poll(struct file *file, poll_table *wait)
{
struct evdev_list *list = file->private_data;
+ struct evdev *evdev = list->evdev;
- poll_wait(file, &list->evdev->wait, wait);
- return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
- (list->evdev->exist ? 0 : (POLLHUP | POLLERR));
+ poll_wait(file, &evdev->wait, wait);
+ return (list->head != list->tail ? POLLIN | POLLRDNORM : 0) |
+ (evdev->dead ? POLLHUP | POLLERR : 0);
}
#ifdef CONFIG_COMPAT
@@ -407,7 +411,7 @@ static long evdev_ioctl_handler(struct f
int i, t, u, v;
int error;
- if (!evdev->exist)
+ if (evdev->dead)
return -ENODEV;
switch (cmd) {
@@ -650,7 +654,6 @@ static int evdev_connect(struct input_ha
INIT_LIST_HEAD(&evdev->list);
init_waitqueue_head(&evdev->wait);
- evdev->exist = 1;
evdev->minor = minor;
evdev->handle.dev = dev;
evdev->handle.name = evdev->name;
@@ -698,15 +701,11 @@ static void evdev_disconnect(struct inpu
sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
- evdev->exist = 0;
-
- if (evdev->open) {
- input_flush_device(handle, NULL);
- input_close_device(handle);
- wake_up_interruptible(&evdev->wait);
- list_for_each_entry(list, &evdev->list, node)
- kill_fasync(&list->fasync, SIGIO, POLL_HUP);
- }
+
+ evdev->dead = 1;
+ wake_up_interruptible(&evdev->wait);
+ list_for_each_entry(list, &evdev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
kref_put(&evdev->kref, evdev_free);
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 5ac4a28..6ff85ca 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -261,26 +261,43 @@ int input_open_device(struct input_handl
if (err)
return err;
+ if (dev->dead) {
+ err = -ENODEV;
+ goto out;
+ }
+
handle->open++;
- if (!dev->users++ && dev->open)
+ if (!dev->users++ && dev->open) {
err = dev->open(dev);
+ if (err) {
+ dev->users--;
+ handle->open--;
+ }
+ }
- if (err)
- handle->open--;
-
+ out:
mutex_unlock(&dev->mutex);
-
return err;
}
EXPORT_SYMBOL(input_open_device);
-int input_flush_device(struct input_handle* handle, struct file* file)
+int input_flush_device(struct input_handle *handle, struct file *file)
{
- if (handle->dev->flush)
- return handle->dev->flush(handle->dev, file);
+ struct input_dev *dev = handle->dev;
+ int ret;
- return 0;
+ mutex_lock(&dev->mutex);
+
+ if (dev->dead)
+ ret = -ENODEV;
+ else if (dev->flush)
+ ret = dev->flush(dev, file);
+ else
+ ret = 0;
+
+ mutex_unlock(&dev->mutex);
+ return ret;
}
EXPORT_SYMBOL(input_flush_device);
@@ -292,9 +309,14 @@ void input_close_device(struct input_han
mutex_lock(&dev->mutex);
- if (!--dev->users && dev->close)
- dev->close(dev);
- handle->open--;
+ if (handle->open) {
+ if (dev->users) {
+ if (dev->close && !dev->dead)
+ dev->close(dev);
+ dev->users--;
+ }
+ handle->open--;
+ }
mutex_unlock(&dev->mutex);
}
@@ -1029,14 +1051,19 @@ void input_unregister_device(struct inpu
list_del_init(&dev->node);
- sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
- sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
- sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
-
mutex_lock(&dev->mutex);
+ if (dev->flush)
+ dev->flush(dev, NULL);
+ if (dev->users && dev->close)
+ dev->close(dev);
dev->name = dev->phys = dev->uniq = NULL;
+ dev->dead = 1;
mutex_unlock(&dev->mutex);
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
+ sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
+
class_device_unregister(&dev->cdev);
input_wakeup_procfs_readers();
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index aa5ddef..67a3c68 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -37,8 +37,7 @@ #define JOYDEV_MINORS 16
#define JOYDEV_BUFFER_SIZE 64
struct joydev {
- int exist;
- int open;
+ int dead;
int minor;
char name[16];
struct input_handle handle;
@@ -159,9 +158,7 @@ static int joydev_release(struct inode *
list_del(&list->node);
kfree(list);
- if (!--joydev->open && joydev->exist)
- input_close_device(&list->joydev->handle);
-
+ input_close_device(&joydev->handle);
kref_put(&joydev->kref, joydev_free);
return 0;
@@ -171,13 +168,14 @@ static int joydev_open(struct inode *ino
{
struct joydev_list *list;
struct joydev *joydev;
+ int error;
int i = iminor(inode) - JOYDEV_MINOR_BASE;
if (i >= JOYDEV_MINORS)
return -ENODEV;
joydev = joydev_table[i];
- if (!joydev || !joydev->exist)
+ if (!joydev || joydev->dead)
return -ENODEV;
list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL);
@@ -190,10 +188,16 @@ static int joydev_open(struct inode *ino
list_add_tail(&list->node, &joydev->list);
file->private_data = list;
- if (!joydev->open++ && joydev->exist)
- input_open_device(&list->joydev->handle);
+ error = input_open_device(&joydev->handle);
+ if (error)
+ goto fail;
return 0;
+
+ fail: list_del(&list->node);
+ kfree(list);
+ kref_put(&joydev->kref, joydev_free);
+ return error;
}
static ssize_t joydev_write(struct file * file, const char __user * buffer,
size_t count, loff_t *ppos)
@@ -208,7 +212,7 @@ static ssize_t joydev_read(struct file *
struct input_dev *input = joydev->handle.dev;
int retval = 0;
- if (!joydev->exist)
+ if (joydev->dead)
return -ENODEV;
if (count < sizeof(struct js_event))
@@ -237,15 +241,15 @@ static ssize_t joydev_read(struct file *
list->head == list->tail && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
- retval = wait_event_interruptible(list->joydev->wait,
- !list->joydev->exist ||
+ retval = wait_event_interruptible(joydev->wait,
+ joydev->dead ||
list->startup < joydev->nabs +
joydev->nkey ||
list->head != list->tail);
if (retval)
return retval;
- if (!list->joydev->exist)
+ if (joydev->dead)
return -ENODEV;
while (list->startup < joydev->nabs + joydev->nkey && retval +
sizeof(struct js_event) <= count) {
@@ -287,10 +291,12 @@ static ssize_t joydev_read(struct file *
static unsigned int joydev_poll(struct file *file, poll_table *wait)
{
struct joydev_list *list = file->private_data;
+ struct joydev *joydev = list->joydev;
- poll_wait(file, &list->joydev->wait, wait);
- return ((list->head != list->tail || list->startup < list->joydev->nabs
+ list->joydev->nkey) ?
- (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 :
(POLLHUP | POLLERR));
+ poll_wait(file, &joydev->wait, wait);
+ return (list->head != list->tail ||
+ list->startup < joydev->nabs + joydev->nkey ? POLLIN |
POLLRDNORM : 0) |
+ (joydev->dead ? POLLHUP | POLLERR : 0);
}
static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void
__user *argp)
@@ -391,7 +397,7 @@ static long joydev_compat_ioctl(struct f
struct JS_DATA_SAVE_TYPE_32 ds32;
int err;
- if (!joydev->exist)
+ if (joydev->dead)
return -ENODEV;
switch(cmd) {
@@ -442,7 +448,7 @@ static int joydev_ioctl(struct inode *in
struct joydev *joydev = list->joydev;
void __user *argp = (void __user *)arg;
- if (!joydev->exist)
+ if (joydev->dead)
return -ENODEV;
switch(cmd) {
@@ -499,7 +505,6 @@ static int joydev_connect(struct input_h
init_waitqueue_head(&joydev->wait);
joydev->minor = minor;
- joydev->exist = 1;
joydev->handle.dev = dev;
joydev->handle.name = joydev->name;
joydev->handle.handler = handler;
@@ -586,14 +591,11 @@ static void joydev_disconnect(struct inp
sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE
+ joydev->minor));
- joydev->exist = 0;
- if (joydev->open) {
- input_close_device(handle);
- wake_up_interruptible(&joydev->wait);
- list_for_each_entry(list, &joydev->list, node)
- kill_fasync(&list->fasync, SIGIO, POLL_HUP);
- }
+ joydev->dead = 1;
+ wake_up_interruptible(&joydev->wait);
+ list_for_each_entry(list, &joydev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
kref_put(&joydev->kref, joydev_free);
}
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 685a622..3c3ff63 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -58,8 +58,7 @@ struct mousedev_hw_data {
};
struct mousedev {
- int exist;
- int open;
+ int dead;
int minor;
char name[16];
struct input_handle handle;
@@ -112,6 +111,7 @@ static struct input_handler mousedev_han
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
static struct mousedev mousedev_mix;
+static int mousedev_mix_open;
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
@@ -371,11 +371,12 @@ static void mixdev_release(void)
{
struct input_handle *handle;
+ mousedev_mix_open--;
+
list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
struct mousedev *mousedev = handle->private;
- if (!mousedev->open && mousedev->exist)
- input_close_device(&mousedev->handle);
+ input_close_device(handle);
kref_put(&mousedev->kref, mousedev_free);
}
}
@@ -390,12 +391,10 @@ static int mousedev_release(struct inode
list_del(&list->node);
kfree(list);
- if (!--mousedev->open) {
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_release();
- else if (!mousedev_mix.open && mousedev->exist)
- input_close_device(&mousedev->handle);
- }
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_release();
+ else
+ input_close_device(&mousedev->handle);
kref_put(&mousedev->kref, mousedev_free);
@@ -407,6 +406,7 @@ static int mousedev_open(struct inode *i
struct mousedev_list *list;
struct input_handle *handle;
struct mousedev *mousedev, *md;
+ int error;
int i;
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -420,7 +420,7 @@ #endif
return -ENODEV;
mousedev = mousedev_table[i];
- if (!mousedev || !mousedev->exist)
+ if (!mousedev || mousedev->dead)
return -ENODEV;
list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL);
@@ -436,17 +436,21 @@ #endif
list_add_tail(&list->node, &mousedev->list);
file->private_data = list;
- if (!mousedev->open++) {
- if (mousedev->minor == MOUSEDEV_MIX) {
- list_for_each_entry(handle, &mousedev_handler.h_list,
h_node) {
- md = handle->private;
- kref_get(&md->kref);
- if (!md->open && md->exist)
- input_open_device(handle);
- }
- } else
- if (!mousedev_mix.open && mousedev->exist)
- input_open_device(&mousedev->handle);
+ if (mousedev->minor == MOUSEDEV_MIX) {
+ mousedev_mix_open++;
+ list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
+ md = handle->private;
+ kref_get(&md->kref);
+ input_open_device(handle);
+ }
+ } else {
+ error = input_open_device(&mousedev->handle);
+ if (error) {
+ list_del(&list->node);
+ kfree(list);
+ kref_put(&mousedev->kref, mousedev_free);
+ return error;
+ }
}
return 0;
@@ -581,18 +585,19 @@ static ssize_t mousedev_write(struct fil
static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t
count, loff_t *ppos)
{
struct mousedev_list *list = file->private_data;
+ struct mousedev *mousedev = list->mousedev;
int retval = 0;
if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
- retval = wait_event_interruptible(list->mousedev->wait,
- !list->mousedev->exist || list->ready
|| list->buffer);
+ retval = wait_event_interruptible(mousedev->wait,
+ mousedev->dead || list->ready ||
list->buffer);
if (retval)
return retval;
- if (!list->mousedev->exist)
+ if (mousedev->dead)
return -ENODEV;
if (!list->buffer && list->ready) {
@@ -615,10 +620,11 @@ static ssize_t mousedev_read(struct file
static unsigned int mousedev_poll(struct file *file, poll_table *wait)
{
struct mousedev_list *list = file->private_data;
+ struct mousedev *mousedev = list->mousedev;
- poll_wait(file, &list->mousedev->wait, wait);
- return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
- (list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
+ poll_wait(file, &mousedev->wait, wait);
+ return (list->ready || list->buffer ? POLLIN | POLLRDNORM : 0) |
+ (mousedev->dead ? POLLHUP | POLLERR : 0);
}
static const struct file_operations mousedev_fops = {
@@ -655,7 +661,6 @@ static int mousedev_connect(struct input
init_waitqueue_head(&mousedev->wait);
mousedev->minor = minor;
- mousedev->exist = 1;
mousedev->handle.dev = dev;
mousedev->handle.name = mousedev->name;
mousedev->handle.handler = handler;
@@ -681,7 +686,7 @@ static int mousedev_connect(struct input
if (error)
goto err_remove_link;
- if (mousedev_mix.open) {
+ if (mousedev_mix_open) {
error = input_open_device(&mousedev->handle);
if (error)
goto err_unlink_handle;
@@ -711,15 +716,11 @@ static void mousedev_disconnect(struct i
sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE +
mousedev->minor));
- mousedev->exist = 0;
- if (mousedev->open) {
- input_close_device(handle);
- wake_up_interruptible(&mousedev->wait);
- list_for_each_entry(list, &mousedev->list, node)
- kill_fasync(&list->fasync, SIGIO, POLL_HUP);
- } else if (mousedev_mix.open)
- input_close_device(handle);
+ mousedev->dead = 1;
+ wake_up_interruptible(&mousedev->wait);
+ list_for_each_entry(list, &mousedev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
kref_put(&mousedev->kref, mousedev_free);
}
@@ -783,7 +784,6 @@ static int __init mousedev_init(void)
kref_init(&mousedev_mix.kref);
INIT_LIST_HEAD(&mousedev_mix.list);
init_waitqueue_head(&mousedev_mix.wait);
- mousedev_mix.exist = 1;
mousedev_mix.minor = MOUSEDEV_MIX;
mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 123bbe7..d61da4b 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -106,8 +106,7 @@ struct ts_calibration {
};
struct tsdev {
- int exist;
- int open;
+ int dead;
int minor;
char name[8];
struct input_handle handle;
@@ -148,17 +147,26 @@ static int tsdev_fasync(int fd, struct f
return retval < 0 ? retval : 0;
}
+static void tsdev_free(struct kref *kref)
+{
+ struct tsdev *tsdev = container_of(kref, struct tsdev, kref);
+
+ tsdev_table[tsdev->minor] = NULL;
+ kfree(tsdev);
+}
+
static int tsdev_open(struct inode *inode, struct file *file)
{
- int i = iminor(inode) - TSDEV_MINOR_BASE;
struct tsdev_list *list;
struct tsdev *tsdev;
+ int error;
+ int i = iminor(inode) - TSDEV_MINOR_BASE;
if (i >= TSDEV_MINORS)
return -ENODEV;
tsdev = tsdev_table[i & TSDEV_MINOR_MASK];
- if (!tsdev || !tsdev->exist)
+ if (!tsdev || tsdev->dead)
return -ENODEV;
list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL);
@@ -172,18 +180,16 @@ static int tsdev_open(struct inode *inod
list_add_tail(&list->node, &tsdev->list);
file->private_data = list;
- if (!tsdev->open++ && tsdev->exist)
- input_open_device(&list->tsdev->handle);
+ error = input_open_device(&tsdev->handle);
+ if (error)
+ goto fail;
return 0;
-}
-static void tsdev_free(struct kref *kref)
-{
- struct tsdev *tsdev = container_of(kref, struct tsdev, kref);
-
- tsdev_table[tsdev->minor] = NULL;
- kfree(tsdev);
+ fail: list_del(&list->node);
+ kfree(list);
+ kref_put(&tsdev->kref, tsdev_free);
+ return error;
}
static int tsdev_release(struct inode *inode, struct file *file)
@@ -196,9 +202,7 @@ static int tsdev_release(struct inode *i
list_del(&list->node);
kfree(list);
- if (!--tsdev->open && tsdev->exist)
- input_close_device(&tsdev->handle);
-
+ input_close_device(&tsdev->handle);
kref_put(&tsdev->kref, tsdev_free);
return 0;
@@ -211,16 +215,16 @@ static ssize_t tsdev_read(struct file *f
struct tsdev *tsdev = list->tsdev;
int retval = 0;
- if (list->head == list->tail && tsdev->exist && (file->f_flags &
O_NONBLOCK))
+ if (list->head == list->tail && !tsdev->dead && (file->f_flags &
O_NONBLOCK))
return -EAGAIN;
retval = wait_event_interruptible(tsdev->wait,
- list->head != list->tail || !tsdev->exist);
+ list->head != list->tail || tsdev->dead);
if (retval)
return retval;
- if (!tsdev->exist)
+ if (tsdev->dead)
return -ENODEV;
while (list->head != list->tail &&
@@ -239,10 +243,11 @@ static ssize_t tsdev_read(struct file *f
static unsigned int tsdev_poll(struct file *file, poll_table * wait)
{
struct tsdev_list *list = file->private_data;
+ struct tsdev *tsdev = list->tsdev;
- poll_wait(file, &list->tsdev->wait, wait);
- return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
- (list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
+ poll_wait(file, &tsdev->wait, wait);
+ return (list->head != list->tail ? POLLIN | POLLRDNORM : 0) |
+ (tsdev->dead ? POLLHUP | POLLERR : 0);
}
static int tsdev_ioctl(struct inode *inode, struct file *file,
@@ -404,7 +409,6 @@ static int tsdev_connect(struct input_ha
sprintf(tsdev->name, "ts%d", minor);
- tsdev->exist = 1;
tsdev->minor = minor;
tsdev->handle.dev = dev;
tsdev->handle.name = tsdev->name;
@@ -464,14 +468,11 @@ static void tsdev_disconnect(struct inpu
sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
- tsdev->exist = 0;
- if (tsdev->open) {
- input_close_device(handle);
- wake_up_interruptible(&tsdev->wait);
- list_for_each_entry(list, &tsdev->list, node)
- kill_fasync(&list->fasync, SIGIO, POLL_HUP);
- }
+ tsdev->dead = 1;
+ wake_up_interruptible(&tsdev->wait);
+ list_for_each_entry(list, &tsdev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
kref_put(&tsdev->kref, tsdev_free);
}
diff --git a/include/linux/input.h b/include/linux/input.h
index 3c42ef9..a5799e7 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -954,7 +954,8 @@ struct input_dev {
struct timer_list timer;
struct pt_regs *regs;
- int state;
+
+ int dead;
int sync;
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel