WorkStruct: make allyesconfig
[safe/jmp/linux-2.6] / drivers / usb / core / message.c
index 88d1b37..89572bc 100644 (file)
@@ -2,14 +2,6 @@
  * message.c - synchronous message handling
  */
 
-#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>
 #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"
 
-static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
+static void usb_api_blocking_completion(struct urb *urb)
 {
        complete((struct completion *)urb->context);
 }
 
 
-static void timeout_kill(unsigned long data)
-{
-       struct urb      *urb = (struct urb *) data;
-
-       usb_unlink_urb(urb);
-}
-
-// Starts urb and waits for completion or timeout
-// note that this call is NOT interruptible, while
-// many device driver i/o requests should be interruptible
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+/*
+ * Starts urb and waits for completion or timeout. Note that this call
+ * is NOT interruptible. Many device driver i/o requests should be
+ * interruptible and therefore these drivers should implement their
+ * own interruptible routines.
+ */
+static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
 { 
-       struct completion       done;
-       struct timer_list       timer;
-       int                     status;
+       struct completion done;
+       unsigned long expire;
+       int status;
 
        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 + msecs_to_jiffies(timeout);
-                       timer.data = (unsigned long)urb;
-                       timer.function = timeout_kill;
-                       /* grr.  timeout _should_ include submit delays. */
-                       add_timer(&timer);
-               }
-               wait_for_completion(&done);
+       if (unlikely(status))
+               goto out;
+
+       expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
+       if (!wait_for_completion_timeout(&done, expire)) {
+
+               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",
+                       urb->actual_length,
+                       urb->transfer_buffer_length);
+
+               usb_kill_urb(urb);
+               status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
+       } else
                status = urb->status;
-               /* note:  HCDs return ETIMEDOUT for other reasons too */
-               if (status == -ECONNRESET) {
-                       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",
-                               urb->actual_length,
-                               urb->transfer_buffer_length
-                               );
-                       if (urb->actual_length > 0)
-                               status = 0;
-                       else
-                               status = -ETIMEDOUT;
-               }
-               if (timeout > 0)
-                       del_timer_sync(&timer);
-       }
-
+out:
        if (actual_length)
                *actual_length = urb->actual_length;
+
        usb_free_urb(urb);
        return status;
 }
@@ -165,6 +142,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
 
 
 /**
+ * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion
+ * @usb_dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @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 msecs to wait for the message to complete before
+ *     timing out (if 0 the wait is forever)
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple interrupt message to a specified endpoint and
+ * waits for the message to complete, or timeout.
+ *
+ * If successful, it returns 0, otherwise a negative error number.  The number
+ * of actual bytes transferred will be stored in the actual_length paramater.
+ *
+ * Don't use this function from within an interrupt context, like a bottom half
+ * handler.  If you need an asynchronous message, or need to send a message
+ * from within interrupt context, use usb_submit_urb() 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.
+ */
+int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
+                     void *data, int len, int *actual_length, int timeout)
+{
+       return usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout);
+}
+EXPORT_SYMBOL_GPL(usb_interrupt_msg);
+
+/**
  *     usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
  *     @usb_dev: pointer to the usb device to send the message to
  *     @pipe: endpoint "pipe" to send the message to
@@ -188,21 +196,37 @@ 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);
+       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);
 }
@@ -222,9 +246,9 @@ static void sg_clean (struct usb_sg_request *io)
        io->dev = NULL;
 }
 
-static void sg_complete (struct urb *urb, struct pt_regs *regs)
+static void sg_complete (struct urb *urb)
 {
-       struct usb_sg_request   *io = (struct usb_sg_request *) urb->context;
+       struct usb_sg_request   *io = urb->context;
 
        spin_lock (&io->lock);
 
@@ -266,7 +290,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);
@@ -320,7 +346,7 @@ int usb_sg_init (
        struct scatterlist      *sg,
        int                     nents,
        size_t                  length,
-       unsigned                mem_flags
+       gfp_t                   mem_flags
 )
 {
        int                     i;
@@ -357,8 +383,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;
 
@@ -621,8 +646,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;
@@ -771,6 +796,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
@@ -778,10 +828,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
  * Context: !in_interrupt ()
  *
  * Updates the copy of the device descriptor stored in the device structure,
- * which dedicates space for this purpose.  Note that several fields are
- * converted to the host CPU's byte order:  the USB version (bcdUSB), and
- * vendors product and version fields (idVendor, idProduct, and bcdDevice).
- * That lets device drivers compare against non-byteswapped constants.
+ * which dedicates space for this purpose.
  *
  * Not exported, only for use by the core.  If drivers really want to read
  * the device descriptor directly, they can call usb_get_descriptor() with
@@ -934,8 +981,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
                ep = dev->ep_in[epnum];
                dev->ep_in[epnum] = NULL;
        }
-       if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
-               dev->bus->op->disable(dev, ep);
+       if (ep && dev->bus)
+               usb_hcd_endpoint_disable(dev, ep);
 }
 
 /**
@@ -987,13 +1034,11 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 
                        /* remove this interface if it has been registered */
                        interface = dev->actconfig->interface[i];
