[PATCH master 15/23] firmware: qemu_fw_cfg: use bounce buffer for write

Ahmad Fatoum a.fatoum at pengutronix.de
Tue Apr 23 23:40:50 PDT 2024


qemu_fw_cfg seems to be the only cdev that expect DMA-aligned memory in
its write operation. We don't generally allocate buffers for read() with
dma_alloc though, so introduce a bounce buffer. The write callback is
only used once for initial configuration of the frame buffer device, so
the allocation won't be noticeable.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/firmware/qemu_fw_cfg.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 1ba81d1b5002..3f129a2c1e02 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -173,14 +173,24 @@ static ssize_t fw_cfg_write(struct cdev *cdev, const void *buf, size_t count,
 	struct fw_cfg *fw_cfg = to_fw_cfg(cdev);
 	struct device *dev = cdev->dev;
 	struct fw_cfg_dma __iomem *acc = fw_cfg->acc_virt;
+	void *dma_buf;
 	dma_addr_t mapping;
+	int ret = 0;
 
 	if (pos != 0)
 		return -EINVAL;
 
-	mapping = dma_map_single(dev, (void *)buf, count, DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, mapping))
-		return -EFAULT;
+	dma_buf = dma_alloc(count);
+	if (!dma_buf)
+		return -ENOMEM;
+
+	memcpy(dma_buf, buf, count);
+
+	mapping = dma_map_single(dev, dma_buf, count, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, mapping)) {
+		ret = -EFAULT;
+		goto free_buf;
+	}
 
 	fw_cfg->next_read_offset = 0;
 
@@ -195,8 +205,10 @@ static ssize_t fw_cfg_write(struct cdev *cdev, const void *buf, size_t count,
 		;
 
 	dma_unmap_single(dev, mapping, count, DMA_FROM_DEVICE);
+free_buf:
+	dma_free(dma_buf);
 
-	return count;
+	return ret ?: count;
 }
 
 static struct cdev_operations fw_cfg_ops = {
-- 
2.39.2




More information about the barebox mailing list