summaryrefslogtreecommitdiffstats
path: root/drivers/hid/usbhid
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-08-19 12:48:09 +0200
committerIngo Molnar <mingo@elte.hu>2010-08-19 12:48:09 +0200
commitc8710ad38900153af7a3e6762e99c062cfa46443 (patch)
treea0c0632274c4eb72f51e99a5861f71cffe65ea60 /drivers/hid/usbhid
parent6016ee13db518ab1cd0cbf43fc2ad5712021e338 (diff)
parent86397dc3ccfc0e17b7550d05eaf15fe91f6498dd (diff)
Merge branch 'tip/perf/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into perf/core
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--drivers/hid/usbhid/hiddev.c54
2 files changed, 14 insertions, 42 deletions
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 5f5aa39b398..2643d314762 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -75,6 +75,8 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE },
+
{ 0, 0 }
};
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index c24d2fa3e3b..254a003af04 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -67,7 +67,7 @@ struct hiddev_list {
struct mutex thread_lock;
};
-static struct hiddev *hiddev_table[HIDDEV_MINORS];
+static struct usb_driver hiddev_driver;
/*
* Find a report, given the report's type and ID. The ID can be specified
@@ -265,22 +265,19 @@ static int hiddev_release(struct inode * inode, struct file * file)
static int hiddev_open(struct inode *inode, struct file *file)
{
struct hiddev_list *list;
- int res, i;
-
- /* See comment in hiddev_connect() for BKL explanation */
- lock_kernel();
- i = iminor(inode) - HIDDEV_MINOR_BASE;
+ struct usb_interface *intf;
+ struct hiddev *hiddev;
+ int res;
- if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i])
+ intf = usb_find_interface(&hiddev_driver, iminor(inode));
+ if (!intf)
return -ENODEV;
+ hiddev = usb_get_intfdata(intf);
if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
return -ENOMEM;
mutex_init(&list->thread_lock);
-
- list->hiddev = hiddev_table[i];
-
-
+ list->hiddev = hiddev;
file->private_data = list;
/*
@@ -289,7 +286,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
*/
if (list->hiddev->exist) {
if (!list->hiddev->open++) {
- res = usbhid_open(hiddev_table[i]->hid);
+ res = usbhid_open(hiddev->hid);
if (res < 0) {
res = -EIO;
goto bail;
@@ -301,12 +298,12 @@ static int hiddev_open(struct inode *inode, struct file *file)
}
spin_lock_irq(&list->hiddev->list_lock);
- list_add_tail(&list->node, &hiddev_table[i]->list);
+ list_add_tail(&list->node, &hiddev->list);
spin_unlock_irq(&list->hiddev->list_lock);
if (!list->hiddev->open++)
if (list->hiddev->exist) {
- struct hid_device *hid = hiddev_table[i]->hid;
+ struct hid_device *hid = hiddev->hid;
res = usbhid_get_power(hid);
if (res < 0) {
res = -EIO;
@@ -314,13 +311,10 @@ static int hiddev_open(struct inode *inode, struct file *file)
}
usbhid_open(hid);
}
-
- unlock_kernel();
return 0;
bail:
file->private_data = NULL;
kfree(list);
- unlock_kernel();
return res;
}
@@ -894,37 +888,14 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
hid->hiddev = hiddev;
hiddev->hid = hid;
hiddev->exist = 1;
-
- /*
- * BKL here is used to avoid race after usb_register_dev().
- * Once the device node has been created, open() could happen on it.
- * The code below will then fail, as hiddev_table hasn't been
- * updated.
- *
- * The obvious fix -- introducing mutex to guard hiddev_table[]
- * doesn't work, as usb_open() and usb_register_dev() both take
- * minor_rwsem, thus we'll have ABBA deadlock.
- *
- * Before BKL pushdown, usb_open() had been acquiring it in right
- * order, so _open() was safe to use it to protect from this race.
- * Now the order is different, but AB-BA deadlock still doesn't occur
- * as BKL is dropped on schedule() (i.e. while sleeping on
- * minor_rwsem). Fugly.
- */
- lock_kernel();
+ usb_set_intfdata(usbhid->intf, usbhid);
retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) {
err_hid("Not able to get a minor for this device.");
hid->hiddev = NULL;
- unlock_kernel();
kfree(hiddev);
return -1;
- } else {
- hid->minor = usbhid->intf->minor;
- hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
}
- unlock_kernel();
-
return 0;
}
@@ -942,7 +913,6 @@ void hiddev_disconnect(struct hid_device *hid)
hiddev->exist = 0;
mutex_unlock(&hiddev->existancelock);
- hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
usb_deregister_dev(usbhid->intf, &hiddev_class);
if (hiddev->open) {