]> git.hungrycats.org Git - linux/commitdiff
[PATCH] USB: Fix DMA coherence when reading device descriptor
authorAlan Stern <stern@rowland.harvard.edu>
Mon, 26 Jan 2004 09:12:05 +0000 (01:12 -0800)
committerGreg Kroah-Hartman <greg@kroah.com>
Mon, 26 Jan 2004 09:12:05 +0000 (01:12 -0800)
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
include/linux/usb.h

index 99553a58bfaec2475b474005913a3142f53ba0ca..c28626d2e4d4e75eca3113eee7e08b3f7b543a65 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
+#include "usb.h"
 #include "hcd.h"
 #include "hub.h"
 
@@ -1316,8 +1317,8 @@ int usb_physical_reset_device(struct usb_device *dev)
                kfree(descriptor);
                usb_destroy_configuration(dev);
 
-               ret = usb_get_device_descriptor(dev);
-               if (ret < sizeof(dev->descriptor)) {
+               ret = usb_get_device_descriptor(dev, sizeof(dev->descriptor));
+               if (ret != sizeof(dev->descriptor)) {
                        if (ret < 0)
                                err("unable to get device %s descriptor "
                                        "(error=%d)", dev->devpath, ret);
index 04d08713e2bf430fd57ed0c10903e43c423fdf93..430c5b15f91d4a2ca221837d697fc76a66ba2e6e 100644 (file)
@@ -546,10 +546,10 @@ void usb_sg_cancel (struct usb_sg_request *io)
  *
  * Gets a USB descriptor.  Convenience functions exist to simplify
  * getting some types of descriptors.  Use
- * usb_get_device_descriptor() for USB_DT_DEVICE,
+ * usb_get_device_descriptor() for USB_DT_DEVICE (not exported),
  * and usb_get_string() or usb_string() for USB_DT_STRING.
- * Configuration descriptors (USB_DT_CONFIG) are part of the device
- * structure, at least for the current configuration.
+ * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG)
+ * are part of the device structure.
  * In addition to a number of USB-standard descriptors, some
  * devices also use class-specific or vendor-specific descriptors.
  *
@@ -610,6 +610,7 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char
 /**
  * usb_get_device_descriptor - (re)reads the device descriptor
  * @dev: the device whose device descriptor is being updated
+ * @size: how much of the descriptor to read
  * Context: !in_interrupt ()
  *
  * Updates the copy of the device descriptor stored in the device structure,
@@ -618,24 +619,35 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char
  * vendors product and version fields (idVendor, idProduct, and bcdDevice).
  * That lets device drivers compare against non-byteswapped constants.
  *
- * There's normally no need to use this call, although some devices
- * will change their descriptors after events like updating firmware.
+ * 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
+ * type = USB_DT_DEVICE and index = 0.
  *
  * This call is synchronous, and may not be used in an interrupt context.
  *
  * Returns the number of bytes received on success, or else the status code
  * returned by the underlying usb_control_msg() call.
  */
-int usb_get_device_descriptor(struct usb_device *dev)
+int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
 {
-       int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
-                                    sizeof(dev->descriptor));
+       struct usb_device_descriptor *desc;
+       int ret;
+
+       if (size > sizeof(*desc))
+               return -EINVAL;
+       desc = kmalloc(sizeof(*desc), GFP_NOIO);
+       if (!desc)
+               return -ENOMEM;
+
+       ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
        if (ret >= 0) {
-               le16_to_cpus(&dev->descriptor.bcdUSB);
-               le16_to_cpus(&dev->descriptor.idVendor);
-               le16_to_cpus(&dev->descriptor.idProduct);
-               le16_to_cpus(&dev->descriptor.bcdDevice);
+               le16_to_cpus(&desc->bcdUSB);
+               le16_to_cpus(&desc->idVendor);
+               le16_to_cpus(&desc->idProduct);
+               le16_to_cpus(&desc->bcdDevice);
+               memcpy(&dev->descriptor, desc, size);
        }
+       kfree(desc);
        return ret;
 }
 
@@ -1241,7 +1253,6 @@ EXPORT_SYMBOL(usb_sg_wait);
 
 // synchronous control message convenience routines
 EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_device_descriptor);
 EXPORT_SYMBOL(usb_get_status);
 EXPORT_SYMBOL(usb_get_string);
 EXPORT_SYMBOL(usb_string);
index 89d18fa37d0b2cf52b550881dcd74cc2a64b8cf4..e3b10d895a51cab9eb7825c2ef2787c57cf64c44 100644 (file)
@@ -1065,7 +1065,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
                wait_ms(10);    /* Let the SET_ADDRESS settle */
 
                /* high and low speed devices don't need this... */
-               err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
+               err = usb_get_device_descriptor(dev, 8);
                if (err >= 8)
                        break;
                wait_ms(100);
@@ -1085,8 +1085,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
 
        /* USB device state == addressed ... still not usable */
 
-       err = usb_get_device_descriptor(dev);
-       if (err < (signed)sizeof(dev->descriptor)) {
+       err = usb_get_device_descriptor(dev, sizeof(dev->descriptor));
+       if (err != (signed)sizeof(dev->descriptor)) {
                dev_err(&dev->dev, "device descriptor read/all, error %d\n", err);
                goto fail;
        }
index 5f03c160036ac85b9b8439002c4e85bbe9ab9012..ea0336fd58544ccf45b68aa1a8c79f405da9a2c8 100644 (file)
@@ -14,3 +14,6 @@ extern void usb_enable_endpoint (struct usb_device *dev,
                struct usb_endpoint_descriptor *epd);
 extern void usb_enable_interface (struct usb_device *dev,
                struct usb_interface *intf);
+
+extern int usb_get_device_descriptor(struct usb_device *dev,
+               unsigned int size);
index 5e49f861230d745f16216e7f64b9a8d064896883..c405f81be7658eddf0051fba0a35d2baf90864cd 100644 (file)
@@ -856,7 +856,6 @@ extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
 /* wrappers around usb_control_msg() for the most common standard requests */
 extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
        unsigned char descindex, void *buf, int size);
-extern int usb_get_device_descriptor(struct usb_device *dev);
 extern int usb_get_status(struct usb_device *dev,
        int type, int target, void *data);
 extern int usb_get_string(struct usb_device *dev,