aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/usbhid
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2012-05-22 05:32:31 -0400
committerJiri Kosina <jkosina@suse.cz>2012-05-22 05:32:31 -0400
commit56ccd186f1837dd418cd094f0e96b3196bbab9ef (patch)
tree195cdd3973a1288eb84f51f0ec28a947b333c2c5 /drivers/hid/usbhid
parentb3d07e0344ea36dd3f3a2fdbfaab883e1c5ca69e (diff)
parentd1257081aecf44455fcab8675f1d54e8b242faa1 (diff)
Merge branch 'upstream' into for-linus
Conflicts: drivers/hid/hid-core.c
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r--drivers/hid/usbhid/hid-core.c65
-rw-r--r--drivers/hid/usbhid/hiddev.c9
-rw-r--r--drivers/hid/usbhid/usbhid.h1
3 files changed, 61 insertions, 14 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 9cba5006b5ed..df3789f5d9a5 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -28,6 +28,7 @@
28#include <linux/input.h> 28#include <linux/input.h>
29#include <linux/wait.h> 29#include <linux/wait.h>
30#include <linux/workqueue.h> 30#include <linux/workqueue.h>
31#include <linux/string.h>
31 32
32#include <linux/usb.h> 33#include <linux/usb.h>
33 34
@@ -86,8 +87,13 @@ static int hid_start_in(struct hid_device *hid)
86 !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) && 87 !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) &&
87 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { 88 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
88 rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); 89 rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
89 if (rc != 0) 90 if (rc != 0) {
90 clear_bit(HID_IN_RUNNING, &usbhid->iofl); 91 clear_bit(HID_IN_RUNNING, &usbhid->iofl);
92 if (rc == -ENOSPC)
93 set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
94 } else {
95 clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
96 }
91 } 97 }
92 spin_unlock_irqrestore(&usbhid->lock, flags); 98 spin_unlock_irqrestore(&usbhid->lock, flags);
93 return rc; 99 return rc;
@@ -173,8 +179,10 @@ static void hid_io_error(struct hid_device *hid)
173 179
174 if (time_after(jiffies, usbhid->stop_retry)) { 180 if (time_after(jiffies, usbhid->stop_retry)) {
175 181
176 /* Retries failed, so do a port reset */ 182 /* Retries failed, so do a port reset unless we lack bandwidth*/
177 if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { 183 if (test_bit(HID_NO_BANDWIDTH, &usbhid->iofl)
184 && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
185
178 schedule_work(&usbhid->reset_work); 186 schedule_work(&usbhid->reset_work);
179 goto done; 187 goto done;
180 } 188 }
@@ -700,7 +708,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
700int usbhid_open(struct hid_device *hid) 708int usbhid_open(struct hid_device *hid)
701{ 709{
702 struct usbhid_device *usbhid = hid->driver_data; 710 struct usbhid_device *usbhid = hid->driver_data;
703 int res; 711 int res = 0;
704 712
705 mutex_lock(&hid_open_mut); 713 mutex_lock(&hid_open_mut);
706 if (!hid->open++) { 714 if (!hid->open++) {
@@ -708,17 +716,27 @@ int usbhid_open(struct hid_device *hid)
708 /* the device must be awake to reliably request remote wakeup */ 716 /* the device must be awake to reliably request remote wakeup */
709 if (res < 0) { 717 if (res < 0) {
710 hid->open--; 718 hid->open--;
711 mutex_unlock(&hid_open_mut); 719 res = -EIO;
712 return -EIO; 720 goto done;
713 } 721 }
714 usbhid->intf->needs_remote_wakeup = 1; 722 usbhid->intf->needs_remote_wakeup = 1;
715 if (hid_start_in(hid)) 723 res = hid_start_in(hid);
716 hid_io_error(hid); 724 if (res) {
717 725 if (res != -ENOSPC) {
726 hid_io_error(hid);
727 res = 0;
728 } else {
729 /* no use opening if resources are insufficient */
730 hid->open--;
731 res = -EBUSY;
732 usbhid->intf->needs_remote_wakeup = 0;
733 }
734 }
718 usb_autopm_put_interface(usbhid->intf); 735 usb_autopm_put_interface(usbhid->intf);
719 } 736 }
737done:
720 mutex_unlock(&hid_open_mut); 738 mutex_unlock(&hid_open_mut);
721 return 0; 739 return res;
722} 740}
723 741
724void usbhid_close(struct hid_device *hid) 742void usbhid_close(struct hid_device *hid)
@@ -1347,7 +1365,34 @@ static int hid_post_reset(struct usb_interface *intf)
1347 struct usb_device *dev = interface_to_usbdev (intf); 1365 struct usb_device *dev = interface_to_usbdev (intf);
1348 struct hid_device *hid = usb_get_intfdata(intf); 1366 struct hid_device *hid = usb_get_intfdata(intf);
1349 struct usbhid_device *usbhid = hid->driver_data; 1367 struct usbhid_device *usbhid = hid->driver_data;
1368 struct usb_host_interface *interface = intf->cur_altsetting;
1350 int status; 1369 int status;
1370 char *rdesc;
1371
1372 /* Fetch and examine the HID report descriptor. If this
1373 * has changed, then rebind. Since usbcore's check of the
1374 * configuration descriptors passed, we already know that
1375 * the size of the HID report descriptor has not changed.
1376 */
1377 rdesc = kmalloc(hid->rsize, GFP_KERNEL);
1378 if (!rdesc) {
1379 dbg_hid("couldn't allocate rdesc memory (post_reset)\n");
1380 return 1;
1381 }
1382 status = hid_get_class_descriptor(dev,
1383 interface->desc.bInterfaceNumber,
1384 HID_DT_REPORT, rdesc, hid->rsize);
1385 if (status < 0) {
1386 dbg_hid("reading report descriptor failed (post_reset)\n");
1387 kfree(rdesc);
1388 return 1;
1389 }
1390 status = memcmp(rdesc, hid->rdesc, hid->rsize);
1391 kfree(rdesc);
1392 if (status != 0) {
1393 dbg_hid("report descriptor changed\n");
1394 return 1;
1395 }
1351 1396
1352 spin_lock_irq(&usbhid->lock); 1397 spin_lock_irq(&usbhid->lock);
1353 clear_bit(HID_RESET_PENDING, &usbhid->iofl); 1398 clear_bit(HID_RESET_PENDING, &usbhid->iofl);
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index b1ec0e2aeb57..14599e256791 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -34,6 +34,7 @@
34#include <linux/hid.h> 34#include <linux/hid.h>
35#include <linux/hiddev.h> 35#include <linux/hiddev.h>
36#include <linux/compat.h> 36#include <linux/compat.h>
37#include <linux/vmalloc.h>
37#include "usbhid.h" 38#include "usbhid.h"
38 39
39#ifdef CONFIG_USB_DYNAMIC_MINORS 40#ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -250,13 +251,13 @@ static int hiddev_release(struct inode * inode, struct file * file)
250 } else { 251 } else {
251 mutex_unlock(&list->hiddev->existancelock); 252 mutex_unlock(&list->hiddev->existancelock);
252 kfree(list->hiddev); 253 kfree(list->hiddev);
253 kfree(list); 254 vfree(list);
254 return 0; 255 return 0;
255 } 256 }
256 } 257 }
257 258
258 mutex_unlock(&list->hiddev->existancelock); 259 mutex_unlock(&list->hiddev->existancelock);
259 kfree(list); 260 vfree(list);
260 261
261 return 0; 262 return 0;
262} 263}
@@ -278,7 +279,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
278 hid = usb_get_intfdata(intf); 279 hid = usb_get_intfdata(intf);
279 hiddev = hid->hiddev; 280 hiddev = hid->hiddev;
280 281
281 if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) 282 if (!(list = vzalloc(sizeof(struct hiddev_list))))
282 return -ENOMEM; 283 return -ENOMEM;
283 mutex_init(&list->thread_lock); 284 mutex_init(&list->thread_lock);
284 list->hiddev = hiddev; 285 list->hiddev = hiddev;
@@ -322,7 +323,7 @@ bail_unlock:
322 mutex_unlock(&hiddev->existancelock); 323 mutex_unlock(&hiddev->existancelock);
323bail: 324bail:
324 file->private_data = NULL; 325 file->private_data = NULL;
325 kfree(list); 326 vfree(list);
326 return res; 327 return res;
327} 328}
328 329
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index cb8f703efde5..1883d7b94870 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -55,6 +55,7 @@ struct usb_interface *usbhid_find_interface(int minor);
55#define HID_STARTED 8 55#define HID_STARTED 8
56#define HID_REPORTED_IDLE 9 56#define HID_REPORTED_IDLE 9
57#define HID_KEYS_PRESSED 10 57#define HID_KEYS_PRESSED 10
58#define HID_NO_BANDWIDTH 11
58 59
59/* 60/*
60 * USB-specific HID struct, to be pointed to 61 * USB-specific HID struct, to be pointed to