[PATCH] usbhid: fix suspend crash by moving initializations earlier

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Although the usbhid driver allocates its usbhid structure in the probe
routine, several critical fields in that structure don't get
initialized until usbhid_start().  However if report descriptor
parsing fails then usbhid_start() is never called.  This leads to
problems during system suspend -- the system will freeze.

This patch (as1378) fixes the bug by moving the initialization
statements up into usbhid_probe().

Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Reported-by: Bruno Prémont <bonbons@xxxxxxxxxxxxxxxxx>
Tested-By: Bruno Prémont <bonbons@xxxxxxxxxxxxxxxxx>

---

On Thu, 6 May 2010, Bruno [UTF-8] Prémont wrote:

> This very much reminds me the resume issue with the same keyboard on a
> !CONFIG_SMP system back in February when the fix was to copy/move
> usbhid->intf = intf; from usbhid_start() to usbhid_probe()!

Yes indeed, I had exactly the same thought.

> Hopefully these are all those initializations that need to be taken
> care of...

I looked and didn't see any others.

Jiri, this clearly is needed for 2.6.34.  It might or might not be 
added to the -stable trees; if the patch moving the usbhid->intf 
initialization hasn't gotten into -stable then there's no point adding 
this one.

Alan Stern



Index: usb-2.6/drivers/hid/usbhid/hid-core.c
===================================================================
--- usb-2.6.orig/drivers/hid/usbhid/hid-core.c
+++ usb-2.6/drivers/hid/usbhid/hid-core.c
@@ -998,13 +998,6 @@ static int usbhid_start(struct hid_devic
 		}
 	}
 
-	init_waitqueue_head(&usbhid->wait);
-	INIT_WORK(&usbhid->reset_work, hid_reset);
-	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
-	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
-
-	spin_lock_init(&usbhid->lock);
-
 	usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
 	if (!usbhid->urbctrl) {
 		ret = -ENOMEM;
@@ -1180,6 +1173,12 @@ static int usbhid_probe(struct usb_inter
 	usbhid->intf = intf;
 	usbhid->ifnum = interface->desc.bInterfaceNumber;
 
+	init_waitqueue_head(&usbhid->wait);
+	INIT_WORK(&usbhid->reset_work, hid_reset);
+	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
+	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+	spin_lock_init(&usbhid->lock);
+
 	ret = hid_add_device(hid);
 	if (ret) {
 		if (ret != -ENODEV)

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux