[PATCH] net: cpsw: map/unmap buffers used for DMA

Ahmad Fatoum a.fatoum at pengutronix.de
Wed Mar 13 10:50:02 PDT 2024


This doesn't fix any bugs, but it allows CONFIG_DMA_API_DEBUG to check
for any future issues that may be introduced.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/net/cpsw.c | 46 ++++++++++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index 3f24c21594c1..31ca61a230e9 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -804,7 +804,8 @@ static void cpdma_desc_free(struct cpsw_priv *priv, struct cpdma_desc *desc)
 }
 
 static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan,
-			void *buffer, int len, int port)
+			void *sw_buffer, dma_addr_t hw_buffer,
+			int len, int port)
 {
 	struct cpdma_desc *desc, *prev;
 	u32 mode;
@@ -823,10 +824,10 @@ static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan,
 			(port << CPDMA_FROM_TO_PORT_SHIFT);
 
 	writel(0, &desc->hw_next);
-	writel((u32)buffer, &desc->hw_buffer);
+	writel(hw_buffer, &desc->hw_buffer);
 	writel(len, &desc->hw_len);
 	writel(mode | len, &desc->hw_mode);
-	writel((u32)buffer, &desc->sw_buffer);
+	writel((u32)sw_buffer, &desc->sw_buffer);
 	writel((u32)len, &desc->sw_len);
 
 	if (!chan->head) {
@@ -853,7 +854,7 @@ static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan,
 }
 
 static int cpdma_process(struct cpsw_slave *slave, struct cpdma_chan *chan,
-			 void **buffer, int *len)
+			 void **buffer, dma_addr_t *dma, int *len)
 {
 	struct cpdma_desc *desc = chan->head;
 	struct cpsw_priv *priv = slave->cpsw;
@@ -867,6 +868,8 @@ static int cpdma_process(struct cpsw_slave *slave, struct cpdma_chan *chan,
 	if (len)
 		*len = status & 0x7ff;
 
+	if (dma)
+		*dma = readl(&desc->hw_buffer);
 	if (buffer)
 		*buffer = (void *)readl(&desc->sw_buffer);
 
@@ -982,8 +985,15 @@ static int cpsw_setup(struct device *dev)
 
 	/* submit rx descs */
 	for (i = 0; i < PKTBUFSRX - 2; i++) {
-		ret = cpdma_submit(priv, &priv->rx_chan, priv->rx_buffer[i],
-				   PKTSIZE, 0);
+		void *buffer = priv->rx_buffer[i];
+		unsigned len = PKTSIZE;
+		dma_addr_t dma;
+
+		dma = dma_map_single(priv->dev, buffer, len, DMA_FROM_DEVICE);
+		if (dma_mapping_error(priv->dev, dma))
+			return -EFAULT;
+
+		ret = cpdma_submit(priv, &priv->rx_chan, buffer, dma, len, 0);
 		if (ret < 0) {
 			dev_err(dev, "error %d submitting rx desc\n", ret);
 			break;
@@ -1014,20 +1024,21 @@ static int cpsw_send(struct eth_device *edev, void *packet, int length)
 {
 	struct cpsw_slave *slave = edev->priv;
 	struct cpsw_priv *priv = slave->cpsw;
-	void *buffer;
-	int ret, len;
+	dma_addr_t dma;
+	int ret;
 
 	dev_dbg(&slave->dev, "* %s slave %d\n", __func__, slave->slave_num);
 
 	/* first reap completed packets */
-	while (cpdma_process(slave, &priv->tx_chan, &buffer, &len) >= 0);
+	while (cpdma_process(slave, &priv->tx_chan, NULL, NULL, NULL) >= 0)
+		;
 
 	dev_dbg(&slave->dev, "%s: %i bytes @ 0x%p\n", __func__, length, packet);
 
-	dma_sync_single_for_device(priv->dev, (unsigned long)packet, length, DMA_TO_DEVICE);
-	ret = cpdma_submit(priv, &priv->tx_chan, packet,
+	dma = dma_map_single(priv->dev, packet, length, DMA_TO_DEVICE);
+	ret = cpdma_submit(priv, &priv->tx_chan, packet, dma,
 			   length, BIT(slave->slave_num));
-	dma_sync_single_for_cpu(priv->dev, (unsigned long)packet, length, DMA_TO_DEVICE);
+	dma_unmap_single(priv->dev, dma, length, DMA_TO_DEVICE);
 
 	return ret;
 }
@@ -1036,16 +1047,15 @@ static int cpsw_recv(struct eth_device *edev)
 {
 	struct cpsw_slave *slave = edev->priv;
 	struct cpsw_priv *priv = slave->cpsw;
+	dma_addr_t dma;
 	void *buffer;
 	int len;
 
-	while (cpdma_process(slave, &priv->rx_chan, &buffer, &len) >= 0) {
-		dma_sync_single_for_cpu(priv->dev, (unsigned long)buffer, len,
-				DMA_FROM_DEVICE);
+	while (cpdma_process(slave, &priv->rx_chan, &buffer, &dma, &len) >= 0) {
+		dma_sync_single_for_cpu(priv->dev, dma, len, DMA_FROM_DEVICE);
 		net_receive(edev, buffer, len);
-		dma_sync_single_for_device(priv->dev, (unsigned long)buffer, len,
-				DMA_FROM_DEVICE);
-		cpdma_submit(priv, &priv->rx_chan, buffer, PKTSIZE, 0);
+		dma_sync_single_for_device(priv->dev, dma, len, DMA_FROM_DEVICE);
+		cpdma_submit(priv, &priv->rx_chan, buffer, dma, PKTSIZE, 0);
 	}
 
 	return 0;
-- 
2.39.2




More information about the barebox mailing list