vserver 1.9.3
[linux-2.6.git] / drivers / usb / core / devio.c
index 2979912..776c1bf 100644 (file)
@@ -72,6 +72,8 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
        } while (0)
 
 
+#define        MAX_USBFS_BUFFER_SIZE   16384
+
 static inline int connected (struct usb_device *dev)
 {
        return dev->state != USB_STATE_NOTATTACHED;
@@ -269,7 +271,7 @@ static void async_completed(struct urb *urb, struct pt_regs *regs)
                sinfo.si_signo = as->signr;
                sinfo.si_errno = as->urb->status;
                sinfo.si_code = SI_ASYNCIO;
-               sinfo.si_addr = (void *)as->userurb;
+               sinfo.si_addr = as->userurb;
                send_sig_info(as->signr, &sinfo, as->task);
        }
         wake_up(&ps->wait);
@@ -290,8 +292,11 @@ static void destroy_async (struct dev_state *ps, struct list_head *list)
                spin_lock_irqsave(&ps->lock, flags);
        }
        spin_unlock_irqrestore(&ps->lock, flags);
-       while ((as = async_getcompleted(ps)))
+       as = async_getcompleted(ps);
+       while (as) {
                free_async(as);
+               as = async_getcompleted(ps);
+       }
 }
 
 static void destroy_async_on_interface (struct dev_state *ps, unsigned int ifnum)
@@ -552,13 +557,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
                snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", 
                        ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);
 
+               up(&dev->serialize);
                i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
                                       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+               down(&dev->serialize);
                if ((i > 0) && ctrl.wLength) {
                        if (usbfs_snoop) {
                                dev_info(&dev->dev, "control read: data ");
                                for (j = 0; j < ctrl.wLength; ++j)
-                                       printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
+                                       printk ("%02x ", (unsigned char)(tbuf)[j]);
                                printk("\n");
                        }
                        if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {
@@ -578,11 +585,13 @@ static int proc_control(struct dev_state *ps, void __user *arg)
                if (usbfs_snoop) {
                        dev_info(&dev->dev, "control write: data: ");
                        for (j = 0; j < ctrl.wLength; ++j)
-                               printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
+                               printk ("%02x ", (unsigned char)(tbuf)[j]);
                        printk("\n");
                }
+               up(&dev->serialize);
                i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
                                       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+               down(&dev->serialize);
        }
        free_page((unsigned long)tbuf);
        if (i<0) {
@@ -616,6 +625,8 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
        if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
                return -EINVAL;
        len1 = bulk.len;
+       if (len1 > MAX_USBFS_BUFFER_SIZE)
+               return -EINVAL;
        if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
                return -ENOMEM;
        tmo = (bulk.timeout * HZ + 999) / 1000;
@@ -624,7 +635,9 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
                        kfree(tbuf);
                        return -EINVAL;
                }
+               up(&dev->serialize);
                i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+               down(&dev->serialize);
                if (!i && len2) {
                        if (copy_to_user(bulk.data, tbuf, len2)) {
                                kfree(tbuf);
@@ -638,7 +651,9 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
                                return -EFAULT;
                        }
                }
+               up(&dev->serialize);
                i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+               down(&dev->serialize);
        }
        kfree(tbuf);
        if (i < 0) {
@@ -846,7 +861,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
 
        case USBDEVFS_URB_TYPE_BULK:
                uurb.number_of_packets = 0;
-               if (uurb.buffer_length > 16384)
+               if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
                        return -EINVAL;
                if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
                        return -EFAULT;
@@ -888,7 +903,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
                        interval = 1 << min (15, ep_desc->bInterval - 1);
                else
                        interval = ep_desc->bInterval;
-               if (uurb.buffer_length > 16384)
+               if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
                        return -EINVAL;
                if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
                        return -EFAULT;
@@ -968,29 +983,27 @@ static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
 static int processcompl(struct async *as)
 {
        struct urb *urb = as->urb;
+       struct usbdevfs_urb __user *userurb = as->userurb;
        unsigned int i;
 
        if (as->userbuffer)
                if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
                        return -EFAULT;
-       if (put_user(urb->status,
-                    &((struct usbdevfs_urb *)as->userurb)->status))
+       if (put_user(urb->status, &userurb->status))
                return -EFAULT;
-       if (put_user(urb->actual_length,
-                    &((struct usbdevfs_urb *)as->userurb)->actual_length))
+       if (put_user(urb->actual_length, &userurb->actual_length))
                return -EFAULT;
-       if (put_user(urb->error_count,
-                    &((struct usbdevfs_urb *)as->userurb)->error_count))
+       if (put_user(urb->error_count, &userurb->error_count))
                return -EFAULT;
 
        if (!(usb_pipeisoc(urb->pipe)))
                return 0;
        for (i = 0; i < urb->number_of_packets; i++) {
                if (put_user(urb->iso_frame_desc[i].actual_length,
-                            &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length))
+                            &userurb->iso_frame_desc[i].actual_length))
                        return -EFAULT;
                if (put_user(urb->iso_frame_desc[i].status,
-                            &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status))
+                            &userurb->iso_frame_desc[i].status))
                        return -EFAULT;
        }
        return 0;
@@ -1089,10 +1102,10 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
 {
        struct usbdevfs_ioctl   ctrl;
        int                     size;
-       void                    *buf = 0;
+       void                    *buf = NULL;
        int                     retval = 0;
-       struct usb_interface    *intf = 0;
-       struct usb_driver       *driver = 0;
+       struct usb_interface    *intf = NULL;
+       struct usb_driver       *driver = NULL;
 
        /* get input parameters and alloc buffer */
        if (copy_from_user(&ctrl, arg, sizeof (ctrl)))