From e76ed39f3b296562b1490a4793cff4cf4986649d Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Mon, 3 Nov 2025 18:19:14 +0100 Subject: [PATCH] realtek: dsa: Refresh link_stats in .get_stats64 If an architecture doesn't need to sleep for retrieving the current statistics from the HW, it is possible to directly retrieve the last values from the HW when .get_stats64 is called. This avoids the stale counters with the current refresh interval of 60 seconds. Signed-off-by: Sven Eckelmann Link: https://github.com/openwrt/openwrt/pull/20631 Signed-off-by: Hauke Mehrtens --- .../files-6.12/drivers/net/dsa/rtl83xx/dsa.c | 10 ++++++++++ .../files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c | 1 + .../files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h | 15 ++++++++++++++- .../files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c | 1 + .../files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c | 1 + 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c index d34dd3b03b..6786abbe74 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c @@ -1430,6 +1430,13 @@ static void rtldsa_get_rmon_stats(struct dsa_switch *ds, int port, rtldsa_counters_unlock(priv, port); } +void rtldsa_update_counters_atomically(struct rtl838x_switch_priv *priv, int port) +{ + rtldsa_counters_lock(priv, port); + rtldsa_update_port_counters(priv, port); + rtldsa_counters_unlock(priv, port); +} + static void rtldsa_get_stats64(struct dsa_switch *ds, int port, struct rtnl_link_stats64 *s) { @@ -1444,6 +1451,9 @@ static void rtldsa_get_stats64(struct dsa_switch *ds, int port, return; } + if (priv->r->stat_update_counters_atomically) + priv->r->stat_update_counters_atomically(priv, port); + /* retrieve prepared return data without potentially sleeping via mutex */ spin_lock(&counters->link_stat_lock); memcpy(s, &counters->link_stat, sizeof(*s)); diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c index c57027ed1d..af3e88a632 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c @@ -1675,6 +1675,7 @@ const struct rtl838x_reg rtl838x_reg = { .stat_port_std_mib = RTL838X_STAT_PORT_STD_MIB, .stat_counters_lock = rtldsa_counters_lock_register, .stat_counters_unlock = rtldsa_counters_unlock_register, + .stat_update_counters_atomically = rtldsa_update_counters_atomically, .port_iso_ctrl = rtl838x_port_iso_ctrl, .traffic_enable = rtl838x_traffic_enable, .traffic_disable = rtl838x_traffic_disable, diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h index bca2d8a1f7..267a6b80f7 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.h @@ -712,7 +712,7 @@ struct rtldsa_counter { struct rtldsa_counter_state { /** * @lock: protect updates to members of the structure when the - * priv->counters_lock is not used. + * priv->counters_lock is not used. (see rtl931x_reg->stat_update_counters_atomically) */ spinlock_t lock; ktime_t last_update; @@ -1129,6 +1129,17 @@ struct rtl838x_reg { u64 (*stat_port_table_read)(int port, unsigned int mib_size, unsigned int offset, bool is_pvt); void (*stat_counters_lock)(struct rtl838x_switch_priv *priv, int port); void (*stat_counters_unlock)(struct rtl838x_switch_priv *priv, int port); + + /** + * @stat_update_counters_atomically: When set, the SoC family allows atomically retrieving + * of statistic counters using this function. This function must not require "might_sleep" + * code. + * + * Any SoC family which requires stat_port_table_read must use the table + * rtldsa_counters_(un)lock_table helpers. They are using a mutex for locking. The counters + * update is therefore not atomic. + */ + void (*stat_update_counters_atomically)(struct rtl838x_switch_priv *priv, int port); int (*port_iso_ctrl)(int p); void (*traffic_enable)(int source, int dest); void (*traffic_disable)(int source, int dest); @@ -1300,6 +1311,8 @@ void rtldsa_counters_lock_table(struct rtl838x_switch_priv *priv, int port) void rtldsa_counters_unlock_table(struct rtl838x_switch_priv *priv, int port) __releases(&priv->ports[port].counters.lock); +void rtldsa_update_counters_atomically(struct rtl838x_switch_priv *priv, int port); + extern int rtldsa_max_available_queue[]; extern int rtldsa_default_queue_weights[]; diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c index e3adefcd10..c421fb819d 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c @@ -1649,6 +1649,7 @@ const struct rtl838x_reg rtl839x_reg = { .stat_port_std_mib = RTL839X_STAT_PORT_STD_MIB, .stat_counters_lock = rtldsa_counters_lock_register, .stat_counters_unlock = rtldsa_counters_unlock_register, + .stat_update_counters_atomically = rtldsa_update_counters_atomically, .traffic_enable = rtl839x_traffic_enable, .traffic_disable = rtl839x_traffic_disable, .traffic_set = rtl839x_traffic_set, diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c index f835681541..8f19056072 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c @@ -2618,6 +2618,7 @@ const struct rtl838x_reg rtl930x_reg = { .stat_port_prv_mib = RTL930X_STAT_PORT_PRVTE_CNTR, .stat_counters_lock = rtldsa_counters_lock_register, .stat_counters_unlock = rtldsa_counters_unlock_register, + .stat_update_counters_atomically = rtldsa_update_counters_atomically, .traffic_enable = rtl930x_traffic_enable, .traffic_disable = rtl930x_traffic_disable, .traffic_set = rtl930x_traffic_set, -- 2.30.2