summaryrefslogtreecommitdiff
path: root/drivers/hid/hidraw.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-05-26 11:25:26 +0200
committerJiri Kosina <jkosina@suse.cz>2008-07-23 15:21:55 +0200
commit979c407e3b89b606e810fa494ef316896eadbfad (patch)
tree87cd809c8ef5bcb7957a29354e2e7e17fec27e00 /drivers/hid/hidraw.c
parent7961df16819085b8a357720d89d0239036e6af2a (diff)
downloadlwn-979c407e3b89b606e810fa494ef316896eadbfad.tar.gz
lwn-979c407e3b89b606e810fa494ef316896eadbfad.zip
HID: Push down BKL into ioctl handler in hidraw
In this case I simply wrapped it as code review suggests the locking already terminally broken and I didn't want to make it first. See added comment Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r--drivers/hid/hidraw.c46
1 files changed, 24 insertions, 22 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 0c6b4d4e7e27..1018f380de35 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -105,6 +105,7 @@ out:
static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ /* FIXME: What stops hidraw_table going NULL */
struct hid_device *dev = hidraw_table[minor]->hid;
__u8 *buf;
int ret = 0;
@@ -214,35 +215,38 @@ static int hidraw_release(struct inode * inode, struct file * file)
return 0;
}
-static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long hidraw_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
+ struct inode *inode = file->f_path.dentry->d_inode;
unsigned int minor = iminor(inode);
+ long ret = 0;
+ /* FIXME: What stops hidraw_table going NULL */
struct hidraw *dev = hidraw_table[minor];
void __user *user_arg = (void __user*) arg;
+ lock_kernel();
switch (cmd) {
case HIDIOCGRDESCSIZE:
if (put_user(dev->hid->rsize, (int __user *)arg))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ break;
case HIDIOCGRDESC:
{
__u32 len;
if (get_user(len, (int __user *)arg))
- return -EFAULT;
-
- if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
- return -EINVAL;
-
- if (copy_to_user(user_arg + offsetof(
- struct hidraw_report_descriptor,
- value[0]),
- dev->hid->rdesc,
- min(dev->hid->rsize, len)))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
+ ret = -EINVAL;
+ else if (copy_to_user(user_arg + offsetof(
+ struct hidraw_report_descriptor,
+ value[0]),
+ dev->hid->rdesc,
+ min(dev->hid->rsize, len)))
+ ret = -EFAULT;
+ break;
}
case HIDIOCGRAWINFO:
{
@@ -252,15 +256,13 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dinfo.vendor = dev->hid->vendor;
dinfo.product = dev->hid->product;
if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
- return -EFAULT;
-
- return 0;
+ ret = -EFAULT;
+ break;
}
default:
- printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n",
- cmd);
+ ret = -ENOTTY;
}
- return -EINVAL;
+ return ret;
}
static const struct file_operations hidraw_ops = {
@@ -270,7 +272,7 @@ static const struct file_operations hidraw_ops = {
.poll = hidraw_poll,
.open = hidraw_open,
.release = hidraw_release,
- .ioctl = hidraw_ioctl,
+ .unlocked_ioctl = hidraw_ioctl,
};
void hidraw_report_event(struct hid_device *hid, u8 *data, int len)