summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut <marek.vasut@gmail.com>2011-11-05 23:35:12 +0100
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2011-11-15 22:24:50 +0100
commit5e8baf878ea0976b9ec5f46d64cec5810ba9c195 (patch)
treef1dd7a3fcaf135f53eb6be55d9bd5afd35baa6bc
parent54cd51bf7910164e6640c7f428f2fd95e15019da (diff)
downloadu-boot-imx-5e8baf878ea0976b9ec5f46d64cec5810ba9c195.zip
u-boot-imx-5e8baf878ea0976b9ec5f46d64cec5810ba9c195.tar.gz
u-boot-imx-5e8baf878ea0976b9ec5f46d64cec5810ba9c195.tar.bz2
GCC4.6: Fix common/usb.c on xscale
The problem was that the code, when the function was compiled with -Os, was misgenerated. As in the function description, this is likely another manifestation of the bug in GCC. Signed-off-by: Marek Vasut <marek.vasut@gmail.com> Cc: Wolfgang Denk <wd@denx.de> Cc: Remy Bohmer <linux@bohmer.net>
-rw-r--r--common/usb.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/common/usb.c b/common/usb.c
index bed5116..4418c70 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -263,18 +263,24 @@ 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;
+
+ ep = &dev->config.if_desc[if_idx].ep_desc[ep_idx];
b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
@@ -313,8 +319,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;
}