-                       if (!klist_node_attached(&interface->dev.knode_bus))
+                       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);
-                       kfree(interface->cur_altsetting->string);
-                       interface->cur_altsetting->string = NULL;
                        device_del (&interface->dev);
                }
 
@@ -1133,6 +1178,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;
@@ -1168,6 +1215,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;
 }
@@ -1217,10 +1266,8 @@ int usb_reset_configuration(struct usb_device *dev)
                        USB_REQ_SET_CONFIGURATION, 0,
                        config->desc.bConfigurationValue, 0,
                        NULL, 0, USB_CTRL_SET_TIMEOUT);
-       if (retval < 0) {
-               usb_set_device_state(dev, USB_STATE_ADDRESS);
+       if (retval < 0)
                return retval;
-       }
 
        dev->toggle[0] = dev->toggle[1] = 0;
 
@@ -1229,6 +1276,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.
@@ -1241,6 +1290,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;
 }
@@ -1312,9 +1363,6 @@ 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;
@@ -1328,7 +1376,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]) {
@@ -1341,8 +1389,19 @@ free_interfaces:
                                return ret;
                        }
                }
+
+               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);
        }
 
+       /* Wake up the device so we can send it the Set-Config request */
+       ret = usb_autoresume_device(dev, 1);
+       if (ret)
+               goto free_interfaces;
+
        /* if it's already configured, clear out old state first.
         * getting rid of old interfaces means unbinding their drivers.
         */
@@ -1351,98 +1410,149 @@ free_interfaces:
 
        if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                        USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-                       NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
-               goto free_interfaces;
+                       NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
+
+               /* All the old state is gone, so what else can we do?
+                * The device is probably useless now anyway.
+                */
+               cp = NULL;
+       }
 
        dev->actconfig = cp;
-       if (!cp)
+       if (!cp) {
                usb_set_device_state(dev, USB_STATE_ADDRESS);
-       else {
-               usb_set_device_state(dev, USB_STATE_CONFIGURED);
+               usb_autosuspend_device(dev, 1);
+               goto free_interfaces;
+       }
+       usb_set_device_state(dev, USB_STATE_CONFIGURED);
 
-               /* Initialize the new interface structures and the
-                * hc/hcd/usbcore interface/endpoint state.
-                */
-               for (i = 0; i < nintf; ++i) {
-                       struct usb_interface_cache *intfc;
-                       struct usb_interface *intf;
-                       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;
-                       kref_get(&intfc->ref);
-
-                       alt = usb_altnum_to_altsetting(intf, 0);
-
-                       /* No altsetting 0?  We'll assume the first altsetting.
-                        * We could use a GetInterface call, but if a device is
-                        * so non-compliant that it doesn't have altsetting 0
-                        * then I wouldn't trust its reply anyway.
-                        */
-                       if (!alt)
-                               alt = &intf->altsetting[0];
-
-                       intf->cur_altsetting = alt;
-                       usb_enable_interface(dev, intf);
-                       intf->dev.parent = &dev->dev;
-                       intf->dev.driver = NULL;
-                       intf->dev.bus = &usb_bus_type;
-                       intf->dev.dma_mask = dev->dev.dma_mask;
-                       intf->dev.release = release_interface;
-                       device_initialize (&intf->dev);
-                       sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
-                                dev->bus->busnum, dev->devpath,
-                                configuration,
-                                alt->desc.bInterfaceNumber);
-               }
-               kfree(new_interfaces);
+       /* Initialize the new interface structures and the
+        * hc/hcd/usbcore interface/endpoint state.
+        */
+       for (i = 0; i < nintf; ++i) {
+               struct usb_interface_cache *intfc;
+               struct usb_interface *intf;
+               struct usb_host_interface *alt;
 
-               if ((cp->desc.iConfiguration) &&
-                   (cp->string == NULL)) {
-                       cp->string = kmalloc(256, GFP_KERNEL);
-                       if (cp->string)
-                               usb_string(dev, cp->desc.iConfiguration, cp->string, 256);
-               }
+               cp->interface[i] = intf = new_interfaces[i];
+               intfc = cp->intf_cache[i];
+               intf->altsetting = intfc->altsetting;
+               intf->num_altsetting = intfc->num_altsetting;
+               kref_get(&intfc->ref);
 
-               /* 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
-                * claim() any interfaces not yet bound.  Many class drivers
-                * need that: CDC, audio, video, etc.
+               alt = usb_altnum_to_altsetting(intf, 0);
+
+               /* No altsetting 0?  We'll assume the first altsetting.
+                * We could use a GetInterface call, but if a device is
+                * so non-compliant that it doesn't have altsetting 0
+                * then I wouldn't trust its reply anyway.
                 */
-               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);
-                       ret = device_add (&intf->dev);
-                       if (ret != 0) {
-                               dev_err(&dev->dev,
-                                       "device_add(%s) --> %d\n",
-                                       intf->dev.bus_id,
-                                       ret);
-                               continue;
-                       }
-                       if ((intf->cur_altsetting->desc.iInterface) &&
-                           (intf->cur_altsetting->string == NULL)) {
-                               intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL);
-                               if (intf->cur_altsetting->string)
-                                       usb_string(dev, intf->cur_altsetting->desc.iInterface,
-                                                  intf->cur_altsetting->string, 256);
-                       }
-                       usb_create_sysfs_intf_files (intf);
+               if (!alt)
+                       alt = &intf->altsetting[0];
+
+               intf->cur_altsetting = alt;
+               usb_enable_interface(dev, intf);
+               intf->dev.parent = &dev->dev;
+               intf->dev.driver = NULL;
+               intf->dev.bus = &usb_bus_type;
+               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, alt->desc.bInterfaceNumber);
+       }
+       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
+        * claim() any interfaces not yet bound.  Many class drivers
+        * need that: CDC, audio, video, etc.
+        */
+       for (i = 0; i < nintf; ++i) {
+               struct usb_interface *intf = cp->interface[i];
+
+               dev_dbg (&dev->dev,
+                       "adding %s (config #%d, interface %d)\n",
+                       intf->dev.bus_id, configuration,
+                       intf->cur_altsetting->desc.bInterfaceNumber);
+               ret = device_add (&intf->dev);
+               if (ret != 0) {
+                       dev_err(&dev->dev, "device_add(%s) --> %d\n",
+                               intf->dev.bus_id, ret);
+                       continue;
                }
+               usb_create_sysfs_intf_files (intf);
        }
 
+       usb_autosuspend_device(dev, 1);
+       return 0;
+}
+
+struct set_config_request {
+       struct usb_device       *udev;
+       int                     config;
+       struct work_struct      work;
+};
+
+/* Worker routine for usb_driver_set_configuration() */
+static void driver_set_config_work(struct work_struct *work)
+{
+       struct set_config_request *req =
+               container_of(work, struct set_config_request, work);
+
+       usb_lock_device(req->udev);
+       usb_set_configuration(req->udev, req->config);
+       usb_unlock_device(req->udev);
+       usb_put_dev(req->udev);
+       kfree(req);
+}
+
+/**
+ * usb_driver_set_configuration - Provide a way for drivers to change device configurations
+ * @udev: the device whose configuration is being updated
+ * @config: the configuration being chosen.
+ * Context: In process context, must be able to sleep
+ *
+ * Device interface drivers are not allowed to change device configurations.
+ * This is because changing configurations will destroy the interface the
+ * driver is bound to and create new ones; it would be like a floppy-disk
+ * driver telling the computer to replace the floppy-disk drive with a
+ * tape drive!
+ *
+ * Still, in certain specialized circumstances the need may arise.  This
+ * routine gets around the normal restrictions by using a work thread to
+ * submit the change-config request.
+ *
+ * Returns 0 if the request was succesfully queued, error code otherwise.
+ * The caller has no way to know whether the queued request will eventually
+ * succeed.
+ */
+int usb_driver_set_configuration(struct usb_device *udev, int config)
+{
+       struct set_config_request *req;
+
+       req = kmalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+       req->udev = udev;
+       req->config = config;
+       INIT_WORK(&req->work, driver_set_config_work);
+
+       usb_get_dev(udev);
+       if (!schedule_work(&req->work)) {
+               usb_put_dev(udev);
+               kfree(req);
+               return -EINVAL;
+       }
        return 0;
 }
+EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
 
 // synchronous request completion model
 EXPORT_SYMBOL(usb_control_msg);
@@ -1455,7 +1565,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