Add patch fixing regression from stmmac TX timer.
Refer to the single patch for extensive details on the problem.
This should restore original performance before 4.19 kernel.
Fixes: #11676
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- /dev/null
+From b5532bdc6d09e6e789417f0c7a0b665b57b0e7be Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Mon, 18 Sep 2023 14:21:56 +0200
+Subject: [PATCH 1/3] net: introduce napi_is_scheduled helper
+
+We currently have napi_if_scheduled_mark_missed that can be used to
+check if napi is scheduled but that does more thing than simply checking
+it and return a bool. Some driver already implement custom function to
+check if napi is scheduled.
+
+Drop these custom function and introduce napi_is_scheduled that simply
+check if napi is scheduled atomically.
+
+Update any driver and code that implement a similar check and instead
+use this new helper.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/net/ethernet/chelsio/cxgb3/sge.c | 8 --------
+ drivers/net/wireless/realtek/rtw89/core.c | 2 +-
+ include/linux/netdevice.h | 5 +++++
+ net/core/dev.c | 2 +-
+ 4 files changed, 7 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
+@@ -2507,14 +2507,6 @@ static int napi_rx_handler(struct napi_s
+ return work_done;
+ }
+
+-/*
+- * Returns true if the device is already scheduled for polling.
+- */
+-static inline int napi_is_scheduled(struct napi_struct *napi)
+-{
+- return test_bit(NAPI_STATE_SCHED, &napi->state);
+-}
+-
+ /**
+ * process_pure_responses - process pure responses from a response queue
+ * @adap: the adapter
+--- a/drivers/net/wireless/realtek/rtw89/core.c
++++ b/drivers/net/wireless/realtek/rtw89/core.c
+@@ -1479,7 +1479,7 @@ static void rtw89_core_rx_to_mac80211(st
+ struct napi_struct *napi = &rtwdev->napi;
+
+ /* In low power mode, napi isn't scheduled. Receive it to netif. */
+- if (unlikely(!test_bit(NAPI_STATE_SCHED, &napi->state)))
++ if (unlikely(!napi_is_scheduled(napi)))
+ napi = NULL;
+
+ rtw89_core_hw_to_sband_rate(rx_status);
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -468,6 +468,11 @@ static inline bool napi_prefer_busy_poll
+ return test_bit(NAPI_STATE_PREFER_BUSY_POLL, &n->state);
+ }
+
++static inline bool napi_is_scheduled(struct napi_struct *n)
++{
++ return test_bit(NAPI_STATE_SCHED, &n->state);
++}
++
+ bool napi_schedule_prep(struct napi_struct *n);
+
+ /**
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -6562,7 +6562,7 @@ static int __napi_poll(struct napi_struc
+ * accidentally calling ->poll() when NAPI is not scheduled.
+ */
+ work = 0;
+- if (test_bit(NAPI_STATE_SCHED, &n->state)) {
++ if (napi_is_scheduled(n)) {
+ work = n->poll(n, weight);
+ trace_napi_poll(n, work, weight);
+ }
--- /dev/null
+From 26e872db0f14c09ab57486b538ecc3a24c579df2 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Mon, 18 Sep 2023 14:39:01 +0200
+Subject: [PATCH 2/3] net: stmmac: improve TX timer arm logic
+
+There is currently a problem with the TX timer getting armed multiple
+unnecessary times causing big performance regression on some device that
+suffer from heavy handling of hrtimer rearm.
+
+The use of the TX timer is an old implementation that predates the napi
+implementation and the interrupt enable/disable handling.
+
+Due to stmmac being a very old code, the TX timer was never evaluated
+again with this new implementation and was kept there causing
+performance regression. The performance regression started to appear
+with kernel version 4.19 with 8fce33317023 ("net: stmmac: Rework coalesce
+timer and fix multi-queue races") where the timer was reduced to 1ms
+causing it to be armed 40 times more than before.
+
+Decreasing the timer made the problem more present and caused the
+regression in the other of 600-700mbps on some device (regression where
+this was notice is ipq806x).
+
+The problem is in the fact that handling the hrtimer on some target is
+expensive and recent kernel made the timer armed much more times.
+A solution that was proposed was reverting the hrtimer change and use
+mod_timer but such solution would still hide the real problem in the
+current implementation.
+
+To fix the regression, apply some additional logic and skip arming the
+timer when not needed.
+
+Arm the timer ONLY if a napi is not already scheduled. Running the timer
+is redundant since the same function (stmmac_tx_clean) will run in the
+napi TX poll. Also try to cancel any timer if a napi is scheduled to
+prevent redundant run of TX call.
+
+With the following new logic the original performance are restored while
+keeping using the hrtimer.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2974,13 +2974,25 @@ static void stmmac_tx_timer_arm(struct s
+ {
+ struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue];
+ u32 tx_coal_timer = priv->tx_coal_timer[queue];
++ struct stmmac_channel *ch;
++ struct napi_struct *napi;
+
+ if (!tx_coal_timer)
+ return;
+
+- hrtimer_start(&tx_q->txtimer,
+- STMMAC_COAL_TIMER(tx_coal_timer),
+- HRTIMER_MODE_REL);
++ ch = &priv->channel[tx_q->queue_index];
++ napi = tx_q->xsk_pool ? &ch->rxtx_napi : &ch->tx_napi;
++
++ /* Arm timer only if napi is not already scheduled.
++ * Try to cancel any timer if napi is scheduled, timer will be armed
++ * again in the next scheduled napi.
++ */
++ if (unlikely(!napi_is_scheduled(napi)))
++ hrtimer_start(&tx_q->txtimer,
++ STMMAC_COAL_TIMER(tx_coal_timer),
++ HRTIMER_MODE_REL);
++ else
++ hrtimer_try_to_cancel(&tx_q->txtimer);
+ }
+
+ /**
--- /dev/null
+From 13e24b0c4318b8b4d0a0fde7e5e7ccb982821c63 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Mon, 18 Sep 2023 15:11:13 +0200
+Subject: [PATCH 3/3] net: stmmac: increase TX coalesce timer to 5ms
+
+Commit 8fce33317023 ("net: stmmac: Rework coalesce timer and fix
+multi-queue races") decreased the TX coalesce timer from 40ms to 1ms.
+
+This caused some performance regression on some target (regression was
+reported at least on ipq806x) in the order of 600mbps dropping from
+gigabit handling to only 200mbps.
+
+The problem was identified in the TX timer getting armed too much time.
+While this was fixed and improved in another commit, performance can be
+improved even further by increasing the timer delay a bit moving from
+1ms to 5ms.
+
+The value is a good balance between battery saving by prevending too
+much interrupt to be generated and permitting good performance for
+internet oriented devices.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/net/ethernet/stmicro/stmmac/common.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/common.h
++++ b/drivers/net/ethernet/stmicro/stmmac/common.h
+@@ -286,7 +286,7 @@ struct stmmac_safety_stats {
+ #define MIN_DMA_RIWT 0x10
+ #define DEF_DMA_RIWT 0xa0
+ /* Tx coalesce parameters */
+-#define STMMAC_COAL_TX_TIMER 1000
++#define STMMAC_COAL_TX_TIMER 5000
+ #define STMMAC_MAX_COAL_TX_TICK 100000
+ #define STMMAC_TX_MAX_FRAMES 256
+ #define STMMAC_TX_FRAMES 25