From ce1023de730ffa37beae46a5276061a74a041a09 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Wed, 2 Oct 2024 16:48:45 +0200 Subject: [PATCH 1/5] Make AVB_VERIFY depend on FASTBOOT AVB_BUF_ADDR, which is under "if AVB_VERIFY", defaults to FASTBOOT_BUF_ADDR. Therefore AVB_VERIFY should depend on FASTBOOT. Signed-off-by: Jerome Forissier Reviewed-by: Mattijs Korpershoek Tested-by: Tom Rini # Raspberry Pi 3 (32b, 64b, Reviewed-by: Simon Glass Link: https://lore.kernel.org/r/20241002144845.1439316-1-jerome.forissier@linaro.org Signed-off-by: Mattijs Korpershoek --- common/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/common/Kconfig b/common/Kconfig index 957de0c5c02..c011ab6e820 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -850,6 +850,7 @@ config AVB_VERIFY depends on LIBAVB depends on MMC depends on PARTITION_UUIDS + depends on FASTBOOT help This option enables compilation of bootloader-dependent operations, used by Android Verified Boot 2.0 library (libavb). Includes: From c54c72dec7948093b200ae1290575a1e9abbbb40 Mon Sep 17 00:00:00 2001 From: Siddharth Vadapalli Date: Mon, 7 Oct 2024 17:49:27 +0530 Subject: [PATCH 2/5] usb: gadget: cdns3: Fix cdns3_ep_config() by setting ep.maxpacket The function cdns3_ep_config() calculates the maximum packet size based on the Endpoint Type and the Gadget Speed and stores it in the variable "max_packet_size". This value is then programmed in the USB Controller for the corresponding Endpoint. This may result in a mismatch between the maximum packet size programmed in the USB controller and the maximum packet size seen by the UDC Core via "maxpacket" member of "struct usb_ep". Additionally, since TD_SIZE is calculated in cdns3_ep_run_transfer() on the basis of the maximum packet size stored in the "maxpacket" member of "struct usb_ep", it may lead to an incorrect value of TD_SIZE when compared with what the USB controller actually expects (max_packet_size). Fix this. Fixes: 7e91f6ccdc84 ("usb: Add Cadence USB3 host and gadget driver") Signed-off-by: Siddharth Vadapalli Reviewed-by: Roger Quadros Reviewed-by: Mattijs Korpershoek Link: https://lore.kernel.org/r/20241007121927.1680039-1-s-vadapalli@ti.com Signed-off-by: Mattijs Korpershoek --- drivers/usb/cdns3/gadget.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index ac7e469469a..a30c40ef80e 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -1637,6 +1637,14 @@ void cdns3_ep_config(struct cdns3_endpoint *priv_ep) else priv_ep->trb_burst_size = 16; + /* + * The Endpoint is configured to handle a maximum packet size of + * max_packet_size. Hence, set priv_ep->endpoint.maxpacket to + * max_packet_size. This is necessary to ensure that the TD_SIZE + * is calculated correctly in cdns3_ep_run_transfer(). + */ + priv_ep->endpoint.maxpacket = max_packet_size; + ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1, !!priv_ep->dir); if (ret) { From 1f12fc7e3350b179d17efaf5ba00fc3683cf33ec Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 11 Oct 2024 16:38:24 +0200 Subject: [PATCH 3/5] usb: dwc3: allocate setup_buf with dma_alloc_coherent() 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 Reviewed-by: Marek Vasut Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20241011-u-boot-dwc3-gadget-dcache-fixup-v4-1-5f3498d8035b@linaro.org Signed-off-by: Mattijs Korpershoek --- 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); From 502a50ab1f7e32e3e90056597e8ce6a0931789ba Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 11 Oct 2024 16:38:25 +0200 Subject: [PATCH 4/5] usb: dwc3: fix dcache flush range calculation 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 Signed-off-by: Neil Armstrong Reviewed-by: Marek Vasut Link: https://lore.kernel.org/r/20241011-u-boot-dwc3-gadget-dcache-fixup-v4-2-5f3498d8035b@linaro.org Signed-off-by: Mattijs Korpershoek --- 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 */ From 3e47302dd71267b85e5ec65c5b6d881c23cce6cb Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 11 Oct 2024 16:38:26 +0200 Subject: [PATCH 5/5] usb: dwc3: invalidate dcache on buffer used in interrupt handling 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 Signed-off-by: Neil Armstrong Reviewed-by: Marek Vasut Link: https://lore.kernel.org/r/20241011-u-boot-dwc3-gadget-dcache-fixup-v4-3-5f3498d8035b@linaro.org Signed-off-by: Mattijs Korpershoek --- 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 */