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

Reply via email to