* [PATCH v4 1/3] usb: dwc3: allocate setup_buf with dma_alloc_coherent()
2024-10-11 14:38 [PATCH v4 0/3] dwc3: gadget: properly fix cache operations Neil Armstrong
@ 2024-10-11 14:38 ` Neil Armstrong
2024-10-11 14:38 ` [PATCH v4 2/3] usb: dwc3: fix dcache flush range calculation Neil Armstrong
` (3 subsequent siblings)
4 siblings, 0 replies; 15+ messages in thread
From: Neil Armstrong @ 2024-10-11 14:38 UTC (permalink / raw)
To: Marek Vasut, Tom Rini, Lukasz Majewski, Mattijs Korpershoek,
Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot, Neil Armstrong
Since setup_buf is also consumed by hardware DMA, aligns it's
allocation like other hardware buffers by introduce setup_buf_addr
populated by dma_alloc_coherent(), and use it to pass the physical
address of the buffer to the hardware.
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
Reviewed-by: Marek Vasut <marex@denx.de>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
drivers/usb/dwc3/core.h | 2 ++
drivers/usb/dwc3/ep0.c | 4 ++--
drivers/usb/dwc3/gadget.c | 8 ++++----
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 7374ce950da..b572ea340c8 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -670,6 +670,7 @@ struct dwc3_scratchpad_array {
* @ep0_trb: dma address of ep0_trb
* @ep0_usb_req: dummy req used while handling STD USB requests
* @ep0_bounce_addr: dma address of ep0_bounce
+ * @setup_buf_addr: dma address of setup_buf
* @scratch_addr: dma address of scratchbuf
* @lock: for synchronizing
* @dev: pointer to our struct device
@@ -757,6 +758,7 @@ struct dwc3 {
dma_addr_t ep0_trb_addr;
dma_addr_t ep0_bounce_addr;
dma_addr_t scratch_addr;
+ dma_addr_t setup_buf_addr;
struct dwc3_request ep0_usb_req;
/* device lock */
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 24f516a131b..8ba5fcd5312 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -380,7 +380,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
- dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+ dwc->ep0_usb_req.request.buf = (void *)dwc->setup_buf_addr;
dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
@@ -662,7 +662,7 @@ static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
- dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+ dwc->ep0_usb_req.request.buf = (void *)dwc->setup_buf_addr;
dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index fe33e307d3e..19c3a5f5e58 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2653,8 +2653,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err1;
}
- dwc->setup_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
- DWC3_EP0_BOUNCE_SIZE);
+ dwc->setup_buf = dma_alloc_coherent(DWC3_EP0_BOUNCE_SIZE,
+ (unsigned long *)&dwc->setup_buf_addr);
if (!dwc->setup_buf) {
ret = -ENOMEM;
goto err2;
@@ -2701,7 +2701,7 @@ err4:
dma_free_coherent(dwc->ep0_bounce);
err3:
- kfree(dwc->setup_buf);
+ dma_free_coherent(dwc->setup_buf);
err2:
dma_free_coherent(dwc->ep0_trb);
@@ -2723,7 +2723,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dma_free_coherent(dwc->ep0_bounce);
- kfree(dwc->setup_buf);
+ dma_free_coherent(dwc->setup_buf);
dma_free_coherent(dwc->ep0_trb);
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v4 2/3] usb: dwc3: fix dcache flush range calculation
2024-10-11 14:38 [PATCH v4 0/3] dwc3: gadget: properly fix cache operations Neil Armstrong
2024-10-11 14:38 ` [PATCH v4 1/3] usb: dwc3: allocate setup_buf with dma_alloc_coherent() Neil Armstrong
@ 2024-10-11 14:38 ` Neil Armstrong
2024-10-12 3:37 ` Marek Vasut
2024-10-11 14:38 ` [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling Neil Armstrong
` (2 subsequent siblings)
4 siblings, 1 reply; 15+ messages in thread
From: Neil Armstrong @ 2024-10-11 14:38 UTC (permalink / raw)
To: Marek Vasut, Tom Rini, Lukasz Majewski, Mattijs Korpershoek,
Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot, Neil Armstrong
The current flush operation will omit doing a flush/invalidate on
the first and last bytes if the base address and size are not aligned
with CACHELINE_SIZE.
This causes operation failures Qualcomm platforms.
Take in account the alignment and size of the buffer and also
flush the previous and last cacheline.
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
drivers/usb/dwc3/io.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 04791d4c9be..0ede323671b 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -50,6 +50,9 @@ static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
static inline void dwc3_flush_cache(uintptr_t addr, int length)
{
- flush_dcache_range(addr, addr + ROUND(length, CACHELINE_SIZE));
+ uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
+ uintptr_t end_addr = ALIGN((uintptr_t)addr + length, CACHELINE_SIZE);
+
+ flush_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
}
#endif /* __DRIVERS_USB_DWC3_IO_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH v4 2/3] usb: dwc3: fix dcache flush range calculation
2024-10-11 14:38 ` [PATCH v4 2/3] usb: dwc3: fix dcache flush range calculation Neil Armstrong
@ 2024-10-12 3:37 ` Marek Vasut
2024-10-13 16:35 ` Neil Armstrong
0 siblings, 1 reply; 15+ messages in thread
From: Marek Vasut @ 2024-10-12 3:37 UTC (permalink / raw)
To: Neil Armstrong, Tom Rini, Lukasz Majewski, Mattijs Korpershoek,
Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot
On 10/11/24 4:38 PM, Neil Armstrong wrote:
> The current flush operation will omit doing a flush/invalidate on
> the first and last bytes if the base address and size are not aligned
> with CACHELINE_SIZE.
>
> This causes operation failures Qualcomm platforms.
>
> Take in account the alignment and size of the buffer and also
> flush the previous and last cacheline.
>
> Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> drivers/usb/dwc3/io.h | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
> index 04791d4c9be..0ede323671b 100644
> --- a/drivers/usb/dwc3/io.h
> +++ b/drivers/usb/dwc3/io.h
> @@ -50,6 +50,9 @@ static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
>
> static inline void dwc3_flush_cache(uintptr_t addr, int length)
> {
> - flush_dcache_range(addr, addr + ROUND(length, CACHELINE_SIZE));
> + uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
> + uintptr_t end_addr = ALIGN((uintptr_t)addr + length, CACHELINE_SIZE);
> +
> + flush_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
> }
> #endif /* __DRIVERS_USB_DWC3_IO_H */
You likely want a max(CONFIG_SYS_CACHELINE_SIZE,
dwc3-buffer-alignment-requirement) to really correctly align the buffer.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH v4 2/3] usb: dwc3: fix dcache flush range calculation
2024-10-12 3:37 ` Marek Vasut
@ 2024-10-13 16:35 ` Neil Armstrong
2024-10-13 20:37 ` Marek Vasut
0 siblings, 1 reply; 15+ messages in thread
From: Neil Armstrong @ 2024-10-13 16:35 UTC (permalink / raw)
To: Marek Vasut, Tom Rini, Lukasz Majewski, Mattijs Korpershoek,
Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot
Hi,
Le 12/10/2024 à 05:37, Marek Vasut a écrit :
> On 10/11/24 4:38 PM, Neil Armstrong wrote:
>> The current flush operation will omit doing a flush/invalidate on
>> the first and last bytes if the base address and size are not aligned
>> with CACHELINE_SIZE.
>>
>> This causes operation failures Qualcomm platforms.
>>
>> Take in account the alignment and size of the buffer and also
>> flush the previous and last cacheline.
>>
>> Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
>> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
>> ---
>> drivers/usb/dwc3/io.h | 5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
>> index 04791d4c9be..0ede323671b 100644
>> --- a/drivers/usb/dwc3/io.h
>> +++ b/drivers/usb/dwc3/io.h
>> @@ -50,6 +50,9 @@ static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
>> static inline void dwc3_flush_cache(uintptr_t addr, int length)
>> {
>> - flush_dcache_range(addr, addr + ROUND(length, CACHELINE_SIZE));
>> + uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
>> + uintptr_t end_addr = ALIGN((uintptr_t)addr + length, CACHELINE_SIZE);
>> +
>> + flush_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
>> }
>> #endif /* __DRIVERS_USB_DWC3_IO_H */
>
> You likely want a max(CONFIG_SYS_CACHELINE_SIZE, dwc3-buffer-alignment-requirement) to really correctly align the buffer.
No this change is related to the system cacheline to properly flush/invalidate the data
to the system memory, the dwc3 buffer alignment (if there's one) should be handled
when allocating the memory, but here we're using dma_alloc_coherent() which
use DMA_MINALIGN.
So it's another unrelated story.
Neil
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH v4 2/3] usb: dwc3: fix dcache flush range calculation
2024-10-13 16:35 ` Neil Armstrong
@ 2024-10-13 20:37 ` Marek Vasut
0 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2024-10-13 20:37 UTC (permalink / raw)
To: Neil Armstrong, Tom Rini, Lukasz Majewski, Mattijs Korpershoek,
Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot
On 10/13/24 6:35 PM, Neil Armstrong wrote:
> Hi,
>
> Le 12/10/2024 à 05:37, Marek Vasut a écrit :
>> On 10/11/24 4:38 PM, Neil Armstrong wrote:
>>> The current flush operation will omit doing a flush/invalidate on
>>> the first and last bytes if the base address and size are not aligned
>>> with CACHELINE_SIZE.
>>>
>>> This causes operation failures Qualcomm platforms.
>>>
>>> Take in account the alignment and size of the buffer and also
>>> flush the previous and last cacheline.
>>>
>>> Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
>>> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
>>> ---
>>> drivers/usb/dwc3/io.h | 5 ++++-
>>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
>>> index 04791d4c9be..0ede323671b 100644
>>> --- a/drivers/usb/dwc3/io.h
>>> +++ b/drivers/usb/dwc3/io.h
>>> @@ -50,6 +50,9 @@ static inline void dwc3_writel(void __iomem *base,
>>> u32 offset, u32 value)
>>> static inline void dwc3_flush_cache(uintptr_t addr, int length)
>>> {
>>> - flush_dcache_range(addr, addr + ROUND(length, CACHELINE_SIZE));
>>> + uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
>>> + uintptr_t end_addr = ALIGN((uintptr_t)addr + length,
>>> CACHELINE_SIZE);
>>> +
>>> + flush_dcache_range((unsigned long)start_addr, (unsigned
>>> long)end_addr);
>>> }
>>> #endif /* __DRIVERS_USB_DWC3_IO_H */
>>
>> You likely want a max(CONFIG_SYS_CACHELINE_SIZE, dwc3-buffer-
>> alignment-requirement) to really correctly align the buffer.
>
> No this change is related to the system cacheline to properly flush/
> invalidate the data
> to the system memory, the dwc3 buffer alignment (if there's one) should
> be handled
> when allocating the memory, but here we're using dma_alloc_coherent() which
> use DMA_MINALIGN.
OK
Reviewed-by: Marek Vasut <marex@denx.de>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling
2024-10-11 14:38 [PATCH v4 0/3] dwc3: gadget: properly fix cache operations Neil Armstrong
2024-10-11 14:38 ` [PATCH v4 1/3] usb: dwc3: allocate setup_buf with dma_alloc_coherent() Neil Armstrong
2024-10-11 14:38 ` [PATCH v4 2/3] usb: dwc3: fix dcache flush range calculation Neil Armstrong
@ 2024-10-11 14:38 ` Neil Armstrong
2024-10-13 20:38 ` Marek Vasut
2024-12-28 13:46 ` Ahmad Fatoum
2024-10-15 9:06 ` [PATCH v4 0/3] dwc3: gadget: properly fix cache operations Mattijs Korpershoek
2024-10-21 23:31 ` Tom Rini
4 siblings, 2 replies; 15+ messages in thread
From: Neil Armstrong @ 2024-10-11 14:38 UTC (permalink / raw)
To: Marek Vasut, Tom Rini, Lukasz Majewski, Mattijs Korpershoek,
Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot, Neil Armstrong
On Qualcomm systems, the setup buffer and even buffers are in
a bad state at interrupt handling, so invalidate the dcache lines
for the setup_buf and event buffer to make sure we read correct
data written by the hardware.
This fixes the following error:
dwc3-generic-peripheral usb@a600000: UNKNOWN IRQ type -1
dwc3-generic-peripheral usb@a600000: UNKNOWN IRQ type 4673109
and invalid situation in dwc3_gadget_giveback() because setup_buf content
is read at 0s and leads to fatal crash fixed by [1].
[1] https://lore.kernel.org/all/20240528-topic-sm8x50-dwc3-gadget-crash-fix-v1-1-58434ab4b3d3@linaro.org/
Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
drivers/usb/dwc3/ep0.c | 2 ++
drivers/usb/dwc3/gadget.c | 2 ++
drivers/usb/dwc3/io.h | 8 ++++++++
3 files changed, 12 insertions(+)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 8ba5fcd5312..531f0b522af 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -742,6 +742,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
if (!dwc->gadget_driver)
goto out;
+ dwc3_invalidate_cache((uintptr_t)ctrl, sizeof(*ctrl));
+
len = le16_to_cpu(ctrl->wLength);
if (!len) {
dwc->three_stage_setup = false;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 19c3a5f5e58..e5a383407a2 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2534,6 +2534,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
while (left > 0) {
union dwc3_event event;
+ dwc3_invalidate_cache((uintptr_t)evt->buf, evt->length);
+
event.raw = *(u32 *) (evt->buf + evt->lpos);
dwc3_process_event_entry(dwc, &event);
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 0ede323671b..c1ab0288142 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -55,4 +55,12 @@ static inline void dwc3_flush_cache(uintptr_t addr, int length)
flush_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
}
+
+static inline void dwc3_invalidate_cache(uintptr_t addr, int length)
+{
+ uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
+ uintptr_t end_addr = ALIGN((uintptr_t)addr + length, CACHELINE_SIZE);
+
+ invalidate_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
+}
#endif /* __DRIVERS_USB_DWC3_IO_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling
2024-10-11 14:38 ` [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling Neil Armstrong
@ 2024-10-13 20:38 ` Marek Vasut
2024-12-28 13:46 ` Ahmad Fatoum
1 sibling, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2024-10-13 20:38 UTC (permalink / raw)
To: Neil Armstrong, Tom Rini, Lukasz Majewski, Mattijs Korpershoek,
Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot
On 10/11/24 4:38 PM, Neil Armstrong wrote:
> On Qualcomm systems, the setup buffer and even buffers are in
> a bad state at interrupt handling, so invalidate the dcache lines
> for the setup_buf and event buffer to make sure we read correct
> data written by the hardware.
>
> This fixes the following error:
> dwc3-generic-peripheral usb@a600000: UNKNOWN IRQ type -1
> dwc3-generic-peripheral usb@a600000: UNKNOWN IRQ type 4673109
>
> and invalid situation in dwc3_gadget_giveback() because setup_buf content
> is read at 0s and leads to fatal crash fixed by [1].
>
> [1] https://lore.kernel.org/all/20240528-topic-sm8x50-dwc3-gadget-crash-fix-v1-1-58434ab4b3d3@linaro.org/
>
> Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Marek Vasut <marex@denx.de>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling
2024-10-11 14:38 ` [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling Neil Armstrong
2024-10-13 20:38 ` Marek Vasut
@ 2024-12-28 13:46 ` Ahmad Fatoum
2024-12-30 10:35 ` Neil Armstrong
1 sibling, 1 reply; 15+ messages in thread
From: Ahmad Fatoum @ 2024-12-28 13:46 UTC (permalink / raw)
To: Neil Armstrong, Marek Vasut, Tom Rini, Lukasz Majewski,
Mattijs Korpershoek, Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot
Hi,
On 11.10.24 16:38, Neil Armstrong wrote:
> On Qualcomm systems, the setup buffer and even buffers are in
> a bad state at interrupt handling, so invalidate the dcache lines
> for the setup_buf and event buffer to make sure we read correct
> data written by the hardware.
>
> This fixes the following error:
> dwc3-generic-peripheral usb@a600000: UNKNOWN IRQ type -1
> dwc3-generic-peripheral usb@a600000: UNKNOWN IRQ type 4673109
>
> and invalid situation in dwc3_gadget_giveback() because setup_buf content
> is read at 0s and leads to fatal crash fixed by [1].
>
> [1] https://lore.kernel.org/all/20240528-topic-sm8x50-dwc3-gadget-crash-fix-v1-1-58434ab4b3d3@linaro.org/
>
> Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> drivers/usb/dwc3/ep0.c | 2 ++
> drivers/usb/dwc3/gadget.c | 2 ++
> drivers/usb/dwc3/io.h | 8 ++++++++
> 3 files changed, 12 insertions(+)
>
> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
> index 8ba5fcd5312..531f0b522af 100644
> --- a/drivers/usb/dwc3/ep0.c
> +++ b/drivers/usb/dwc3/ep0.c
> @@ -742,6 +742,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
> if (!dwc->gadget_driver)
> goto out;
>
> + dwc3_invalidate_cache((uintptr_t)ctrl, sizeof(*ctrl));
I believe this to be incorrect. ctrl here is dwc->ctrl_req, which AFAICS
is allocated in dwc3_gadget_init() using dma_alloc_coherent.
Doing cache maintenance on DMA-coherent memory doesn't make sense.
If this makes things better for you, it's probable that something else
is broken.
Additionally, this will break platforms that have DMA-coherent DWC3
and allocate normal memory instead of uncached memory. I am not sure
if there are such U-Boot platforms yet, as searching for dma-coherent DT
property yields no relevant results, but e.g. LS1046A in barebox would've
been broken by such a change.
Cheers,
Ahmad
> +
> len = le16_to_cpu(ctrl->wLength);
> if (!len) {
> dwc->three_stage_setup = false;
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 19c3a5f5e58..e5a383407a2 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -2534,6 +2534,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
> while (left > 0) {
> union dwc3_event event;
>
> + dwc3_invalidate_cache((uintptr_t)evt->buf, evt->length);
> +
> event.raw = *(u32 *) (evt->buf + evt->lpos);
>
> dwc3_process_event_entry(dwc, &event);
> diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
> index 0ede323671b..c1ab0288142 100644
> --- a/drivers/usb/dwc3/io.h
> +++ b/drivers/usb/dwc3/io.h
> @@ -55,4 +55,12 @@ static inline void dwc3_flush_cache(uintptr_t addr, int length)
>
> flush_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
> }
> +
> +static inline void dwc3_invalidate_cache(uintptr_t addr, int length)
> +{
> + uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
> + uintptr_t end_addr = ALIGN((uintptr_t)addr + length, CACHELINE_SIZE);
> +
> + invalidate_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
> +}
> #endif /* __DRIVERS_USB_DWC3_IO_H */
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling
2024-12-28 13:46 ` Ahmad Fatoum
@ 2024-12-30 10:35 ` Neil Armstrong
2024-12-30 18:49 ` Ahmad Fatoum
0 siblings, 1 reply; 15+ messages in thread
From: Neil Armstrong @ 2024-12-30 10:35 UTC (permalink / raw)
To: Ahmad Fatoum, Marek Vasut, Tom Rini, Lukasz Majewski,
Mattijs Korpershoek, Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot
On 28/12/2024 14:46, Ahmad Fatoum wrote:
> Hi,
>
> On 11.10.24 16:38, Neil Armstrong wrote:
>> On Qualcomm systems, the setup buffer and even buffers are in
>> a bad state at interrupt handling, so invalidate the dcache lines
>> for the setup_buf and event buffer to make sure we read correct
>> data written by the hardware.
>>
>> This fixes the following error:
>> dwc3-generic-peripheral usb@a600000: UNKNOWN IRQ type -1
>> dwc3-generic-peripheral usb@a600000: UNKNOWN IRQ type 4673109
>>
>> and invalid situation in dwc3_gadget_giveback() because setup_buf content
>> is read at 0s and leads to fatal crash fixed by [1].
>>
>> [1] https://lore.kernel.org/all/20240528-topic-sm8x50-dwc3-gadget-crash-fix-v1-1-58434ab4b3d3@linaro.org/
>>
>> Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
>> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
>> ---
>> drivers/usb/dwc3/ep0.c | 2 ++
>> drivers/usb/dwc3/gadget.c | 2 ++
>> drivers/usb/dwc3/io.h | 8 ++++++++
>> 3 files changed, 12 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
>> index 8ba5fcd5312..531f0b522af 100644
>> --- a/drivers/usb/dwc3/ep0.c
>> +++ b/drivers/usb/dwc3/ep0.c
>> @@ -742,6 +742,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
>> if (!dwc->gadget_driver)
>> goto out;
>>
>> + dwc3_invalidate_cache((uintptr_t)ctrl, sizeof(*ctrl));
>
> I believe this to be incorrect. ctrl here is dwc->ctrl_req, which AFAICS
> is allocated in dwc3_gadget_init() using dma_alloc_coherent.
>
> Doing cache maintenance on DMA-coherent memory doesn't make sense.
> If this makes things better for you, it's probable that something else
> is broken.
>
> Additionally, this will break platforms that have DMA-coherent DWC3
> and allocate normal memory instead of uncached memory. I am not sure
> if there are such U-Boot platforms yet, as searching for dma-coherent DT
> property yields no relevant results, but e.g. LS1046A in barebox would've
> been broken by such a change.
dma_alloc_coherent() in U-boot allocates "aligned on cacheline" cached memory,
the function reuses the Linux naming but doesn't actually allocate
uncached/coherent memory.
Neil
>
> Cheers,
> Ahmad
>
>> +
>> len = le16_to_cpu(ctrl->wLength);
>> if (!len) {
>> dwc->three_stage_setup = false;
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 19c3a5f5e58..e5a383407a2 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -2534,6 +2534,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
>> while (left > 0) {
>> union dwc3_event event;
>>
>> + dwc3_invalidate_cache((uintptr_t)evt->buf, evt->length);
>> +
>> event.raw = *(u32 *) (evt->buf + evt->lpos);
>>
>> dwc3_process_event_entry(dwc, &event);
>> diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
>> index 0ede323671b..c1ab0288142 100644
>> --- a/drivers/usb/dwc3/io.h
>> +++ b/drivers/usb/dwc3/io.h
>> @@ -55,4 +55,12 @@ static inline void dwc3_flush_cache(uintptr_t addr, int length)
>>
>> flush_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
>> }
>> +
>> +static inline void dwc3_invalidate_cache(uintptr_t addr, int length)
>> +{
>> + uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
>> + uintptr_t end_addr = ALIGN((uintptr_t)addr + length, CACHELINE_SIZE);
>> +
>> + invalidate_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
>> +}
>> #endif /* __DRIVERS_USB_DWC3_IO_H */
>>
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling
2024-12-30 10:35 ` Neil Armstrong
@ 2024-12-30 18:49 ` Ahmad Fatoum
0 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2024-12-30 18:49 UTC (permalink / raw)
To: neil.armstrong, Marek Vasut, Tom Rini, Lukasz Majewski,
Mattijs Korpershoek, Bin Meng
Cc: Caleb Connolly, u-boot-qcom, u-boot
Hi Neil,
On 30.12.24 11:35, Neil Armstrong wrote:
> On 28/12/2024 14:46, Ahmad Fatoum wrote:
>> Doing cache maintenance on DMA-coherent memory doesn't make sense.
>> If this makes things better for you, it's probable that something else
>> is broken.
>>
>> Additionally, this will break platforms that have DMA-coherent DWC3
>> and allocate normal memory instead of uncached memory. I am not sure
>> if there are such U-Boot platforms yet, as searching for dma-coherent DT
>> property yields no relevant results, but e.g. LS1046A in barebox would've
>> been broken by such a change.
>
> dma_alloc_coherent() in U-boot allocates "aligned on cacheline" cached memory,
> the function reuses the Linux naming but doesn't actually allocate
> uncached/coherent memory.
:/
No wonder these bugs happen. Thanks for clarifying.
Cheers,
Ahmad
>
> Neil
>
>>
>> Cheers,
>> Ahmad
>>
>>> +
>>> len = le16_to_cpu(ctrl->wLength);
>>> if (!len) {
>>> dwc->three_stage_setup = false;
>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>> index 19c3a5f5e58..e5a383407a2 100644
>>> --- a/drivers/usb/dwc3/gadget.c
>>> +++ b/drivers/usb/dwc3/gadget.c
>>> @@ -2534,6 +2534,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
>>> while (left > 0) {
>>> union dwc3_event event;
>>> + dwc3_invalidate_cache((uintptr_t)evt->buf, evt->length);
>>> +
>>> event.raw = *(u32 *) (evt->buf + evt->lpos);
>>> dwc3_process_event_entry(dwc, &event);
>>> diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
>>> index 0ede323671b..c1ab0288142 100644
>>> --- a/drivers/usb/dwc3/io.h
>>> +++ b/drivers/usb/dwc3/io.h
>>> @@ -55,4 +55,12 @@ static inline void dwc3_flush_cache(uintptr_t addr, int length)
>>> flush_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
>>> }
>>> +
>>> +static inline void dwc3_invalidate_cache(uintptr_t addr, int length)
>>> +{
>>> + uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
>>> + uintptr_t end_addr = ALIGN((uintptr_t)addr + length, CACHELINE_SIZE);
>>> +
>>> + invalidate_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
>>> +}
>>> #endif /* __DRIVERS_USB_DWC3_IO_H */
>>>
>>
>>
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/3] dwc3: gadget: properly fix cache operations
2024-10-11 14:38 [PATCH v4 0/3] dwc3: gadget: properly fix cache operations Neil Armstrong
` (2 preceding siblings ...)
2024-10-11 14:38 ` [PATCH v4 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling Neil Armstrong
@ 2024-10-15 9:06 ` Mattijs Korpershoek
2024-10-21 23:31 ` Tom Rini
4 siblings, 0 replies; 15+ messages in thread
From: Mattijs Korpershoek @ 2024-10-15 9:06 UTC (permalink / raw)
To: Marek Vasut, Tom Rini, Lukasz Majewski, Bin Meng, Neil Armstrong
Cc: Caleb Connolly, u-boot-qcom, u-boot
Hi,
On Fri, 11 Oct 2024 16:38:23 +0200, Neil Armstrong wrote:
> We experience huge problems with cache handling on Qualcomm
> systems, and it appears the dcache handling in the DWC3 gadget
> code is quite wrong and causes operational issues.
>
> This serie fixes the dcache operations on unaligned data,
> and properly invalidate buffers when reading back data from
> hardware.
>
> [...]
Thanks, Applied to https://source.denx.de/u-boot/custodians/u-boot-dfu (u-boot-dfu)
[1/3] usb: dwc3: allocate setup_buf with dma_alloc_coherent()
https://source.denx.de/u-boot/custodians/u-boot-dfu/-/commit/1f12fc7e3350b179d17efaf5ba00fc3683cf33ec
[2/3] usb: dwc3: fix dcache flush range calculation
https://source.denx.de/u-boot/custodians/u-boot-dfu/-/commit/502a50ab1f7e32e3e90056597e8ce6a0931789ba
[3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling
https://source.denx.de/u-boot/custodians/u-boot-dfu/-/commit/3e47302dd71267b85e5ec65c5b6d881c23cce6cb
--
Mattijs
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH v4 0/3] dwc3: gadget: properly fix cache operations
2024-10-11 14:38 [PATCH v4 0/3] dwc3: gadget: properly fix cache operations Neil Armstrong
` (3 preceding siblings ...)
2024-10-15 9:06 ` [PATCH v4 0/3] dwc3: gadget: properly fix cache operations Mattijs Korpershoek
@ 2024-10-21 23:31 ` Tom Rini
2024-10-22 9:10 ` Mattijs Korpershoek
4 siblings, 1 reply; 15+ messages in thread
From: Tom Rini @ 2024-10-21 23:31 UTC (permalink / raw)
To: Marek Vasut, Lukasz Majewski, Mattijs Korpershoek, Bin Meng,
Neil Armstrong
Cc: Caleb Connolly, u-boot-qcom, u-boot
On Fri, 11 Oct 2024 16:38:23 +0200, Neil Armstrong wrote:
> We experience huge problems with cache handling on Qualcomm
> systems, and it appears the dcache handling in the DWC3 gadget
> code is quite wrong and causes operational issues.
>
> This serie fixes the dcache operations on unaligned data,
> and properly invalidate buffers when reading back data from
> hardware.
>
> [...]
Applied to u-boot/master, thanks!
--
Tom
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH v4 0/3] dwc3: gadget: properly fix cache operations
2024-10-21 23:31 ` Tom Rini
@ 2024-10-22 9:10 ` Mattijs Korpershoek
2024-10-22 14:19 ` Tom Rini
0 siblings, 1 reply; 15+ messages in thread
From: Mattijs Korpershoek @ 2024-10-22 9:10 UTC (permalink / raw)
To: Tom Rini, Marek Vasut, Lukasz Majewski, Bin Meng, Neil Armstrong
Cc: Caleb Connolly, u-boot-qcom, u-boot
Hi Tom,
On lun., oct. 21, 2024 at 17:31, Tom Rini <trini@konsulko.com> wrote:
> On Fri, 11 Oct 2024 16:38:23 +0200, Neil Armstrong wrote:
>
>> We experience huge problems with cache handling on Qualcomm
>> systems, and it appears the dcache handling in the DWC3 gadget
>> code is quite wrong and causes operational issues.
>>
>> This serie fixes the dcache operations on unaligned data,
>> and properly invalidate buffers when reading back data from
>> hardware.
>>
>> [...]
>
> Applied to u-boot/master, thanks!
I think you already pulled this via:
https://patchwork.ozlabs.org/project/uboot/patch/87iktr2l9t.fsf@baylibre.com/
>
> --
> Tom
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v4 0/3] dwc3: gadget: properly fix cache operations
2024-10-22 9:10 ` Mattijs Korpershoek
@ 2024-10-22 14:19 ` Tom Rini
0 siblings, 0 replies; 15+ messages in thread
From: Tom Rini @ 2024-10-22 14:19 UTC (permalink / raw)
To: Mattijs Korpershoek
Cc: Marek Vasut, Lukasz Majewski, Bin Meng, Neil Armstrong,
Caleb Connolly, u-boot-qcom, u-boot
[-- Attachment #1: Type: text/plain, Size: 983 bytes --]
On Tue, Oct 22, 2024 at 11:10:27AM +0200, Mattijs Korpershoek wrote:
> Hi Tom,
>
> On lun., oct. 21, 2024 at 17:31, Tom Rini <trini@konsulko.com> wrote:
>
> > On Fri, 11 Oct 2024 16:38:23 +0200, Neil Armstrong wrote:
> >
> >> We experience huge problems with cache handling on Qualcomm
> >> systems, and it appears the dcache handling in the DWC3 gadget
> >> code is quite wrong and causes operational issues.
> >>
> >> This serie fixes the dcache operations on unaligned data,
> >> and properly invalidate buffers when reading back data from
> >> hardware.
> >>
> >> [...]
> >
> > Applied to u-boot/master, thanks!
>
> I think you already pulled this via:
>
> https://patchwork.ozlabs.org/project/uboot/patch/87iktr2l9t.fsf@baylibre.com/
Ah, hunh. OK. So, I should try and run the script to update patchwork
status based on patch hashes more often. And I think b4 applied it to
the original merge base, then merged to master as a no-op.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread