diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2010-05-07 10:41:10 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-09-20 13:17:51 -0700 |
commit | 3df1ba0d074919fef36e919220aec1b379d82684 (patch) | |
tree | 37a899d95e8ba420e2e9c967e93c94027dbd4331 | |
parent | c7260ac8c7a413285419dd3835e81d43ec39fba6 (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.c | 13 |
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) |