dwc3: flush the buffers before using it
authorKishon Vijay Abraham I <kishon@ti.com>
Mon, 23 Feb 2015 13:10:13 +0000 (18:40 +0530)
committerMarek Vasut <marex@denx.de>
Tue, 14 Apr 2015 03:48:10 +0000 (05:48 +0200)
In the linux kernel, non cacheable buffers are used. However in uboot
since there are no APIs to allocate non cacheable memory, all
the buffers should be flushed before using it.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
drivers/usb/dwc3/core.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/io.h

index 5a8d5ea8817115316cb8b4478315d06af5e95010..78fce1bf12a969e2d8546b70314c72b293524f81 100644 (file)
@@ -157,8 +157,8 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
        num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
        dwc->num_event_buffers = num;
 
-       dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
-                       GFP_KERNEL);
+       dwc->ev_buffs = memalign(CONFIG_SYS_CACHELINE_SIZE,
+                                sizeof(*dwc->ev_buffs) * num);
        if (!dwc->ev_buffs)
                return -ENOMEM;
 
@@ -769,11 +769,18 @@ void dwc3_uboot_exit(int index)
 void dwc3_uboot_handle_interrupt(int index)
 {
        struct dwc3 *dwc = NULL;
+       int i;
+       struct dwc3_event_buffer *evt;
 
        list_for_each_entry(dwc, &dwc3_list, list) {
                if (dwc->index != index)
                        continue;
 
+               for (i = 0; i < dwc->num_event_buffers; i++) {
+                       evt = dwc->ev_buffs[i];
+                       dwc3_flush_cache((int)evt->buf, evt->length);
+               }
+
                dwc3_gadget_uboot_handle_interrupt(dwc);
                break;
        }
index 803ba5198bf666fccc887b63418d6e4cb5fede67..977d6d4fd2e875dd7bb9040e0a4ead20c54a10c9 100644 (file)
@@ -74,6 +74,9 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
                        | DWC3_TRB_CTRL_IOC
                        | DWC3_TRB_CTRL_ISP_IMI);
 
+       dwc3_flush_cache((int)buf_dma, len);
+       dwc3_flush_cache((int)trb, sizeof(*trb));
+
        memset(&params, 0, sizeof(params));
        params.param0 = upper_32_bits(dwc->ep0_trb_addr);
        params.param1 = lower_32_bits(dwc->ep0_trb_addr);
@@ -774,6 +777,8 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
        if (!r)
                return;
 
+       dwc3_flush_cache((int)trb, sizeof(*trb));
+
        status = DWC3_TRB_SIZE_TRBSTS(trb->size);
        if (status == DWC3_TRBSTS_SETUP_PENDING) {
                dev_dbg(dwc->dev, "Setup Pending received");
@@ -795,6 +800,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
                transfer_size += (maxp - (transfer_size % maxp));
                transferred = min_t(u32, ur->length,
                                transfer_size - length);
+               dwc3_flush_cache((int)dwc->ep0_bounce, DWC3_EP0_BOUNCE_SIZE);
                memcpy(ur->buf, dwc->ep0_bounce, transferred);
        } else {
                transferred = ur->length - length;
index 1f977290ff0eee2438996a921faffc1fbbbab6ca..8560b88dd11655b56a0a1ee89d2a22e5c8a7a0c9 100644 (file)
@@ -244,6 +244,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 
        list_del(&req->list);
        req->trb = NULL;
+       dwc3_flush_cache((int)req->request.dma, req->request.length);
 
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
@@ -769,6 +770,9 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
                trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
 
        trb->ctrl |= DWC3_TRB_CTRL_HWO;
+
+       dwc3_flush_cache((int)dma, length);
+       dwc3_flush_cache((int)trb, sizeof(*trb));
 }
 
 /*
@@ -1770,6 +1774,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
                slot %= DWC3_TRB_NUM;
                trb = &dep->trb_pool[slot];
 
+               dwc3_flush_cache((int)trb, sizeof(*trb));
                ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
                                event, status);
                if (ret)
@@ -2583,7 +2588,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
                goto err1;
        }
 
-       dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL);
+       dwc->setup_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
+                                 DWC3_EP0_BOUNCE_SIZE);
        if (!dwc->setup_buf) {
                ret = -ENOMEM;
                goto err2;
index b6da1352fb8664b8fbccc71f8eed59b7afe3730c..5042a2419369416db4abe8b6dca2a7b66c0885f9 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <asm/io.h>
 
+#define        CACHELINE_SIZE          CONFIG_SYS_CACHELINE_SIZE
 static inline u32 dwc3_readl(void __iomem *base, u32 offset)
 {
        u32 offs = offset - DWC3_GLOBALS_REGS_START;
@@ -47,4 +48,8 @@ static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
        writel(value, base + offs);
 }
 
+static inline void dwc3_flush_cache(int addr, int length)
+{
+       flush_dcache_range(addr, addr + ROUND(length, CACHELINE_SIZE));
+}
 #endif /* __DRIVERS_USB_DWC3_IO_H */