From 0db3e9ac75b107d2158b227426f58df9bb00529f Mon Sep 17 00:00:00 2001
From: Oskari Lemmela <oskari@lemmela.net>
Date: Sun, 20 Aug 2023 15:25:09 +0300
Subject: [PATCH] Revert "net: stmmac: Use hrtimer for TX coalescing"

This reverts commit d5a05e69ac6e4c431c380ced2b534c91f7bc3280.

hrtimer uses raw_spin_lock which causes high CPU usage.
ipq806x platform's TCP transmit speed dropped from 950 Mbps to 250 Mbps
due to high ksoftirq.

Signed-off-by: Oskari Lemmela <oskari@lemmela.net>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h  |  3 +--
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 25 +++++++------------
 2 files changed, 10 insertions(+), 18 deletions(-)

--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -13,7 +13,6 @@
 #define DRV_MODULE_VERSION	"Jan_2016"
 
 #include <linux/clk.h>
-#include <linux/hrtimer.h>
 #include <linux/if_vlan.h>
 #include <linux/stmmac.h>
 #include <linux/phylink.h>
@@ -59,7 +58,7 @@ struct stmmac_tx_info {
 struct stmmac_tx_queue {
 	u32 tx_count_frames;
 	int tbs;
-	struct hrtimer txtimer;
+	struct timer_list txtimer;
 	u32 queue_index;
 	struct stmmac_priv *priv_data;
 	struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp;
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -142,7 +142,7 @@ static void stmmac_init_fs(struct net_de
 static void stmmac_exit_fs(struct net_device *dev);
 #endif
 
-#define STMMAC_COAL_TIMER(x) (ns_to_ktime((x) * NSEC_PER_USEC))
+#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
 
 int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled)
 {
@@ -2728,9 +2728,7 @@ static int stmmac_tx_clean(struct stmmac
 
 	/* We still have pending packets, let's call for a new scheduling */
 	if (tx_q->dirty_tx != tx_q->cur_tx)
-		hrtimer_start(&tx_q->txtimer,
-			      STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]),
-			      HRTIMER_MODE_REL);
+		mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]));
 
 	__netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue));
 
@@ -3022,9 +3020,7 @@ static void stmmac_tx_timer_arm(struct s
 {
 	struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
 
-	hrtimer_start(&tx_q->txtimer,
-		      STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]),
-		      HRTIMER_MODE_REL);
+	mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(priv->tx_coal_timer[queue]));
 }
 
 /**
@@ -3033,9 +3029,9 @@ static void stmmac_tx_timer_arm(struct s
  * Description:
  * This is the timer handler to directly invoke the stmmac_tx_clean.
  */
-static enum hrtimer_restart stmmac_tx_timer(struct hrtimer *t)
+static void stmmac_tx_timer(struct timer_list *t)
 {
-	struct stmmac_tx_queue *tx_q = container_of(t, struct stmmac_tx_queue, txtimer);
+	struct stmmac_tx_queue *tx_q = from_timer(tx_q, t, txtimer);
 	struct stmmac_priv *priv = tx_q->priv_data;
 	struct stmmac_channel *ch;
 	struct napi_struct *napi;
@@ -3051,8 +3047,6 @@ static enum hrtimer_restart stmmac_tx_ti
 		spin_unlock_irqrestore(&ch->lock, flags);
 		__napi_schedule(napi);
 	}
-
-	return HRTIMER_NORESTART;
 }
 
 /**
@@ -3075,8 +3069,7 @@ static void stmmac_init_coalesce(struct
 		priv->tx_coal_frames[chan] = STMMAC_TX_FRAMES;
 		priv->tx_coal_timer[chan] = STMMAC_COAL_TX_TIMER;
 
-		hrtimer_init(&tx_q->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-		tx_q->txtimer.function = stmmac_tx_timer;
+		timer_setup(&tx_q->txtimer, stmmac_tx_timer, 0);
 	}
 
 	for (chan = 0; chan < rx_channel_count; chan++)
@@ -3906,7 +3899,7 @@ irq_error:
 	phylink_stop(priv->phylink);
 
 	for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
-		hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
+		del_timer_sync(&priv->dma_conf.tx_queue[chan].txtimer);
 
 	stmmac_hw_teardown(dev);
 init_error:
@@ -3964,7 +3957,7 @@ static int stmmac_release(struct net_dev
 	stmmac_disable_all_queues(priv);
 
 	for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
-		hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
+		del_timer_sync(&priv->dma_conf.tx_queue[chan].txtimer);
 
 	netif_tx_disable(dev);
 
@@ -6639,7 +6632,7 @@ void stmmac_xdp_release(struct net_devic
 	stmmac_disable_all_queues(priv);
 
 	for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
-		hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
+		del_timer_sync(&priv->dma_conf.tx_queue[chan].txtimer);
 
 	/* Free the IRQ lines */
 	stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0);
@@ -6734,8 +6727,7 @@ int stmmac_xdp_open(struct net_device *d
 		stmmac_set_tx_tail_ptr(priv, priv->ioaddr,
 				       tx_q->tx_tail_addr, chan);
 
-		hrtimer_init(&tx_q->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-		tx_q->txtimer.function = stmmac_tx_timer;
+		timer_setup(&tx_q->txtimer, stmmac_tx_timer, 0);
 	}
 
 	/* Enable the MAC Rx/Tx */
@@ -6758,7 +6750,7 @@ int stmmac_xdp_open(struct net_device *d
 
 irq_error:
 	for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
-		hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
+		del_timer_sync(&priv->dma_conf.tx_queue[chan].txtimer);
 
 	stmmac_hw_teardown(dev);
 init_error:
@@ -7485,7 +7477,7 @@ int stmmac_suspend(struct device *dev)
 	stmmac_disable_all_queues(priv);
 
 	for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
-		hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
+		del_timer_sync(&priv->dma_conf.tx_queue[chan].txtimer);
 
 	if (priv->eee_enabled) {
 		priv->tx_path_in_lpi_mode = false;