summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2025-09-11 10:03:12 -0600
committerTom Rini <trini@konsulko.com>2025-09-11 10:03:12 -0600
commitc9800dc906ad21a1157ec718f5e450daaf42e4b3 (patch)
tree5cdca416f0b4afe0db09a7899ad3b572bd180953
parentfd7510e516b519864680c4a56bc14dabdc91607f (diff)
parent7bcc604ef80244ac45d8112b823ceff21af61e39 (diff)
Merge patch series "Fix dma_addr_t for R5 SPL"
Anshul Dalal <anshuld@ti.com> says: On various TI's K3 platforms boot failure was observed on SPI NOR since the commit 5609f200d062 ("arm: Kconfig: enable LTO for ARCH_K3"). This issue was root caused to stack corruption by the 'udma_transfer' function. Where the local variable 'paddr' of type 'dma_addr_t' was being written to as a 64-bit value which overwrote the stack frame of the caller (dma_memcpy) as only 32-bits had been reserved for paddr on the stack, specifically the r4 register in the frame of dma_memcpy was being overwritten with a 0. drivers/dma/ti/k3-udma.c:2192: int udma_transfer(...) { ... dma_addr_t paddr = 0; ... /* paddr was written to as 64-bit value here */ udma_poll_completion(uc, &paddr); } drivers/dma/dma-uclass.c:234: int dma_memcpy(...) { dma_addr_t destination; dma_addr_t source; int ret; ... /* This call resolves to udma_transfer */ ret = ops->transfer(...); ... dma_unmap_single(destination, ...); dma_unmap_single(...); return ret; } Enabling LTO changed how gcc mapped local variables of dma_memcpy to CPU registers, where earlier the bug was hidden since the overwritten register 'r4' was allotted to 'ret' but was allotted to 'destination' once LTO was enabled. And since the overwritten value was 0, the bug remained undetected as it just meant ret was 0, but having 'destination' set to 0 caused dma_unmap_single to fail silently leading to boot failures. The fix entails enabling DMA_ADDR_T_64BIT which changes dma_addr_t from u32 to u64 for the R5 SPL thus reserving enough space for 'paddr' to prevent the overflow. Link: https://lore.kernel.org/r/20250903115207.572304-1-anshuld@ti.com
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--drivers/dma/ti/k3-udma.c6
-rw-r--r--drivers/usb/dwc3/ep0.c4
3 files changed, 6 insertions, 5 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 40368abc297..16db046f4b8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -833,6 +833,7 @@ config ARCH_K3
select FIT
select REGEX
select FIT_SIGNATURE if ARM64
+ select DMA_ADDR_T_64BIT
select LTO
imply TI_SECURE_DEVICE
imply DM_RNG if ARM64
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index 723265ab2e5..01824310995 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -2327,7 +2327,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata)
{
struct udma_dev *ud = dev_get_priv(dma->dev);
struct cppi5_host_desc_t *desc_tx;
- dma_addr_t dma_src = (dma_addr_t)src;
+ dma_addr_t dma_src = (uintptr_t)src;
struct ti_udma_drv_packet_data packet_data = { 0 };
dma_addr_t paddr;
struct udma_chan *uc;
@@ -2426,7 +2426,7 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata)
cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
- *dst = (void *)buf_dma;
+ *dst = (void *)(uintptr_t)buf_dma;
uc->num_rx_bufs--;
return pkt_len;
@@ -2518,7 +2518,7 @@ int udma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
desc_num = uc->desc_rx_cur % UDMA_RX_DESC_NUM;
desc_rx = uc->desc_rx + (desc_num * uc->config.hdesc_size);
- dma_dst = (dma_addr_t)dst;
+ dma_dst = (uintptr_t)dst;
cppi5_hdesc_reset_hbdesc(desc_rx);
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 531f0b522af..c656cbe25ce 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 = (void *)dwc->setup_buf_addr;
+ dwc->ep0_usb_req.request.buf = (void *)(uintptr_t)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 = (void *)dwc->setup_buf_addr;
+ dwc->ep0_usb_req.request.buf = (void *)(uintptr_t)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);