diff mbox series

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

Message ID 1512700637-47-3-git-send-email-rosenp@gmail.com
State Rejected
Headers show
Series [LEDE-DEV,1/7] ag71xx: Reorder some more structs based on warmth. | expand

Commit Message

Rosen Penev Dec. 8, 2017, 2:37 a.m. UTC
Seems to remove a few instructions. Original message below:

From: Ben Menchaca <ben.menchaca@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@qca.qualcomm.com>
Signed-off-by: Rosen Penev <rosenp@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(-)

Comments

Felix Fietkau Feb. 22, 2018, 4:58 p.m. UTC | #1
On 2017-12-08 03:37, Rosen Penev wrote:
> Seems to remove a few instructions. Original message below:
> 
> From: Ben Menchaca <ben.menchaca@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@qca.qualcomm.com>
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
Caching direct pointers to individual register does not make much sense
to me, especially when considering performance. Addition is cheap, using
more cache lines isn't.

- Felix
diff mbox series

Patch

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,