[RFC PATCH net-next 23/28] net: ethernet: ti: cpsw-proxy-client: add sw tx/rx irq coalescing

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

 



Add coalescing support for the interrupts corresponding to the TX and RX
DMA Channels using hrtimer.

Signed-off-by: Siddharth Vadapalli <s-vadapalli@xxxxxx>
---
 drivers/net/ethernet/ti/cpsw-proxy-client.c | 57 +++++++++++++++++++--
 1 file changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw-proxy-client.c b/drivers/net/ethernet/ti/cpsw-proxy-client.c
index 450fc183eaac..408c9f78c059 100644
--- a/drivers/net/ethernet/ti/cpsw-proxy-client.c
+++ b/drivers/net/ethernet/ti/cpsw-proxy-client.c
@@ -58,13 +58,16 @@ struct rx_dma_chan {
 	struct k3_cppi_desc_pool	*desc_pool;
 	struct k3_udma_glue_rx_channel	*rx_chan;
 	struct napi_struct		napi_rx;
+	struct hrtimer			rx_hrtimer;
 	u32				rel_chan_idx;
 	u32				flow_base;
 	u32				flow_offset;
 	u32				thread_id;
 	u32				num_descs;
 	unsigned int			irq;
+	unsigned long			rx_pace_timeout;
 	char				rx_chan_name[CHAN_NAME_LEN];
+	bool				rx_irq_disabled;
 	bool				in_use;
 };
 
@@ -74,10 +77,12 @@ struct tx_dma_chan {
 	struct k3_cppi_desc_pool	*desc_pool;
 	struct k3_udma_glue_tx_channel	*tx_chan;
 	struct napi_struct		napi_tx;
+	struct hrtimer			tx_hrtimer;
 	u32				rel_chan_idx;
 	u32				thread_id;
 	u32				num_descs;
 	unsigned int			irq;
+	unsigned long			tx_pace_timeout;
 	char				tx_chan_name[CHAN_NAME_LEN];
 	bool				in_use;
 };
@@ -996,8 +1001,15 @@ static int vport_tx_poll(struct napi_struct *napi_tx, int budget)
 	if (num_tx >= budget)
 		return budget;
 
-	if (napi_complete_done(napi_tx, num_tx))
-		enable_irq(tx_chn->irq);
+	if (napi_complete_done(napi_tx, num_tx)) {
+		if (unlikely(tx_chn->tx_pace_timeout && !tdown)) {
+			hrtimer_start(&tx_chn->tx_hrtimer,
+				      ns_to_ktime(tx_chn->tx_pace_timeout),
+				      HRTIMER_MODE_REL_PINNED);
+		} else {
+			enable_irq(tx_chn->irq);
+		}
+	}
 
 	return 0;
 }
@@ -1179,12 +1191,38 @@ static int vport_rx_poll(struct napi_struct *napi_rx, int budget)
 		num_rx++;
 	}
 
-	if (num_rx < budget && napi_complete_done(napi_rx, num_rx))
-		enable_irq(rx_chn->irq);
+	if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) {
+		if (rx_chn->rx_irq_disabled) {
+			rx_chn->rx_irq_disabled = false;
+			if (unlikely(rx_chn->rx_pace_timeout)) {
+				hrtimer_start(&rx_chn->rx_hrtimer,
+					      ns_to_ktime(rx_chn->rx_pace_timeout),
+					      HRTIMER_MODE_REL_PINNED);
+			} else {
+				enable_irq(rx_chn->irq);
+			}
+		}
+	}
 
 	return num_rx;
 }
 
+static enum hrtimer_restart vport_tx_timer_cb(struct hrtimer *timer)
+{
+	struct tx_dma_chan *tx_chn = container_of(timer, struct tx_dma_chan, tx_hrtimer);
+
+	enable_irq(tx_chn->irq);
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart vport_rx_timer_cb(struct hrtimer *timer)
+{
+	struct rx_dma_chan *rx_chn = container_of(timer, struct rx_dma_chan, rx_hrtimer);
+
+	enable_irq(rx_chn->irq);
+	return HRTIMER_NORESTART;
+}
+
 static u32 vport_get_link(struct net_device *ndev)
 {
 	struct virtual_port *vport = vport_ndev_to_vport(ndev);
@@ -1326,6 +1364,7 @@ static void vport_stop(struct virtual_port *vport)
 		k3_udma_glue_reset_tx_chn(tx_chn->tx_chan, tx_chn, vport_tx_cleanup);
 		k3_udma_glue_disable_tx_chn(tx_chn->tx_chan);
 		napi_disable(&tx_chn->napi_tx);
+		hrtimer_cancel(&tx_chn->tx_hrtimer);
 	}
 
 	for (i = 0; i < vport->num_rx_chan; i++) {
@@ -1336,6 +1375,7 @@ static void vport_stop(struct virtual_port *vport)
 		k3_udma_glue_reset_rx_chn(rx_chn->rx_chan, 0, rx_chn, vport_rx_cleanup,
 					  false);
 		napi_disable(&rx_chn->napi_rx);
+		hrtimer_cancel(&rx_chn->rx_hrtimer);
 	}
 }
 
@@ -1381,6 +1421,10 @@ static int vport_open(struct virtual_port *vport, netdev_features_t features)
 	for (i = 0; i < vport->num_rx_chan; i++) {
 		rx_chn = &vport->rx_chans[i];
 		napi_enable(&rx_chn->napi_rx);
+		if (rx_chn->rx_irq_disabled) {
+			rx_chn->rx_irq_disabled = false;
+			enable_irq(rx_chn->irq);
+		}
 	}
 
 	return 0;
@@ -1708,11 +1752,15 @@ static int init_netdev(struct cpsw_proxy_priv *proxy_priv, struct virtual_port *
 	for (i = 0; i < vport->num_tx_chan; i++) {
 		tx_chn = &vport->tx_chans[i];
 		netif_napi_add_tx(vport->ndev, &tx_chn->napi_tx, vport_tx_poll);
+		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+		tx_chn->tx_hrtimer.function = &vport_tx_timer_cb;
 	}
 
 	for (i = 0; i < vport->num_rx_chan; i++) {
 		rx_chn = &vport->rx_chans[i];
 		netif_napi_add(vport->ndev, &rx_chn->napi_rx, vport_rx_poll);
+		hrtimer_init(&rx_chn->rx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+		rx_chn->rx_hrtimer.function = &vport_rx_timer_cb;
 	}
 
 	ret = register_netdev(vport->ndev);
@@ -1771,6 +1819,7 @@ static irqreturn_t rx_irq_handler(int irq, void *dev_id)
 {
 	struct rx_dma_chan *rx_chn = dev_id;
 
+	rx_chn->rx_irq_disabled = true;
 	disable_irq_nosync(irq);
 	napi_schedule(&rx_chn->napi_rx);
 
-- 
2.40.1





[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux