[U-Boot] [PATCH] usb: dwc3: gadget: make cache-maintenance on event buffers more robust
Felipe Balbi
felipe.balbi at linux.intel.com
Wed Apr 5 08:18:21 UTC 2017
Hi,
Marek Vasut <marex at denx.de> writes:
>>>> Merely using dma_alloc_coherent does not ensure that there is no stale
>>>> data left in the caches for the allocated DMA buffer (i.e. that the
>>>> affected cacheline may still be dirty).
>>>>
>>>> The original code was doing the following (on AArch64, which
>>>> translates a 'flush' into a 'clean + invalidate'):
>>>> # during initialisation:
>>>> 1. allocate buffers via memalign
>>>> => buffers may still be modified (cached, dirty)
>>>> # during interrupt processing
>>>> 2. clean + invalidate buffers
>>>> => may commit stale data from a modified cacheline
>>>> 3. read from buffers
>>>>
>>>> This could lead to garbage info being written to buffers before
>>>> reading them during even-processing.
>>>>
>>>> To make the event processing more robust, we use the following sequence
>>>> for the cache-maintenance:
>>>> # during initialisation:
>>>> 1. allocate buffers via memalign
>>>> 2. clean + invalidate buffers
>>>> (we only need the 'invalidate' part, but dwc3_flush_cache()
>>>> always performs a 'clean + invalidate')
>>>> # during interrupt processing
>>>> 3. read the buffers
>>>> (we know these lines are not cached, due to the previous
>>>> invalidation and no other code touching them in-between)
>>>> 4. clean + invalidate buffers
>>>> => writes back any modification we may have made during event
>>>> processing and ensures that the lines are not in the cache
>>>> the next time we enter interrupt processing
>>>>
>>>> Note that with the original sequence, we observe reproducible
>>>> (depending on the cache state: i.e. running dhcp/usb start before will
>>>> upset caches to get us around this) issues in the event processing (a
>>>> fatal synchronous abort in dwc3_gadget_uboot_handle_interrupt on the
>>>> first time interrupt handling is invoked) when running USB mass
>>>> storage emulation on our RK3399-Q7 with data-caches on.
>>>>
>>>> Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
>>>>
>>>> ---
>>>>
>>>> drivers/usb/dwc3/core.c | 2 ++
>>>> drivers/usb/dwc3/gadget.c | 5 +++--
>>>> 2 files changed, 5 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>> index b2c7eb1..f58c7ba 100644
>>>> --- a/drivers/usb/dwc3/core.c
>>>> +++ b/drivers/usb/dwc3/core.c
>>>> @@ -125,6 +125,8 @@ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
>>>> if (!evt->buf)
>>>> return ERR_PTR(-ENOMEM);
>>>>
>>>> + dwc3_flush_cache((long)evt->buf, evt->length);
>>>> +
>>>
>>> Is the length aligned ? If not, you will get cache alignment warning.
>>> Also, address should be uintptr_t to avoid 32/64 bit issues .
>>
>> The length is a well-known value and aligned (it expands to PAGE_SIZE in the end).
>
> Uh, the event buffer is 4k ? That's quite big, but OK.
it really isn't when you're dealing with LPM. I've seen 4k cause
overflow events before.
>> Good point on the “long”, especially as I just copied this from other occurences and it’s consistently wrong throughout DWC3 in U-Boot:
>
> Hrm, I thought the driver was ported over from Linux, so is this broken
> in Linux too ?
haven't seen a problem in almost 6 years dealing with this IP.
--
balbi
More information about the U-Boot
mailing list