[U-Boot] [PATH V2] usb: dwc2: invalidate the dcache before starting the DMA

Kever Yang kever.yang at rock-chips.com
Tue Apr 18 03:55:13 UTC 2017


Hi Marek,

On 04/06/2017 06:20 PM, Marek Vasut wrote:
> On 04/06/2017 10:34 AM, Kever Yang wrote:
>> Hi Eddie,
>>
>>
>> On 04/06/2017 10:14 AM, Marek Vasut wrote:
>>> On 04/06/2017 04:03 AM, Eddie Cai wrote:
>>>> We should invalidate the dcache before starting the DMA. In case
>>>> there are
>>>> any dirty lines from the DMA buffer in the cache, subsequent cache-line
>>>> replacements may corrupt the buffer in memory while the DMA is still
>>>> going on.
>>>> Cache-line replacement can happen if the CPU tries to bring some
>>>> other memory
>>>> locations into the cache while the DMA is going on.
>>>>
>>>> Signed-off-by: Eddie Cai <eddie.cai.linux at gmail.com>
>>>> Reviewed-by: Stefan BrĂ¼ns <stefan.bruens at rwth-aachen.de>
>>>> ---
>>>>    drivers/usb/host/dwc2.c | 19 +++++++++++++------
>>>>    1 file changed, 13 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
>>>> index 5ac602e..e3a5d7d 100644
>>>> --- a/drivers/usb/host/dwc2.c
>>>> +++ b/drivers/usb/host/dwc2.c
>>>> @@ -811,12 +811,19 @@ static int transfer_chunk(struct dwc2_hc_regs
>>>> *hc_regs, void *aligned_buffer,
>>>>               (*pid << DWC2_HCTSIZ_PID_OFFSET),
>>>>               &hc_regs->hctsiz);
>>>>    -    if (!in && xfer_len) {
>>>> -        memcpy(aligned_buffer, buffer, xfer_len);
>>>> -
>>>> -        flush_dcache_range((unsigned long)aligned_buffer,
>>>> -                   (unsigned long)aligned_buffer +
>>>> -                   roundup(xfer_len, ARCH_DMA_MINALIGN));
>>>> +    if (xfer_len) {
>>>> +        if (in) {
>>>> +            invalidate_dcache_range(
>>>> +                    (unsigned long)aligned_buffer,
>>>> +                    (unsigned long)aligned_buffer +
>>> Should be uintptr_t all over the place to deal with 32/64 bit systems,
>>> otherwise great, thanks.
>>>
>>>> +                    roundup(xfer_len, ARCH_DMA_MINALIGN));
>>>> +        } else {
>>>> +            memcpy(aligned_buffer, buffer, xfer_len);
>>>> +            flush_dcache_range(
>>>> +                    (unsigned long)aligned_buffer,
>>>> +                    (unsigned long)aligned_buffer +
>>>> +                    roundup(xfer_len, ARCH_DMA_MINALIGN));
>>>> +        }
>>>>        }
>>>>          writel(phys_to_bus((unsigned long)aligned_buffer),
>>>> &hc_regs->hcdma);
>>>>
>> Did you test with remove another invalidate_dcache_range() in this
>> function?
>> I still think no need to have 2 invalidate_dcache in this function.
> You need the first invalidate to prevent having data stuck in the cache
> and accidentally being evicted into the RAM while the USB DMA is also
> running , thus creating a total mess of the result.
>
>

Yes, I'm very clear about what happen here, because it's me report
the origin bug.
What I mean is the fix should be _move_ the invalidate_dcache_range() 
operation
from "after start DMA transfer" to "before DMA transter" for in 
transfer, but not
_add_ a invalidate_dcache_range() operation.

If you apply this patch, then there will be two 
invalidate_dcache_range() operation
for in transfer, and the second one is no need, because CPU should not 
have any
access to the buffer during dma start and done.

Thanks,
- Kever



More information about the U-Boot mailing list