diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2018-07-12 15:05:02 +1000 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2018-07-17 10:12:51 +0300 |
commit | bb2863369562b3f0320fc7d8a96a5cde4b50aaea (patch) | |
tree | 63fda94e45b6e6c6fa9a74c7564de8a8303659c4 /drivers/usb/gadget/udc/aspeed-vhub/epn.c | |
parent | 9566a7c72f4f09b094c5517556d2b5f36a11b4ef (diff) | |
download | linux-stable-bb2863369562b3f0320fc7d8a96a5cde4b50aaea.tar.gz linux-stable-bb2863369562b3f0320fc7d8a96a5cde4b50aaea.tar.bz2 linux-stable-bb2863369562b3f0320fc7d8a96a5cde4b50aaea.zip |
usb: gadget: aspeed: Workaround memory ordering issue
The Aspeed SoC has a memory ordering issue that (thankfully)
only affects the USB gadget device. A read back is necessary
after writing to memory and before letting the device DMA
from it.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/gadget/udc/aspeed-vhub/epn.c')
-rw-r--r-- | drivers/usb/gadget/udc/aspeed-vhub/epn.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c index 80c9feac5147..5939eb1e97f2 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c @@ -66,11 +66,16 @@ static void ast_vhub_epn_kick(struct ast_vhub_ep *ep, struct ast_vhub_req *req) if (!req->req.dma) { /* For IN transfers, copy data over first */ - if (ep->epn.is_in) + if (ep->epn.is_in) { memcpy(ep->buf, req->req.buf + act, chunk); + vhub_dma_workaround(ep->buf); + } writel(ep->buf_dma, ep->epn.regs + AST_VHUB_EP_DESC_BASE); - } else + } else { + if (ep->epn.is_in) + vhub_dma_workaround(req->req.buf); writel(req->req.dma + act, ep->epn.regs + AST_VHUB_EP_DESC_BASE); + } /* Start DMA */ req->active = true; @@ -161,6 +166,7 @@ static inline unsigned int ast_vhub_count_free_descs(struct ast_vhub_ep *ep) static void ast_vhub_epn_kick_desc(struct ast_vhub_ep *ep, struct ast_vhub_req *req) { + struct ast_vhub_desc *desc = NULL; unsigned int act = req->act_count; unsigned int len = req->req.length; unsigned int chunk; @@ -177,7 +183,6 @@ static void ast_vhub_epn_kick_desc(struct ast_vhub_ep *ep, /* While we can create descriptors */ while (ast_vhub_count_free_descs(ep) && req->last_desc < 0) { - struct ast_vhub_desc *desc; unsigned int d_num; /* Grab next free descriptor */ @@ -227,6 +232,9 @@ static void ast_vhub_epn_kick_desc(struct ast_vhub_ep *ep, req->act_count = act = act + chunk; } + if (likely(desc)) + vhub_dma_workaround(desc); + /* Tell HW about new descriptors */ writel(VHUB_EP_DMA_SET_CPU_WPTR(ep->epn.d_next), ep->epn.regs + AST_VHUB_EP_DESC_STATUS); |