* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
[not found] ` <1172622441.4587.14.camel@localhost.localdomain>
@ 2007-02-28 12:45 ` Rafael J. Wysocki
2007-03-01 5:36 ` Dmitry Torokhov
0 siblings, 1 reply; 11+ messages in thread
From: Rafael J. Wysocki @ 2007-02-28 12:45 UTC (permalink / raw)
To: Kristian Grønfeldt Sørensen
Cc: Linux kernel mailing list, linux-input
On Wednesday, 28 February 2007 01:27, Kristian Grønfeldt Sørensen wrote:
> On Tue, 2007-02-27 at 23:30 +0100, Rafael J. Wysocki wrote:
> > On Tuesday, 27 February 2007 23:04, Rafael J. Wysocki wrote:
> > > Hi,
> > >
> > > On Tuesday, 27 February 2007 19:45, Kristian Grønfeldt Sørensen wrote:
> > > > Hi.
> > > >
> > > > PROBLEM: "BUG:" when resumimg from suspend-to-ram
> > > >
> > > > My laptop have a problem with resuming from suspend-to-ram.
> > > > It does not occur every time - most of the time, resume works without
> > > > any problem.at all.
> > > >
> > > > After it occurs, the laptop refuses to go into suspend-to-ram mode until
> > > > next reboot.
> > >
> > > What do you mean by "refuses"? Are there any suspicious messages in
> > > dmesg?
> > >
> > > > The system is a Debian unstable running with a self-compiled 2.6.20
> > > > kernel downloaded from kernel.org.
> > > >
> > > > I've only tried suspend-to-ram on 2.6.20 so I don't know whether or not
> > > > other versions might have the same problem.
> > > >
> > > > I'm not subscribed to the list. Please CC me.
> > >
> > > I guess one of the drivers you use goes awry at some point. Please provide
> > > us with more information (like dmesg output after a failing resume).
> >
> > I'm sorry, I've just been told you sent it. :-)
> >
> > > CLASS: Unregistering class device. ID = 'event3'
> > > class_uevent - name = event3
> > > class_device_create_uevent called for event3
> > > device class 'event3': release.
> > > class_device_create_release called for event3
> > > BUG: unable to handle kernel paging request at virtual address 6b6b6b6b
> > > printing eip:
> > > f8825a81
> > > *pde = 00000000
> > > Oops: 0000 [#1]
> > > PREEMPT
> > > Modules linked in: tg3 battery ac thermal fan button i915 drm binfmt_misc
> > > rfcomm l2cap ipv6 fuse capability commoncap cpufreq_performance aoe
> > > af_packet nls_utf8 ntfs nls_iso8859_1 nls_cp437 vfat fat dm_snapshot
> > > dm_mirror dm_mod ieee80211_cr ypt_tkip ieee80211_crypt pd6729 snd_seq_dummy
> > > snd_seq_oss snd_seq_midi snd_rawmi di snd_seq_midi_event snd_seq
> > > snd_seq_device sermouse hci_vhci hci_uart wbsd mmc _block mmc_core tun msr
> > > cpuid cpufreq_stats container video speedstep_lib speeds tep_centrino
> > > processor sr_mod sbp2 scsi_mod ide_cd cdrom eth1394 hci_usb bluetoo th
> > > pcmcia firmware_class irda snd_intel8x0m snd_intel8x0 snd_ac97_codec
> > > crc_ccit t ac97_bus snd_pcm_oss snd_mixer_oss rtc i2c_i801 snd_pcm
> > > snd_timer ohci1394 iee e1394 i2c_core serio_raw intel_agp iTCO_wdt snd
> > > soundcore snd_page_alloc ehci_hc d pcspkr uhci_hcd yenta_socket
> > > rsrc_nonstatic pcmcia_core usbcore agpgart moused ev evdev
> > > CPU: 0
> > > EIP: 0060:[<f8825a81>] Not tainted VLI
> > > EFLAGS: 00010202 (2.6.20-x300 #1)
> > > EIP is at evdev_disconnect+0xb1/0xe0 [evdev]
> >
> > This points us to a suspect. Can you please run "gdb vmlinux" against the
> > vmlinux in your kernel sources directory and then
> >
> > gdb> l *evdev_disconnect+0xb1
>
> OK. Recopiled the kernel with CONFIG_DEBUG_INFO=y
>
> This gives:
>
> (gdb) l *evdev_disconnect+0xb1
> No symbol "evdev_disconnect" in current context.
>
> I guess you meant gdb drivers/input/evdev.ko
Yes, exactly.
> This gives:
>
> (gdb) l *evdev_disconnect+0xb1
> 0xa81 is in evdev_disconnect (include/asm/processor.h:716).
> 711 However we don't do prefetches for pre XP Athlons currently
> 712 That should be fixed. */
> 713 #define ARCH_HAS_PREFETCH
> 714 static inline void prefetch(const void *x)
> 715 {
> 716 alternative_input(ASM_NOP4,
> 717 "prefetchnta (%1)",
> 718 X86_FEATURE_XMM,
> 719 "r" (x));
> 720 }
Hm, interesting. Looks like a pointer points to nowhere in
input_unregister_device(), but I don't know which one. This may be
an evdev problem ...
Rafael
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-02-28 12:45 ` PROBLEM: "BUG:" when resuming from suspend-to-ram Rafael J. Wysocki
@ 2007-03-01 5:36 ` Dmitry Torokhov
2007-03-01 14:55 ` Kristian Grønfeldt Sørensen
2007-03-01 20:04 ` Kristian Grønfeldt Sørensen
0 siblings, 2 replies; 11+ messages in thread
From: Dmitry Torokhov @ 2007-03-01 5:36 UTC (permalink / raw)
To: linux-input
Cc: Rafael J. Wysocki, Kristian Grønfeldt Sørensen,
Linux kernel mailing list
On Wednesday 28 February 2007 07:45, Rafael J. Wysocki wrote:
>
> > This gives:
> >
> > (gdb) l *evdev_disconnect+0xb1
> > 0xa81 is in evdev_disconnect (include/asm/processor.h:716).
> > 711 However we don't do prefetches for pre XP Athlons currently
> > 712 That should be fixed. */
> > 713 #define ARCH_HAS_PREFETCH
> > 714 static inline void prefetch(const void *x)
> > 715 {
> > 716 alternative_input(ASM_NOP4,
> > 717 "prefetchnta (%1)",
> > 718 X86_FEATURE_XMM,
> > 719 "r" (x));
> > 720 }
>
> Hm, interesting. Looks like a pointer points to nowhere in
> input_unregister_device(), but I don't know which one. This may be
> an evdev problem ...
>
Please try the patch below.
--
Dmitry
Input: use krefs for refcounting in input handlers
This should fix problems whith accessing memory already freed by
another thread.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/evdev.c | 62 ++++++++++-------
drivers/input/joydev.c | 51 +++++++++-----
drivers/input/mousedev.c | 166 +++++++++++++++++++++++++++++++++--------------
drivers/input/tsdev.c | 65 +++++++++++-------
4 files changed, 227 insertions(+), 117 deletions(-)
Index: work/drivers/input/evdev.c
===================================================================
--- work.orig/drivers/input/evdev.c
+++ work/drivers/input/evdev.c
@@ -29,8 +29,10 @@ struct evdev {
char name[16];
struct input_handle handle;
wait_queue_head_t wait;
- struct evdev_list *grab;
+ struct kref kref;
struct list_head list;
+
+ struct evdev_list *grab;
};
struct evdev_list {
@@ -94,53 +96,62 @@ static int evdev_flush(struct file *file
return input_flush_device(&list->evdev->handle, file);
}
-static void evdev_free(struct evdev *evdev)
+static void evdev_free(struct kref *kref)
{
+ struct evdev *evdev = container_of(kref, struct evdev, kref);
+
evdev_table[evdev->minor] = NULL;
kfree(evdev);
}
-static int evdev_release(struct inode * inode, struct file * file)
+static int evdev_release(struct inode *inode, struct file *file)
{
struct evdev_list *list = file->private_data;
+ struct evdev *evdev = list->evdev;
- if (list->evdev->grab == list) {
- input_release_device(&list->evdev->handle);
- list->evdev->grab = NULL;
+ if (evdev->grab == list) {
+ input_release_device(&evdev->handle);
+ evdev->grab = NULL;
}
evdev_fasync(-1, file, 0);
+
list_del(&list->node);
+ kfree(list);
- if (!--list->evdev->open) {
- if (list->evdev->exist)
- input_close_device(&list->evdev->handle);
- else
- evdev_free(list->evdev);
- }
+ if (!--evdev->open && evdev->exist)
+ input_close_device(&evdev->handle);
+
+ kref_put(&evdev->kref, evdev_free);
- kfree(list);
return 0;
}
-static int evdev_open(struct inode * inode, struct file * file)
+static int evdev_open(struct inode *inode, struct file *file)
{
struct evdev_list *list;
+ struct evdev *evdev;
int i = iminor(inode) - EVDEV_MINOR_BASE;
- if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
+ if (i >= EVDEV_MINORS)
+ return -ENODEV;
+
+ evdev = evdev_table[i];
+ if (!evdev || !evdev->exist)
return -ENODEV;
- if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
+ list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL);
+ if (!list)
return -ENOMEM;
- list->evdev = evdev_table[i];
- list_add_tail(&list->node, &evdev_table[i]->list);
+ kref_get(&evdev->kref);
+
+ list->evdev = evdev;
+ list_add_tail(&list->node, &evdev->list);
file->private_data = list;
- if (!list->evdev->open++)
- if (list->evdev->exist)
- input_open_device(&list->evdev->handle);
+ if (!evdev->open++ && evdev->exist)
+ input_open_device(&evdev->handle);
return 0;
}
@@ -629,9 +640,11 @@ static struct input_handle *evdev_connec
return NULL;
}
- if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
+ evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
+ if (!evdev)
return NULL;
+ kref_init(&evdev->kref);
INIT_LIST_HEAD(&evdev->list);
init_waitqueue_head(&evdev->wait);
@@ -672,8 +685,9 @@ static void evdev_disconnect(struct inpu
wake_up_interruptible(&evdev->wait);
list_for_each_entry(list, &evdev->list, node)
kill_fasync(&list->fasync, SIGIO, POLL_HUP);
- } else
- evdev_free(evdev);
+ }
+
+ kref_put(&evdev->kref, evdev_free);
}
static const struct input_device_id evdev_ids[] = {
Index: work/drivers/input/joydev.c
===================================================================
--- work.orig/drivers/input/joydev.c
+++ work/drivers/input/joydev.c
@@ -43,7 +43,9 @@ struct joydev {
char name[16];
struct input_handle handle;
wait_queue_head_t wait;
+ struct kref kref;
struct list_head list;
+
struct js_corr corr[ABS_MAX + 1];
struct JS_DATA_SAVE_TYPE glue;
int nabs;
@@ -139,8 +141,10 @@ static int joydev_fasync(int fd, struct
return retval < 0 ? retval : 0;
}
-static void joydev_free(struct joydev *joydev)
+static void joydev_free(struct kref *kref)
{
+ struct joydev *joydev = container_of(kref, struct joydev, kref);
+
joydev_table[joydev->minor] = NULL;
kfree(joydev);
}
@@ -148,40 +152,46 @@ static void joydev_free(struct joydev *j
static int joydev_release(struct inode * inode, struct file * file)
{
struct joydev_list *list = file->private_data;
+ struct joydev *joydev = list->joydev;
joydev_fasync(-1, file, 0);
list_del(&list->node);
+ kfree(list);
- if (!--list->joydev->open) {
- if (list->joydev->exist)
- input_close_device(&list->joydev->handle);
- else
- joydev_free(list->joydev);
- }
+ if (!--joydev->open && joydev->exist)
+ input_close_device(&list->joydev->handle);
+
+ kref_put(&joydev->kref, joydev_free);
- kfree(list);
return 0;
}
static int joydev_open(struct inode *inode, struct file *file)
{
struct joydev_list *list;
+ struct joydev *joydev;
int i = iminor(inode) - JOYDEV_MINOR_BASE;
- if (i >= JOYDEV_MINORS || !joydev_table[i])
+ if (i >= JOYDEV_MINORS)
return -ENODEV;
- if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
+ joydev = joydev_table[i];
+ if (!joydev || !joydev->exist)
+ return -ENODEV;
+
+ list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL);
+ if (!list)
return -ENOMEM;
- list->joydev = joydev_table[i];
- list_add_tail(&list->node, &joydev_table[i]->list);
+ kref_get(&joydev->kref);
+
+ list->joydev = joydev;
+ list_add_tail(&list->node, &joydev->list);
file->private_data = list;
- if (!list->joydev->open++)
- if (list->joydev->exist)
- input_open_device(&list->joydev->handle);
+ if (!joydev->open++ && joydev->exist)
+ input_open_device(&list->joydev->handle);
return 0;
}
@@ -198,7 +208,7 @@ static ssize_t joydev_read(struct file *
struct input_dev *input = joydev->handle.dev;
int retval = 0;
- if (!list->joydev->exist)
+ if (!joydev->exist)
return -ENODEV;
if (count < sizeof(struct js_event))
@@ -478,9 +488,11 @@ static struct input_handle *joydev_conne
return NULL;
}
- if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL)))
+ joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
+ if (!joydev)
return NULL;
+ kref_init(&joydev->kref);
INIT_LIST_HEAD(&joydev->list);
init_waitqueue_head(&joydev->wait);
@@ -559,8 +571,9 @@ static void joydev_disconnect(struct inp
wake_up_interruptible(&joydev->wait);
list_for_each_entry(list, &joydev->list, node)
kill_fasync(&list->fasync, SIGIO, POLL_HUP);
- } else
- joydev_free(joydev);
+ }
+
+ kref_put(&joydev->kref, joydev_free);
}
static const struct input_device_id joydev_blacklist[] = {
Index: work/drivers/input/mousedev.c
===================================================================
--- work.orig/drivers/input/mousedev.c
+++ work/drivers/input/mousedev.c
@@ -62,9 +62,13 @@ struct mousedev {
int open;
int minor;
char name[16];
+ struct input_handle handle;
wait_queue_head_t wait;
+ struct kref kref;
struct list_head list;
- struct input_handle handle;
+
+ struct list_head mixdev_node;
+ int mixdev_open;
struct mousedev_hw_data packet;
unsigned int pkt_count;
@@ -111,6 +115,8 @@ static struct input_handler mousedev_han
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
static struct mousedev mousedev_mix;
+static LIST_HEAD(mousedev_mix_list);
+static DEFINE_MUTEX(mousedev_mix_mutex);
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
@@ -358,55 +364,112 @@ static int mousedev_fasync(int fd, struc
return retval < 0 ? retval : 0;
}
-static void mousedev_free(struct mousedev *mousedev)
+static void mousedev_free(struct kref *kref)
{
+ struct mousedev *mousedev = container_of(kref, struct mousedev, kref);
+
mousedev_table[mousedev->minor] = NULL;
kfree(mousedev);
}
-static void mixdev_release(void)
+static int mixdev_add_device(struct mousedev *mousedev)
+{
+ int retval = 0;
+
+ mutex_lock(&mousedev_mix_mutex);
+
+ if (mousedev_mix.open) {
+ if (!mousedev->open && mousedev->exist) {
+ retval = input_open_device(&mousedev->handle);
+ if (retval)
+ goto out;
+
+ mousedev->open++;
+ }
+ mousedev->mixdev_open++;
+ }
+
+ list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
+
+ out:
+ mutex_unlock(&mousedev_mix_mutex);
+ return retval;
+}
+
+static void mixdev_remove_device(struct mousedev *mousedev)
{
- struct input_handle *handle;
+ mutex_lock(&mousedev_mix_mutex);
- list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
- struct mousedev *mousedev = handle->private;
+ if (!--mousedev->mixdev_open)
+ if (!--mousedev->open && mousedev->exist)
+ input_close_device(&mousedev->handle);
- if (!mousedev->open) {
- if (mousedev->exist)
+ list_del_init(&mousedev->mixdev_node);
+
+ mutex_unlock(&mousedev_mix_mutex);
+}
+
+static void mixdev_open_devices(void)
+{
+ struct mousedev *mousedev;
+
+ mutex_lock(&mousedev_mix_mutex);
+
+ list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
+ if (!mousedev->mixdev_open)
+ if (!mousedev->open && mousedev->exist) {
+ if (input_open_device(&mousedev->handle))
+ continue;
+ mousedev->open++;
+ }
+ mousedev->mixdev_open++;
+ }
+
+ mutex_unlock(&mousedev_mix_mutex);
+}
+
+static void mixdev_close_devices(void)
+{
+ struct mousedev *mousedev, *next;
+
+ mutex_lock(&mousedev_mix_mutex);
+
+ list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+ if (mousedev->mixdev_open) {
+ if (!--mousedev->open && mousedev->exist)
input_close_device(&mousedev->handle);
- else
- mousedev_free(mousedev);
+ mousedev->mixdev_open--;
}
}
+
+ mutex_unlock(&mousedev_mix_mutex);
}
-static int mousedev_release(struct inode * inode, struct file * file)
+static int mousedev_release(struct inode *inode, struct file *file)
{
struct mousedev_list *list = file->private_data;
+ struct mousedev *mousedev = list->mousedev;
mousedev_fasync(-1, file, 0);
list_del(&list->node);
+ kfree(list);
- if (!--list->mousedev->open) {
- if (list->mousedev->minor == MOUSEDEV_MIX)
- mixdev_release();
- else if (!mousedev_mix.open) {
- if (list->mousedev->exist)
- input_close_device(&list->mousedev->handle);
- else
- mousedev_free(list->mousedev);
- }
+ if (!--mousedev->open) {
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_close_devices();
+ else if (mousedev->exist)
+ input_close_device(&mousedev->handle);
}
- kfree(list);
+ kref_put(&mousedev->kref, mousedev_free);
+
return 0;
}
-static int mousedev_open(struct inode * inode, struct file * file)
+static int mousedev_open(struct inode *inode, struct file *file)
{
struct mousedev_list *list;
- struct input_handle *handle;
struct mousedev *mousedev;
int i;
@@ -417,29 +480,31 @@ static int mousedev_open(struct inode *
#endif
i = iminor(inode) - MOUSEDEV_MINOR_BASE;
- if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
+ if (i >= MOUSEDEV_MINORS)
+ return -ENODEV;
+
+ mousedev = mousedev_table[i];
+ if (!mousedev || !mousedev->exist)
return -ENODEV;
- if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
+ list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL);
+ if (!list)
return -ENOMEM;
+ kref_get(&mousedev->kref);
+
spin_lock_init(&list->packet_lock);
list->pos_x = xres / 2;
list->pos_y = yres / 2;
- list->mousedev = mousedev_table[i];
- list_add_tail(&list->node, &mousedev_table[i]->list);
+ list->mousedev = mousedev;
+ list_add_tail(&list->node, &mousedev->list);
file->private_data = list;
- if (!list->mousedev->open++) {
- if (list->mousedev->minor == MOUSEDEV_MIX) {
- list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
- mousedev = handle->private;
- if (!mousedev->open && mousedev->exist)
- input_open_device(handle);
- }
- } else
- if (!mousedev_mix.open && list->mousedev->exist)
- input_open_device(&list->mousedev->handle);
+ if (!mousedev->open++) {
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_open_devices();
+ else if (mousedev->exist)
+ input_open_device(&mousedev->handle);
}
return 0;
@@ -629,7 +694,7 @@ static struct input_handle *mousedev_con
{
struct mousedev *mousedev;
struct class_device *cdev;
- int minor = 0;
+ int minor;
for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
if (minor == MOUSEDEV_MINORS) {
@@ -637,10 +702,13 @@ static struct input_handle *mousedev_con
return NULL;
}
- if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL)))
+ mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
+ if (!mousedev)
return NULL;
+ kref_init(&mousedev->kref);
INIT_LIST_HEAD(&mousedev->list);
+ INIT_LIST_HEAD(&mousedev->mixdev_node);
init_waitqueue_head(&mousedev->wait);
mousedev->minor = minor;
@@ -651,8 +719,7 @@ static struct input_handle *mousedev_con
mousedev->handle.private = mousedev;
sprintf(mousedev->name, "mouse%d", minor);
- if (mousedev_mix.open)
- input_open_device(&mousedev->handle);
+ mixdev_add_device(mousedev);
mousedev_table[minor] = mousedev;
@@ -675,18 +742,18 @@ 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;
+ mixdev_remove_device(mousedev);
+
+ 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_free(mousedev);
}
+
+ kref_put(&mousedev->kref, mousedev_free);
}
static const struct input_device_id mousedev_ids[] = {
@@ -714,7 +781,7 @@ static const struct input_device_id mous
.absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
}, /* A touchpad */
- { }, /* Terminating entry */
+ { }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(input, mousedev_ids);
@@ -745,13 +812,14 @@ static int __init mousedev_init(void)
if (error)
return error;
- memset(&mousedev_mix, 0, sizeof(struct mousedev));
+ kref_init(&mousedev_mix.kref);
INIT_LIST_HEAD(&mousedev_mix.list);
init_waitqueue_head(&mousedev_mix.wait);
- mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
mousedev_mix.exist = 1;
mousedev_mix.minor = MOUSEDEV_MIX;
+ mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
+
cdev = class_device_create(&input_class, NULL,
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
if (IS_ERR(cdev)) {
Index: work/drivers/input/tsdev.c
===================================================================
--- work.orig/drivers/input/tsdev.c
+++ work/drivers/input/tsdev.c
@@ -110,9 +110,11 @@ struct tsdev {
int open;
int minor;
char name[8];
+ struct input_handle handle;
wait_queue_head_t wait;
+ struct kref kref;
struct list_head list;
- struct input_handle handle;
+
int x, y, pressure;
struct ts_calibration cal;
};
@@ -150,6 +152,7 @@ static int tsdev_open(struct inode *inod
{
int i = iminor(inode) - TSDEV_MINOR_BASE;
struct tsdev_list *list;
+ struct tsdev *tsdev;
printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
"for removal.\nSee Documentation/feature-removal-schedule.txt "
@@ -158,24 +161,31 @@ static int tsdev_open(struct inode *inod
if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
return -ENODEV;
- if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
+ tsdev = tsdev_table[i & TSDEV_MINOR_MASK];
+ if (!tsdev || !tsdev->exist)
+ return -ENODEV;
+
+ list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL);
+ if (!list)
return -ENOMEM;
- list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
+ kref_get(&tsdev->kref);
- i &= TSDEV_MINOR_MASK;
- list->tsdev = tsdev_table[i];
- list_add_tail(&list->node, &tsdev_table[i]->list);
+ list->tsdev = tsdev;
+ list->raw = (i >= TSDEV_MINORS / 2);
+ list_add_tail(&list->node, &tsdev->list);
file->private_data = list;
- if (!list->tsdev->open++)
- if (list->tsdev->exist)
- input_open_device(&list->tsdev->handle);
+ if (!tsdev->open++ && tsdev->exist)
+ input_open_device(&list->tsdev->handle);
+
return 0;
}
-static void tsdev_free(struct tsdev *tsdev)
+static void tsdev_free(struct kref *kref)
{
+ struct tsdev *tsdev = container_of(kref, struct tsdev, kref);
+
tsdev_table[tsdev->minor] = NULL;
kfree(tsdev);
}
@@ -183,17 +193,18 @@ static void tsdev_free(struct tsdev *tsd
static int tsdev_release(struct inode *inode, struct file *file)
{
struct tsdev_list *list = file->private_data;
+ struct tsdev *tsdev = list->tsdev;
tsdev_fasync(-1, file, 0);
- list_del(&list->node);
- if (!--list->tsdev->open) {
- if (list->tsdev->exist)
- input_close_device(&list->tsdev->handle);
- else
- tsdev_free(list->tsdev);
- }
+ list_del(&list->node);
kfree(list);
+
+ if (!--tsdev->open && tsdev->exist)
+ input_close_device(&tsdev->handle);
+
+ kref_put(&tsdev->kref, tsdev_free);
+
return 0;
}
@@ -201,22 +212,23 @@ static ssize_t tsdev_read(struct file *f
loff_t * ppos)
{
struct tsdev_list *list = file->private_data;
+ struct tsdev *tsdev = list->tsdev;
int retval = 0;
- if (list->head == list->tail && list->tsdev->exist && (file->f_flags & O_NONBLOCK))
+ if (list->head == list->tail && tsdev->exist && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
- retval = wait_event_interruptible(list->tsdev->wait,
- list->head != list->tail || !list->tsdev->exist);
+ retval = wait_event_interruptible(tsdev->wait,
+ list->head != list->tail || !tsdev->exist);
if (retval)
return retval;
- if (!list->tsdev->exist)
+ if (!tsdev->exist)
return -ENODEV;
while (list->head != list->tail &&
- retval + sizeof (struct ts_event) <= count) {
+ retval + sizeof(struct ts_event) <= count) {
if (copy_to_user (buffer + retval, list->event + list->tail,
sizeof (struct ts_event)))
return -EFAULT;
@@ -385,9 +397,11 @@ static struct input_handle *tsdev_connec
return NULL;
}
- if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL)))
+ tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL);
+ if (!tsdev)
return NULL;
+ kref_init(&tsdev->kref);
INIT_LIST_HEAD(&tsdev->list);
init_waitqueue_head(&tsdev->wait);
@@ -441,8 +455,9 @@ static void tsdev_disconnect(struct inpu
wake_up_interruptible(&tsdev->wait);
list_for_each_entry(list, &tsdev->list, node)
kill_fasync(&list->fasync, SIGIO, POLL_HUP);
- } else
- tsdev_free(tsdev);
+ }
+
+ kref_put(&tsdev->kref, tsdev_free);
}
static const struct input_device_id tsdev_ids[] = {
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-01 5:36 ` Dmitry Torokhov
@ 2007-03-01 14:55 ` Kristian Grønfeldt Sørensen
2007-03-01 15:01 ` Dmitry Torokhov
2007-03-01 20:04 ` Kristian Grønfeldt Sørensen
1 sibling, 1 reply; 11+ messages in thread
From: Kristian Grønfeldt Sørensen @ 2007-03-01 14:55 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Rafael J. Wysocki, Linux kernel mailing list
On Thu, 2007-03-01 at 00:36 -0500, Dmitry Torokhov wrote:
> On Wednesday 28 February 2007 07:45, Rafael J. Wysocki wrote:
> >
> > > This gives:
> > >
> > > (gdb) l *evdev_disconnect+0xb1
> > > 0xa81 is in evdev_disconnect (include/asm/processor.h:716).
> > > 711 However we don't do prefetches for pre XP Athlons currently
> > > 712 That should be fixed. */
> > > 713 #define ARCH_HAS_PREFETCH
> > > 714 static inline void prefetch(const void *x)
> > > 715 {
> > > 716 alternative_input(ASM_NOP4,
> > > 717 "prefetchnta (%1)",
> > > 718 X86_FEATURE_XMM,
> > > 719 "r" (x));
> > > 720 }
> >
> > Hm, interesting. Looks like a pointer points to nowhere in
> > input_unregister_device(), but I don't know which one. This may be
> > an evdev problem ...
> >
>
> Please try the patch below.
Hmmm. Is the diff against 2.6.20? All hunks except one fails when i try
it. If I pass "-F 3" to patch, then one more hunk succeeds. Am I doing
something wrong?
/Kristian
> --
> Dmitry
>
> Input: use krefs for refcounting in input handlers
>
> This should fix problems whith accessing memory already freed by
> another thread.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-01 14:55 ` Kristian Grønfeldt Sørensen
@ 2007-03-01 15:01 ` Dmitry Torokhov
2007-03-01 16:23 ` Kristian Grønfeldt Sørensen
0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2007-03-01 15:01 UTC (permalink / raw)
To: Kristian Grønfeldt Sørensen
Cc: linux-input, Rafael J. Wysocki, Linux kernel mailing list
On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> On Thu, 2007-03-01 at 00:36 -0500, Dmitry Torokhov wrote:
> >
> > Please try the patch below.
>
> Hmmm. Is the diff against 2.6.20? All hunks except one fails when i try
> it. If I pass "-F 3" to patch, then one more hunk succeeds. Am I doing
> something wrong?
>
Hm, technically speaking it is against 2.6.21-rc2 but I think exceppt
for tsdev part it should apply to 2.6.20...
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-01 15:01 ` Dmitry Torokhov
@ 2007-03-01 16:23 ` Kristian Grønfeldt Sørensen
0 siblings, 0 replies; 11+ messages in thread
From: Kristian Grønfeldt Sørensen @ 2007-03-01 16:23 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Rafael J. Wysocki, Linux kernel mailing list
On Thu, 2007-03-01 at 10:01 -0500, Dmitry Torokhov wrote:
> On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> > On Thu, 2007-03-01 at 00:36 -0500, Dmitry Torokhov wrote:
> > >
> > > Please try the patch below.
> >
> > Hmmm. Is the diff against 2.6.20? All hunks except one fails when i try
> > it. If I pass "-F 3" to patch, then one more hunk succeeds. Am I doing
> > something wrong?
> >
>
> Hm, technically speaking it is against 2.6.21-rc2 but I think exceppt
> for tsdev part it should apply to 2.6.20...
>
OK. Something went wrong when copy pasting the patch to a file. Saved
the entire mail, and applied it succesfully to 2.6.21-r2. Still only a
couple of successfull hunks against 2.6.20. I'm compiling 2.6.21-rc2
right now, and then I'll try to see if the problem persists.
/Kristian
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-01 5:36 ` Dmitry Torokhov
2007-03-01 14:55 ` Kristian Grønfeldt Sørensen
@ 2007-03-01 20:04 ` Kristian Grønfeldt Sørensen
2007-03-01 20:25 ` Dmitry Torokhov
1 sibling, 1 reply; 11+ messages in thread
From: Kristian Grønfeldt Sørensen @ 2007-03-01 20:04 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Rafael J. Wysocki, Linux kernel mailing list
On Thu, 2007-03-01 at 00:36 -0500, Dmitry Torokhov wrote:
> On Wednesday 28 February 2007 07:45, Rafael J. Wysocki wrote:
> >
> > > This gives:
> > >
> > > (gdb) l *evdev_disconnect+0xb1
> > > 0xa81 is in evdev_disconnect (include/asm/processor.h:716).
> > > 711 However we don't do prefetches for pre XP Athlons currently
> > > 712 That should be fixed. */
> > > 713 #define ARCH_HAS_PREFETCH
> > > 714 static inline void prefetch(const void *x)
> > > 715 {
> > > 716 alternative_input(ASM_NOP4,
> > > 717 "prefetchnta (%1)",
> > > 718 X86_FEATURE_XMM,
> > > 719 "r" (x));
> > > 720 }
> >
> > Hm, interesting. Looks like a pointer points to nowhere in
> > input_unregister_device(), but I don't know which one. This may be
> > an evdev problem ...
> >
>
> Please try the patch below.
Hmmm.
Now i get this BUG:
BUG: unable to handle kernel paging request at virtual address 6b6b6b6b
printing eip:
f884aa91
*pde = 00000000
Oops: 0000 [#1]
PREEMPT
Modules linked in: tg3 i915 drm binfmt_misc rfcomm l2cap ipv6 fuse
capability commoncap cpufreq_performance aoe af_packet nls_utf8 ntfs
nls_iso8859_1 nls_cp437 vfat fat dm_snapshot dm_mirror dm_mod
ieee80211_crypt_tkip ieee80211_crypt pd6729 snd_seq_dummy snd_seq_oss
snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_seq_device
sermouse hci_vhci hci_uart wbsd mmc_block mmc_core tun msr cpuid
cpufreq_stats container video backlight fan button speedstep_lib thermal
battery ac speedstep_centrino processor sr_mod sbp2 scsi_mod ide_cd
cdrom eth1394 hci_usb snd_intel8x0 pcmcia firmware_class snd_intel8x0m
bluetooth snd_ac97_codec snd_pcm_oss snd_mixer_oss ac97_bus irda snd_pcm
snd_timer i2c_i801 pcspkr crc_ccitt ohci1394 ieee1394 rtc yenta_socket
rsrc_nonstatic pcmcia_core serio_raw i2c_core snd soundcore
snd_page_alloc iTCO_wdt ehci_hcd uhci_hcd usbcore intel_agp agpgart
evdev mousedev
CPU: 0
EIP: 0060:[<f884aa91>] Not tainted VLI
EFLAGS: 00010202 (2.6.21-rc2-x300 #2)
EIP is at evdev_disconnect+0xc1/0xe0 [evdev]
eax: 00000000 ebx: 6b6b675b ecx: 10000000 edx: 00000000
esi: f6db01a8 edi: f6db021c ebp: e0e5dea4 esp: e0e5de94
ds: 007b es: 007b fs: 00d8 gs: 0033 ss: 0068
Process modprobe (pid: 5968, ti=e0e5c000 task=c1a5cac0 task.ti=e0e5c000)
Stack: 00000000 f884c728 f6db01d8 f713832c e0e5dec4 c02aa9ff 00000000
f7138a58
f7138a58 f6d6d808 c1a1202c c1a12238 e0e5ded4 f8e9e0c5 c1a1202c
f8e9fde0
e0e5dee8 c025f6d4 c1a12238 f8e9feb0 f8e9feb0 e0e5def8 c028d84a
c1a12238
Call Trace:
[<c010520a>] show_trace_log_lvl+0x1a/0x30
[<c01052c9>] show_stack_log_lvl+0xa9/0xd0
[<c010550c>] show_registers+0x21c/0x3a0
[<c0105794>] die+0x104/0x240
[<c0115bb5>] do_page_fault+0x2b5/0x5c0
[<c03384ac>] error_code+0x74/0x7c
[<c02aa9ff>] input_unregister_device+0xaf/0x140
[<f8e9e0c5>] acpi_button_remove+0x2b/0x3f [button]
[<c025f6d4>] acpi_device_remove+0x40/0x62
[<c028d84a>] __device_release_driver+0x6a/0xa0
[<c028df65>] driver_detach+0xf5/0x100
[<c028cc67>] bus_remove_driver+0x97/0xc0
[<c028df9b>] driver_unregister+0xb/0x20
[<c0260aa2>] acpi_bus_unregister_driver+0xd/0xf
[<f8e9e7d9>] acpi_button_exit+0xd/0x6a [button]
[<c013feb2>] sys_delete_module+0x142/0x1b0
[<c0104240>] syscall_call+0x7/0xb
=======================
Code: f8 74 a4 8d b4 26 00 00 00 00 8d 83 08 04 00 00 b9 06 00 02 00 ba
1d 00 00 00 e8 8b 24 93 c7 8b 9b 10 04 00 00 81 eb 10 04 00 00 <8b> 83
10 04 00 00 0f 18 00 9
EIP: [<f884aa91>] evdev_disconnect+0xc1/0xe0 [evdev] SS:ESP
0068:e0e5de94
gdb points me in the same direction as before:
(gdb) l *evdev_disconnect+0xc1
0xa91 is in evdev_disconnect (include/asm/processor.h:716).
711 However we don't do prefetches for pre XP Athlons currently
712 That should be fixed. */
713 #define ARCH_HAS_PREFETCH
714 static inline void prefetch(const void *x)
715 {
716 alternative_input(ASM_NOP4,
717 "prefetchnta (%1)",
718 X86_FEATURE_XMM,
719 "r" (x));
720 }
/Kristian
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-01 20:04 ` Kristian Grønfeldt Sørensen
@ 2007-03-01 20:25 ` Dmitry Torokhov
2007-03-01 20:34 ` Kristian Grønfeldt Sørensen
0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2007-03-01 20:25 UTC (permalink / raw)
To: Kristian Grønfeldt Sørensen
Cc: linux-input, Rafael J. Wysocki, Linux kernel mailing list
On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
>
> Hmmm.
>
> Now i get this BUG:
>
Does it die the same way if you just unload the button driver without
suspending?
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-01 20:25 ` Dmitry Torokhov
@ 2007-03-01 20:34 ` Kristian Grønfeldt Sørensen
2007-03-05 14:44 ` Dmitry Torokhov
0 siblings, 1 reply; 11+ messages in thread
From: Kristian Grønfeldt Sørensen @ 2007-03-01 20:34 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Rafael J. Wysocki, Linux kernel mailing list
On Thu, 2007-03-01 at 15:25 -0500, Dmitry Torokhov wrote:
> On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> >
> > Hmmm.
> >
> > Now i get this BUG:
> >
>
> Does it die the same way if you just unload the button driver without
> suspending?
>
No. Tried unloading and loading 30 times after each other. No problems
at all.
/Kristian
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-01 20:34 ` Kristian Grønfeldt Sørensen
@ 2007-03-05 14:44 ` Dmitry Torokhov
2007-03-05 18:32 ` Rafael J. Wysocki
0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2007-03-05 14:44 UTC (permalink / raw)
To: Kristian Grønfeldt Sørensen
Cc: linux-input, Rafael J. Wysocki, Linux kernel mailing list
On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> On Thu, 2007-03-01 at 15:25 -0500, Dmitry Torokhov wrote:
> > On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> > >
> > > Hmmm.
> > >
> > > Now i get this BUG:
> > >
> >
> > Does it die the same way if you just unload the button driver without
> > suspending?
> >
>
> No. Tried unloading and loading 30 times after each other. No problems
> at all.
>
I wonder what causes unloading of the ACPI button driver during resume...
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-05 14:44 ` Dmitry Torokhov
@ 2007-03-05 18:32 ` Rafael J. Wysocki
2007-03-05 20:51 ` Kristian Grønfeldt Sørensen
0 siblings, 1 reply; 11+ messages in thread
From: Rafael J. Wysocki @ 2007-03-05 18:32 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Kristian Grønfeldt Sørensen, linux-input,
Linux kernel mailing list
On Monday, 5 March 2007 15:44, Dmitry Torokhov wrote:
> On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> > On Thu, 2007-03-01 at 15:25 -0500, Dmitry Torokhov wrote:
> > > On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> > > >
> > > > Hmmm.
> > > >
> > > > Now i get this BUG:
> > > >
> > >
> > > Does it die the same way if you just unload the button driver without
> > > suspending?
> > >
> >
> > No. Tried unloading and loading 30 times after each other. No problems
> > at all.
> >
>
> I wonder what causes unloading of the ACPI button driver during resume...
Let me guess: pm-utils in OpenSUSE 10.2.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PROBLEM: "BUG:" when resuming from suspend-to-ram
2007-03-05 18:32 ` Rafael J. Wysocki
@ 2007-03-05 20:51 ` Kristian Grønfeldt Sørensen
0 siblings, 0 replies; 11+ messages in thread
From: Kristian Grønfeldt Sørensen @ 2007-03-05 20:51 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: Dmitry Torokhov, linux-input, Linux kernel mailing list
On Mon, 2007-03-05 at 19:32 +0100, Rafael J. Wysocki wrote:
> On Monday, 5 March 2007 15:44, Dmitry Torokhov wrote:
> > On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> > > On Thu, 2007-03-01 at 15:25 -0500, Dmitry Torokhov wrote:
> > > > On 3/1/07, Kristian Grønfeldt Sørensen <kriller@vkr.dk> wrote:
> > > > >
> > > > > Hmmm.
> > > > >
> > > > > Now i get this BUG:
> > > > >
> > > >
> > > > Does it die the same way if you just unload the button driver without
> > > > suspending?
> > > >
> > >
> > > No. Tried unloading and loading 30 times after each other. No problems
> > > at all.
> > >
> >
> > I wonder what causes unloading of the ACPI button driver during resume...
>
> Let me guess: pm-utils in OpenSUSE 10.2.
>
Nope. acpi-support for Debian unstable.
/Kristian
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2007-03-05 20:51 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1172601905.5428.28.camel@localhost.localdomain>
[not found] ` <200702272330.22968.rjw@sisk.pl>
[not found] ` <1172622441.4587.14.camel@localhost.localdomain>
2007-02-28 12:45 ` PROBLEM: "BUG:" when resuming from suspend-to-ram Rafael J. Wysocki
2007-03-01 5:36 ` Dmitry Torokhov
2007-03-01 14:55 ` Kristian Grønfeldt Sørensen
2007-03-01 15:01 ` Dmitry Torokhov
2007-03-01 16:23 ` Kristian Grønfeldt Sørensen
2007-03-01 20:04 ` Kristian Grønfeldt Sørensen
2007-03-01 20:25 ` Dmitry Torokhov
2007-03-01 20:34 ` Kristian Grønfeldt Sørensen
2007-03-05 14:44 ` Dmitry Torokhov
2007-03-05 18:32 ` Rafael J. Wysocki
2007-03-05 20:51 ` Kristian Grønfeldt Sørensen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).