[LEDE-DEV] [PATCH 3/7] ag71xx: optimized iomapped register access

Rosen Penev rosenp at gmail.com
Thu Dec 7 18:37:13 PST 2017


Seems to remove a few instructions. Original message below:

From: Ben Menchaca <ben.menchaca at qca.qualcomm.com>
Date: Tue, 11 Jun 2013 15:50:17 -0500
Subject: [ag71xx] optimize iomapped register access

Add register accessors that remove the per-register range check that
was done previously.  Additionally, we separate the write from the
subsequent read that is designed to flush the write; this can now be
called separately.

Signed-off-by: Ben Menchaca <ben.menchaca at qca.qualcomm.com>
Signed-off-by: Rosen Penev <rosenp at gmail.com>
---
 .../drivers/net/ethernet/atheros/ag71xx/ag71xx.h   | 23 +++++++++++++++++++
 .../net/ethernet/atheros/ag71xx/ag71xx_main.c      | 26 +++++++++++++++-------
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h
index c39beaf..39237aa 100644
--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h
+++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h
@@ -163,6 +163,12 @@ struct ag71xx {
 	struct ag71xx_ring	rx_ring ____cacheline_aligned;
 	struct ag71xx_ring	tx_ring ____cacheline_aligned;
 
+	void __iomem		*rx_ctrl_reg;
+	void __iomem		*rx_status_reg;
+	void __iomem		*tx_ctrl_reg;
+	void __iomem		*tx_status_reg;
+	void __iomem		*int_status_reg;
+
 	unsigned int            max_frame_len;
 	unsigned int            desc_pktlen_mask;
 	unsigned int            rx_buf_size;
@@ -400,6 +406,17 @@ static inline void ag71xx_check_reg_offset(struct ag71xx *ag, unsigned reg)
 	}
 }
 
+static inline void ag71xx_wr_fast(void  __iomem *r, u32 value)
+{
+	__raw_writel(value, r);
+}
+
+static inline void ag71xx_wr_flush(void  __iomem *r)
+{
+	(void)__raw_readl(r);
+}
+
+
 static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value)
 {
 	ag71xx_check_reg_offset(ag, reg);
@@ -409,6 +426,12 @@ static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value)
 	(void) __raw_readl(ag->mac_base + reg);
 }
 
+static inline u32 ag71xx_rr_fast(void  __iomem *r)
+{
+	return __raw_readl(r);
+}
+
+
 static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg)
 {
 	ag71xx_check_reg_offset(ag, reg);
diff --git a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
index 7760952..ffbe646 100644
--- a/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
+++ b/target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
@@ -842,8 +842,8 @@ static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb,
 	DBG("%s: packet injected into TX queue\n", ag->dev->name);
 
 	/* enable TX engine */
-	ag71xx_wr(ag, AG71XX_REG_TX_CTRL, TX_CTRL_TXE);
-
+	ag71xx_wr_fast(ag->tx_ctrl_reg, TX_CTRL_TXE);
+	ag71xx_wr_flush(ag->tx_ctrl_reg);
 	return NETDEV_TX_OK;
 
 err_drop_unmap:
@@ -994,7 +994,7 @@ static int ag71xx_tx_packets(struct ag71xx *ag, bool flush)
 		ring->dirty += n;
 
 		while (n > 0) {
-			ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS);
+			ag71xx_wr_fast(ag->tx_status_reg, TX_STATUS_PS);
 			n--;
 		}
 	}
@@ -1048,7 +1048,7 @@ static int ag71xx_rx_packets(struct ag71xx *ag, int limit)
 			break;
 		}
 
-		ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR);
+		ag71xx_wr_fast(ag->rx_status_reg, RX_STATUS_PR);
 
 		pktlen = desc->ctrl & pktlen_mask;
 		pktlen -= ETH_FCS_LEN;
@@ -1087,6 +1087,8 @@ next:
 		ring->curr++;
 	}
 
+	ag71xx_wr_flush(ag->rx_status_reg);
+
 	ag71xx_ring_rx_refill(ag);
 
 	while ((skb = __skb_dequeue(&queue)) != NULL) {
@@ -1123,13 +1125,15 @@ static int ag71xx_poll(struct napi_struct *napi, int limit)
 	if (rx_ring->buf[rx_ring->dirty % rx_ring_size].rx_buf == NULL)
 		goto oom;
 
-	status = ag71xx_rr(ag, AG71XX_REG_RX_STATUS);
+	status = ag71xx_rr_fast(ag->rx_status_reg);
 	if (unlikely(status & RX_STATUS_OF)) {
-		ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_OF);
+		ag71xx_wr_fast(ag->rx_status_reg, RX_STATUS_OF);
+		ag71xx_wr_flush(ag->rx_status_reg);
 		dev->stats.rx_fifo_errors++;
 
 		/* restart RX */
-		ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE);
+		ag71xx_wr_fast(ag->rx_ctrl_reg, RX_CTRL_RXE);
+		ag71xx_wr_flush(ag->rx_ctrl_reg);
 	}
 
 	if (rx_done < limit) {
@@ -1172,7 +1176,7 @@ static irqreturn_t ag71xx_interrupt(int irq, void *dev_id)
 	struct ag71xx *ag = netdev_priv(dev);
 	u32 status;
 
-	status = ag71xx_rr(ag, AG71XX_REG_INT_STATUS);
+	status = ag71xx_rr_fast(ag->int_status_reg);
 	ag71xx_dump_intr(ag, "raw", status);
 
 	if (unlikely(!status))
@@ -1320,6 +1324,12 @@ static int ag71xx_probe(struct platform_device *pdev)
 		goto err_free_dev;
 	}
 
+	ag->rx_ctrl_reg = ag->mac_base + AG71XX_REG_RX_CTRL;
+	ag->rx_status_reg = ag->mac_base + AG71XX_REG_RX_STATUS;
+	ag->tx_ctrl_reg = ag->mac_base + AG71XX_REG_TX_CTRL;
+	ag->tx_status_reg = ag->mac_base + AG71XX_REG_TX_STATUS;
+	ag->int_status_reg = ag->mac_base + AG71XX_REG_INT_STATUS;
+
 	dev->irq = platform_get_irq(pdev, 0);
 	err = request_irq(dev->irq, ag71xx_interrupt,
 			  0x0,
-- 
2.7.4




More information about the Lede-dev mailing list