[U-Boot] [PATCH] usb: align buffers at cache boundary

Puneet Saxena
2012-02-17T10:50:21Z

This aligns buffers,passed to usb controller at
dcache boundary.

Buffer "stop" address = "start" address + size.
Stop address can not be aligned even though
"start" address is aligned as size does not fall
at cache line boundary. Therefore "debug" in place of
"printf" is added in "arch/arm/cpu/armv7/cache_v7.c".
Cleaning and invalidating last cache line to avoid
stale data to be reused.

Ignoring "checkpatch.pl" warnings to replace "__attribute__((packed))"
by "__packed" and "__attribute__((aligned(size)))" by "__aligned(size)".
As "__GNUC__" directive should be defined to use "__packed" and
"__aligned(size)" and current patch is not supporting it, ignoring
the "checkpatch.pl" warning.

Signed-off-by: Puneet Saxena <puneets@nvidia.com>
Signed-off-by: Jim Lin <jilin@nvidia.com>
---
The patch is applicable on tegra U-Boot Custodian Tree owned by Tom Warren.
To apply the patch clone "git://git.denx.de/u-boot-tegra.git" and checkout
"test" branch.

arch/arm/cpu/armv7/cache_v7.c | 8 ++++-
common/cmd_usb.c | 3 +-
common/usb.c | 42 ++++++++++++++++------------
common/usb_storage.c | 60 ++++++++++++++++++++++++-----------------
drivers/usb/host/ehci-hcd.c | 12 ++++++++
include/scsi.h | 8 +++++-
include/usb.h | 8 +++++-
7 files changed, 93 insertions(+), 48 deletions(-)

diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c
index 1b4e808..435d08b 100644
--- a/arch/arm/cpu/armv7/cache_v7.c
+++ b/arch/arm/cpu/armv7/cache_v7.c
@@ -192,12 +192,16 @@ static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len)
}

