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