[PATCH 3/3] firmware: zynqmp-fpga: do not use DMA coherent memory for bitstream

Michael Tretter m.tretter at pengutronix.de
Wed Aug 18 06:35:05 PDT 2021


Trying to do unaligned access of coherent memory on AArch64 will lead to
an abort. This can happen when the FPGA loader copies the bitstream to
the temporary buffer for the transfer to the FPGA.

Convert the driver to use regular memory for the temporary buffer to
prevent the issue.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
 drivers/firmware/zynqmp-fpga.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c
index 667910479aa7..0a0e7e880849 100644
--- a/drivers/firmware/zynqmp-fpga.c
+++ b/drivers/firmware/zynqmp-fpga.c
@@ -203,7 +203,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	size_t body_length;
 	int header_length = 0;
 	enum xilinx_byte_order byte_order;
-	u64 addr;
+	dma_addr_t addr;
 	int status = 0;
 	u8 flags = ZYNQMP_FPGA_BIT_ONLY_BIN;
 
@@ -240,13 +240,19 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	 * memory. Allocate some extra space at the end of the buffer for the
 	 * bitstream size.
 	 */
-	buf_aligned = dma_alloc_coherent(body_length + sizeof(buf_size),
-					 DMA_ADDRESS_BROKEN);
+	buf_aligned = dma_alloc(body_length + sizeof(u32));
 	if (!buf_aligned) {
 		status = -ENOBUFS;
 		goto err_free;
 	}
 
+	addr = dma_map_single(&mgr->dev, buf_aligned,
+			      body_length + sizeof(u32), DMA_TO_DEVICE);
+	if (dma_mapping_error(&mgr->dev, addr)) {
+		status = -EFAULT;
+		goto err_free;
+	}
+
 	if (!(mgr->features & ZYNQMP_PM_FEATURE_BYTE_ORDER_IRREL) &&
 	    byte_order == XILINX_BYTE_ORDER_BIN)
 		copy_words_swapped((u32 *)buf_aligned, body,
@@ -254,8 +260,6 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	else
 		memcpy((u32 *)buf_aligned, body, body_length);
 
-	addr = (u64)buf_aligned;
-
 	if (mgr->features & ZYNQMP_PM_FEATURE_SIZE_NOT_NEEDED) {
 		buf_size = body_length;
 	} else {
@@ -263,11 +267,13 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 		buf_size = addr + body_length;
 	}
 
-	status = mgr->eemi_ops->fpga_load(addr, buf_size, flags);
+	dma_sync_single_for_device(addr, body_length + sizeof(u32), DMA_TO_DEVICE);
+	status = mgr->eemi_ops->fpga_load((u64)addr, buf_size, flags);
+	dma_sync_single_for_cpu(addr, body_length + sizeof(u32), DMA_TO_DEVICE);
 	if (status < 0)
 		dev_err(&mgr->dev, "unable to load fpga\n");
 
-	dma_free_coherent(buf_aligned, 0, body_length + sizeof(buf_size));
+	dma_free(buf_aligned);
 
  err_free:
 	free(mgr->buf);
-- 
2.30.2




More information about the barebox mailing list