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@xxxxxxxxxxxxxx> --- 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