Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / usb / core / message.c
index e0165ae..08fb20f 100644 (file)
@@ -3,13 +3,6 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-       #define DEBUG
-#else
-       #undef DEBUG
-#endif
-
 #include <linux/pci.h> /* for scatterlist macros */
 #include <linux/usb.h>
 #include <linux/module.h>
@@ -20,6 +13,7 @@
 #include <linux/ctype.h>
 #include <linux/device.h>
 #include <asm/byteorder.h>
+#include <asm/scatterlist.h>
 
 #include "hcd.h"       /* for usbcore internals */
 #include "usb.h"
@@ -48,14 +42,13 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
 
        init_completion(&done);         
        urb->context = &done;
-       urb->transfer_flags |= URB_ASYNC_UNLINK;
        urb->actual_length = 0;
        status = usb_submit_urb(urb, GFP_NOIO);
 
        if (status == 0) {
                if (timeout > 0) {
                        init_timer(&timer);
-                       timer.expires = jiffies + timeout;
+                       timer.expires = jiffies + msecs_to_jiffies(timeout);
                        timer.data = (unsigned long)urb;
                        timer.function = timeout_kill;
                        /* grr.  timeout _should_ include submit delays. */
@@ -65,12 +58,18 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
                status = urb->status;
                /* note:  HCDs return ETIMEDOUT for other reasons too */
                if (status == -ECONNRESET) {
-                       dev_warn(&urb->dev->dev,
-                               "%s timed out on ep%d%s\n",
+                       dev_dbg(&urb->dev->dev,
+                               "%s timed out on ep%d%s len=%d/%d\n",
                                current->comm,
                                usb_pipeendpoint(urb->pipe),
-                               usb_pipein(urb->pipe) ? "in" : "out");
-                       status = -ETIMEDOUT;
+                               usb_pipein(urb->pipe) ? "in" : "out",
+                               urb->actual_length,
+                               urb->transfer_buffer_length
+                               );
+                       if (urb->actual_length > 0)
+                               status = 0;
+                       else
+                               status = -ETIMEDOUT;
                }
                if (timeout > 0)
                        del_timer_sync(&timer);
@@ -84,8 +83,10 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
 
 /*-------------------------------------------------------------------*/
 // returns status (negative) or length (positive)
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, 
-                           struct usb_ctrlrequest *cmd,  void *data, int len, int timeout)
+static int usb_internal_control_msg(struct usb_device *usb_dev,
+                                   unsigned int pipe, 
+                                   struct usb_ctrlrequest *cmd,
+                                   void *data, int len, int timeout)
 {
        struct urb *urb;
        int retv;
@@ -115,7 +116,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
  *     @index: USB message index value
  *     @data: pointer to the data to send
  *     @size: length in bytes of the data to send
- *     @timeout: time in jiffies to wait for the message to complete before
+ *     @timeout: time in msecs to wait for the message to complete before
  *             timing out (if 0 the wait is forever)
  *     Context: !in_interrupt ()
  *
@@ -163,7 +164,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
  *     @data: pointer to the data to send
  *     @len: length in bytes of the data to send
  *     @actual_length: pointer to a location to put the actual length transferred in bytes
- *     @timeout: time in jiffies to wait for the message to complete before
+ *     @timeout: time in msecs to wait for the message to complete before
  *             timing out (if 0 the wait is forever)
  *     Context: !in_interrupt ()
  *
@@ -180,23 +181,39 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
  *      If a thread in your driver uses this call, make sure your disconnect()
  *      method can wait for it to complete.  Since you don't have a handle on
  *      the URB used, you can't cancel the request.
+ *
+ *     Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
+ *     ioctl, users are forced to abuse this routine by using it to submit
+ *     URBs for interrupt endpoints.  We will take the liberty of creating
+ *     an interrupt URB (with the default interval) if the target is an
+ *     interrupt endpoint.
  */
 int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
                        void *data, int len, int *actual_length, int timeout)
 {
        struct urb *urb;
+       struct usb_host_endpoint *ep;
 
-       if (len < 0)
+       ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
+                       [usb_pipeendpoint(pipe)];
+       if (!ep || len < 0)
                return -EINVAL;
 
-       urb=usb_alloc_urb(0, GFP_KERNEL);
+       urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb)
                return -ENOMEM;
 
-       usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
-                         usb_api_blocking_completion, NULL);
-
-       return usb_start_wait_urb(urb,timeout,actual_length);
+       if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+                       USB_ENDPOINT_XFER_INT) {
+               pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
+               usb_fill_int_urb(urb, usb_dev, pipe, data, len,
+                               usb_api_blocking_completion, NULL,
+                               ep->desc.bInterval);
+       } else
+               usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
+                               usb_api_blocking_completion, NULL);
+
+       return usb_start_wait_urb(urb, timeout, actual_length);
 }
 
 /*-------------------------------------------------------------------*/
@@ -258,7 +275,9 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
                                continue;
                        if (found) {
                                status = usb_unlink_urb (io->urbs [i]);
-                               if (status != -EINPROGRESS && status != -EBUSY)
+                               if (status != -EINPROGRESS
+                                               && status != -ENODEV
+                                               && status != -EBUSY)
                                        dev_err (&io->dev->dev,
                                                "%s, unlink --> %d\n",
                                                __FUNCTION__, status);
@@ -312,7 +331,7 @@ int usb_sg_init (
        struct scatterlist      *sg,
        int                     nents,
        size_t                  length,
-       int                     mem_flags
+       gfp_t                   mem_flags
 )
 {
        int                     i;
@@ -349,8 +368,7 @@ int usb_sg_init (
        if (!io->urbs)
                goto nomem;
 
-       urb_flags = URB_ASYNC_UNLINK | URB_NO_TRANSFER_DMA_MAP
-                       | URB_NO_INTERRUPT;
+       urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
        if (usb_pipein (pipe))
                urb_flags |= URB_SHORT_NOT_OK;
 
@@ -423,7 +441,7 @@ nomem:
  * (2) error, where io->status is a negative errno value.  The number
  *     of io->bytes transferred before the error is usually less
  *     than requested, and can be nonzero.
- * (3) cancelation, a type of error with status -ECONNRESET that
+ * (3) cancellation, a type of error with status -ECONNRESET that
  *     is initiated by usb_sg_cancel().
  *
  * When this function returns, all memory allocated through usb_sg_init() or
@@ -579,7 +597,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
                result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                                USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                                (type << 8) + index, 0, buf, size,
-                               HZ * USB_CTRL_GET_TIMEOUT);
+                               USB_CTRL_GET_TIMEOUT);
                if (result == 0 || result == -EPIPE)
                        continue;
                if (result > 1 && ((u8 *)buf)[1] != type) {
@@ -613,8 +631,8 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
  * Returns the number of bytes received on success, or else the status code
  * returned by the underlying usb_control_msg() call.
  */
-int usb_get_string(struct usb_device *dev, unsigned short langid,
-               unsigned char index, void *buf, int size)
+static int usb_get_string(struct usb_device *dev, unsigned short langid,
+                         unsigned char index, void *buf, int size)
 {
        int i;
        int result;
@@ -624,7 +642,7 @@ int usb_get_string(struct usb_device *dev, unsigned short langid,
                result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
                        (USB_DT_STRING << 8) + index, langid, buf, size,
-                       HZ * USB_CTRL_GET_TIMEOUT);
+                       USB_CTRL_GET_TIMEOUT);
                if (!(result == 0 || result == -EPIPE))
                        break;
        }
@@ -763,6 +781,31 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
        return err;
 }
 
