[PATCH 2/3] nvmem: zynqmp_nvmem: Use streaming DMA with single kmalloc block
Harsh Jain
h.jain at amd.com
Wed May 27 23:43:22 PDT 2026
From: Harish Ediga <harish.ediga at amd.com>
Coherent buffers are required only when the device and host update
memory in parallel, which is not the case here. Replace the coherent
buffer with the streaming DMA API and combine the two allocations
into a single kmalloc block.
Signed-off-by: Harish Ediga <harish.ediga at amd.com>
Co-developed-by: Harsh Jain <h.jain at amd.com>
Signed-off-by: Harsh Jain <h.jain at amd.com>
---
drivers/nvmem/zynqmp_nvmem.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
index 6be00a2be9e4..e8ab4ce23fb9 100644
--- a/drivers/nvmem/zynqmp_nvmem.c
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -60,14 +60,13 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
void *val, size_t bytes, enum efuse_access flag,
unsigned int pufflag)
{
+ size_t words = bytes / WORD_INBYTES;
struct device *dev = context;
struct xilinx_efuse *efuse;
dma_addr_t dma_addr;
- dma_addr_t dma_buf;
- size_t words = bytes / WORD_INBYTES;
- int ret;
unsigned int value;
char *data;
+ int ret;
if (bytes % WORD_INBYTES != 0) {
dev_err(dev, "Bytes requested should be word aligned\n");
@@ -95,18 +94,18 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
}
}
- efuse = dma_alloc_coherent(dev, sizeof(struct xilinx_efuse),
- &dma_addr, GFP_KERNEL);
+ efuse = kmalloc(sizeof(*efuse) + bytes, GFP_KERNEL);
if (!efuse)
return -ENOMEM;
- data = dma_alloc_coherent(dev, bytes,
- &dma_buf, GFP_KERNEL);
- if (!data) {
- ret = -ENOMEM;
- goto efuse_data_fail;
+ dma_addr = dma_map_single(dev, efuse, sizeof(*efuse) + bytes,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, dma_addr)) {
+ kfree(efuse);
+ return -ENOMEM;
}
+ data = (char *)efuse + sizeof(*efuse);
if (flag == EFUSE_WRITE) {
memcpy(data, val, bytes);
efuse->flag = EFUSE_WRITE;
@@ -114,12 +113,18 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
efuse->flag = EFUSE_READ;
}
- efuse->src = dma_buf;
+ efuse->src = dma_addr + sizeof(*efuse);
efuse->size = words;
efuse->offset = offset;
efuse->pufuserfuse = pufflag;
+ /* Sync DMA address updated after mapping*/
+ dma_sync_single_for_device(dev, dma_addr, sizeof(*efuse) + bytes,
+ DMA_BIDIRECTIONAL);
zynqmp_pm_efuse_access(dma_addr, (u32 *)&ret);
+ dma_unmap_single(dev, dma_addr, sizeof(*efuse) + bytes,
+ DMA_BIDIRECTIONAL);
+
if (ret != 0) {
if (ret == EFUSE_NOT_ENABLED) {
dev_err(dev, "efuse access is not enabled\n");
@@ -133,12 +138,9 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
if (flag == EFUSE_READ)
memcpy(val, data, bytes);
+
efuse_access_err:
- dma_free_coherent(dev, bytes,
- data, dma_buf);
-efuse_data_fail:
- dma_free_coherent(dev, sizeof(struct xilinx_efuse),
- efuse, dma_addr);
+ kfree(efuse);
return ret;
}
--
2.34.1
More information about the linux-arm-kernel
mailing list