[PATCH 7/7] net: fec_imx: Do not use DMA coherent memory for Rx buffers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Trying to do unaligned access of coherent memory on AArch64 will lead
to an abort and some parts of our IP stack will do exactly that with
received packet buffer by using memcpy() to extracts parts of it.

Convert the driver to use regular memory for received data buffers to
prevent the issue from happening.

Signed-off-by: Andrey Smirnov <andrew.smirnov@xxxxxxxxx>
---
 drivers/net/fec_imx.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 33f2da84a..d304b94c5 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -558,6 +558,14 @@ static int fec_recv(struct eth_device *dev)
 
 		if (data_length - 4 > 14) {
 			void *frame = phys_to_virt(readl(&rbd->data_pointer));
+			/*
+			 * Sync the data for CPU so that endianness
+			 * fixup and net_receive below would get
+			 * proper data
+			 */
+			dma_sync_single_for_cpu((unsigned long)frame,
+						data_length,
+						DMA_FROM_DEVICE);
 			if (fec_is_imx28(fec))
 				imx28_fix_endianess_rd(frame,
 						       (data_length + 3) >> 2);
@@ -567,6 +575,9 @@ static int fec_recv(struct eth_device *dev)
 			 */
 			len = data_length - 4;
 			net_receive(dev, frame, len);
+			dma_sync_single_for_device((unsigned long)frame,
+						   data_length,
+						   DMA_FROM_DEVICE);
 		}
 	}
 	/*
@@ -585,13 +596,23 @@ static int fec_alloc_receive_packets(struct fec_priv *fec, int count, int size)
 	void *p;
 	int i;
 
-	/* reserve data memory and consider alignment */
-	p = dma_alloc_coherent(size * count, DMA_ADDRESS_BROKEN);
+
+	p = dma_alloc(size * count);
 	if (!p)
 		return -ENOMEM;
 
 	for (i = 0; i < count; i++) {
-		writel(virt_to_phys(p), &fec->rbd_base[i].data_pointer);
+		dma_addr_t dma;
+		/*
+		 * Make sure there are no outstanding writes to the
+		 * region of memory we are going to use as receive
+		 * buffers as well as check that DMA mapping is valid
+		 */
+		dma = dma_map_single(fec->dev, p, size, DMA_FROM_DEVICE);
+		if (dma_mapping_error(fec->dev, dma))
+			return -EFAULT;
+
+		writel(dma, &fec->rbd_base[i].data_pointer);
 		p += size;
 	}
 
@@ -601,7 +622,7 @@ static int fec_alloc_receive_packets(struct fec_priv *fec, int count, int size)
 static void fec_free_receive_packets(struct fec_priv *fec, int count, int size)
 {
 	void *p = phys_to_virt(fec->rbd_base[0].data_pointer);
-	dma_free_coherent(p, 0, size * count);
+	dma_free(p);
 }
 
 #ifdef CONFIG_OFDEVICE
-- 
2.17.1


_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox



[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux