vserver 1.9.3
[linux-2.6.git] / drivers / usb / core / message.c
index e0eacc2..98695c6 100644 (file)
@@ -248,7 +248,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
                 * unlink pending urbs so they won't rx/tx bad data.
                 */
                for (i = 0, found = 0; i < io->entries; i++) {
-                       if (!io->urbs [i])
+                       if (!io->urbs [i] || !io->urbs [i]->dev)
                                continue;
                        if (found) {
                                status = usb_unlink_urb (io->urbs [i]);
@@ -337,7 +337,7 @@ int usb_sg_init (
        if (io->entries <= 0)
                return io->entries;
 
-       io->count = 0;
+       io->count = io->entries;
        io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
        if (!io->urbs)
                goto nomem;
@@ -347,7 +347,7 @@ int usb_sg_init (
        if (usb_pipein (pipe))
                urb_flags |= URB_SHORT_NOT_OK;
 
-       for (i = 0; i < io->entries; i++, io->count = i) {
+       for (i = 0; i < io->entries; i++) {
                unsigned                len;
 
                io->urbs [i] = usb_alloc_urb (0, mem_flags);
@@ -477,24 +477,19 @@ void usb_sg_wait (struct usb_sg_request *io)
 
                        /* fail any uncompleted urbs */
                default:
-                       spin_lock_irq (&io->lock);
-                       io->count -= entries - i;
-                       if (io->status == -EINPROGRESS)
-                               io->status = retval;
-                       if (io->count == 0)
-                               complete (&io->complete);
-                       spin_unlock_irq (&io->lock);
-
-                       io->urbs[i]->dev = NULL;
+                       io->urbs [i]->dev = NULL;
                        io->urbs [i]->status = retval;
                        dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
                                __FUNCTION__, retval);
                        usb_sg_cancel (io);
                }
                spin_lock_irq (&io->lock);
-               if (retval && io->status == -ECONNRESET)
+               if (retval && (io->status == 0 || io->status == -ECONNRESET))
                        io->status = retval;
        }
+       io->count -= entries - i;
+       if (io->count == 0)
+               complete (&io->complete);
        spin_unlock_irq (&io->lock);
 
        /* OK, yes, this could be packaged as non-blocking.
@@ -577,8 +572,13 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
                                USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                                (type << 8) + index, 0, buf, size,
                                HZ * USB_CTRL_GET_TIMEOUT);
-               if (!(result == 0 || result == -EPIPE))
-                       break;
+               if (result == 0 || result == -EPIPE)
+                       continue;
+               if (result > 1 && ((u8 *)buf)[1] != type) {
+                       result = -EPROTO;
+                       continue;
+               }
+               break;
        }
        return result;
 }
@@ -854,9 +854,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
         * the copy in usb-storage, for as long as we need two copies.
         */
 
-       /* toggle was reset by the clear, then ep was reactivated */
+       /* toggle was reset by the clear */
        usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-       usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
 
        return 0;
 }
@@ -870,9 +869,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
  * Deallocates hcd/hardware state for this endpoint ... and nukes all
  * pending urbs.
  *
- * If the HCD hasn't registered a disable() function, this marks the
- * endpoint as halted and sets its maxpacket size to 0 to prevent
- * further submissions.
+ * If the HCD hasn't registered a disable() function, this sets the
+ * endpoint's maxpacket size to 0 to prevent further submissions.
  */
 void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
 {
@@ -881,13 +879,10 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
        else {
                unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
 
-               if (usb_endpoint_out(epaddr)) {
-                       usb_endpoint_halt(dev, epnum, 1);
+               if (usb_endpoint_out(epaddr))
                        dev->epmaxpacketout[epnum] = 0;
-               } else {
-                       usb_endpoint_halt(dev, epnum, 0);
+               else
                        dev->epmaxpacketin[epnum] = 0;
-               }
        }
 }
 
@@ -930,7 +925,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                usb_disable_endpoint(dev, i + USB_DIR_IN);
        }
        dev->toggle[0] = dev->toggle[1] = 0;
-       dev->halted[0] = dev->halted[1] = 0;
 
        /* getting rid of interfaces will disconnect
         * any drivers bound to them (a key side effect)
@@ -966,9 +960,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
  * @dev: the device whose interface is being enabled
  * @epd: pointer to the endpoint descriptor
  *
- * Marks the endpoint as running, resets its toggle, and stores
- * its maxpacket value.  For control endpoints, both the input
- * and output sides are handled.
+ * Resets the endpoint toggle and stores its maxpacket value.
+ * For control endpoints, both the input and output sides are handled.
  */
 void usb_enable_endpoint(struct usb_device *dev,
                struct usb_endpoint_descriptor *epd)
@@ -980,12 +973,10 @@ void usb_enable_endpoint(struct usb_device *dev,
                                USB_ENDPOINT_XFER_CONTROL);
 
        if (usb_endpoint_out(epaddr) || is_control) {
-               usb_endpoint_running(dev, epnum, 1);
                usb_settoggle(dev, epnum, 1, 0);
                dev->epmaxpacketout[epnum] = maxsize;
        }
        if (!usb_endpoint_out(epaddr) || is_control) {
-               usb_endpoint_running(dev, epnum, 0);
                usb_settoggle(dev, epnum, 0, 0);
                dev->epmaxpacketin[epnum] = maxsize;
        }
@@ -1048,6 +1039,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
        int ret;
        int manual = 0;
 
+       if (dev->state == USB_STATE_SUSPENDED)
+               return -EHOSTUNREACH;
+
        iface = usb_ifnum_to_if(dev, interface);
        if (!iface) {
                dev_dbg(&dev->dev, "selecting invalid interface %d\n",
@@ -1145,6 +1139,9 @@ int usb_reset_configuration(struct usb_device *dev)
        int                     i, retval;
        struct usb_host_config  *config;
 
+       if (dev->state == USB_STATE_SUSPENDED)
+               return -EHOSTUNREACH;
+
        /* caller must own dev->serialize (config won't change)
         * and the usb bus readlock (so driver bindings are stable);
         * so calls during probe() are fine
@@ -1166,7 +1163,6 @@ int usb_reset_configuration(struct usb_device *dev)
        }
 
        dev->toggle[0] = dev->toggle[1] = 0;
-       dev->halted[0] = dev->halted[1] = 0;
 
        /* re-init hc/hcd interface/endpoint state */
        for (i = 0; i < config->desc.bNumInterfaces; i++) {
@@ -1195,7 +1191,7 @@ static void release_interface(struct device *dev)
        struct usb_interface_cache *intfc =
                        altsetting_to_usb_interface_cache(intf->altsetting);
 
-       kref_put(&intfc->ref);
+       kref_put(&intfc->ref, usb_release_interface_cache);
        kfree(intf);
 }
 
@@ -1258,6 +1254,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        if (cp && configuration == 0)
                dev_warn(&dev->dev, "config 0 descriptor??\n");
 
+       if (dev->state == USB_STATE_SUSPENDED)
+               return -EHOSTUNREACH;
+
        /* Allocate memory for new interfaces before doing anything else,
         * so that if we run out then nothing will have changed. */
        n = nintf = 0;