54 lines
2.0 KiB
Diff
54 lines
2.0 KiB
Diff
|
commit fde4e2f73208b8f34f123791e39c0cb6bc74b32a
|
||
|
Author: Alan Stern <stern at rowland.harvard.edu>
|
||
|
Date: Fri May 7 10:41:10 2010 -0400
|
||
|
|
||
|
HID: fix suspend crash by moving initializations earlier
|
||
|
|
||
|
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 at rowland.harvard.edu>
|
||
|
Reported-by: Bruno Prémont <bonbons at linux-vserver.org>
|
||
|
Tested-By: Bruno Prémont <bonbons at linux-vserver.org>
|
||
|
Signed-off-by: Jiri Kosina <jkosina at suse.cz>
|
||
|
|
||
|
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
|
||
|
index 56d06cd..7b85b69 100644
|
||
|
--- a/drivers/hid/usbhid/hid-core.c
|
||
|
+++ b/drivers/hid/usbhid/hid-core.c
|
||
|
@@ -999,13 +999,6 @@ static int usbhid_start(struct hid_device *hid)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- 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;
|
||
|
@@ -1179,6 +1172,12 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
|
||
|
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)
|
||
|
|
||
|
|