[U-Boot] [PATCH] dwc: ep0: Allocate and flush dwc->ep0_trb in a cache aligned manner

Dr. Philipp Tomsich philipp.tomsich at theobroma-systems.com
Tue Oct 3 12:18:13 UTC 2017


Marek,

> On 3 Oct 2017, at 14:04, Marek Vasut <marex at denx.de> wrote:
> 
> On 09/19/2017 01:15 PM, Faiz Abbas wrote:
>> A flush of the cache is required before any DMA access can take place.
> 
> You mean invalidation for inbound DMA, flush for outbound DMA, right ?
> 
>> The minimum size that can be flushed from the cache is one cache line
>> size. Therefore, any buffer allocated for DMA should be in multiples
>> of cache line size.
>> 
>> Thus, allocate memory for ep0_trb in multiples of cache line size.
>> 
>> Also, when local variable trb is assigned to dwc->ep0_trb[1] and used
>> to flush cache, it leads to cache misaligned messages as only the base
>> address dwc->ep0_trb is cache aligned.
>> 
>> Therefore, flush cache using ep0_trb_addr which is always cache aligned.
>> 
>> Signed-off-by: Faiz Abbas <faiz_abbas at ti.com>
>> ---
>> drivers/usb/dwc3/ep0.c    | 7 ++++---
>> drivers/usb/dwc3/gadget.c | 3 ++-
>> 2 files changed, 6 insertions(+), 4 deletions(-)
>> 
>> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
>> index e61d980..f3a17a1 100644
>> --- a/drivers/usb/dwc3/ep0.c
>> +++ b/drivers/usb/dwc3/ep0.c
>> @@ -82,7 +82,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
>> 				| DWC3_TRB_CTRL_LST);
>> 
>> 	dwc3_flush_cache((uintptr_t)buf_dma, len);
>> -	dwc3_flush_cache((uintptr_t)trb, sizeof(*trb));
>> +	dwc3_flush_cache((uintptr_t)dwc->ep0_trb_addr, sizeof(*trb) * 2);
>> 
>> 	if (chain)
>> 		return 0;
>> @@ -790,7 +790,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
>> 	if (!r)
>> 		return;
>> 
>> -	dwc3_flush_cache((uintptr_t)trb, sizeof(*trb));
>> +	dwc3_flush_cache((uintptr_t)dwc->ep0_trb_addr, sizeof(*trb) * 2);
> 
> Why *2 ?
> 
>> 	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
>> 	if (status == DWC3_TRBSTS_SETUP_PENDING) {
>> @@ -821,7 +821,8 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
>> 			ur->actual += transferred;
>> 
>> 			trb++;
>> -			dwc3_flush_cache((uintptr_t)trb, sizeof(*trb));
>> +			dwc3_flush_cache((uintptr_t)dwc->ep0_trb_addr,
>> +					 sizeof(*trb) * 2);
>> 			length = trb->size & DWC3_TRB_SIZE_MASK;
>> 
>> 			ep0->free_slot = 0;
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index e065c5a..895a5bc 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -2567,7 +2567,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
>> 		goto err0;
>> 	}
>> 
>> -	dwc->ep0_trb = dma_alloc_coherent(sizeof(*dwc->ep0_trb) * 2,
>> +	dwc->ep0_trb = dma_alloc_coherent(ROUND(sizeof(*dwc->ep0_trb) * 2,
>> +						CACHELINE_SIZE),
> 
> AFAIU dma_alloc_coherent() should mark the memory area uncachable .

We had this discussion a while back, when I submitted the fixes to make
this driver work on the RK3399: dma_alloc_coherent only performs a
memalign on ARM and ARM64:

See the following snippet in arch/arm/include/asm/dma-mapping.h:

static inline void *dma_alloc_coherent(size_t len, unsigned long *handle)
{
        *handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);
        return (void *)*handle;
}


> 
>> 					  (unsigned long *)&dwc->ep0_trb_addr);
>> 	if (!dwc->ep0_trb) {
>> 		dev_err(dwc->dev, "failed to allocate ep0 trb\n");
>> 
> 
> 
> -- 
> Best regards,
> Marek Vasut



More information about the U-Boot mailing list