]> git.sur5r.net Git - u-boot/blobdiff - common/usb.c
common/cmd_nvedit.c: Fix size calculation in do_env_import()
[u-boot] / common / usb.c
index bed51165053ad0e2cbf90639b551ed33c6be60ed..63a11c8f50f0b96759d132a8cb3478af4cdc27b8 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/processor.h>
 #include <linux/ctype.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 
 #include <usb.h>
 #ifdef CONFIG_4xx
@@ -263,40 +264,48 @@ int usb_maxpacket(struct usb_device *dev, unsigned long pipe)
                return dev->epmaxpacketin[((pipe>>15) & 0xf)];
 }
 
-/* The routine usb_set_maxpacket_ep() is extracted from the loop of routine
+/*
+ * The routine usb_set_maxpacket_ep() is extracted from the loop of routine
  * usb_set_maxpacket(), because the optimizer of GCC 4.x chokes on this routine
  * when it is inlined in 1 single routine. What happens is that the register r3
  * is used as loop-count 'i', but gets overwritten later on.
  * This is clearly a compiler bug, but it is easier to workaround it here than
  * to update the compiler (Occurs with at least several GCC 4.{1,2},x
  * CodeSourcery compilers like e.g. 2007q3, 2008q1, 2008q3 lite editions on ARM)
+ *
+ * NOTE: Similar behaviour was observed with GCC4.6 on ARMv5.
  */
 static void  __attribute__((noinline))
-usb_set_maxpacket_ep(struct usb_device *dev, struct usb_endpoint_descriptor *ep)
+usb_set_maxpacket_ep(struct usb_device *dev, int if_idx, int ep_idx)
 {
        int b;
+       struct usb_endpoint_descriptor *ep;
+       u16 ep_wMaxPacketSize;
+
+       ep = &dev->config.if_desc[if_idx].ep_desc[ep_idx];
 
        b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+       ep_wMaxPacketSize = get_unaligned(&ep->wMaxPacketSize);
 
        if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
                                                USB_ENDPOINT_XFER_CONTROL) {
                /* Control => bidirectional */
-               dev->epmaxpacketout[b] = ep->wMaxPacketSize;
-               dev->epmaxpacketin[b] = ep->wMaxPacketSize;
+               dev->epmaxpacketout[b] = ep_wMaxPacketSize;
+               dev->epmaxpacketin[b] = ep_wMaxPacketSize;
                USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",
                           b, dev->epmaxpacketin[b]);
        } else {
                if ((ep->bEndpointAddress & 0x80) == 0) {
                        /* OUT Endpoint */
-                       if (ep->wMaxPacketSize > dev->epmaxpacketout[b]) {
-                               dev->epmaxpacketout[b] = ep->wMaxPacketSize;
+                       if (ep_wMaxPacketSize > dev->epmaxpacketout[b]) {
+                               dev->epmaxpacketout[b] = ep_wMaxPacketSize;
                                USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",
                                           b, dev->epmaxpacketout[b]);
                        }
                } else {
                        /* IN Endpoint */
-                       if (ep->wMaxPacketSize > dev->epmaxpacketin[b]) {
-                               dev->epmaxpacketin[b] = ep->wMaxPacketSize;
+                       if (ep_wMaxPacketSize > dev->epmaxpacketin[b]) {
+                               dev->epmaxpacketin[b] = ep_wMaxPacketSize;
                                USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",
                                           b, dev->epmaxpacketin[b]);
                        }
@@ -313,8 +322,7 @@ int usb_set_maxpacket(struct usb_device *dev)
 
        for (i = 0; i < dev->config.desc.bNumInterfaces; i++)
                for (ii = 0; ii < dev->config.if_desc[i].desc.bNumEndpoints; ii++)
-                       usb_set_maxpacket_ep(dev,
-                                         &dev->config.if_desc[i].ep_desc[ii]);
+                       usb_set_maxpacket_ep(dev, i, ii);
 
        return 0;
 }
@@ -328,6 +336,7 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
        struct usb_descriptor_header *head;
        int index, ifno, epno, curr_if_num;
        int i;
+       u16 ep_wMaxPacketSize;
 
        ifno = -1;
        epno = -1;
@@ -373,8 +382,15 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
                        dev->config.if_desc[ifno].no_of_ep++;
                        memcpy(&dev->config.if_desc[ifno].ep_desc[epno],
                                &buffer[index], buffer[index]);
-                       le16_to_cpus(&(dev->config.if_desc[ifno].ep_desc[epno].\
-                                                              wMaxPacketSize));
+                       ep_wMaxPacketSize = get_unaligned(&dev->config.\
+                                                       if_desc[ifno].\
+                                                       ep_desc[epno].\
+                                                       wMaxPacketSize);
+                       put_unaligned(le16_to_cpu(ep_wMaxPacketSize),
+                                       &dev->config.\
+                                       if_desc[ifno].\
+                                       ep_desc[epno].\
+                                       wMaxPacketSize);
                        USB_PRINTF("if %d, ep %d\n", ifno, epno);
                        break;
                default: