Chuck Ebbert 02278b
commit fde4e2f73208b8f34f123791e39c0cb6bc74b32a
Chuck Ebbert 02278b
Author: Alan Stern <stern at="" rowland.harvard.edu="">
Chuck Ebbert 02278b
Date:   Fri May 7 10:41:10 2010 -0400
Chuck Ebbert 02278b
Chuck Ebbert 02278b
    HID: fix suspend crash by moving initializations earlier
Chuck Ebbert 02278b
    
Chuck Ebbert 02278b
    Although the usbhid driver allocates its usbhid structure in the probe
Chuck Ebbert 02278b
    routine, several critical fields in that structure don't get
Chuck Ebbert 02278b
    initialized until usbhid_start().  However if report descriptor
Chuck Ebbert 02278b
    parsing fails then usbhid_start() is never called.  This leads to
Chuck Ebbert 02278b
    problems during system suspend -- the system will freeze.
Chuck Ebbert 02278b
    
Chuck Ebbert 02278b
    This patch (as1378) fixes the bug by moving the initialization
Chuck Ebbert 02278b
    statements up into usbhid_probe().
Chuck Ebbert 02278b
    
Chuck Ebbert 02278b
    Signed-off-by: Alan Stern <stern at="" rowland.harvard.edu="">
Chuck Ebbert 02278b
    Reported-by: Bruno Prémont <bonbons at="" linux-vserver.org="">
Chuck Ebbert 02278b
    Tested-By: Bruno Prémont <bonbons at="" linux-vserver.org="">
Chuck Ebbert 02278b
    Signed-off-by: Jiri Kosina <jkosina at="" suse.cz="">
Chuck Ebbert 02278b
Chuck Ebbert 02278b
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
Chuck Ebbert 02278b
index 56d06cd..7b85b69 100644
Chuck Ebbert 02278b
--- a/drivers/hid/usbhid/hid-core.c
Chuck Ebbert 02278b
+++ b/drivers/hid/usbhid/hid-core.c
Chuck Ebbert 02278b
@@ -999,13 +999,6 @@ static int usbhid_start(struct hid_device *hid)
Chuck Ebbert 02278b
 		}
Chuck Ebbert 02278b
 	}
Chuck Ebbert 02278b
 
Chuck Ebbert 02278b
-	init_waitqueue_head(&usbhid->wait);
Chuck Ebbert 02278b
-	INIT_WORK(&usbhid->reset_work, hid_reset);
Chuck Ebbert 02278b
-	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
Chuck Ebbert 02278b
-	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
Chuck Ebbert 02278b
-
Chuck Ebbert 02278b
-	spin_lock_init(&usbhid->lock);
Chuck Ebbert 02278b
-
Chuck Ebbert 02278b
 	usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
Chuck Ebbert 02278b
 	if (!usbhid->urbctrl) {
Chuck Ebbert 02278b
 		ret = -ENOMEM;
Chuck Ebbert 02278b
@@ -1179,6 +1172,12 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
Chuck Ebbert 02278b
 	usbhid->intf = intf;
Chuck Ebbert 02278b
 	usbhid->ifnum = interface->desc.bInterfaceNumber;
Chuck Ebbert 02278b
 
Chuck Ebbert 02278b
+	init_waitqueue_head(&usbhid->wait);
Chuck Ebbert 02278b
+	INIT_WORK(&usbhid->reset_work, hid_reset);
Chuck Ebbert 02278b
+	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
Chuck Ebbert 02278b
+	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
Chuck Ebbert 02278b
+	spin_lock_init(&usbhid->lock);
Chuck Ebbert 02278b
+
Chuck Ebbert 02278b
 	ret = hid_add_device(hid);
Chuck Ebbert 02278b
 	if (ret) {
Chuck Ebbert 02278b
 		if (ret != -ENODEV)
Chuck Ebbert 02278b
Chuck Ebbert 02278b