mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-08 19:11:53 +00:00
USB: Use (get|put)_unaligned for accessing wMaxPacketSize
In 9792987721
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>
This commit is contained in:
parent
ddc7e541ae
commit
b2fb47f187
6 changed files with 39 additions and 21 deletions
|
@ -28,6 +28,7 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
#include <asm/unaligned.h>
|
||||||
#include <part.h>
|
#include <part.h>
|
||||||
#include <usb.h>
|
#include <usb.h>
|
||||||
|
|
||||||
|
@ -240,7 +241,7 @@ void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
|
||||||
printf("Interrupt");
|
printf("Interrupt");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf(" MaxPacket %d", epdesc->wMaxPacketSize);
|
printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize));
|
||||||
if ((epdesc->bmAttributes & 0x03) == 0x3)
|
if ((epdesc->bmAttributes & 0x03) == 0x3)
|
||||||
printf(" Interval %dms", epdesc->bInterval);
|
printf(" Interval %dms", epdesc->bInterval);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
27
common/usb.c
27
common/usb.c
|
@ -49,6 +49,7 @@
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#include <usb.h>
|
#include <usb.h>
|
||||||
#ifdef CONFIG_4xx
|
#ifdef CONFIG_4xx
|
||||||
|
@ -279,30 +280,32 @@ usb_set_maxpacket_ep(struct usb_device *dev, int if_idx, int ep_idx)
|
||||||
{
|
{
|
||||||
int b;
|
int b;
|
||||||
struct usb_endpoint_descriptor *ep;
|
struct usb_endpoint_descriptor *ep;
|
||||||
|
u16 ep_wMaxPacketSize;
|
||||||
|
|
||||||
ep = &dev->config.if_desc[if_idx].ep_desc[ep_idx];
|
ep = &dev->config.if_desc[if_idx].ep_desc[ep_idx];
|
||||||
|
|
||||||
b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
|
b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
|
||||||
|
ep_wMaxPacketSize = get_unaligned(&ep->wMaxPacketSize);
|
||||||
|
|
||||||
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||||
USB_ENDPOINT_XFER_CONTROL) {
|
USB_ENDPOINT_XFER_CONTROL) {
|
||||||
/* Control => bidirectional */
|
/* Control => bidirectional */
|
||||||
dev->epmaxpacketout[b] = ep->wMaxPacketSize;
|
dev->epmaxpacketout[b] = ep_wMaxPacketSize;
|
||||||
dev->epmaxpacketin[b] = ep->wMaxPacketSize;
|
dev->epmaxpacketin[b] = ep_wMaxPacketSize;
|
||||||
USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",
|
USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",
|
||||||
b, dev->epmaxpacketin[b]);
|
b, dev->epmaxpacketin[b]);
|
||||||
} else {
|
} else {
|
||||||
if ((ep->bEndpointAddress & 0x80) == 0) {
|
if ((ep->bEndpointAddress & 0x80) == 0) {
|
||||||
/* OUT Endpoint */
|
/* OUT Endpoint */
|
||||||
if (ep->wMaxPacketSize > dev->epmaxpacketout[b]) {
|
if (ep_wMaxPacketSize > dev->epmaxpacketout[b]) {
|
||||||
dev->epmaxpacketout[b] = ep->wMaxPacketSize;
|
dev->epmaxpacketout[b] = ep_wMaxPacketSize;
|
||||||
USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",
|
USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",
|
||||||
b, dev->epmaxpacketout[b]);
|
b, dev->epmaxpacketout[b]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* IN Endpoint */
|
/* IN Endpoint */
|
||||||
if (ep->wMaxPacketSize > dev->epmaxpacketin[b]) {
|
if (ep_wMaxPacketSize > dev->epmaxpacketin[b]) {
|
||||||
dev->epmaxpacketin[b] = ep->wMaxPacketSize;
|
dev->epmaxpacketin[b] = ep_wMaxPacketSize;
|
||||||
USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",
|
USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",
|
||||||
b, dev->epmaxpacketin[b]);
|
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;
|
struct usb_descriptor_header *head;
|
||||||
int index, ifno, epno, curr_if_num;
|
int index, ifno, epno, curr_if_num;
|
||||||
int i;
|
int i;
|
||||||
|
u16 ep_wMaxPacketSize;
|
||||||
|
|
||||||
ifno = -1;
|
ifno = -1;
|
||||||
epno = -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++;
|
dev->config.if_desc[ifno].no_of_ep++;
|
||||||
memcpy(&dev->config.if_desc[ifno].ep_desc[epno],
|
memcpy(&dev->config.if_desc[ifno].ep_desc[epno],
|
||||||
&buffer[index], buffer[index]);
|
&buffer[index], buffer[index]);
|
||||||
le16_to_cpus(&(dev->config.if_desc[ifno].ep_desc[epno].\
|
ep_wMaxPacketSize = get_unaligned(&dev->config.\
|
||||||
wMaxPacketSize));
|
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);
|
USB_PRINTF("if %d, ep %d\n", ifno, epno);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <circbuf.h>
|
#include <circbuf.h>
|
||||||
#include <stdio_dev.h>
|
#include <stdio_dev.h>
|
||||||
|
#include <asm/unaligned.h>
|
||||||
#include "usbtty.h"
|
#include "usbtty.h"
|
||||||
#include "usb_cdc_acm.h"
|
#include "usb_cdc_acm.h"
|
||||||
#include "usbdescriptors.h"
|
#include "usbdescriptors.h"
|
||||||
|
@ -626,6 +627,9 @@ static void usbtty_init_strings (void)
|
||||||
usb_strings = usbtty_string_table;
|
usb_strings = usbtty_string_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define init_wMaxPacketSize(x) le16_to_cpu(get_unaligned(\
|
||||||
|
&ep_descriptor_ptrs[(x) - 1]->wMaxPacketSize));
|
||||||
|
|
||||||
static void usbtty_init_instances (void)
|
static void usbtty_init_instances (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -688,14 +692,12 @@ static void usbtty_init_instances (void)
|
||||||
endpoint_instance[i].rcv_attributes =
|
endpoint_instance[i].rcv_attributes =
|
||||||
ep_descriptor_ptrs[i - 1]->bmAttributes;
|
ep_descriptor_ptrs[i - 1]->bmAttributes;
|
||||||
|
|
||||||
endpoint_instance[i].rcv_packetSize =
|
endpoint_instance[i].rcv_packetSize = init_wMaxPacketSize(i);
|
||||||
le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
|
|
||||||
|
|
||||||
endpoint_instance[i].tx_attributes =
|
endpoint_instance[i].tx_attributes =
|
||||||
ep_descriptor_ptrs[i - 1]->bmAttributes;
|
ep_descriptor_ptrs[i - 1]->bmAttributes;
|
||||||
|
|
||||||
endpoint_instance[i].tx_packetSize =
|
endpoint_instance[i].tx_packetSize = init_wMaxPacketSize(i);
|
||||||
le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
|
|
||||||
|
|
||||||
endpoint_instance[i].tx_attributes =
|
endpoint_instance[i].tx_attributes =
|
||||||
ep_descriptor_ptrs[i - 1]->bmAttributes;
|
ep_descriptor_ptrs[i - 1]->bmAttributes;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <asm/errno.h>
|
#include <asm/errno.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
|
#include <asm/unaligned.h>
|
||||||
#include "gadget_chips.h"
|
#include "gadget_chips.h"
|
||||||
|
|
||||||
#define isdigit(c) ('0' <= (c) && (c) <= '9')
|
#define isdigit(c) ('0' <= (c) && (c) <= '9')
|
||||||
|
@ -127,7 +128,7 @@ static int ep_matches(
|
||||||
* where it's an output parameter representing the full speed limit.
|
* where it's an output parameter representing the full speed limit.
|
||||||
* the usb spec fixes high speed bulk maxpacket at 512 bytes.
|
* the usb spec fixes high speed bulk maxpacket at 512 bytes.
|
||||||
*/
|
*/
|
||||||
max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
|
max = 0x7ff & le16_to_cpu(get_unaligned(&desc->wMaxPacketSize));
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case USB_ENDPOINT_XFER_INT:
|
case USB_ENDPOINT_XFER_INT:
|
||||||
/* INT: limit 64 bytes full speed, 1024 high speed */
|
/* INT: limit 64 bytes full speed, 1024 high speed */
|
||||||
|
@ -143,7 +144,8 @@ static int ep_matches(
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* BOTH: "high bandwidth" works only at high speed */
|
/* BOTH: "high bandwidth" works only at high speed */
|
||||||
if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) {
|
if ((get_unaligned(&desc->wMaxPacketSize) &
|
||||||
|
__constant_cpu_to_le16(3<<11))) {
|
||||||
if (!gadget->is_dualspeed)
|
if (!gadget->is_dualspeed)
|
||||||
return 0;
|
return 0;
|
||||||
/* configure your hardware with enough buffering!! */
|
/* configure your hardware with enough buffering!! */
|
||||||
|
@ -176,7 +178,7 @@ static int ep_matches(
|
||||||
/* min() doesn't work on bitfields with gcc-3.5 */
|
/* min() doesn't work on bitfields with gcc-3.5 */
|
||||||
if (size > 64)
|
if (size > 64)
|
||||||
size = 64;
|
size = 64;
|
||||||
desc->wMaxPacketSize = cpu_to_le16(size);
|
put_unaligned(cpu_to_le16(size), &desc->wMaxPacketSize);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
|
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
#include <asm/unaligned.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
|
@ -586,7 +587,8 @@ static int s3c_ep_enable(struct usb_ep *_ep,
|
||||||
if (!_ep || !desc || ep->desc || _ep->name == ep0name
|
if (!_ep || !desc || ep->desc || _ep->name == ep0name
|
||||||
|| desc->bDescriptorType != USB_DT_ENDPOINT
|
|| desc->bDescriptorType != USB_DT_ENDPOINT
|
||||||
|| ep->bEndpointAddress != desc->bEndpointAddress
|
|| ep->bEndpointAddress != desc->bEndpointAddress
|
||||||
|| ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
|
|| ep_maxpacket(ep) <
|
||||||
|
le16_to_cpu(get_unaligned(&desc->wMaxPacketSize))) {
|
||||||
|
|
||||||
DEBUG("%s: bad ep or descriptor\n", __func__);
|
DEBUG("%s: bad ep or descriptor\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -603,8 +605,8 @@ static int s3c_ep_enable(struct usb_ep *_ep,
|
||||||
|
|
||||||
/* hardware _could_ do smaller, but driver doesn't */
|
/* hardware _could_ do smaller, but driver doesn't */
|
||||||
if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
|
if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
|
||||||
&& le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep))
|
&& le16_to_cpu(get_unaligned(&desc->wMaxPacketSize)) !=
|
||||||
|| !desc->wMaxPacketSize) {
|
ep_maxpacket(ep)) || !get_unaligned(&desc->wMaxPacketSize)) {
|
||||||
|
|
||||||
DEBUG("%s: bad %s maxpacket\n", __func__, _ep->name);
|
DEBUG("%s: bad %s maxpacket\n", __func__, _ep->name);
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
@ -620,7 +622,7 @@ static int s3c_ep_enable(struct usb_ep *_ep,
|
||||||
ep->stopped = 0;
|
ep->stopped = 0;
|
||||||
ep->desc = desc;
|
ep->desc = desc;
|
||||||
ep->pio_irqs = 0;
|
ep->pio_irqs = 0;
|
||||||
ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
|
ep->ep.maxpacket = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize));
|
||||||
|
|
||||||
/* Reset halt state */
|
/* Reset halt state */
|
||||||
s3c_udc_set_nak(ep);
|
s3c_udc_set_nak(ep);
|
||||||
|
|
|
@ -199,7 +199,7 @@ struct usb_endpoint_descriptor {
|
||||||
u8 bmAttributes;
|
u8 bmAttributes;
|
||||||
u16 wMaxPacketSize;
|
u16 wMaxPacketSize;
|
||||||
u8 bInterval;
|
u8 bInterval;
|
||||||
} __attribute__ ((packed)) __attribute__ ((aligned(2)));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct usb_interface_descriptor {
|
struct usb_interface_descriptor {
|
||||||
u8 bLength;
|
u8 bLength;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue