diff options
| author | Tom Rini <trini@ti.com> | 2011-12-15 08:40:51 -0700 | 
|---|---|---|
| committer | Remy Bohmer <linux@bohmer.net> | 2011-12-16 21:37:17 +0100 | 
| commit | b2fb47f1873ae812ce33129996a22b11a36d0aa9 (patch) | |
| tree | 8afeef2bce3d0ca0aa44ed59956086f6dae2767c /common/usb.c | |
| parent | ddc7e541ae62f29d85b35cdf8d12c7322d353d51 (diff) | |
| download | olio-uboot-2014.01-b2fb47f1873ae812ce33129996a22b11a36d0aa9.tar.xz olio-uboot-2014.01-b2fb47f1873ae812ce33129996a22b11a36d0aa9.zip | |
USB: Use (get|put)_unaligned for accessing wMaxPacketSize
In 9792987721c7980453fe6447c3fa6593b44f8458 Stefan describes a usecase
where the previous behavior of leaving wMaxPacketSize be unaligned
caused fatal problems.  The initial fix for this problem was incomplete
however as it showed another cases of non-aligned access that previously
worked implicitly.  This switches to making sure that all access of
wMaxPacketSize are done via (get|put)_unaligned.
In order to maintain a level of readability to the code in some cases
we now use a variable for the value of wMaxPacketSize and in others, a
macro.
Cc: Minkyu Kang <mk7.kang@samsung.com>
Cc: Remy Bohmer <linux@bohmer.net>
OpenRISC:
Tested-by: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
Beagleboard xM, Pandaboard run-tested, s5p_goni build-tested.
Signed-off-by: Tom Rini <trini@ti.com>
Diffstat (limited to 'common/usb.c')
| -rw-r--r-- | common/usb.c | 27 | 
1 files changed, 19 insertions, 8 deletions
| diff --git a/common/usb.c b/common/usb.c index 4418c70f4..63a11c8f5 100644 --- a/common/usb.c +++ b/common/usb.c @@ -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 @@ -279,30 +280,32 @@ 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]);  			} @@ -333,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; @@ -378,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: |