+/**
+ * usb_cache_string - read a string descriptor and cache it for later use
+ * @udev: the device whose string descriptor is being read
+ * @index: the descriptor index
+ *
+ * Returns a pointer to a kmalloc'ed buffer containing the descriptor string,
+ * or NULL if the index is 0 or the string could not be read.
+ */
+char *usb_cache_string(struct usb_device *udev, int index)
+{
+       char *buf;
+       char *smallbuf = NULL;
+       int len;
+
+       if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
+               if ((len = usb_string(udev, index, buf, 256)) > 0) {
+                       if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
+                               return buf;
+                       memcpy(smallbuf, buf, len);
+               }
+               kfree(buf);
+       }
+       return smallbuf;
+}
+
 /*
  * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
  * @dev: the device whose device descriptor is being updated
@@ -834,7 +877,7 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
 
        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
-               sizeof(*status), HZ * USB_CTRL_GET_TIMEOUT);
+               sizeof(*status), USB_CTRL_GET_TIMEOUT);
 
        *(u16 *)data = *status;
        kfree(status);
@@ -879,7 +922,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
                USB_ENDPOINT_HALT, endp, NULL, 0,
-               HZ * USB_CTRL_SET_TIMEOUT);
+               USB_CTRL_SET_TIMEOUT);
 
        /* don't un-halt or force to DATA0 except on success */
        if (result < 0)
@@ -977,8 +1020,10 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
                        struct usb_interface    *interface;
 
-                       /* remove this interface */
+                       /* remove this interface if it has been registered */
                        interface = dev->actconfig->interface[i];
+                       if (!device_is_registered(&interface->dev))
+                               continue;
                        dev_dbg (&dev->dev, "unregistering interface %s\n",
                                interface->dev.bus_id);
                        usb_remove_sysfs_intf_files(interface);
@@ -1033,8 +1078,8 @@ usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
  *
  * Enables all the endpoints for the interface's current altsetting.
  */
-void usb_enable_interface(struct usb_device *dev,
-               struct usb_interface *intf)
+static void usb_enable_interface(struct usb_device *dev,
+                                struct usb_interface *intf)
 {
        struct usb_host_interface *alt = intf->cur_altsetting;
        int i;
@@ -1101,7 +1146,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 
        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                   USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
-                                  alternate, interface, NULL, 0, HZ * 5);
+                                  alternate, interface, NULL, 0, 5000);
 
        /* 9.4.10 says devices don't need this and are free to STALL the
         * request if the interface only has one alternate setting.
@@ -1121,6 +1166,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         */
 
        /* prevent submissions using previous endpoint settings */
+       if (device_is_registered(&iface->dev))
+               usb_remove_sysfs_intf_files(iface);
        usb_disable_interface(dev, iface);
 
        iface->cur_altsetting = alt;
@@ -1156,6 +1203,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         * (Likewise, EP0 never "halts" on well designed devices.)
         */
        usb_enable_interface(dev, iface);
+       if (device_is_registered(&iface->dev))
+               usb_create_sysfs_intf_files(iface);
 
        return 0;
 }
@@ -1173,7 +1222,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
  *
  * Because this affects multiple interfaces, avoid using this with composite
  * (multi-interface) devices.  Instead, the driver for each interface may
- * use usb_set_interface() on the interfaces it claims.  Resetting the whole
+ * use usb_set_interface() on the interfaces it claims.  Be careful though;
+ * some devices don't support the SET_INTERFACE request, and others won't
+ * reset all the interface state (notably data toggles).  Resetting the whole
  * configuration would affect other drivers' interfaces.
  *
  * The caller must own the device lock.
@@ -1202,11 +1253,9 @@ int usb_reset_configuration(struct usb_device *dev)
        retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                        USB_REQ_SET_CONFIGURATION, 0,
                        config->desc.bConfigurationValue, 0,
-                       NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
-       if (retval < 0) {
-               usb_set_device_state(dev, USB_STATE_ADDRESS);
+                       NULL, 0, USB_CTRL_SET_TIMEOUT);
+       if (retval < 0)
                return retval;
-       }
 
        dev->toggle[0] = dev->toggle[1] = 0;
 
@@ -1215,6 +1264,8 @@ int usb_reset_configuration(struct usb_device *dev)
                struct usb_interface *intf = config->interface[i];
                struct usb_host_interface *alt;
 
+               if (device_is_registered(&intf->dev))
+                       usb_remove_sysfs_intf_files(intf);
                alt = usb_altnum_to_altsetting(intf, 0);
 
                /* No altsetting 0?  We'll assume the first altsetting.
@@ -1227,6 +1278,8 @@ int usb_reset_configuration(struct usb_device *dev)
 
                intf->cur_altsetting = alt;
                usb_enable_interface(dev, intf);
+               if (device_is_registered(&intf->dev))
+                       usb_create_sysfs_intf_files(intf);
        }
        return 0;
 }
@@ -1270,7 +1323,7 @@ static void release_interface(struct device *dev)
  * bus rwsem; usb device driver probe() methods cannot use this routine.
  *
  * Returns zero on success, or else the status code returned by the
- * underlying call that failed.  On succesful completion, each interface
+ * underlying call that failed.  On successful completion, each interface
  * in the original device configuration has been destroyed, and each one
  * in the new configuration has been probed by all relevant usb device
  * drivers currently known to the kernel.
@@ -1314,7 +1367,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
                }
 
                for (; n < nintf; ++n) {
-                       new_interfaces[n] = kmalloc(
+                       new_interfaces[n] = kzalloc(
                                        sizeof(struct usb_interface),
                                        GFP_KERNEL);
                        if (!new_interfaces[n]) {
@@ -1335,9 +1388,17 @@ free_interfaces:
        if (dev->state != USB_STATE_ADDRESS)
                usb_disable_device (dev, 1);    // Skip ep0
 
+       if (cp) {
+               i = dev->bus_mA - cp->desc.bMaxPower * 2;
+               if (i < 0)
+                       dev_warn(&dev->dev, "new config #%d exceeds power "
+                                       "limit by %dmA\n",
+                                       configuration, -i);
+       }
+
        if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                        USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-                       NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
+                       NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
                goto free_interfaces;
 
        dev->actconfig = cp;
@@ -1355,7 +1416,6 @@ free_interfaces:
                        struct usb_host_interface *alt;
 
                        cp->interface[i] = intf = new_interfaces[i];
-                       memset(intf, 0, sizeof(*intf));
                        intfc = cp->intf_cache[i];
                        intf->altsetting = intfc->altsetting;
                        intf->num_altsetting = intfc->num_altsetting;
@@ -1379,6 +1439,7 @@ free_interfaces:
                        intf->dev.dma_mask = dev->dev.dma_mask;
                        intf->dev.release = release_interface;
                        device_initialize (&intf->dev);
+                       mark_quiesced(intf);
                        sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
                                 dev->bus->busnum, dev->devpath,
                                 configuration,
@@ -1386,6 +1447,10 @@ free_interfaces:
                }
                kfree(new_interfaces);
 
+               if (cp->string == NULL)
+                       cp->string = usb_cache_string(dev,
+                                       cp->desc.iConfiguration);
+
                /* Now that all the interfaces are set up, register them
                 * to trigger binding of drivers to interfaces.  probe()
                 * routines may install different altsettings and may
@@ -1394,13 +1459,11 @@ free_interfaces:
                 */
                for (i = 0; i < nintf; ++i) {
                        struct usb_interface *intf = cp->interface[i];
-                       struct usb_interface_descriptor *desc;
 
-                       desc = &intf->altsetting [0].desc;
                        dev_dbg (&dev->dev,
                                "adding %s (config #%d, interface %d)\n",
                                intf->dev.bus_id, configuration,
-                               desc->bInterfaceNumber);
+                               intf->cur_altsetting->desc.bInterfaceNumber);
                        ret = device_add (&intf->dev);
                        if (ret != 0) {
                                dev_err(&dev->dev,
@@ -1413,7 +1476,7 @@ free_interfaces:
                }
        }
 
-       return ret;
+       return 0;
 }
 
 // synchronous request completion model
@@ -1427,7 +1490,6 @@ EXPORT_SYMBOL(usb_sg_wait);
 // synchronous control message convenience routines
 EXPORT_SYMBOL(usb_get_descriptor);
 EXPORT_SYMBOL(usb_get_status);
-EXPORT_SYMBOL(usb_get_string);
 EXPORT_SYMBOL(usb_string);
 
 // synchronous calls that also maintain usbcore state