Hi,
ioctl has the same locking requirements as read and write.
This patch should fix it.
Regards
Oliver
PS: Simple diff this time. My BK-trees are at home.
--- /tmp/scanner.c Sun Dec 22 22:09:57 2002
+++ drivers/usb/scanner.c Mon Dec 23 23:19:12 2002
@@ -388,7 +388,7 @@
dev = scn->scn_dev;
- down(&(scn->sem)); /* Now protect the scn_usb_data structure */
+ down(&(scn->sem)); /* Now protect the scn_usb_data structure */
up(&scn_mutex); /* Now handled by the above */
@@ -621,7 +621,7 @@
goto data_recvd;
}
}
-
+
if (result == -EPIPE) { /* No hope */
if(usb_clear_halt(dev, scn->bulk_in_ep)) {
err("read_scanner(%d): Failure to clear endpoint halt condition (%Zd).", scn_minor, ret);
@@ -669,30 +669,26 @@
ioctl_scanner(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct scn_usb_data *scn;
struct usb_device *dev;
+ int retval = -ENOTTY;
- kdev_t scn_minor;
-
- scn_minor = USB_SCN_MINOR(inode);
-
- if (!p_scn_table[scn_minor]) {
- err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
- return -ENODEV;
- }
+ scn = file->private_data;
+ down(&(scn->sem));
- dev = p_scn_table[scn_minor]->scn_dev;
+ dev = scn->scn_dev;
switch (cmd)
{
case SCANNER_IOCTL_VENDOR :
- return (put_user(dev->descriptor.idVendor, (unsigned int *) arg));
+ retval = (put_user(dev->descriptor.idVendor, (unsigned int *) arg));
+ break;
case SCANNER_IOCTL_PRODUCT :
- return (put_user(dev->descriptor.idProduct, (unsigned int *) arg));
+ retval = (put_user(dev->descriptor.idProduct, (unsigned int *) arg));
+ break;
#ifdef PV8630
case PV8630_IOCTL_INREQUEST :
{
- int result;
-
struct {
__u8 data;
__u8 request;
@@ -700,10 +696,12 @@
__u16 index;
} args;
- if (copy_from_user(&args, (void *)arg, sizeof(args)))
- return -EFAULT;
+ if (copy_from_user(&args, (void *)arg, sizeof(args))) {
+ retval = -EFAULT;
+ break;
+ }
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
args.request, USB_TYPE_VENDOR|
USB_RECIP_DEVICE|USB_DIR_IN,
args.value, args.index, &args.data,
@@ -712,28 +710,28 @@
dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index, args.request);
if (copy_to_user((void *)arg, &args, sizeof(args)))
- return -EFAULT;
+ retval = -EFAULT;
dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result);
- return result;
+ break;
}
case PV8630_IOCTL_OUTREQUEST :
{
- int result;
-
struct {
__u8 request;
__u16 value;
__u16 index;
} args;
- if (copy_from_user(&args, (void *)arg, sizeof(args)))
- return -EFAULT;
+ if (copy_from_user(&args, (void *)arg, sizeof(args))) {
+ retval = -EFAULT;
+ break;
+ }
dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x args.request:%x\n", scn_minor, args.value, args.index, args.request);
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
args.request, USB_TYPE_VENDOR|
USB_RECIP_DEVICE|USB_DIR_OUT,
args.value, args.index, NULL,
@@ -741,7 +739,7 @@
dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result);
- return result;
+ break;
}
#endif /* PV8630 */
case SCANNER_IOCTL_CTRLMSG:
@@ -752,19 +750,26 @@
} cmsg;
int pipe, nb, ret;
unsigned char buf[64];
-
- if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg)))
- return -EFAULT;
+ retval = 0;
+
+ if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg))) {
+ retval = -EFAULT;
+ break;
+ }
nb = le16_to_cpup(&cmsg.req.length);
- if (nb > sizeof(buf))
- return -EINVAL;
+ if (nb > sizeof(buf)) {
+ retval = -EINVAL;
+ break;
+ }
if ((cmsg.req.requesttype & 0x80) == 0) {
pipe = usb_sndctrlpipe(dev, 0);
- if (nb > 0 && copy_from_user(buf, cmsg.data, nb))
- return -EFAULT;
+ if (nb > 0 && copy_from_user(buf, cmsg.data, nb)) {
+ retval = -EFAULT;
+ break;
+ }
} else {
pipe = usb_rcvctrlpipe(dev, 0);
}
@@ -776,19 +781,21 @@
buf, nb, HZ);
if (ret < 0) {
- err("ioctl_scanner(%d): control_msg returned %d\n", scn_minor, ret);
- return -EIO;
+ err("ioctl_scanner: control_msg returned %d\n", ret);
+ retval = -EIO;
+ break;
}
if (nb > 0 && (cmsg.req.requesttype & 0x80) && copy_to_user(cmsg.data, buf, nb))
- return -EFAULT;
+ retval = -EFAULT;
- return 0;
+ break;
}
default:
- return -ENOTTY;
+ break;
}
- return 0;
+ up(&(scn->sem));
+ return retval;
}
static struct