/*
+ * We can't avoid stop address not aligned with cache-line.
+ * Allocating cache -aligned buffer might waste memory.
* If stop address is not aligned to cache-line do not
- * invalidate the last cache-line
+ * invalidate the last cache-line and flush the last
+ * line to prevent affecting somebody else's buffer.
*/
if (stop & (line_len - 1)) {
- printf("ERROR: %s - stop address is not aligned - 0x%08x\n",
+ debug("ERROR: %s - stop address is not aligned - 0x%08x\n",
__func__, stop);
+ v7_dcache_clean_inval_range(stop, stop + 1, line_len);
/* align to the beginning of this cache line */
stop &= ~(line_len - 1);
}
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 320667f..bca9d94 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -150,7 +150,8 @@ void usb_display_class_sub(unsigned char dclass, unsigned char subclass,

void usb_display_string(struct usb_device *dev, int index)
{
- char buffer[256];
+ ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256);
+
if (index != 0) {
if (usb_string(dev, index, &buffer[0], 256) > 0)
printf("String: \"%s\"", buffer);
diff --git a/common/usb.c b/common/usb.c
index 63a11c8..07f7ed6 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -73,7 +73,12 @@ static struct usb_device usb_dev[USB_MAX_DEVICE];
static int dev_index;
static int running;
static int asynch_allowed;
-static struct devrequest setup_packet;
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ static struct devrequest setup_packet
+ __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ static struct devrequest setup_packet;
+#endif

char usb_started; /* flag for the started/stopped USB status */

@@ -694,7 +699,7 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
*/
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
{
- unsigned char mybuf[USB_BUFSIZ];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, mybuf, USB_BUFSIZ);
unsigned char *tbuf;
int err;
unsigned int u, idx;
@@ -794,7 +799,7 @@ int usb_new_device(struct usb_device *dev)
{
int addr, err;
int tmp;
- unsigned char tmpbuf[USB_BUFSIZ];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);

/* We still haven't set the Address yet */
addr = dev->devnum;
@@ -921,8 +926,8 @@ int usb_new_device(struct usb_device *dev)
le16_to_cpus(&dev->descriptor.idProduct);
le16_to_cpus(&dev->descriptor.bcdDevice);
/* only support for one config for now */
- usb_get_configuration_no(dev, &tmpbuf[0], 0);
- usb_parse_config(dev, &tmpbuf[0], 0);
+ usb_get_configuration_no(dev, tmpbuf, 0);
+ usb_parse_config(dev, tmpbuf, 0);
usb_set_maxpacket(dev);
/* we set the default configuration here */
if (usb_set_configuration(dev, dev->config.desc.bConfigurationValue)) {
@@ -1076,7 +1081,7 @@ static int hub_port_reset(struct usb_device *dev, int port,
unsigned short *portstat)
{
int tries;
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus, portchange;

USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
@@ -1085,13 +1090,13 @@ static int hub_port_reset(struct usb_device *dev, int port,
usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
wait_ms(200);

- if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, port + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed status %lX\n",
dev->status);
return -1;
}
- portstatus = le16_to_cpu(portsts.wPortStatus);
- portchange = le16_to_cpu(portsts.wPortChange);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
+ portchange = le16_to_cpu(portsts->wPortChange);

USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
portstatus, portchange,
@@ -1129,19 +1134,19 @@ static int hub_port_reset(struct usb_device *dev, int port,
void usb_hub_port_connect_change(struct usb_device *dev, int port)
{
struct usb_device *usb;
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus;

/* Check status */
- if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, port + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed\n");
return;
}

- portstatus = le16_to_cpu(portsts.wPortStatus);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
portstatus,
- le16_to_cpu(portsts.wPortChange),
+ le16_to_cpu(portsts->wPortChange),
portspeed(portstatus));

/* Clear the connection change status */
@@ -1190,7 +1195,8 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
int usb_hub_configure(struct usb_device *dev)
{
int i;
- unsigned char buffer[USB_BUFSIZ], *bitmap;
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, USB_BUFSIZ);
+ unsigned char *bitmap;
struct usb_hub_descriptor *descriptor;
struct usb_hub_device *hub;
#ifdef USB_HUB_DEBUG
@@ -1312,16 +1318,16 @@ int usb_hub_configure(struct usb_device *dev)
usb_hub_power_on(hub);

for (i = 0; i < dev->maxchild; i++) {
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus, portchange;

- if (usb_get_port_status(dev, i + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, i + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed\n");
continue;
}

- portstatus = le16_to_cpu(portsts.wPortStatus);
- portchange = le16_to_cpu(portsts.wPortChange);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
+ portchange = le16_to_cpu(portsts->wPortChange);
USB_HUB_PRINTF("Port %d Status %X Change %X\n",
i + 1, portstatus, portchange);

diff --git a/common/usb_storage.c b/common/usb_storage.c
index de84c8d..71e13b1 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -79,8 +79,18 @@ static const unsigned char us_direction[256/8] = {
};
#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)

-static unsigned char usb_stor_buf[512];
-static ccb usb_ccb;
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ static unsigned char usb_stor_buf[512]
+ __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ static unsigned char usb_stor_buf[512];
+#endif
+
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ static ccb usb_ccb __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ static ccb usb_ccb;
+#endif

/*
* CBI style
@@ -210,17 +220,17 @@ int usb_stor_info(void)
static unsigned int usb_get_max_lun(struct us_data *us)
{
int len;
- unsigned char result;
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
len = usb_control_msg(us->pusb_dev,
usb_rcvctrlpipe(us->pusb_dev, 0),
US_BBB_GET_MAX_LUN,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
0, us->ifnum,
- &result, sizeof(result),
+ result, sizeof(char),
USB_CNTL_TIMEOUT * 5);
USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
- len, (int) result);
- return (len > 0) ? result : 0;
+ len, (int) *result);
+ return (len > 0) ? *result : 0;
}

/*******************************************************************************
@@ -499,7 +509,7 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
int actlen;
int dir_in;
unsigned int pipe;
- umass_bbb_cbw_t cbw;
+ ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);

dir_in = US_DIRECTION(srb->cmd[0]);

@@ -522,16 +532,16 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
/* always OUT to the ep */
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);

- cbw.dCBWSignature = cpu_to_le32(CBWSIGNATURE);
- cbw.dCBWTag = cpu_to_le32(CBWTag++);
- cbw.dCBWDataTransferLength = cpu_to_le32(srb->datalen);
- cbw.bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
- cbw.bCBWLUN = srb->lun;
- cbw.bCDBLength = srb->cmdlen;
+ cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
+ cbw->dCBWTag = cpu_to_le32(CBWTag++);
+ cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
+ cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
+ cbw->bCBWLUN = srb->lun;
+ cbw->bCDBLength = srb->cmdlen;
/* copy the command data into the CBW command data buffer */
/* DST SRC LEN!!! */
- memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
- result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
+ memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
+ result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
&actlen, USB_CNTL_TIMEOUT * 5);
if (result < 0)
USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
@@ -675,7 +685,7 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
int dir_in;
int actlen, data_actlen;
unsigned int pipe, pipein, pipeout;
- umass_bbb_csw_t csw;
+ ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
#ifdef BBB_XPORT_TRACE
unsigned char *ptr;
int index;
@@ -733,7 +743,7 @@ st:
retry = 0;
again:
USB_STOR_PRINTF("STATUS phase\n");
- result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
+ result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
&actlen, USB_CNTL_TIMEOUT*5);

/* special handling of STALL in STATUS phase */
@@ -753,28 +763,28 @@ again:
return USB_STOR_TRANSPORT_FAILED;
}
#ifdef BBB_XPORT_TRACE
- ptr = (unsigned char *)&csw;
+ ptr = (unsigned char *)csw;
for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
printf("ptr[%d] %#x ", index, ptr[index]);
printf("\n");
#endif
/* misuse pipe to get the residue */
- pipe = le32_to_cpu(csw.dCSWDataResidue);
+ pipe = le32_to_cpu(csw->dCSWDataResidue);
if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
pipe = srb->datalen - data_actlen;
- if (CSWSIGNATURE != le32_to_cpu(csw.dCSWSignature)) {
+ if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
USB_STOR_PRINTF("!CSWSIGNATURE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if ((CBWTag - 1) != le32_to_cpu(csw.dCSWTag)) {
+ } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
USB_STOR_PRINTF("!Tag\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
+ } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
USB_STOR_PRINTF(">PHASE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
+ } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
USB_STOR_PRINTF("=PHASE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
@@ -782,7 +792,7 @@ again:
USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
data_actlen, srb->datalen);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
+ } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
USB_STOR_PRINTF("FAILED\n");
return USB_STOR_TRANSPORT_FAILED;
}
@@ -1343,7 +1353,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
block_dev_desc_t *dev_desc)
{
unsigned char perq, modi;
- unsigned long cap[2];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
unsigned long *capacity, *blksz;
ccb *pccb = &usb_ccb;

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d893b2a..7929c26 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -132,8 +132,20 @@ static void cache_qtd(struct qTD *qtd, int flush)
int len = (qtd->qt_token & 0x7fff0000) >> 16;

flush_invalidate((u32)qtd, sizeof(struct qTD), flush);
+
+ /*
+ * Invalidate cache for the aligned address
+ * and for the data length which is DMAed.
+ * Do not invalidate again intermidiate address
+ * as it may not be aligned.
+ */
+#if CONFIG_SYS_CACHELINE_SIZE
+ if (!((u32) ptr & (CONFIG_SYS_CACHELINE_SIZE - 1)) && len)
+ flush_invalidate((u32)ptr, len, flush);
+#else
if (ptr && len)
flush_invalidate((u32)ptr, len, flush);
+#endif
}

diff --git a/include/scsi.h b/include/scsi.h
index c52759c..c07b1dd 100644
--- a/include/scsi.h
+++ b/include/scsi.h
@@ -26,7 +26,13 @@

typedef struct SCSI_cmd_block{
unsigned char cmd[16]; /* command */
- unsigned char sense_buf[64]; /* for request sense */
+ /* for request sense */
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ unsigned char sense_buf[64]
+ __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ unsigned char sense_buf[64];
+#endif
unsigned char status; /* SCSI Status */
unsigned char target; /* Target ID */
unsigned char lun; /* Target LUN */
diff --git a/include/usb.h b/include/usb.h
index 06170cd..55b786e 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -109,7 +109,13 @@ struct usb_device {
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */

int configno; /* selected config number */
- struct usb_device_descriptor descriptor; /* Device Descriptor */
+ /* Device Descriptor */
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ struct usb_device_descriptor descriptor
+ __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ struct usb_device_descriptor descriptor;
+#endif
struct usb_config config; /* config descriptor */

int have_langid; /* whether string_langid is valid yet */
--
1.7.1