aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2010-05-07 10:41:10 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-09-20 13:17:51 -0700
commit3df1ba0d074919fef36e919220aec1b379d82684 (patch)
tree37a899d95e8ba420e2e9c967e93c94027dbd4331
parentc7260ac8c7a413285419dd3835e81d43ec39fba6 (diff)
HID: fix suspend crash by moving initializations earlier
commit fde4e2f73208b8f34f123791e39c0cb6bc74b32a upstream. 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@rowland.harvard.edu> Reported-by: Bruno Prémont <bonbons@linux-vserver.org> Tested-By: Bruno Prémont <bonbons@linux-vserver.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Cc: maximilian attems <max@stro.at> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/hid/usbhid/hid-core.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index adfaa7d760d..e9add5b3481 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1000,13 +1000,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;
@@ -1180,6 +1173,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)