diff options
| author | Macpaul Lin <[email protected]> | 2026-04-06 15:13:33 -0500 |
|---|---|---|
| committer | David Lechner <[email protected]> | 2026-04-28 13:11:19 -0500 |
| commit | 28bd63967784d1dbeff75289560e71fd1deac902 (patch) | |
| tree | 0118b7deeee9fbfc743402ac763495439ab97275 /drivers | |
| parent | 1cfcd7100d54b706b7d4ee17dd016b83e5eb88ff (diff) | |
spi: mtk_snor: fix zeroed data in DMA read bounce path
Implement proper bounce buffer handling for the read path to fix zeroed
data when using DMA. In the bounce path, map the bounce buffer with
dma_map_single(), perform DMA using bounce_dma, then copy data from the
bounce buffer to the user buffer, and finally unmap with
dma_unmap_single().
Signed-off-by: Macpaul Lin <[email protected]>
Reviewed-by: Julien Stephan <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: David Lechner <[email protected]>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/spi/mtk_snor.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/spi/mtk_snor.c b/drivers/spi/mtk_snor.c index 649bca5716c..21ac115e3c3 100644 --- a/drivers/spi/mtk_snor.c +++ b/drivers/spi/mtk_snor.c @@ -274,6 +274,7 @@ static int mtk_snor_read_bounce(struct mtk_snor_priv *priv, { unsigned int rdlen; int ret; + dma_addr_t bounce_dma; if (op->data.nbytes & MTK_NOR_DMA_ALIGN_MASK) rdlen = (op->data.nbytes + MTK_NOR_DMA_ALIGN) & @@ -281,11 +282,21 @@ static int mtk_snor_read_bounce(struct mtk_snor_priv *priv, else rdlen = op->data.nbytes; - ret = mtk_snor_dma_exec(priv, op->addr.val, rdlen, - (dma_addr_t)priv->buffer); + /* Map bounce buffer for DMA */ + bounce_dma = dma_map_single(priv->buffer, rdlen, DMA_FROM_DEVICE); + if (dma_mapping_error(priv->dev, bounce_dma)) { + dev_err(priv->dev, "bounce buffer dma map failed\n"); + return -EINVAL; + } - if (!ret) + ret = mtk_snor_dma_exec(priv, op->addr.val, rdlen, bounce_dma); + /* Ensure DMA writes are visible to CPU and copy the requested bytes */ + if (!ret) { + /* Synchronize cached data to CPU visible memory if needed */ memcpy(op->data.buf.in, priv->buffer, op->data.nbytes); + } + /* Unmap bounce buffer regardless of success/failure */ + dma_unmap_single(bounce_dma, rdlen, DMA_FROM_DEVICE); return ret; } |
