From: Sven Eckelmann Date: Mon, 3 Nov 2025 17:19:14 +0000 (+0100) Subject: realtek: dsa: rtl931x: Reduce HW counters polling interval X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=e20ab65281bb8cd5b28378945a774a7540843cd2;p=openwrt%2Fopenwrt.git realtek: dsa: rtl931x: Reduce HW counters polling interval Some SoC families require table access to get the HW counters. A mutex is required for this access - which will potentially cause a sleep in the current context. This is not always possible with .get_stats64 because it is also called in atomic contexts. For these SoCs, the retrieval of the current counters in .get_stats64 is skipped and the counters are simply retrieved a lot more often from the HW. Signed-off-by: Sven Eckelmann Link: https://github.com/openwrt/openwrt/pull/20631 Signed-off-by: Hauke Mehrtens --- 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 6786abbe74..0c20f626a7 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 @@ -16,14 +16,6 @@ static const u8 ipv6_all_hosts_mcast_addr_base[ETH_ALEN] = static const u8 ipv6_all_hosts_mcast_addr_mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -/* This interval needs to be short enough to prevent an undetected counter - * overflow. The octet counters don't need to be considered for this, because - * they are 64 bits on all platforms. Based on the possible packets per second - * at the highest supported speeds, an interval of a minute is probably a safe - * choice for the other counters. - */ -#define RTLDSA_COUNTERS_POLL_INTERVAL (60 * HZ) - extern struct rtl83xx_soc_info soc_info; static void rtldsa_init_counters(struct rtl838x_switch_priv *priv); @@ -1213,7 +1205,7 @@ static void rtldsa_poll_counters(struct work_struct *work) } queue_delayed_work(priv->wq, &priv->counters_work, - RTLDSA_COUNTERS_POLL_INTERVAL); + priv->r->stat_counter_poll_interval); } static void rtldsa_init_counters(struct rtl838x_switch_priv *priv) @@ -1233,7 +1225,7 @@ static void rtldsa_init_counters(struct rtl838x_switch_priv *priv) INIT_DELAYED_WORK(&priv->counters_work, rtldsa_poll_counters); queue_delayed_work(priv->wq, &priv->counters_work, - RTLDSA_COUNTERS_POLL_INTERVAL); + priv->r->stat_counter_poll_interval); } static void rtldsa_get_strings(struct dsa_switch *ds, 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 af3e88a632..7fbd561c3f 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 @@ -1676,6 +1676,7 @@ const struct rtl838x_reg rtl838x_reg = { .stat_counters_lock = rtldsa_counters_lock_register, .stat_counters_unlock = rtldsa_counters_unlock_register, .stat_update_counters_atomically = rtldsa_update_counters_atomically, + .stat_counter_poll_interval = RTLDSA_COUNTERS_POLL_INTERVAL, .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 267a6b80f7..b0cfa21d76 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 @@ -684,6 +684,24 @@ typedef enum { #define MAX_SMACS 64 #define DSCP_MAP_MAX 64 +/* This interval needs to be short enough to prevent an undetected counter + * overflow. The octet counters don't need to be considered for this, because + * they are 64 bits on all platforms. Based on the possible packets per second + * at the highest supported speeds, an interval of a minute is probably a safe + * choice for the other counters. + */ +#define RTLDSA_COUNTERS_POLL_INTERVAL (60 * HZ) + +/* Some SoC families require table access to get the HW counters. A mutex is + * required for this access - which will potentially cause a sleep in the + * current context. This is not always possible with .get_stats64 because it + * is also called in atomic contexts. + * + * For these SoCs, the retrieval of the current counters in .get_stats64 is + * skipped and the counters are simply retrieved a lot more often from the HW. + */ +#define RTLDSA_COUNTERS_FAST_POLL_INTERVAL (3 * HZ) + enum phy_type { PHY_NONE = 0, PHY_RTL838X_SDS = 1, @@ -1140,6 +1158,7 @@ struct rtl838x_reg { * update is therefore not atomic. */ void (*stat_update_counters_atomically)(struct rtl838x_switch_priv *priv, int port); + unsigned long stat_counter_poll_interval; int (*port_iso_ctrl)(int p); void (*traffic_enable)(int source, int dest); void (*traffic_disable)(int source, int dest); 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 c421fb819d..9acb277de8 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 @@ -1650,6 +1650,7 @@ const struct rtl838x_reg rtl839x_reg = { .stat_counters_lock = rtldsa_counters_lock_register, .stat_counters_unlock = rtldsa_counters_unlock_register, .stat_update_counters_atomically = rtldsa_update_counters_atomically, + .stat_counter_poll_interval = RTLDSA_COUNTERS_POLL_INTERVAL, .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 8f19056072..bad4b30ce2 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 @@ -2619,6 +2619,7 @@ const struct rtl838x_reg rtl930x_reg = { .stat_counters_lock = rtldsa_counters_lock_register, .stat_counters_unlock = rtldsa_counters_unlock_register, .stat_update_counters_atomically = rtldsa_update_counters_atomically, + .stat_counter_poll_interval = RTLDSA_COUNTERS_POLL_INTERVAL, .traffic_enable = rtl930x_traffic_enable, .traffic_disable = rtl930x_traffic_disable, .traffic_set = rtl930x_traffic_set, diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c index f0817e7f45..6bc3db84d8 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c @@ -1777,6 +1777,7 @@ const struct rtl838x_reg rtl931x_reg = { .stat_port_table_read = rtldsa_931x_stat_port_table_read, .stat_counters_lock = rtldsa_counters_lock_table, .stat_counters_unlock = rtldsa_counters_unlock_table, + .stat_counter_poll_interval = RTLDSA_COUNTERS_FAST_POLL_INTERVAL, .traffic_enable = rtl931x_traffic_enable, .traffic_disable = rtl931x_traffic_disable, .traffic_set = rtl931x_traffic_set,