linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* 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).