* [PATCH net-next v5 0/6] net: dsa: motorcomm: MIB fixup
@ 2026-10-04 16:06 David Yang
2026-10-04 16:06 ` [PATCH net-next v5 1/6] net: dsa: motorcomm: Hoist type casting helper into chip.h David Yang
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: David Yang @ 2026-10-04 16:06 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel
Fix (theoretical) MIB inconsistency and prepare for new devices. No new
features are introduced.
v5:
- rebase
- hoist type casting helper into chip.h
- fix enable_delayed_work/disable_delayed_work pair
- remove counter reader in favor of an independent series
- reword commit messages
v4: https://lore.kernel.org/r/20260921203040.1203911-1-mmyangfl@gmail.com
- reuse port_to_priv helper
- re-enable delayed_work on port_setup
- disable preemption for u64_stats_set
v3: https://lore.kernel.org/r/20260906131414.2683362-1-mmyangfl@gmail.com
- fix build errors
- fix logic error on MIB buffer creation
v2: https://lore.kernel.org/r/20260904162952.709368-1-mmyangfl@gmail.com
- split patches
v1: https://lore.kernel.org/r/20260903143514.532023-1-mmyangfl@gmail.com
David Yang (6):
net: dsa: motorcomm: Hoist type casting helper into chip.h
net: dsa: motorcomm: Rename MIB stuff
net: dsa: motorcomm: Split MIB buffers
net: dsa: motorcomm: Split MIB module
net: dsa: motorcomm: Use u64_stats_t for MIB stats
net: dsa: motorcomm: Fix MIB synchronization
drivers/net/dsa/motorcomm/Makefile | 1 +
drivers/net/dsa/motorcomm/chip.c | 534 ++++++---------------------
drivers/net/dsa/motorcomm/chip.h | 128 +------
drivers/net/dsa/motorcomm/leds.c | 7 +-
drivers/net/dsa/motorcomm/mdio_bus.c | 10 +-
drivers/net/dsa/motorcomm/mib.c | 431 +++++++++++++++++++++
drivers/net/dsa/motorcomm/mib.h | 167 +++++++++
drivers/net/dsa/motorcomm/pcs-921x.c | 8 +-
8 files changed, 721 insertions(+), 565 deletions(-)
create mode 100644 drivers/net/dsa/motorcomm/mib.c
create mode 100644 drivers/net/dsa/motorcomm/mib.h
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next v5 1/6] net: dsa: motorcomm: Hoist type casting helper into chip.h
2026-10-04 16:06 [PATCH net-next v5 0/6] net: dsa: motorcomm: MIB fixup David Yang
@ 2026-10-04 16:06 ` David Yang
2026-10-04 16:06 ` [PATCH net-next v5 2/6] net: dsa: motorcomm: Rename MIB stuff David Yang
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Yang @ 2026-10-04 16:06 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel
Rename and move dsa_to_yt921x_priv() and yt921x_priv_to_device() to
chip.h so all files use one definition.
Signed-off-by: David Yang <mmyangfl@gmail.com>
---
drivers/net/dsa/motorcomm/chip.c | 127 +++++++++++++--------------
drivers/net/dsa/motorcomm/chip.h | 2 +
drivers/net/dsa/motorcomm/leds.c | 7 +-
drivers/net/dsa/motorcomm/mdio_bus.c | 10 +--
drivers/net/dsa/motorcomm/pcs-921x.c | 8 +-
5 files changed, 74 insertions(+), 80 deletions(-)
diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/chip.c
index 3ff2de383157..2c0f53cb2b8e 100644
--- a/drivers/net/dsa/motorcomm/chip.c
+++ b/drivers/net/dsa/motorcomm/chip.c
@@ -171,9 +171,6 @@ struct yt921x_reg_mdio {
/* TODO: SPI/I2C */
-#define to_yt921x_priv(_ds) container_of_const(_ds, struct yt921x_priv, ds)
-#define to_device(priv) ((priv)->ds.dev)
-
static u32 ethaddr_hi4_to_u32(const unsigned char *addr)
{
return (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
@@ -271,8 +268,8 @@ static const struct yt921x_reg_ops yt921x_reg_ops_mdio = {
/* Read and handle overflow of 32bit MIBs. MIB buffer must be zeroed before. */
static int yt921x_read_mib(struct yt921x_priv *priv, int port)
{
+ struct device *dev = yt921x_priv_to_device(priv);
struct yt921x_port *pp = &priv->ports[port];
- struct device *dev = to_device(priv);
struct yt921x_mib *mib = &pp->mib;
int res = 0;
@@ -364,7 +361,7 @@ yt921x_dsa_get_strings(struct dsa_switch *ds, int port, u32 stringset,
static void
yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
size_t j;
@@ -406,7 +403,7 @@ static void
yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_mac_stats *mac_stats)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
@@ -442,7 +439,7 @@ static void
yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
@@ -471,7 +468,7 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
@@ -507,7 +504,7 @@ static void
yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
struct rtnl_link_stats64 *stats)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
@@ -543,7 +540,7 @@ static void
yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
struct ethtool_pause_stats *pause_stats)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *mib = &pp->mib;
@@ -598,7 +595,7 @@ yt921x_set_eee(struct yt921x_priv *priv, int port, struct ethtool_keee *e)
static int
yt921x_dsa_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
mutex_lock(&priv->reg_lock);
@@ -622,7 +619,7 @@ yt921x_dsa_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
* maximum after reset
*/
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct dsa_port *dp = dsa_to_port(ds, port);
int frame_size;
int res;
@@ -697,7 +694,7 @@ yt921x_marker_tfm(struct yt921x_marker *marker, u64 rate, u64 burst,
{
const int C = flags & YT921X_MARKER_PKT_MODE ? YT921X_TOKEN_PKT_C :
YT921X_TOKEN_BYTE_C;
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
struct yt921x_marker m;
u64 burst_est;
u64 burst_sug;
@@ -873,8 +870,8 @@ yt921x_meter_config(struct yt921x_priv *priv, unsigned int id,
static void yt921x_dsa_port_policer_del(struct dsa_switch *ds, int port)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct device *dev = to_device(priv);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct device *dev = yt921x_priv_to_device(priv);
int res;
mutex_lock(&priv->reg_lock);
@@ -891,7 +888,7 @@ yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port,
const struct flow_action_police *police,
struct netlink_ext_ack *extack)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_marker marker;
u32 ctrl;
int res;
@@ -921,7 +918,7 @@ static int
yt921x_dsa_port_setup_tc_tbf_port(struct dsa_switch *ds, int port,
const struct tc_tbf_qopt_offload *qopt)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct netlink_ext_ack *extack = qopt->extack;
u32 ctrls[2];
int res;
@@ -1970,7 +1967,7 @@ static int
yt921x_dsa_cls_flower_del(struct dsa_switch *ds, int port,
struct flow_cls_offload *cls, bool ingress)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
mutex_lock(&priv->reg_lock);
@@ -1985,7 +1982,7 @@ yt921x_dsa_cls_flower_add(struct dsa_switch *ds, int port,
struct flow_cls_offload *cls, bool ingress)
{
struct netlink_ext_ack *extack = cls->common.extack;
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_acl_rule_ext ruleext;
int res;
@@ -2056,8 +2053,8 @@ static void
yt921x_dsa_port_mirror_del(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct device *dev = to_device(priv);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct device *dev = yt921x_priv_to_device(priv);
int res;
mutex_lock(&priv->reg_lock);
@@ -2074,7 +2071,7 @@ yt921x_dsa_port_mirror_add(struct dsa_switch *ds, int port,
struct dsa_mall_mirror_tc_entry *mirror,
bool ingress, struct netlink_ext_ack *extack)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
mutex_lock(&priv->reg_lock);
@@ -2143,7 +2140,7 @@ static int yt921x_lag_set(struct yt921x_priv *priv, u8 index, u16 ports_mask)
static int
yt921x_dsa_port_lag_leave(struct dsa_switch *ds, int port, struct dsa_lag lag)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct dsa_port *dp;
u32 ctrl;
int res;
@@ -2206,7 +2203,7 @@ yt921x_dsa_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag,
struct netdev_lag_upper_info *info,
struct netlink_ext_ack *extack)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct dsa_port *dp;
bool unique_lag;
unsigned int i;
@@ -2269,7 +2266,7 @@ yt921x_dsa_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag,
static int yt921x_fdb_wait(struct yt921x_priv *priv, u32 *valp)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
u32 val = YT921X_FDB_RESULT_DONE;
int res;
@@ -2338,7 +2335,7 @@ static int
yt921x_fdb_read(struct yt921x_priv *priv, unsigned char *addr, u16 *vidp,
u16 *ports_maskp, u16 *indexp, u8 *statusp)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
u16 index;
u32 data0;
u32 data1;
@@ -2629,7 +2626,7 @@ static int
yt921x_dsa_port_fdb_dump(struct dsa_switch *ds, int port,
dsa_fdb_dump_cb_t *cb, void *data)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
mutex_lock(&priv->reg_lock);
@@ -2644,8 +2641,8 @@ yt921x_dsa_port_fdb_dump(struct dsa_switch *ds, int port,
static void yt921x_dsa_port_fast_age(struct dsa_switch *ds, int port)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct device *dev = to_device(priv);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct device *dev = yt921x_priv_to_device(priv);
int res;
mutex_lock(&priv->reg_lock);
@@ -2660,7 +2657,7 @@ static void yt921x_dsa_port_fast_age(struct dsa_switch *ds, int port)
static int
yt921x_dsa_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u32 ctrl;
int res;
@@ -2678,7 +2675,7 @@ static int
yt921x_dsa_port_fdb_del(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid, struct dsa_db db)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
mutex_lock(&priv->reg_lock);
@@ -2692,7 +2689,7 @@ static int
yt921x_dsa_port_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid, struct dsa_db db)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
mutex_lock(&priv->reg_lock);
@@ -2707,7 +2704,7 @@ yt921x_dsa_port_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
const unsigned char *addr = mdb->addr;
u16 vid = mdb->vid;
int res;
@@ -2724,7 +2721,7 @@ yt921x_dsa_port_mdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb,
struct dsa_db db)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
const unsigned char *addr = mdb->addr;
u16 vid = mdb->vid;
int res;
@@ -2889,7 +2886,7 @@ yt921x_dsa_port_vlan_filtering(struct dsa_switch *ds, int port,
bool vlan_filtering,
struct netlink_ext_ack *extack)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
if (dsa_is_cpu_port(ds, port))
@@ -2906,7 +2903,7 @@ static int
yt921x_dsa_port_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u16 vid = vlan->vid;
u16 pvid;
int res;
@@ -2940,7 +2937,7 @@ yt921x_dsa_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u16 vid = vlan->vid;
u16 pvid;
int res;
@@ -3185,7 +3182,7 @@ yt921x_dsa_port_bridge_flags(struct dsa_switch *ds, int port,
struct switchdev_brport_flags flags,
struct netlink_ext_ack *extack)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
if (dsa_is_cpu_port(ds, port))
@@ -3202,8 +3199,8 @@ static void
yt921x_dsa_port_bridge_leave(struct dsa_switch *ds, int port,
struct dsa_bridge bridge)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct device *dev = to_device(priv);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct device *dev = yt921x_priv_to_device(priv);
int res;
if (dsa_is_cpu_port(ds, port))
@@ -3223,7 +3220,7 @@ yt921x_dsa_port_bridge_join(struct dsa_switch *ds, int port,
struct dsa_bridge bridge, bool *tx_fwd_offload,
struct netlink_ext_ack *extack)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u16 ports_mask;
int res;
@@ -3244,7 +3241,7 @@ static int
yt921x_dsa_port_mst_state_set(struct dsa_switch *ds, int port,
const struct switchdev_mst_state *st)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u32 mask;
u32 ctrl;
int res;
@@ -3278,7 +3275,7 @@ static int
yt921x_dsa_vlan_msti_set(struct dsa_switch *ds, struct dsa_bridge bridge,
const struct switchdev_vlan_msti *msti)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u32 masks[2];
u32 ctrls[2];
int res;
@@ -3304,9 +3301,9 @@ yt921x_dsa_vlan_msti_set(struct dsa_switch *ds, struct dsa_bridge bridge,
static void
yt921x_dsa_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct device *dev = yt921x_priv_to_device(priv);
struct dsa_port *dp = dsa_to_port(ds, port);
- struct device *dev = to_device(priv);
bool learning;
u32 mask;
u32 ctrl;
@@ -3356,7 +3353,7 @@ yt921x_dsa_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
static int __maybe_unused
yt921x_dsa_port_get_default_prio(struct dsa_switch *ds, int port)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u32 val;
int res;
@@ -3373,7 +3370,7 @@ yt921x_dsa_port_get_default_prio(struct dsa_switch *ds, int port)
static int __maybe_unused
yt921x_dsa_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u32 mask;
u32 ctrl;
int res;
@@ -3399,7 +3396,7 @@ static int __maybe_unused
yt921x_dsa_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel,
int *nselp)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u8 appprios[2][2] = {};
int nsel;
u32 val;
@@ -3433,8 +3430,8 @@ static int __maybe_unused
yt921x_dsa_port_set_apptrust(struct dsa_switch *ds, int port, const u8 *sel,
int nsel)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct device *dev = to_device(priv);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct device *dev = yt921x_priv_to_device(priv);
u32 ctrl;
int res;
@@ -3574,9 +3571,9 @@ static int
yt921x_port_config(struct yt921x_priv *priv, int port, unsigned int mode,
phy_interface_t interface)
{
+ struct device *dev = yt921x_priv_to_device(priv);
const struct yt921x_info *info = priv->info;
struct yt921x_port *pp = &priv->ports[port];
- struct device *dev = to_device(priv);
u32 mask;
int res;
@@ -3628,7 +3625,7 @@ yt921x_phylink_mac_select_pcs(struct phylink_config *config,
phy_interface_t interface)
{
struct dsa_port *dp = dsa_phylink_to_port(config);
- struct yt921x_priv *priv = to_yt921x_priv(dp->ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(dp->ds);
const struct yt921x_info *info = priv->info;
int port = dp->index;
@@ -3651,7 +3648,7 @@ yt921x_phylink_mac_link_down(struct phylink_config *config, unsigned int mode,
phy_interface_t interface)
{
struct dsa_port *dp = dsa_phylink_to_port(config);
- struct yt921x_priv *priv = to_yt921x_priv(dp->ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(dp->ds);
int port = dp->index;
int res;
@@ -3674,7 +3671,7 @@ yt921x_phylink_mac_link_up(struct phylink_config *config,
bool tx_pause, bool rx_pause)
{
struct dsa_port *dp = dsa_phylink_to_port(config);
- struct yt921x_priv *priv = to_yt921x_priv(dp->ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(dp->ds);
int port = dp->index;
int res;
@@ -3695,7 +3692,7 @@ yt921x_phylink_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
struct dsa_port *dp = dsa_phylink_to_port(config);
- struct yt921x_priv *priv = to_yt921x_priv(dp->ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(dp->ds);
int port = dp->index;
int res;
@@ -3712,7 +3709,7 @@ static void
yt921x_dsa_phylink_get_caps(struct dsa_switch *ds, int port,
struct phylink_config *config)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
const struct yt921x_info *info = priv->info;
config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
@@ -3803,7 +3800,7 @@ yt921x_dsa_get_tag_protocol(struct dsa_switch *ds, int port,
static int yt921x_dsa_port_setup(struct dsa_switch *ds, int port)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
mutex_lock(&priv->reg_lock);
@@ -3817,7 +3814,7 @@ static int yt921x_dsa_port_setup(struct dsa_switch *ds, int port)
static int __maybe_unused
yt921x_dsa_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u32 val;
int res;
@@ -3834,7 +3831,7 @@ yt921x_dsa_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp)
static int __maybe_unused
yt921x_dsa_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
u32 val;
int res;
@@ -3859,7 +3856,7 @@ yt921x_dsa_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)
static int __maybe_unused
yt921x_dsa_port_add_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
int res;
if (prio >= YT921X_PRIO_NUM)
@@ -3920,7 +3917,7 @@ static int yt921x_edata_read(struct yt921x_priv *priv, u8 addr, u8 *valp)
static void yt921x_dsa_teardown(struct dsa_switch *ds)
{
#if IS_ENABLED(CONFIG_NET_DSA_YT921X_LEDS)
- struct yt921x_priv *priv = to_yt921x_priv(ds);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
yt921x_leds_remove(priv);
#endif
@@ -3928,7 +3925,7 @@ static void yt921x_dsa_teardown(struct dsa_switch *ds)
static int yt921x_chip_detect(struct yt921x_priv *priv)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
const struct yt921x_info *info;
u8 extmode;
u32 chipid;
@@ -3995,7 +3992,7 @@ static int yt921x_chip_detect(struct yt921x_priv *priv)
static int yt921x_chip_reset(struct yt921x_priv *priv)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
u16 eth_p_tag;
u32 val;
int res;
@@ -4243,8 +4240,8 @@ static int yt921x_chip_setup(struct yt921x_priv *priv)
static int yt921x_dsa_setup(struct dsa_switch *ds)
{
- struct yt921x_priv *priv = to_yt921x_priv(ds);
- struct device *dev = to_device(priv);
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct device *dev = yt921x_priv_to_device(priv);
struct device_node *np = dev->of_node;
struct device_node *child;
unsigned long mask;
diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/chip.h
index 28e4f26f9cc4..9c34fb704bf8 100644
--- a/drivers/net/dsa/motorcomm/chip.h
+++ b/drivers/net/dsa/motorcomm/chip.h
@@ -984,8 +984,10 @@ struct yt921x_priv {
struct yt921x_acl_blk *acl_blks[YT921X_ACL_BLK_NUM];
};
+#define dsa_to_yt921x_priv(_ds) container_of_const(_ds, struct yt921x_priv, ds)
#define yt921x_port_to_priv(pp) \
container_of_const((pp), struct yt921x_priv, ports[(pp)->index])
+#define yt921x_priv_to_device(priv) ((priv)->ds.dev)
static inline int ethtool_speed_to_yt921x(int speed)
{
diff --git a/drivers/net/dsa/motorcomm/leds.c b/drivers/net/dsa/motorcomm/leds.c
index 6613fe3b0471..79a4659b3a53 100644
--- a/drivers/net/dsa/motorcomm/leds.c
+++ b/drivers/net/dsa/motorcomm/leds.c
@@ -12,7 +12,6 @@
#define to_yt921x_led(led_cdev) \
container_of_const((led_cdev), struct yt921x_led, cdev)
#define to_yt921x_port(led) ((led)->port)
-#define to_device(priv) ((priv)->ds.dev)
static u32 yt921x_led_regaddr(struct yt921x_priv *priv, int port, int group)
{
@@ -413,8 +412,8 @@ static int
yt921x_led_setup(struct yt921x_priv *priv, int port,
struct fwnode_handle *fwnode)
{
+ struct device *dev = yt921x_priv_to_device(priv);
struct yt921x_port *pp = &priv->ports[port];
- struct device *dev = to_device(priv);
struct led_init_data init_data;
struct led_classdev *led_cdev;
char name[LED_MAX_NAME_SIZE];
@@ -568,8 +567,8 @@ yt921x_led_setup(struct yt921x_priv *priv, int port,
static void yt921x_leds_remove_port(struct yt921x_priv *priv, int port)
{
+ struct device *dev = yt921x_priv_to_device(priv);
struct yt921x_port *pp = &priv->ports[port];
- struct device *dev = to_device(priv);
for (int group = 0; group < YT921X_LED_GROUP_NUM; group++) {
struct yt921x_led *led = pp->leds[group];
@@ -587,7 +586,7 @@ static void yt921x_leds_remove_port(struct yt921x_priv *priv, int port)
static int yt921x_leds_setup_port(struct yt921x_priv *priv, int port)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
struct dsa_switch *ds = &priv->ds;
struct device_node *leds_np;
struct dsa_port *dp;
diff --git a/drivers/net/dsa/motorcomm/mdio_bus.c b/drivers/net/dsa/motorcomm/mdio_bus.c
index 1a3f3cc68275..dd6c52f37bbf 100644
--- a/drivers/net/dsa/motorcomm/mdio_bus.c
+++ b/drivers/net/dsa/motorcomm/mdio_bus.c
@@ -9,8 +9,6 @@
#include "mdio_bus.h"
#include "smi.h"
-#define to_device(priv) ((priv)->ds.dev)
-
static int yt921x_intif_wait(struct yt921x_priv *priv)
{
u32 val = 0;
@@ -21,7 +19,7 @@ static int yt921x_intif_wait(struct yt921x_priv *priv)
int yt921x_intif_read(struct yt921x_priv *priv, int port, int reg, u16 *valp)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
u32 mask;
u32 ctrl;
u32 val;
@@ -145,7 +143,7 @@ yt921x_mbus_int_write(struct mii_bus *mbus, int port, int reg, u16 data)
int yt921x_mbus_int_init(struct yt921x_priv *priv, struct device_node *mnp)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
struct mii_bus *mbus;
int res;
@@ -181,7 +179,7 @@ static int yt921x_extif_wait(struct yt921x_priv *priv)
static int
yt921x_extif_read(struct yt921x_priv *priv, int port, int reg, u16 *valp)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
u32 mask;
u32 ctrl;
u32 val;
@@ -275,7 +273,7 @@ yt921x_mbus_ext_write(struct mii_bus *mbus, int port, int reg, u16 data)
int yt921x_mbus_ext_init(struct yt921x_priv *priv, struct device_node *mnp)
{
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
struct mii_bus *mbus;
int res;
diff --git a/drivers/net/dsa/motorcomm/pcs-921x.c b/drivers/net/dsa/motorcomm/pcs-921x.c
index 47467d803e13..e942b61d8eb2 100644
--- a/drivers/net/dsa/motorcomm/pcs-921x.c
+++ b/drivers/net/dsa/motorcomm/pcs-921x.c
@@ -8,8 +8,6 @@
#include "pcs.h"
#include "smi.h"
-#define to_device(priv) ((priv)->ds.dev)
-
static int
yt921x_serdes_config(struct yt921x_priv *priv, int port, unsigned int neg_mode,
phy_interface_t interface,
@@ -116,7 +114,7 @@ yt921x_phylink_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
{
struct yt921x_port *pp = pcs_to_yt921x_port(pcs);
struct yt921x_priv *priv = yt921x_port_to_priv(pp);
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
int port = pp->index;
u16 bmsr;
u16 lpa;
@@ -155,7 +153,7 @@ static void yt921x_phylink_pcs_an_restart(struct phylink_pcs *pcs)
{
struct yt921x_port *pp = pcs_to_yt921x_port(pcs);
struct yt921x_priv *priv = yt921x_port_to_priv(pp);
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
int port = pp->index;
u16 val;
int res;
@@ -181,7 +179,7 @@ static void yt921x_phylink_pcs_disable(struct phylink_pcs *pcs)
{
struct yt921x_port *pp = pcs_to_yt921x_port(pcs);
struct yt921x_priv *priv = yt921x_port_to_priv(pp);
- struct device *dev = to_device(priv);
+ struct device *dev = yt921x_priv_to_device(priv);
int port = pp->index;
int res;
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next v5 2/6] net: dsa: motorcomm: Rename MIB stuff
2026-10-04 16:06 [PATCH net-next v5 0/6] net: dsa: motorcomm: MIB fixup David Yang
2026-10-04 16:06 ` [PATCH net-next v5 1/6] net: dsa: motorcomm: Hoist type casting helper into chip.h David Yang
@ 2026-10-04 16:06 ` David Yang
2026-10-04 16:06 ` [PATCH net-next v5 3/6] net: dsa: motorcomm: Split MIB buffers David Yang
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Yang @ 2026-10-04 16:06 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel
Rename them in preparation of major MIB refactor.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/motorcomm/chip.c | 34 ++++++++++++++++----------------
drivers/net/dsa/motorcomm/chip.h | 4 ++--
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/chip.c
index 2c0f53cb2b8e..690ee0eb5192 100644
--- a/drivers/net/dsa/motorcomm/chip.c
+++ b/drivers/net/dsa/motorcomm/chip.c
@@ -40,7 +40,7 @@ struct yt921x_mib_desc {
#define MIB_DESC(_size, _offset, _name) \
{_size, _offset, _name}
-/* Must agree with yt921x_mib
+/* Must agree with yt921x_mib_stats
*
* Unstructured fields (name != NULL) will appear in get_ethtool_stats(),
* structured go to their *_stats() methods, but we need their sizes and offsets
@@ -266,11 +266,11 @@ static const struct yt921x_reg_ops yt921x_reg_ops_mdio = {
/* TODO: SPI/I2C */
/* Read and handle overflow of 32bit MIBs. MIB buffer must be zeroed before. */
-static int yt921x_read_mib(struct yt921x_priv *priv, int port)
+static int yt921x_mib_read(struct yt921x_priv *priv, int port)
{
struct device *dev = yt921x_priv_to_device(priv);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *mib = &pp->mib;
+ struct yt921x_mib_stats *mib = &pp->mib;
int res = 0;
/* Reading of yt921x_port::mib is not protected by a lock and it's vain
@@ -325,7 +325,7 @@ static int yt921x_read_mib(struct yt921x_priv *priv, int port)
return res;
}
-static void yt921x_poll_mib(struct work_struct *work)
+static void yt921x_mib_poll(struct work_struct *work)
{
struct yt921x_port *pp = container_of_const(work, struct yt921x_port,
mib_read.work);
@@ -335,7 +335,7 @@ static void yt921x_poll_mib(struct work_struct *work)
int res;
mutex_lock(&priv->reg_lock);
- res = yt921x_read_mib(priv, port);
+ res = yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
if (res)
delay *= 4;
@@ -363,11 +363,11 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *mib = &pp->mib;
+ struct yt921x_mib_stats *mib = &pp->mib;
size_t j;
mutex_lock(&priv->reg_lock);
- yt921x_read_mib(priv, port);
+ yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
j = 0;
@@ -405,10 +405,10 @@ yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *mib = &pp->mib;
+ struct yt921x_mib_stats *mib = &pp->mib;
mutex_lock(&priv->reg_lock);
- yt921x_read_mib(priv, port);
+ yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
mac_stats->FramesTransmittedOK = pp->tx_frames;
@@ -441,10 +441,10 @@ yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *mib = &pp->mib;
+ struct yt921x_mib_stats *mib = &pp->mib;
mutex_lock(&priv->reg_lock);
- yt921x_read_mib(priv, port);
+ yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
ctrl_stats->MACControlFramesTransmitted = mib->tx_pause;
@@ -470,10 +470,10 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *mib = &pp->mib;
+ struct yt921x_mib_stats *mib = &pp->mib;
mutex_lock(&priv->reg_lock);
- yt921x_read_mib(priv, port);
+ yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
*ranges = yt921x_rmon_ranges;
@@ -506,7 +506,7 @@ yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *mib = &pp->mib;
+ struct yt921x_mib_stats *mib = &pp->mib;
stats->rx_length_errors = mib->rx_undersize_errors +
mib->rx_fragment_errors;
@@ -542,10 +542,10 @@ yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *mib = &pp->mib;
+ struct yt921x_mib_stats *mib = &pp->mib;
mutex_lock(&priv->reg_lock);
- yt921x_read_mib(priv, port);
+ yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
pause_stats->tx_pause_frames = mib->tx_pause;
@@ -4464,7 +4464,7 @@ static int yt921x_mdio_probe(struct mdio_device *mdiodev)
struct yt921x_port *pp = &priv->ports[i];
pp->index = i;
- INIT_DELAYED_WORK(&pp->mib_read, yt921x_poll_mib);
+ INIT_DELAYED_WORK(&pp->mib_read, yt921x_mib_poll);
}
ds = &priv->ds;
diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/chip.h
index 9c34fb704bf8..c1b24b6d1d97 100644
--- a/drivers/net/dsa/motorcomm/chip.h
+++ b/drivers/net/dsa/motorcomm/chip.h
@@ -833,7 +833,7 @@ enum yt921x_fdb_entry_status {
#define YT921X_NAME "yt921x"
-struct yt921x_mib {
+struct yt921x_mib_stats {
u64 rx_broadcast;
u64 rx_pause;
u64 rx_multicast;
@@ -918,7 +918,7 @@ struct yt921x_port {
bool isolated:1;
struct delayed_work mib_read;
- struct yt921x_mib mib;
+ struct yt921x_mib_stats mib;
u64 rx_frames;
u64 tx_frames;
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next v5 3/6] net: dsa: motorcomm: Split MIB buffers
2026-10-04 16:06 [PATCH net-next v5 0/6] net: dsa: motorcomm: MIB fixup David Yang
2026-10-04 16:06 ` [PATCH net-next v5 1/6] net: dsa: motorcomm: Hoist type casting helper into chip.h David Yang
2026-10-04 16:06 ` [PATCH net-next v5 2/6] net: dsa: motorcomm: Rename MIB stuff David Yang
@ 2026-10-04 16:06 ` David Yang
2026-10-04 16:06 ` [PATCH net-next v5 4/6] net: dsa: motorcomm: Split MIB module David Yang
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Yang @ 2026-10-04 16:06 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel
With MIB improvement introduced later, struct yt921x_priv will be over
20 KiB which is not very good for a single kmalloc(). Dynamically
allocate the MIB structures to reduce the size of struct yt921x_priv
(and adjust polling work lifecycle), and do not waste memory on dummy
ports.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/motorcomm/chip.c | 124 ++++++++++++++++++++++++-------
drivers/net/dsa/motorcomm/chip.h | 20 +++--
2 files changed, 112 insertions(+), 32 deletions(-)
diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/chip.c
index 690ee0eb5192..8341d4d1c784 100644
--- a/drivers/net/dsa/motorcomm/chip.c
+++ b/drivers/net/dsa/motorcomm/chip.c
@@ -270,10 +270,13 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
{
struct device *dev = yt921x_priv_to_device(priv);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib_stats *mib = &pp->mib;
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
int res = 0;
- /* Reading of yt921x_port::mib is not protected by a lock and it's vain
+ mib = &pm->stats;
+
+ /* Reading of yt921x_mib_stats is not protected by a lock and it's vain
* to keep its consistency, since we have to read registers one by one
* and there is no way to make a snapshot of MIB stats.
*
@@ -310,11 +313,11 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
WRITE_ONCE(*valp, val);
}
- pp->rx_frames = mib->rx_64byte + mib->rx_65_127byte +
+ pm->rx_frames = mib->rx_64byte + mib->rx_65_127byte +
mib->rx_128_255byte + mib->rx_256_511byte +
mib->rx_512_1023byte + mib->rx_1024_1518byte +
mib->rx_jumbo;
- pp->tx_frames = mib->tx_64byte + mib->tx_65_127byte +
+ pm->tx_frames = mib->tx_64byte + mib->tx_65_127byte +
mib->tx_128_255byte + mib->tx_256_511byte +
mib->tx_512_1023byte + mib->tx_1024_1518byte +
mib->tx_jumbo;
@@ -327,8 +330,9 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
static void yt921x_mib_poll(struct work_struct *work)
{
- struct yt921x_port *pp = container_of_const(work, struct yt921x_port,
- mib_read.work);
+ struct yt921x_mib *pm = container_of_const(work, struct yt921x_mib,
+ work.work);
+ struct yt921x_port *pp = pm->port;
unsigned long delay = YT921X_STATS_INTERVAL_JIFFIES;
struct yt921x_priv *priv = yt921x_port_to_priv(pp);
int port = pp->index;
@@ -340,7 +344,7 @@ static void yt921x_mib_poll(struct work_struct *work)
if (res)
delay *= 4;
- schedule_delayed_work(&pp->mib_read, delay);
+ schedule_delayed_work(&pm->work, delay);
}
static void
@@ -363,9 +367,14 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib_stats *mib = &pp->mib;
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
size_t j;
+ if (!pm)
+ return;
+ mib = &pm->stats;
+
mutex_lock(&priv->reg_lock);
yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
@@ -405,16 +414,21 @@ yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib_stats *mib = &pp->mib;
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
mutex_lock(&priv->reg_lock);
yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
- mac_stats->FramesTransmittedOK = pp->tx_frames;
+ mac_stats->FramesTransmittedOK = pm->tx_frames;
mac_stats->SingleCollisionFrames = mib->tx_single_collisions;
mac_stats->MultipleCollisionFrames = mib->tx_multiple_collisions;
- mac_stats->FramesReceivedOK = pp->rx_frames;
+ mac_stats->FramesReceivedOK = pm->rx_frames;
mac_stats->FrameCheckSequenceErrors = mib->rx_crc_errors;
mac_stats->AlignmentErrors = mib->rx_alignment_errors;
mac_stats->OctetsTransmittedOK = mib->tx_good_bytes;
@@ -441,7 +455,12 @@ yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib_stats *mib = &pp->mib;
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
mutex_lock(&priv->reg_lock);
yt921x_mib_read(priv, port);
@@ -470,7 +489,12 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib_stats *mib = &pp->mib;
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
mutex_lock(&priv->reg_lock);
yt921x_mib_read(priv, port);
@@ -506,7 +530,12 @@ yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib_stats *mib = &pp->mib;
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
stats->rx_length_errors = mib->rx_undersize_errors +
mib->rx_fragment_errors;
@@ -522,8 +551,8 @@ yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
/* stats->tx_heartbeat_errors */
stats->tx_window_errors = mib->tx_late_collisions;
- stats->rx_packets = pp->rx_frames;
- stats->tx_packets = pp->tx_frames;
+ stats->rx_packets = pm->rx_frames;
+ stats->tx_packets = pm->tx_frames;
stats->rx_bytes = mib->rx_good_bytes - ETH_FCS_LEN * stats->rx_packets;
stats->tx_bytes = mib->tx_good_bytes - ETH_FCS_LEN * stats->tx_packets;
stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors +
@@ -542,7 +571,12 @@ yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib_stats *mib = &pp->mib;
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
mutex_lock(&priv->reg_lock);
yt921x_mib_read(priv, port);
@@ -3649,11 +3683,14 @@ yt921x_phylink_mac_link_down(struct phylink_config *config, unsigned int mode,
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct yt921x_priv *priv = dsa_to_yt921x_priv(dp->ds);
+ struct yt921x_mib *pm;
int port = dp->index;
int res;
/* No need to sync; port control block is hold until device remove */
- cancel_delayed_work(&priv->ports[port].mib_read);
+ pm = priv->ports[port].mib;
+ if (pm)
+ cancel_delayed_work(&pm->work);
mutex_lock(&priv->reg_lock);
res = yt921x_port_down(priv, port);
@@ -3672,6 +3709,7 @@ yt921x_phylink_mac_link_up(struct phylink_config *config,
{
struct dsa_port *dp = dsa_phylink_to_port(config);
struct yt921x_priv *priv = dsa_to_yt921x_priv(dp->ds);
+ struct yt921x_mib *pm;
int port = dp->index;
int res;
@@ -3684,7 +3722,9 @@ yt921x_phylink_mac_link_up(struct phylink_config *config,
dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "bring up",
port, res);
- schedule_delayed_work(&priv->ports[port].mib_read, 0);
+ pm = priv->ports[port].mib;
+ if (pm)
+ schedule_delayed_work(&pm->work, 0);
}
static void
@@ -3798,16 +3838,52 @@ yt921x_dsa_get_tag_protocol(struct dsa_switch *ds, int port,
return DSA_TAG_PROTO_YT921X;
}
+static void yt921x_dsa_port_teardown(struct dsa_switch *ds, int port)
+{
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_mib *pm = pp->mib;
+
+ /* get_stats64() might not be synchronized with port_teardown(), hold
+ * the MIB block till the device teardown
+ */
+ if (pm)
+ disable_delayed_work_sync(&pm->work);
+}
+
static int yt921x_dsa_port_setup(struct dsa_switch *ds, int port)
{
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct yt921x_port *pp = &priv->ports[port];
+ const struct yt921x_info *info = priv->info;
+ struct device *dev = yt921x_priv_to_device(priv);
+ struct yt921x_mib *pm = pp->mib;
int res;
+ if (!pm && (BIT(port) & yt921x_info_ports_mask(info))) {
+ pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
+ if (!pm)
+ return -ENOMEM;
+ pp->mib = pm;
+
+ pm->port = pp;
+ INIT_DELAYED_WORK(&pm->work, yt921x_mib_poll);
+ /* Start disabled, so that the enable below always pairs with
+ * either this disable or the one from a previous teardown
+ */
+ disable_delayed_work_sync(&pm->work);
+ }
+
mutex_lock(&priv->reg_lock);
res = yt921x_port_setup(priv, port);
mutex_unlock(&priv->reg_lock);
+ if (res)
+ return res;
- return res;
+ if (pm)
+ enable_delayed_work(&pm->work);
+
+ return 0;
}
/* Not "port" - DSCP mapping is global */
@@ -4382,6 +4458,7 @@ static const struct dsa_switch_ops yt921x_dsa_switch_ops = {
/* port */
.get_tag_protocol = yt921x_dsa_get_tag_protocol,
.phylink_get_caps = yt921x_dsa_phylink_get_caps,
+ .port_teardown = yt921x_dsa_port_teardown,
.port_setup = yt921x_dsa_port_setup,
#if IS_ENABLED(CONFIG_DCB)
/* dscp */
@@ -4411,12 +4488,6 @@ static void yt921x_mdio_remove(struct mdio_device *mdiodev)
if (!priv)
return;
- for (size_t i = ARRAY_SIZE(priv->ports); i-- > 0; ) {
- struct yt921x_port *pp = &priv->ports[i];
-
- disable_delayed_work_sync(&pp->mib_read);
- }
-
dsa_unregister_switch(&priv->ds);
for (unsigned int i = 0; i < ARRAY_SIZE(priv->acl_blks); i++) {
@@ -4464,7 +4535,6 @@ static int yt921x_mdio_probe(struct mdio_device *mdiodev)
struct yt921x_port *pp = &priv->ports[i];
pp->index = i;
- INIT_DELAYED_WORK(&pp->mib_read, yt921x_mib_poll);
}
ds = &priv->ds;
diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/chip.h
index c1b24b6d1d97..d1764b635630 100644
--- a/drivers/net/dsa/motorcomm/chip.h
+++ b/drivers/net/dsa/motorcomm/chip.h
@@ -885,6 +885,15 @@ struct yt921x_mib_stats {
u64 tx_oam;
};
+struct yt921x_mib {
+ struct yt921x_port *port;
+
+ struct delayed_work work;
+ struct yt921x_mib_stats stats;
+ u64 rx_frames;
+ u64 tx_frames;
+};
+
struct yt921x_acl_entry {
u32 key[2];
u32 mask[2];
@@ -917,11 +926,6 @@ struct yt921x_port {
/* BR_ISOLATED */
bool isolated:1;
- struct delayed_work mib_read;
- struct yt921x_mib_stats mib;
- u64 rx_frames;
- u64 tx_frames;
-
#if IS_ENABLED(CONFIG_NET_DSA_YT921X_LEDS)
unsigned char led_duty;
unsigned short led_cycle;
@@ -932,6 +936,7 @@ struct yt921x_port {
struct yt921x_led *leds[YT921X_LED_GROUP_NUM];
#endif
+ struct yt921x_mib *mib;
struct phylink_pcs pcs;
};
@@ -955,6 +960,11 @@ struct yt921x_info {
u16 serdes_mask;
};
+static inline u16 yt921x_info_ports_mask(const struct yt921x_info *info)
+{
+ return info->internal_mask | info->xmii_mask | info->serdes_mask;
+}
+
struct yt921x_priv {
struct dsa_switch ds;
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next v5 4/6] net: dsa: motorcomm: Split MIB module
2026-10-04 16:06 [PATCH net-next v5 0/6] net: dsa: motorcomm: MIB fixup David Yang
` (2 preceding siblings ...)
2026-10-04 16:06 ` [PATCH net-next v5 3/6] net: dsa: motorcomm: Split MIB buffers David Yang
@ 2026-10-04 16:06 ` David Yang
2026-10-04 16:06 ` [PATCH net-next v5 5/6] net: dsa: motorcomm: Use u64_stats_t for MIB stats David Yang
2026-10-04 16:06 ` [PATCH net-next v5 6/6] net: dsa: motorcomm: Fix MIB synchronization David Yang
5 siblings, 0 replies; 7+ messages in thread
From: David Yang @ 2026-10-04 16:06 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel
yt922x is going to use a different MIB scheme, split it to reduce the
length of chip.c.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/motorcomm/Makefile | 1 +
drivers/net/dsa/motorcomm/chip.c | 397 +---------------------------
drivers/net/dsa/motorcomm/chip.h | 124 ---------
drivers/net/dsa/motorcomm/mib.c | 404 +++++++++++++++++++++++++++++
drivers/net/dsa/motorcomm/mib.h | 159 ++++++++++++
5 files changed, 565 insertions(+), 520 deletions(-)
create mode 100644 drivers/net/dsa/motorcomm/mib.c
create mode 100644 drivers/net/dsa/motorcomm/mib.h
diff --git a/drivers/net/dsa/motorcomm/Makefile b/drivers/net/dsa/motorcomm/Makefile
index 1d2c1b3064c4..9c1e3d538d21 100644
--- a/drivers/net/dsa/motorcomm/Makefile
+++ b/drivers/net/dsa/motorcomm/Makefile
@@ -3,5 +3,6 @@ obj-$(CONFIG_NET_DSA_YT921X) += yt921x.o
yt921x-objs := chip.o
yt921x-$(CONFIG_NET_DSA_YT921X_LEDS) += leds.o
yt921x-objs += mdio_bus.o
+yt921x-objs += mib.o
yt921x-objs += pcs-921x.o
yt921x-objs += smi.o
diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/chip.c
index 8341d4d1c784..9e3be08b3465 100644
--- a/drivers/net/dsa/motorcomm/chip.c
+++ b/drivers/net/dsa/motorcomm/chip.c
@@ -28,76 +28,10 @@
#include "chip.h"
#include "leds.h"
#include "mdio_bus.h"
+#include "mib.h"
#include "pcs.h"
#include "smi.h"
-struct yt921x_mib_desc {
- unsigned int size;
- unsigned int offset;
- const char *name;
-};
-
-#define MIB_DESC(_size, _offset, _name) \
- {_size, _offset, _name}
-
-/* Must agree with yt921x_mib_stats
- *
- * Unstructured fields (name != NULL) will appear in get_ethtool_stats(),
- * structured go to their *_stats() methods, but we need their sizes and offsets
- * to perform 32bit MIB overflow wraparound.
- */
-static const struct yt921x_mib_desc yt921x_mib_descs[] = {
- MIB_DESC(1, YT921X_MIB_DATA_RX_BROADCAST, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_PAUSE, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_MULTICAST, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_CRC_ERR, NULL),
-
- MIB_DESC(1, YT921X_MIB_DATA_RX_ALIGN_ERR, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_UNDERSIZE_ERR, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_FRAG_ERR, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_64, NULL),
-
- MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_65_TO_127, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_128_TO_255, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_256_TO_511, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_512_TO_1023, NULL),
-
- MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_1024_TO_1518, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_1519_TO_MAX, NULL),
- MIB_DESC(2, YT921X_MIB_DATA_RX_GOOD_BYTES, NULL),
-
- MIB_DESC(2, YT921X_MIB_DATA_RX_BAD_BYTES, "RxBadBytes"),
- MIB_DESC(1, YT921X_MIB_DATA_RX_OVERSIZE_ERR, NULL),
-
- MIB_DESC(1, YT921X_MIB_DATA_RX_DROPPED, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_BROADCAST, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_PAUSE, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_MULTICAST, NULL),
-
- MIB_DESC(1, YT921X_MIB_DATA_TX_UNDERSIZE_ERR, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_64, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_65_TO_127, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_128_TO_255, NULL),
-
- MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_256_TO_511, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_512_TO_1023, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_1024_TO_1518, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_1519_TO_MAX, NULL),
-
- MIB_DESC(2, YT921X_MIB_DATA_TX_GOOD_BYTES, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_COLLISION, NULL),
-
- MIB_DESC(1, YT921X_MIB_DATA_TX_EXCESSIVE_COLLISION, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_MULTIPLE_COLLISION, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_SINGLE_COLLISION, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_PKT, NULL),
-
- MIB_DESC(1, YT921X_MIB_DATA_TX_DEFERRED, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_TX_LATE_COLLISION, NULL),
- MIB_DESC(1, YT921X_MIB_DATA_RX_OAM, "RxOAM"),
- MIB_DESC(1, YT921X_MIB_DATA_TX_OAM, "TxOAM"),
-};
-
static const struct yt921x_info yt921x_infos[] = {
{
"YT9215SC", YT9215_MAJOR, 1, 0,
@@ -146,14 +80,6 @@ static const struct yt921x_info yt921x_infos[] = {
#define YT921X_VID_UNWARE 4095
-/* The interval should be small enough to avoid overflow of 32bit MIBs.
- *
- * Until we can read MIBs from stats64 call directly (i.e. sleep
- * there), we have to poll stats more frequently then it is actually needed.
- * For overflow protection, normally, 100 sec interval should have been OK.
- */
-#define YT921X_STATS_INTERVAL_JIFFIES (3 * HZ)
-
struct yt921x_reg_mdio {
struct mii_bus *bus;
int addr;
@@ -265,327 +191,6 @@ static const struct yt921x_reg_ops yt921x_reg_ops_mdio = {
/* TODO: SPI/I2C */
-/* Read and handle overflow of 32bit MIBs. MIB buffer must be zeroed before. */
-static int yt921x_mib_read(struct yt921x_priv *priv, int port)
-{
- struct device *dev = yt921x_priv_to_device(priv);
- struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *pm = pp->mib;
- struct yt921x_mib_stats *mib;
- int res = 0;
-
- mib = &pm->stats;
-
- /* Reading of yt921x_mib_stats is not protected by a lock and it's vain
- * to keep its consistency, since we have to read registers one by one
- * and there is no way to make a snapshot of MIB stats.
- *
- * Writing (by this function only) is and should be protected by
- * reg_lock.
- */
-
- for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
- const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
- u32 reg = YT921X_MIBn_DATA0(port) + desc->offset;
- u64 *valp = &((u64 *)mib)[i];
- u32 val0;
- u64 val;
-
- res = yt921x_reg_read(priv, reg, &val0);
- if (res)
- break;
-
- if (desc->size <= 1) {
- u64 old_val = *valp;
-
- val = (old_val & ~(u64)U32_MAX) | val0;
- if (val < old_val)
- val += 1ull << 32;
- } else {
- u32 val1;
-
- res = yt921x_reg_read(priv, reg + 4, &val1);
- if (res)
- break;
- val = ((u64)val1 << 32) | val0;
- }
-
- WRITE_ONCE(*valp, val);
- }
-
- pm->rx_frames = mib->rx_64byte + mib->rx_65_127byte +
- mib->rx_128_255byte + mib->rx_256_511byte +
- mib->rx_512_1023byte + mib->rx_1024_1518byte +
- mib->rx_jumbo;
- pm->tx_frames = mib->tx_64byte + mib->tx_65_127byte +
- mib->tx_128_255byte + mib->tx_256_511byte +
- mib->tx_512_1023byte + mib->tx_1024_1518byte +
- mib->tx_jumbo;
-
- if (res)
- dev_err(dev, "Failed to %s port %d: %i\n", "read stats for",
- port, res);
- return res;
-}
-
-static void yt921x_mib_poll(struct work_struct *work)
-{
- struct yt921x_mib *pm = container_of_const(work, struct yt921x_mib,
- work.work);
- struct yt921x_port *pp = pm->port;
- unsigned long delay = YT921X_STATS_INTERVAL_JIFFIES;
- struct yt921x_priv *priv = yt921x_port_to_priv(pp);
- int port = pp->index;
- int res;
-
- mutex_lock(&priv->reg_lock);
- res = yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
- if (res)
- delay *= 4;
-
- schedule_delayed_work(&pm->work, delay);
-}
-
-static void
-yt921x_dsa_get_strings(struct dsa_switch *ds, int port, u32 stringset,
- uint8_t *data)
-{
- if (stringset != ETH_SS_STATS)
- return;
-
- for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
- const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
-
- if (desc->name)
- ethtool_puts(&data, desc->name);
- }
-}
-
-static void
-yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
-{
- struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *pm = pp->mib;
- struct yt921x_mib_stats *mib;
- size_t j;
-
- if (!pm)
- return;
- mib = &pm->stats;
-
- mutex_lock(&priv->reg_lock);
- yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
-
- j = 0;
- for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
- const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
-
- if (!desc->name)
- continue;
-
- data[j] = ((u64 *)mib)[i];
- j++;
- }
-}
-
-static int yt921x_dsa_get_sset_count(struct dsa_switch *ds, int port, int sset)
-{
- int cnt = 0;
-
- if (sset != ETH_SS_STATS)
- return 0;
-
- for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
- const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
-
- if (desc->name)
- cnt++;
- }
-
- return cnt;
-}
-
-static void
-yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
- struct ethtool_eth_mac_stats *mac_stats)
-{
- struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *pm = pp->mib;
- struct yt921x_mib_stats *mib;
-
- if (!pm)
- return;
- mib = &pm->stats;
-
- mutex_lock(&priv->reg_lock);
- yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
-
- mac_stats->FramesTransmittedOK = pm->tx_frames;
- mac_stats->SingleCollisionFrames = mib->tx_single_collisions;
- mac_stats->MultipleCollisionFrames = mib->tx_multiple_collisions;
- mac_stats->FramesReceivedOK = pm->rx_frames;
- mac_stats->FrameCheckSequenceErrors = mib->rx_crc_errors;
- mac_stats->AlignmentErrors = mib->rx_alignment_errors;
- mac_stats->OctetsTransmittedOK = mib->tx_good_bytes;
- mac_stats->FramesWithDeferredXmissions = mib->tx_deferred;
- mac_stats->LateCollisions = mib->tx_late_collisions;
- mac_stats->FramesAbortedDueToXSColls = mib->tx_aborted_errors;
- /* mac_stats->FramesLostDueToIntMACXmitError */
- /* mac_stats->CarrierSenseErrors */
- mac_stats->OctetsReceivedOK = mib->rx_good_bytes;
- /* mac_stats->FramesLostDueToIntMACRcvError */
- mac_stats->MulticastFramesXmittedOK = mib->tx_multicast;
- mac_stats->BroadcastFramesXmittedOK = mib->tx_broadcast;
- /* mac_stats->FramesWithExcessiveDeferral */
- mac_stats->MulticastFramesReceivedOK = mib->rx_multicast;
- mac_stats->BroadcastFramesReceivedOK = mib->rx_broadcast;
- /* mac_stats->InRangeLengthErrors */
- /* mac_stats->OutOfRangeLengthField */
- mac_stats->FrameTooLongErrors = mib->rx_oversize_errors;
-}
-
-static void
-yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
- struct ethtool_eth_ctrl_stats *ctrl_stats)
-{
- struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *pm = pp->mib;
- struct yt921x_mib_stats *mib;
-
- if (!pm)
- return;
- mib = &pm->stats;
-
- mutex_lock(&priv->reg_lock);
- yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
-
- ctrl_stats->MACControlFramesTransmitted = mib->tx_pause;
- ctrl_stats->MACControlFramesReceived = mib->rx_pause;
- /* ctrl_stats->UnsupportedOpcodesReceived */
-}
-
-static const struct ethtool_rmon_hist_range yt921x_rmon_ranges[] = {
- { 0, 64 },
- { 65, 127 },
- { 128, 255 },
- { 256, 511 },
- { 512, 1023 },
- { 1024, 1518 },
- { 1519, YT921X_FRAME_SIZE_MAX },
- {}
-};
-
-static void
-yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
- struct ethtool_rmon_stats *rmon_stats,
- const struct ethtool_rmon_hist_range **ranges)
-{
- struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *pm = pp->mib;
- struct yt921x_mib_stats *mib;
-
- if (!pm)
- return;
- mib = &pm->stats;
-
- mutex_lock(&priv->reg_lock);
- yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
-
- *ranges = yt921x_rmon_ranges;
-
- rmon_stats->undersize_pkts = mib->rx_undersize_errors;
- rmon_stats->oversize_pkts = mib->rx_oversize_errors;
- rmon_stats->fragments = mib->rx_alignment_errors;
- /* rmon_stats->jabbers */
-
- rmon_stats->hist[0] = mib->rx_64byte;
- rmon_stats->hist[1] = mib->rx_65_127byte;
- rmon_stats->hist[2] = mib->rx_128_255byte;
- rmon_stats->hist[3] = mib->rx_256_511byte;
- rmon_stats->hist[4] = mib->rx_512_1023byte;
- rmon_stats->hist[5] = mib->rx_1024_1518byte;
- rmon_stats->hist[6] = mib->rx_jumbo;
-
- rmon_stats->hist_tx[0] = mib->tx_64byte;
- rmon_stats->hist_tx[1] = mib->tx_65_127byte;
- rmon_stats->hist_tx[2] = mib->tx_128_255byte;
- rmon_stats->hist_tx[3] = mib->tx_256_511byte;
- rmon_stats->hist_tx[4] = mib->tx_512_1023byte;
- rmon_stats->hist_tx[5] = mib->tx_1024_1518byte;
- rmon_stats->hist_tx[6] = mib->tx_jumbo;
-}
-
-static void
-yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
- struct rtnl_link_stats64 *stats)
-{
- struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *pm = pp->mib;
- struct yt921x_mib_stats *mib;
-
- if (!pm)
- return;
- mib = &pm->stats;
-
- stats->rx_length_errors = mib->rx_undersize_errors +
- mib->rx_fragment_errors;
- stats->rx_over_errors = mib->rx_oversize_errors;
- stats->rx_crc_errors = mib->rx_crc_errors;
- stats->rx_frame_errors = mib->rx_alignment_errors;
- /* stats->rx_fifo_errors */
- /* stats->rx_missed_errors */
-
- stats->tx_aborted_errors = mib->tx_aborted_errors;
- /* stats->tx_carrier_errors */
- stats->tx_fifo_errors = mib->tx_undersize_errors;
- /* stats->tx_heartbeat_errors */
- stats->tx_window_errors = mib->tx_late_collisions;
-
- stats->rx_packets = pm->rx_frames;
- stats->tx_packets = pm->tx_frames;
- stats->rx_bytes = mib->rx_good_bytes - ETH_FCS_LEN * stats->rx_packets;
- stats->tx_bytes = mib->tx_good_bytes - ETH_FCS_LEN * stats->tx_packets;
- stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors +
- stats->rx_crc_errors + stats->rx_frame_errors;
- stats->tx_errors = stats->tx_aborted_errors + stats->tx_fifo_errors +
- stats->tx_window_errors;
- stats->rx_dropped = mib->rx_dropped;
- /* stats->tx_dropped */
- stats->multicast = mib->rx_multicast;
- stats->collisions = mib->tx_collisions;
-}
-
-static void
-yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
- struct ethtool_pause_stats *pause_stats)
-{
- struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
- struct yt921x_port *pp = &priv->ports[port];
- struct yt921x_mib *pm = pp->mib;
- struct yt921x_mib_stats *mib;
-
- if (!pm)
- return;
- mib = &pm->stats;
-
- mutex_lock(&priv->reg_lock);
- yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
-
- pause_stats->tx_pause_frames = mib->tx_pause;
- pause_stats->rx_pause_frames = mib->rx_pause;
-}
-
static int
yt921x_set_eee(struct yt921x_priv *priv, int port, struct ethtool_keee *e)
{
diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/chip.h
index d1764b635630..25ff77054de3 100644
--- a/drivers/net/dsa/motorcomm/chip.h
+++ b/drivers/net/dsa/motorcomm/chip.h
@@ -163,69 +163,6 @@ enum yt921x_speed {
#define YT921X_EEE_CTRL 0xb0000
#define YT921X_EEE_CTRL_ENn(port) BIT(port)
-#define YT921X_MIB_CTRL 0xc0004
-#define YT921X_MIB_CTRL_CLEAN BIT(30)
-#define YT921X_MIB_CTRL_PORT_M GENMASK(6, 3)
-#define YT921X_MIB_CTRL_PORT(x) FIELD_PREP(YT921X_MIB_CTRL_PORT_M, (x))
-#define YT921X_MIB_CTRL_ONE_PORT BIT(1)
-#define YT921X_MIB_CTRL_ALL_PORT BIT(0)
-#define YT921X_MIBn_DATA0(port) (0xc0100 + 0x100 * (port))
-#define YT921X_MIBn_DATAm(port, x) (YT921X_MIBn_DATA0(port) + 4 * (x))
-#define YT921X_MIB_DATA_RX_BROADCAST 0x00
-#define YT921X_MIB_DATA_RX_PAUSE 0x04
-#define YT921X_MIB_DATA_RX_MULTICAST 0x08
-#define YT921X_MIB_DATA_RX_CRC_ERR 0x0c
-
-#define YT921X_MIB_DATA_RX_ALIGN_ERR 0x10
-#define YT921X_MIB_DATA_RX_UNDERSIZE_ERR 0x14
-#define YT921X_MIB_DATA_RX_FRAG_ERR 0x18
-#define YT921X_MIB_DATA_RX_PKT_SZ_64 0x1c
-
-#define YT921X_MIB_DATA_RX_PKT_SZ_65_TO_127 0x20
-#define YT921X_MIB_DATA_RX_PKT_SZ_128_TO_255 0x24
-#define YT921X_MIB_DATA_RX_PKT_SZ_256_TO_511 0x28
-#define YT921X_MIB_DATA_RX_PKT_SZ_512_TO_1023 0x2c
-
-#define YT921X_MIB_DATA_RX_PKT_SZ_1024_TO_1518 0x30
-#define YT921X_MIB_DATA_RX_PKT_SZ_1519_TO_MAX 0x34
-/* 0x38: unused */
-#define YT921X_MIB_DATA_RX_GOOD_BYTES 0x3c
-
-/* 0x40: 64 bytes */
-#define YT921X_MIB_DATA_RX_BAD_BYTES 0x44
-/* 0x48: 64 bytes */
-#define YT921X_MIB_DATA_RX_OVERSIZE_ERR 0x4c
-
-#define YT921X_MIB_DATA_RX_DROPPED 0x50
-#define YT921X_MIB_DATA_TX_BROADCAST 0x54
-#define YT921X_MIB_DATA_TX_PAUSE 0x58
-#define YT921X_MIB_DATA_TX_MULTICAST 0x5c
-
-#define YT921X_MIB_DATA_TX_UNDERSIZE_ERR 0x60
-#define YT921X_MIB_DATA_TX_PKT_SZ_64 0x64
-#define YT921X_MIB_DATA_TX_PKT_SZ_65_TO_127 0x68
-#define YT921X_MIB_DATA_TX_PKT_SZ_128_TO_255 0x6c
-
-#define YT921X_MIB_DATA_TX_PKT_SZ_256_TO_511 0x70
-#define YT921X_MIB_DATA_TX_PKT_SZ_512_TO_1023 0x74
-#define YT921X_MIB_DATA_TX_PKT_SZ_1024_TO_1518 0x78
-#define YT921X_MIB_DATA_TX_PKT_SZ_1519_TO_MAX 0x7c
-
-/* 0x80: unused */
-#define YT921X_MIB_DATA_TX_GOOD_BYTES 0x84
-/* 0x88: 64 bytes */
-#define YT921X_MIB_DATA_TX_COLLISION 0x8c
-
-#define YT921X_MIB_DATA_TX_EXCESSIVE_COLLISION 0x90
-#define YT921X_MIB_DATA_TX_MULTIPLE_COLLISION 0x94
-#define YT921X_MIB_DATA_TX_SINGLE_COLLISION 0x98
-#define YT921X_MIB_DATA_TX_PKT 0x9c
-
-#define YT921X_MIB_DATA_TX_DEFERRED 0xa0
-#define YT921X_MIB_DATA_TX_LATE_COLLISION 0xa4
-#define YT921X_MIB_DATA_RX_OAM 0xa8
-#define YT921X_MIB_DATA_TX_OAM 0xac
-
#define YT921X_EDATA_CTRL 0xe0000
#define YT921X_EDATA_CTRL_ADDR_M GENMASK(15, 8)
#define YT921X_EDATA_CTRL_ADDR(x) FIELD_PREP(YT921X_EDATA_CTRL_ADDR_M, (x))
@@ -833,67 +770,6 @@ enum yt921x_fdb_entry_status {
#define YT921X_NAME "yt921x"
-struct yt921x_mib_stats {
- u64 rx_broadcast;
- u64 rx_pause;
- u64 rx_multicast;
- u64 rx_crc_errors;
-
- u64 rx_alignment_errors;
- u64 rx_undersize_errors;
- u64 rx_fragment_errors;
- u64 rx_64byte;
-
- u64 rx_65_127byte;
- u64 rx_128_255byte;
- u64 rx_256_511byte;
- u64 rx_512_1023byte;
-
- u64 rx_1024_1518byte;
- u64 rx_jumbo;
- u64 rx_good_bytes;
-
- u64 rx_bad_bytes;
- u64 rx_oversize_errors;
-
- u64 rx_dropped;
- u64 tx_broadcast;
- u64 tx_pause;
- u64 tx_multicast;
-
- u64 tx_undersize_errors;
- u64 tx_64byte;
- u64 tx_65_127byte;
- u64 tx_128_255byte;
-
- u64 tx_256_511byte;
- u64 tx_512_1023byte;
- u64 tx_1024_1518byte;
- u64 tx_jumbo;
-
- u64 tx_good_bytes;
- u64 tx_collisions;
-
- u64 tx_aborted_errors;
- u64 tx_multiple_collisions;
- u64 tx_single_collisions;
- u64 tx_good;
-
- u64 tx_deferred;
- u64 tx_late_collisions;
- u64 rx_oam;
- u64 tx_oam;
-};
-
-struct yt921x_mib {
- struct yt921x_port *port;
-
- struct delayed_work work;
- struct yt921x_mib_stats stats;
- u64 rx_frames;
- u64 tx_frames;
-};
-
struct yt921x_acl_entry {
u32 key[2];
u32 mask[2];
diff --git a/drivers/net/dsa/motorcomm/mib.c b/drivers/net/dsa/motorcomm/mib.c
new file mode 100644
index 000000000000..fd634c8e2c04
--- /dev/null
+++ b/drivers/net/dsa/motorcomm/mib.c
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 David Yang
+ */
+
+#include "chip.h"
+#include "mib.h"
+#include "smi.h"
+
+struct yt921x_mib_desc {
+ unsigned int size;
+ unsigned int offset;
+ const char *name;
+};
+
+#define MIB_DESC(_size, _offset, _name) \
+ {_size, _offset, _name}
+
+/* Must agree with yt921x_mib_stats
+ *
+ * Unstructured fields (name != NULL) will appear in get_ethtool_stats(),
+ * structured go to their *_stats() methods, but we need their sizes and offsets
+ * to perform 32bit MIB overflow wraparound.
+ */
+static const struct yt921x_mib_desc yt921x_mib_descs[] = {
+ MIB_DESC(1, YT921X_MIB_DATA_RX_BROADCAST, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_PAUSE, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_MULTICAST, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_CRC_ERR, NULL),
+
+ MIB_DESC(1, YT921X_MIB_DATA_RX_ALIGN_ERR, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_UNDERSIZE_ERR, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_FRAG_ERR, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_64, NULL),
+
+ MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_65_TO_127, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_128_TO_255, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_256_TO_511, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_512_TO_1023, NULL),
+
+ MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_1024_TO_1518, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_1519_TO_MAX, NULL),
+ MIB_DESC(2, YT921X_MIB_DATA_RX_GOOD_BYTES, NULL),
+
+ MIB_DESC(2, YT921X_MIB_DATA_RX_BAD_BYTES, "RxBadBytes"),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_OVERSIZE_ERR, NULL),
+
+ MIB_DESC(1, YT921X_MIB_DATA_RX_DROPPED, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_BROADCAST, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PAUSE, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_MULTICAST, NULL),
+
+ MIB_DESC(1, YT921X_MIB_DATA_TX_UNDERSIZE_ERR, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_64, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_65_TO_127, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_128_TO_255, NULL),
+
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_256_TO_511, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_512_TO_1023, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_1024_TO_1518, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_1519_TO_MAX, NULL),
+
+ MIB_DESC(2, YT921X_MIB_DATA_TX_GOOD_BYTES, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_COLLISION, NULL),
+
+ MIB_DESC(1, YT921X_MIB_DATA_TX_EXCESSIVE_COLLISION, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_MULTIPLE_COLLISION, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_SINGLE_COLLISION, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_PKT, NULL),
+
+ MIB_DESC(1, YT921X_MIB_DATA_TX_DEFERRED, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_LATE_COLLISION, NULL),
+ MIB_DESC(1, YT921X_MIB_DATA_RX_OAM, "RxOAM"),
+ MIB_DESC(1, YT921X_MIB_DATA_TX_OAM, "TxOAM"),
+};
+
+/* The interval should be small enough to avoid overflow of 32bit MIBs.
+ *
+ * Until we can read MIBs from stats64 call directly (i.e. sleep
+ * there), we have to poll stats more frequently then it is actually needed.
+ * For overflow protection, normally, 100 sec interval should have been OK.
+ */
+#define YT921X_STATS_INTERVAL_JIFFIES (3 * HZ)
+
+/* Read and handle overflow of 32bit MIBs. MIB buffer must be zeroed before. */
+static int yt921x_mib_read(struct yt921x_priv *priv, int port)
+{
+ struct device *dev = yt921x_priv_to_device(priv);
+ struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+ int res = 0;
+
+ mib = &pm->stats;
+
+ /* Reading of yt921x_mib_stats is not protected by a lock and it's vain
+ * to keep its consistency, since we have to read registers one by one
+ * and there is no way to make a snapshot of MIB stats.
+ *
+ * Writing (by this function only) is and should be protected by
+ * reg_lock.
+ */
+
+ for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
+ const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
+ u32 reg = YT921X_MIBn_DATA0(port) + desc->offset;
+ u64 *valp = &((u64 *)mib)[i];
+ u32 val0;
+ u64 val;
+
+ res = yt921x_reg_read(priv, reg, &val0);
+ if (res)
+ break;
+
+ if (desc->size <= 1) {
+ u64 old_val = *valp;
+
+ val = (old_val & ~(u64)U32_MAX) | val0;
+ if (val < old_val)
+ val += 1ull << 32;
+ } else {
+ u32 val1;
+
+ res = yt921x_reg_read(priv, reg + 4, &val1);
+ if (res)
+ break;
+ val = ((u64)val1 << 32) | val0;
+ }
+
+ WRITE_ONCE(*valp, val);
+ }
+
+ pm->rx_frames = mib->rx_64byte + mib->rx_65_127byte +
+ mib->rx_128_255byte + mib->rx_256_511byte +
+ mib->rx_512_1023byte + mib->rx_1024_1518byte +
+ mib->rx_jumbo;
+ pm->tx_frames = mib->tx_64byte + mib->tx_65_127byte +
+ mib->tx_128_255byte + mib->tx_256_511byte +
+ mib->tx_512_1023byte + mib->tx_1024_1518byte +
+ mib->tx_jumbo;
+
+ if (res)
+ dev_err(dev, "Failed to %s port %d: %i\n", "read stats for",
+ port, res);
+ return res;
+}
+
+void yt921x_mib_poll(struct work_struct *work)
+{
+ struct yt921x_mib *pm = container_of_const(work, struct yt921x_mib,
+ work.work);
+ struct yt921x_port *pp = pm->port;
+ unsigned long delay = YT921X_STATS_INTERVAL_JIFFIES;
+ struct yt921x_priv *priv = yt921x_port_to_priv(pp);
+ int port = pp->index;
+ int res;
+
+ mutex_lock(&priv->reg_lock);
+ res = yt921x_mib_read(priv, port);
+ mutex_unlock(&priv->reg_lock);
+ if (res)
+ delay *= 4;
+
+ schedule_delayed_work(&pm->work, delay);
+}
+
+void
+yt921x_dsa_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ uint8_t *data)
+{
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
+ const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
+
+ if (desc->name)
+ ethtool_puts(&data, desc->name);
+ }
+}
+
+void
+yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
+{
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+ size_t j;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
+
+ mutex_lock(&priv->reg_lock);
+ yt921x_mib_read(priv, port);
+ mutex_unlock(&priv->reg_lock);
+
+ j = 0;
+ for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
+ const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
+
+ if (!desc->name)
+ continue;
+
+ data[j] = ((u64 *)mib)[i];
+ j++;
+ }
+}
+
+int yt921x_dsa_get_sset_count(struct dsa_switch *ds, int port, int sset)
+{
+ int cnt = 0;
+
+ if (sset != ETH_SS_STATS)
+ return 0;
+
+ for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
+ const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
+
+ if (desc->name)
+ cnt++;
+ }
+
+ return cnt;
+}
+
+void
+yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
+ struct ethtool_eth_mac_stats *mac_stats)
+{
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
+
+ mutex_lock(&priv->reg_lock);
+ yt921x_mib_read(priv, port);
+ mutex_unlock(&priv->reg_lock);
+
+ mac_stats->FramesTransmittedOK = pm->tx_frames;
+ mac_stats->SingleCollisionFrames = mib->tx_single_collisions;
+ mac_stats->MultipleCollisionFrames = mib->tx_multiple_collisions;
+ mac_stats->FramesReceivedOK = pm->rx_frames;
+ mac_stats->FrameCheckSequenceErrors = mib->rx_crc_errors;
+ mac_stats->AlignmentErrors = mib->rx_alignment_errors;
+ mac_stats->OctetsTransmittedOK = mib->tx_good_bytes;
+ mac_stats->FramesWithDeferredXmissions = mib->tx_deferred;
+ mac_stats->LateCollisions = mib->tx_late_collisions;
+ mac_stats->FramesAbortedDueToXSColls = mib->tx_aborted_errors;
+ /* mac_stats->FramesLostDueToIntMACXmitError */
+ /* mac_stats->CarrierSenseErrors */
+ mac_stats->OctetsReceivedOK = mib->rx_good_bytes;
+ /* mac_stats->FramesLostDueToIntMACRcvError */
+ mac_stats->MulticastFramesXmittedOK = mib->tx_multicast;
+ mac_stats->BroadcastFramesXmittedOK = mib->tx_broadcast;
+ /* mac_stats->FramesWithExcessiveDeferral */
+ mac_stats->MulticastFramesReceivedOK = mib->rx_multicast;
+ mac_stats->BroadcastFramesReceivedOK = mib->rx_broadcast;
+ /* mac_stats->InRangeLengthErrors */
+ /* mac_stats->OutOfRangeLengthField */
+ mac_stats->FrameTooLongErrors = mib->rx_oversize_errors;
+}
+
+void
+yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
+ struct ethtool_eth_ctrl_stats *ctrl_stats)
+{
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
+
+ mutex_lock(&priv->reg_lock);
+ yt921x_mib_read(priv, port);
+ mutex_unlock(&priv->reg_lock);
+
+ ctrl_stats->MACControlFramesTransmitted = mib->tx_pause;
+ ctrl_stats->MACControlFramesReceived = mib->rx_pause;
+ /* ctrl_stats->UnsupportedOpcodesReceived */
+}
+
+static const struct ethtool_rmon_hist_range yt921x_rmon_ranges[] = {
+ { 0, 64 },
+ { 65, 127 },
+ { 128, 255 },
+ { 256, 511 },
+ { 512, 1023 },
+ { 1024, 1518 },
+ { 1519, YT921X_FRAME_SIZE_MAX },
+ {}
+};
+
+void
+yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
+ struct ethtool_rmon_stats *rmon_stats,
+ const struct ethtool_rmon_hist_range **ranges)
+{
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
+
+ mutex_lock(&priv->reg_lock);
+ yt921x_mib_read(priv, port);
+ mutex_unlock(&priv->reg_lock);
+
+ *ranges = yt921x_rmon_ranges;
+
+ rmon_stats->undersize_pkts = mib->rx_undersize_errors;
+ rmon_stats->oversize_pkts = mib->rx_oversize_errors;
+ rmon_stats->fragments = mib->rx_alignment_errors;
+ /* rmon_stats->jabbers */
+
+ rmon_stats->hist[0] = mib->rx_64byte;
+ rmon_stats->hist[1] = mib->rx_65_127byte;
+ rmon_stats->hist[2] = mib->rx_128_255byte;
+ rmon_stats->hist[3] = mib->rx_256_511byte;
+ rmon_stats->hist[4] = mib->rx_512_1023byte;
+ rmon_stats->hist[5] = mib->rx_1024_1518byte;
+ rmon_stats->hist[6] = mib->rx_jumbo;
+
+ rmon_stats->hist_tx[0] = mib->tx_64byte;
+ rmon_stats->hist_tx[1] = mib->tx_65_127byte;
+ rmon_stats->hist_tx[2] = mib->tx_128_255byte;
+ rmon_stats->hist_tx[3] = mib->tx_256_511byte;
+ rmon_stats->hist_tx[4] = mib->tx_512_1023byte;
+ rmon_stats->hist_tx[5] = mib->tx_1024_1518byte;
+ rmon_stats->hist_tx[6] = mib->tx_jumbo;
+}
+
+void
+yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
+ struct rtnl_link_stats64 *stats)
+{
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
+
+ stats->rx_length_errors = mib->rx_undersize_errors +
+ mib->rx_fragment_errors;
+ stats->rx_over_errors = mib->rx_oversize_errors;
+ stats->rx_crc_errors = mib->rx_crc_errors;
+ stats->rx_frame_errors = mib->rx_alignment_errors;
+ /* stats->rx_fifo_errors */
+ /* stats->rx_missed_errors */
+
+ stats->tx_aborted_errors = mib->tx_aborted_errors;
+ /* stats->tx_carrier_errors */
+ stats->tx_fifo_errors = mib->tx_undersize_errors;
+ /* stats->tx_heartbeat_errors */
+ stats->tx_window_errors = mib->tx_late_collisions;
+
+ stats->rx_packets = pm->rx_frames;
+ stats->tx_packets = pm->tx_frames;
+ stats->rx_bytes = mib->rx_good_bytes - ETH_FCS_LEN * stats->rx_packets;
+ stats->tx_bytes = mib->tx_good_bytes - ETH_FCS_LEN * stats->tx_packets;
+ stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors +
+ stats->rx_crc_errors + stats->rx_frame_errors;
+ stats->tx_errors = stats->tx_aborted_errors + stats->tx_fifo_errors +
+ stats->tx_window_errors;
+ stats->rx_dropped = mib->rx_dropped;
+ /* stats->tx_dropped */
+ stats->multicast = mib->rx_multicast;
+ stats->collisions = mib->tx_collisions;
+}
+
+void
+yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
+ struct ethtool_pause_stats *pause_stats)
+{
+ struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
+ struct yt921x_port *pp = &priv->ports[port];
+ struct yt921x_mib *pm = pp->mib;
+ struct yt921x_mib_stats *mib;
+
+ if (!pm)
+ return;
+ mib = &pm->stats;
+
+ mutex_lock(&priv->reg_lock);
+ yt921x_mib_read(priv, port);
+ mutex_unlock(&priv->reg_lock);
+
+ pause_stats->tx_pause_frames = mib->tx_pause;
+ pause_stats->rx_pause_frames = mib->rx_pause;
+}
diff --git a/drivers/net/dsa/motorcomm/mib.h b/drivers/net/dsa/motorcomm/mib.h
new file mode 100644
index 000000000000..cfad0665baae
--- /dev/null
+++ b/drivers/net/dsa/motorcomm/mib.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2026 David Yang
+ */
+
+#ifndef _YT_MIB_H
+#define _YT_MIB_H
+
+#include <net/dsa.h>
+
+#define YT921X_MIB_CTRL 0xc0004
+#define YT921X_MIB_CTRL_CLEAN BIT(30)
+#define YT921X_MIB_CTRL_PORT_M GENMASK(6, 3)
+#define YT921X_MIB_CTRL_PORT(x) FIELD_PREP(YT921X_MIB_CTRL_PORT_M, (x))
+#define YT921X_MIB_CTRL_ONE_PORT BIT(1)
+#define YT921X_MIB_CTRL_ALL_PORT BIT(0)
+#define YT921X_MIBn_DATA0(port) (0xc0100 + 0x100 * (port))
+#define YT921X_MIBn_DATAm(port, x) (YT921X_MIBn_DATA0(port) + 4 * (x))
+#define YT921X_MIB_DATA_RX_BROADCAST 0x00
+#define YT921X_MIB_DATA_RX_PAUSE 0x04
+#define YT921X_MIB_DATA_RX_MULTICAST 0x08
+#define YT921X_MIB_DATA_RX_CRC_ERR 0x0c
+
+#define YT921X_MIB_DATA_RX_ALIGN_ERR 0x10
+#define YT921X_MIB_DATA_RX_UNDERSIZE_ERR 0x14
+#define YT921X_MIB_DATA_RX_FRAG_ERR 0x18
+#define YT921X_MIB_DATA_RX_PKT_SZ_64 0x1c
+
+#define YT921X_MIB_DATA_RX_PKT_SZ_65_TO_127 0x20
+#define YT921X_MIB_DATA_RX_PKT_SZ_128_TO_255 0x24
+#define YT921X_MIB_DATA_RX_PKT_SZ_256_TO_511 0x28
+#define YT921X_MIB_DATA_RX_PKT_SZ_512_TO_1023 0x2c
+
+#define YT921X_MIB_DATA_RX_PKT_SZ_1024_TO_1518 0x30
+#define YT921X_MIB_DATA_RX_PKT_SZ_1519_TO_MAX 0x34
+/* 0x38: unused */
+#define YT921X_MIB_DATA_RX_GOOD_BYTES 0x3c
+
+/* 0x40: 64 bytes */
+#define YT921X_MIB_DATA_RX_BAD_BYTES 0x44
+/* 0x48: 64 bytes */
+#define YT921X_MIB_DATA_RX_OVERSIZE_ERR 0x4c
+
+#define YT921X_MIB_DATA_RX_DROPPED 0x50
+#define YT921X_MIB_DATA_TX_BROADCAST 0x54
+#define YT921X_MIB_DATA_TX_PAUSE 0x58
+#define YT921X_MIB_DATA_TX_MULTICAST 0x5c
+
+#define YT921X_MIB_DATA_TX_UNDERSIZE_ERR 0x60
+#define YT921X_MIB_DATA_TX_PKT_SZ_64 0x64
+#define YT921X_MIB_DATA_TX_PKT_SZ_65_TO_127 0x68
+#define YT921X_MIB_DATA_TX_PKT_SZ_128_TO_255 0x6c
+
+#define YT921X_MIB_DATA_TX_PKT_SZ_256_TO_511 0x70
+#define YT921X_MIB_DATA_TX_PKT_SZ_512_TO_1023 0x74
+#define YT921X_MIB_DATA_TX_PKT_SZ_1024_TO_1518 0x78
+#define YT921X_MIB_DATA_TX_PKT_SZ_1519_TO_MAX 0x7c
+
+/* 0x80: unused */
+#define YT921X_MIB_DATA_TX_GOOD_BYTES 0x84
+/* 0x88: 64 bytes */
+#define YT921X_MIB_DATA_TX_COLLISION 0x8c
+
+#define YT921X_MIB_DATA_TX_EXCESSIVE_COLLISION 0x90
+#define YT921X_MIB_DATA_TX_MULTIPLE_COLLISION 0x94
+#define YT921X_MIB_DATA_TX_SINGLE_COLLISION 0x98
+#define YT921X_MIB_DATA_TX_PKT 0x9c
+
+#define YT921X_MIB_DATA_TX_DEFERRED 0xa0
+#define YT921X_MIB_DATA_TX_LATE_COLLISION 0xa4
+#define YT921X_MIB_DATA_RX_OAM 0xa8
+#define YT921X_MIB_DATA_TX_OAM 0xac
+
+struct yt921x_mib_stats {
+ u64 rx_broadcast;
+ u64 rx_pause;
+ u64 rx_multicast;
+ u64 rx_crc_errors;
+
+ u64 rx_alignment_errors;
+ u64 rx_undersize_errors;
+ u64 rx_fragment_errors;
+ u64 rx_64byte;
+
+ u64 rx_65_127byte;
+ u64 rx_128_255byte;
+ u64 rx_256_511byte;
+ u64 rx_512_1023byte;
+
+ u64 rx_1024_1518byte;
+ u64 rx_jumbo;
+ u64 rx_good_bytes;
+
+ u64 rx_bad_bytes;
+ u64 rx_oversize_errors;
+
+ u64 rx_dropped;
+ u64 tx_broadcast;
+ u64 tx_pause;
+ u64 tx_multicast;
+
+ u64 tx_undersize_errors;
+ u64 tx_64byte;
+ u64 tx_65_127byte;
+ u64 tx_128_255byte;
+
+ u64 tx_256_511byte;
+ u64 tx_512_1023byte;
+ u64 tx_1024_1518byte;
+ u64 tx_jumbo;
+
+ u64 tx_good_bytes;
+ u64 tx_collisions;
+
+ u64 tx_aborted_errors;
+ u64 tx_multiple_collisions;
+ u64 tx_single_collisions;
+ u64 tx_good;
+
+ u64 tx_deferred;
+ u64 tx_late_collisions;
+ u64 rx_oam;
+ u64 tx_oam;
+};
+
+struct yt921x_mib {
+ struct yt921x_port *port;
+
+ struct delayed_work work;
+ struct yt921x_mib_stats stats;
+ u64 rx_frames;
+ u64 tx_frames;
+};
+
+void yt921x_mib_poll(struct work_struct *work);
+void
+yt921x_dsa_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ uint8_t *data);
+void
+yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
+int yt921x_dsa_get_sset_count(struct dsa_switch *ds, int port, int sset);
+void
+yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
+ struct ethtool_eth_mac_stats *mac_stats);
+void
+yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
+ struct ethtool_eth_ctrl_stats *ctrl_stats);
+void
+yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
+ struct ethtool_rmon_stats *rmon_stats,
+ const struct ethtool_rmon_hist_range **ranges);
+void
+yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
+ struct rtnl_link_stats64 *stats);
+void
+yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
+ struct ethtool_pause_stats *pause_stats);
+
+#endif
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next v5 5/6] net: dsa: motorcomm: Use u64_stats_t for MIB stats
2026-10-04 16:06 [PATCH net-next v5 0/6] net: dsa: motorcomm: MIB fixup David Yang
` (3 preceding siblings ...)
2026-10-04 16:06 ` [PATCH net-next v5 4/6] net: dsa: motorcomm: Split MIB module David Yang
@ 2026-10-04 16:06 ` David Yang
2026-10-04 16:06 ` [PATCH net-next v5 6/6] net: dsa: motorcomm: Fix MIB synchronization David Yang
5 siblings, 0 replies; 7+ messages in thread
From: David Yang @ 2026-10-04 16:06 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel
64-bit variables might not be atomic on 32-bit architectures, and could
lead to load/store tearing.
This is a verbatim change that replaces every u64 statistics into
u64_stats_t. This is not a self-contained fix-all commit: u64_stats_sync
is equipped in the next commit for easy reviewing.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/motorcomm/mib.c | 152 ++++++++++++++++----------------
drivers/net/dsa/motorcomm/mib.h | 104 +++++++++++-----------
2 files changed, 131 insertions(+), 125 deletions(-)
diff --git a/drivers/net/dsa/motorcomm/mib.c b/drivers/net/dsa/motorcomm/mib.c
index fd634c8e2c04..7d83bb3a8a86 100644
--- a/drivers/net/dsa/motorcomm/mib.c
+++ b/drivers/net/dsa/motorcomm/mib.c
@@ -89,22 +89,16 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *pm = pp->mib;
struct yt921x_mib_stats *mib;
+ u64 rx_frames;
+ u64 tx_frames;
int res = 0;
mib = &pm->stats;
- /* Reading of yt921x_mib_stats is not protected by a lock and it's vain
- * to keep its consistency, since we have to read registers one by one
- * and there is no way to make a snapshot of MIB stats.
- *
- * Writing (by this function only) is and should be protected by
- * reg_lock.
- */
-
for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
u32 reg = YT921X_MIBn_DATA0(port) + desc->offset;
- u64 *valp = &((u64 *)mib)[i];
+ u64_stats_t *valp = &((u64_stats_t *)mib)[i];
u32 val0;
u64 val;
@@ -113,7 +107,7 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
break;
if (desc->size <= 1) {
- u64 old_val = *valp;
+ u64 old_val = u64_stats_read(valp);
val = (old_val & ~(u64)U32_MAX) | val0;
if (val < old_val)
@@ -127,17 +121,25 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
val = ((u64)val1 << 32) | val0;
}
- WRITE_ONCE(*valp, val);
+ u64_stats_set(valp, val);
}
- pm->rx_frames = mib->rx_64byte + mib->rx_65_127byte +
- mib->rx_128_255byte + mib->rx_256_511byte +
- mib->rx_512_1023byte + mib->rx_1024_1518byte +
- mib->rx_jumbo;
- pm->tx_frames = mib->tx_64byte + mib->tx_65_127byte +
- mib->tx_128_255byte + mib->tx_256_511byte +
- mib->tx_512_1023byte + mib->tx_1024_1518byte +
- mib->tx_jumbo;
+ rx_frames = u64_stats_read(&mib->rx_64byte) +
+ u64_stats_read(&mib->rx_65_127byte) +
+ u64_stats_read(&mib->rx_128_255byte) +
+ u64_stats_read(&mib->rx_256_511byte) +
+ u64_stats_read(&mib->rx_512_1023byte) +
+ u64_stats_read(&mib->rx_1024_1518byte) +
+ u64_stats_read(&mib->rx_jumbo);
+ tx_frames = u64_stats_read(&mib->tx_64byte) +
+ u64_stats_read(&mib->tx_65_127byte) +
+ u64_stats_read(&mib->tx_128_255byte) +
+ u64_stats_read(&mib->tx_256_511byte) +
+ u64_stats_read(&mib->tx_512_1023byte) +
+ u64_stats_read(&mib->tx_1024_1518byte) +
+ u64_stats_read(&mib->tx_jumbo);
+ u64_stats_set(&pm->rx_frames, rx_frames);
+ u64_stats_set(&pm->tx_frames, tx_frames);
if (res)
dev_err(dev, "Failed to %s port %d: %i\n", "read stats for",
@@ -203,7 +205,7 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
if (!desc->name)
continue;
- data[j] = ((u64 *)mib)[i];
+ data[j] = u64_stats_read(&((u64_stats_t *)mib)[i]);
j++;
}
}
@@ -242,28 +244,28 @@ yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
- mac_stats->FramesTransmittedOK = pm->tx_frames;
- mac_stats->SingleCollisionFrames = mib->tx_single_collisions;
- mac_stats->MultipleCollisionFrames = mib->tx_multiple_collisions;
- mac_stats->FramesReceivedOK = pm->rx_frames;
- mac_stats->FrameCheckSequenceErrors = mib->rx_crc_errors;
- mac_stats->AlignmentErrors = mib->rx_alignment_errors;
- mac_stats->OctetsTransmittedOK = mib->tx_good_bytes;
- mac_stats->FramesWithDeferredXmissions = mib->tx_deferred;
- mac_stats->LateCollisions = mib->tx_late_collisions;
- mac_stats->FramesAbortedDueToXSColls = mib->tx_aborted_errors;
+ mac_stats->FramesTransmittedOK = u64_stats_read(&pm->tx_frames);
+ mac_stats->SingleCollisionFrames = u64_stats_read(&mib->tx_single_collisions);
+ mac_stats->MultipleCollisionFrames = u64_stats_read(&mib->tx_multiple_collisions);
+ mac_stats->FramesReceivedOK = u64_stats_read(&pm->rx_frames);
+ mac_stats->FrameCheckSequenceErrors = u64_stats_read(&mib->rx_crc_errors);
+ mac_stats->AlignmentErrors = u64_stats_read(&mib->rx_alignment_errors);
+ mac_stats->OctetsTransmittedOK = u64_stats_read(&mib->tx_good_bytes);
+ mac_stats->FramesWithDeferredXmissions = u64_stats_read(&mib->tx_deferred);
+ mac_stats->LateCollisions = u64_stats_read(&mib->tx_late_collisions);
+ mac_stats->FramesAbortedDueToXSColls = u64_stats_read(&mib->tx_aborted_errors);
/* mac_stats->FramesLostDueToIntMACXmitError */
/* mac_stats->CarrierSenseErrors */
- mac_stats->OctetsReceivedOK = mib->rx_good_bytes;
+ mac_stats->OctetsReceivedOK = u64_stats_read(&mib->rx_good_bytes);
/* mac_stats->FramesLostDueToIntMACRcvError */
- mac_stats->MulticastFramesXmittedOK = mib->tx_multicast;
- mac_stats->BroadcastFramesXmittedOK = mib->tx_broadcast;
+ mac_stats->MulticastFramesXmittedOK = u64_stats_read(&mib->tx_multicast);
+ mac_stats->BroadcastFramesXmittedOK = u64_stats_read(&mib->tx_broadcast);
/* mac_stats->FramesWithExcessiveDeferral */
- mac_stats->MulticastFramesReceivedOK = mib->rx_multicast;
- mac_stats->BroadcastFramesReceivedOK = mib->rx_broadcast;
+ mac_stats->MulticastFramesReceivedOK = u64_stats_read(&mib->rx_multicast);
+ mac_stats->BroadcastFramesReceivedOK = u64_stats_read(&mib->rx_broadcast);
/* mac_stats->InRangeLengthErrors */
/* mac_stats->OutOfRangeLengthField */
- mac_stats->FrameTooLongErrors = mib->rx_oversize_errors;
+ mac_stats->FrameTooLongErrors = u64_stats_read(&mib->rx_oversize_errors);
}
void
@@ -283,8 +285,8 @@ yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
- ctrl_stats->MACControlFramesTransmitted = mib->tx_pause;
- ctrl_stats->MACControlFramesReceived = mib->rx_pause;
+ ctrl_stats->MACControlFramesTransmitted = u64_stats_read(&mib->tx_pause);
+ ctrl_stats->MACControlFramesReceived = u64_stats_read(&mib->rx_pause);
/* ctrl_stats->UnsupportedOpcodesReceived */
}
@@ -319,26 +321,26 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
*ranges = yt921x_rmon_ranges;
- rmon_stats->undersize_pkts = mib->rx_undersize_errors;
- rmon_stats->oversize_pkts = mib->rx_oversize_errors;
- rmon_stats->fragments = mib->rx_alignment_errors;
+ rmon_stats->undersize_pkts = u64_stats_read(&mib->rx_undersize_errors);
+ rmon_stats->oversize_pkts = u64_stats_read(&mib->rx_oversize_errors);
+ rmon_stats->fragments = u64_stats_read(&mib->rx_alignment_errors);
/* rmon_stats->jabbers */
- rmon_stats->hist[0] = mib->rx_64byte;
- rmon_stats->hist[1] = mib->rx_65_127byte;
- rmon_stats->hist[2] = mib->rx_128_255byte;
- rmon_stats->hist[3] = mib->rx_256_511byte;
- rmon_stats->hist[4] = mib->rx_512_1023byte;
- rmon_stats->hist[5] = mib->rx_1024_1518byte;
- rmon_stats->hist[6] = mib->rx_jumbo;
-
- rmon_stats->hist_tx[0] = mib->tx_64byte;
- rmon_stats->hist_tx[1] = mib->tx_65_127byte;
- rmon_stats->hist_tx[2] = mib->tx_128_255byte;
- rmon_stats->hist_tx[3] = mib->tx_256_511byte;
- rmon_stats->hist_tx[4] = mib->tx_512_1023byte;
- rmon_stats->hist_tx[5] = mib->tx_1024_1518byte;
- rmon_stats->hist_tx[6] = mib->tx_jumbo;
+ rmon_stats->hist[0] = u64_stats_read(&mib->rx_64byte);
+ rmon_stats->hist[1] = u64_stats_read(&mib->rx_65_127byte);
+ rmon_stats->hist[2] = u64_stats_read(&mib->rx_128_255byte);
+ rmon_stats->hist[3] = u64_stats_read(&mib->rx_256_511byte);
+ rmon_stats->hist[4] = u64_stats_read(&mib->rx_512_1023byte);
+ rmon_stats->hist[5] = u64_stats_read(&mib->rx_1024_1518byte);
+ rmon_stats->hist[6] = u64_stats_read(&mib->rx_jumbo);
+
+ rmon_stats->hist_tx[0] = u64_stats_read(&mib->tx_64byte);
+ rmon_stats->hist_tx[1] = u64_stats_read(&mib->tx_65_127byte);
+ rmon_stats->hist_tx[2] = u64_stats_read(&mib->tx_128_255byte);
+ rmon_stats->hist_tx[3] = u64_stats_read(&mib->tx_256_511byte);
+ rmon_stats->hist_tx[4] = u64_stats_read(&mib->tx_512_1023byte);
+ rmon_stats->hist_tx[5] = u64_stats_read(&mib->tx_1024_1518byte);
+ rmon_stats->hist_tx[6] = u64_stats_read(&mib->tx_jumbo);
}
void
@@ -354,32 +356,34 @@ yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
return;
mib = &pm->stats;
- stats->rx_length_errors = mib->rx_undersize_errors +
- mib->rx_fragment_errors;
- stats->rx_over_errors = mib->rx_oversize_errors;
- stats->rx_crc_errors = mib->rx_crc_errors;
- stats->rx_frame_errors = mib->rx_alignment_errors;
+ stats->rx_length_errors = u64_stats_read(&mib->rx_undersize_errors) +
+ u64_stats_read(&mib->rx_fragment_errors);
+ stats->rx_over_errors = u64_stats_read(&mib->rx_oversize_errors);
+ stats->rx_crc_errors = u64_stats_read(&mib->rx_crc_errors);
+ stats->rx_frame_errors = u64_stats_read(&mib->rx_alignment_errors);
/* stats->rx_fifo_errors */
/* stats->rx_missed_errors */
- stats->tx_aborted_errors = mib->tx_aborted_errors;
+ stats->tx_aborted_errors = u64_stats_read(&mib->tx_aborted_errors);
/* stats->tx_carrier_errors */
- stats->tx_fifo_errors = mib->tx_undersize_errors;
+ stats->tx_fifo_errors = u64_stats_read(&mib->tx_undersize_errors);
/* stats->tx_heartbeat_errors */
- stats->tx_window_errors = mib->tx_late_collisions;
-
- stats->rx_packets = pm->rx_frames;
- stats->tx_packets = pm->tx_frames;
- stats->rx_bytes = mib->rx_good_bytes - ETH_FCS_LEN * stats->rx_packets;
- stats->tx_bytes = mib->tx_good_bytes - ETH_FCS_LEN * stats->tx_packets;
+ stats->tx_window_errors = u64_stats_read(&mib->tx_late_collisions);
+
+ stats->rx_packets = u64_stats_read(&pm->rx_frames);
+ stats->tx_packets = u64_stats_read(&pm->tx_frames);
+ stats->rx_bytes = u64_stats_read(&mib->rx_good_bytes) -
+ ETH_FCS_LEN * stats->rx_packets;
+ stats->tx_bytes = u64_stats_read(&mib->tx_good_bytes) -
+ ETH_FCS_LEN * stats->tx_packets;
stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors +
stats->rx_crc_errors + stats->rx_frame_errors;
stats->tx_errors = stats->tx_aborted_errors + stats->tx_fifo_errors +
stats->tx_window_errors;
- stats->rx_dropped = mib->rx_dropped;
+ stats->rx_dropped = u64_stats_read(&mib->rx_dropped);
/* stats->tx_dropped */
- stats->multicast = mib->rx_multicast;
- stats->collisions = mib->tx_collisions;
+ stats->multicast = u64_stats_read(&mib->rx_multicast);
+ stats->collisions = u64_stats_read(&mib->tx_collisions);
}
void
@@ -399,6 +403,6 @@ yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
yt921x_mib_read(priv, port);
mutex_unlock(&priv->reg_lock);
- pause_stats->tx_pause_frames = mib->tx_pause;
- pause_stats->rx_pause_frames = mib->rx_pause;
+ pause_stats->tx_pause_frames = u64_stats_read(&mib->tx_pause);
+ pause_stats->rx_pause_frames = u64_stats_read(&mib->rx_pause);
}
diff --git a/drivers/net/dsa/motorcomm/mib.h b/drivers/net/dsa/motorcomm/mib.h
index cfad0665baae..d84ae2f449ac 100644
--- a/drivers/net/dsa/motorcomm/mib.h
+++ b/drivers/net/dsa/motorcomm/mib.h
@@ -6,6 +6,8 @@
#ifndef _YT_MIB_H
#define _YT_MIB_H
+#include <linux/u64_stats_sync.h>
+
#include <net/dsa.h>
#define YT921X_MIB_CTRL 0xc0004
@@ -72,55 +74,55 @@
#define YT921X_MIB_DATA_TX_OAM 0xac
struct yt921x_mib_stats {
- u64 rx_broadcast;
- u64 rx_pause;
- u64 rx_multicast;
- u64 rx_crc_errors;
-
- u64 rx_alignment_errors;
- u64 rx_undersize_errors;
- u64 rx_fragment_errors;
- u64 rx_64byte;
-
- u64 rx_65_127byte;
- u64 rx_128_255byte;
- u64 rx_256_511byte;
- u64 rx_512_1023byte;
-
- u64 rx_1024_1518byte;
- u64 rx_jumbo;
- u64 rx_good_bytes;
-
- u64 rx_bad_bytes;
- u64 rx_oversize_errors;
-
- u64 rx_dropped;
- u64 tx_broadcast;
- u64 tx_pause;
- u64 tx_multicast;
-
- u64 tx_undersize_errors;
- u64 tx_64byte;
- u64 tx_65_127byte;
- u64 tx_128_255byte;
-
- u64 tx_256_511byte;
- u64 tx_512_1023byte;
- u64 tx_1024_1518byte;
- u64 tx_jumbo;
-
- u64 tx_good_bytes;
- u64 tx_collisions;
-
- u64 tx_aborted_errors;
- u64 tx_multiple_collisions;
- u64 tx_single_collisions;
- u64 tx_good;
-
- u64 tx_deferred;
- u64 tx_late_collisions;
- u64 rx_oam;
- u64 tx_oam;
+ u64_stats_t rx_broadcast;
+ u64_stats_t rx_pause;
+ u64_stats_t rx_multicast;
+ u64_stats_t rx_crc_errors;
+
+ u64_stats_t rx_alignment_errors;
+ u64_stats_t rx_undersize_errors;
+ u64_stats_t rx_fragment_errors;
+ u64_stats_t rx_64byte;
+
+ u64_stats_t rx_65_127byte;
+ u64_stats_t rx_128_255byte;
+ u64_stats_t rx_256_511byte;
+ u64_stats_t rx_512_1023byte;
+
+ u64_stats_t rx_1024_1518byte;
+ u64_stats_t rx_jumbo;
+ u64_stats_t rx_good_bytes;
+
+ u64_stats_t rx_bad_bytes;
+ u64_stats_t rx_oversize_errors;
+
+ u64_stats_t rx_dropped;
+ u64_stats_t tx_broadcast;
+ u64_stats_t tx_pause;
+ u64_stats_t tx_multicast;
+
+ u64_stats_t tx_undersize_errors;
+ u64_stats_t tx_64byte;
+ u64_stats_t tx_65_127byte;
+ u64_stats_t tx_128_255byte;
+
+ u64_stats_t tx_256_511byte;
+ u64_stats_t tx_512_1023byte;
+ u64_stats_t tx_1024_1518byte;
+ u64_stats_t tx_jumbo;
+
+ u64_stats_t tx_good_bytes;
+ u64_stats_t tx_collisions;
+
+ u64_stats_t tx_aborted_errors;
+ u64_stats_t tx_multiple_collisions;
+ u64_stats_t tx_single_collisions;
+ u64_stats_t tx_good;
+
+ u64_stats_t tx_deferred;
+ u64_stats_t tx_late_collisions;
+ u64_stats_t rx_oam;
+ u64_stats_t tx_oam;
};
struct yt921x_mib {
@@ -128,8 +130,8 @@ struct yt921x_mib {
struct delayed_work work;
struct yt921x_mib_stats stats;
- u64 rx_frames;
- u64 tx_frames;
+ u64_stats_t rx_frames;
+ u64_stats_t tx_frames;
};
void yt921x_mib_poll(struct work_struct *work);
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH net-next v5 6/6] net: dsa: motorcomm: Fix MIB synchronization
2026-10-04 16:06 [PATCH net-next v5 0/6] net: dsa: motorcomm: MIB fixup David Yang
` (4 preceding siblings ...)
2026-10-04 16:06 ` [PATCH net-next v5 5/6] net: dsa: motorcomm: Use u64_stats_t for MIB stats David Yang
@ 2026-10-04 16:06 ` David Yang
5 siblings, 0 replies; 7+ messages in thread
From: David Yang @ 2026-10-04 16:06 UTC (permalink / raw)
To: netdev
Cc: David Yang, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Russell King,
linux-kernel
The previous MIB sync was based on the false assumption that 64-bit
variables are always atomic. To fix that:
* .get_stats64() uses u64_stats_sync, together with u64_stats_t;
* others take the free mutex lock if possible.
To minimize time of the write side of u64_stats_sync, a per-port buffer
is used so that all the stat can be written back altogether after all IO
operations.
The odds of this issue are very low and it does not affect the control
flow, while fixing it would require a thorough refactoring (together with
the previous commit), so it may not be worth backporting.
Signed-off-by: David Yang <mmyangfl@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/motorcomm/chip.c | 2 +
drivers/net/dsa/motorcomm/mib.c | 93 ++++++++++++++++++++------------
drivers/net/dsa/motorcomm/mib.h | 6 +++
3 files changed, 66 insertions(+), 35 deletions(-)
diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/chip.c
index 9e3be08b3465..91cc5647f2b6 100644
--- a/drivers/net/dsa/motorcomm/chip.c
+++ b/drivers/net/dsa/motorcomm/chip.c
@@ -19,6 +19,7 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/sort.h>
+#include <linux/u64_stats_sync.h>
#include <net/dsa.h>
#include <net/dscp.h>
@@ -3472,6 +3473,7 @@ static int yt921x_dsa_port_setup(struct dsa_switch *ds, int port)
pp->mib = pm;
pm->port = pp;
+ u64_stats_init(&pm->syncp);
INIT_DELAYED_WORK(&pm->work, yt921x_mib_poll);
/* Start disabled, so that the enable below always pairs with
* either this disable or the one from a previous teardown
diff --git a/drivers/net/dsa/motorcomm/mib.c b/drivers/net/dsa/motorcomm/mib.c
index 7d83bb3a8a86..6b170fc6e187 100644
--- a/drivers/net/dsa/motorcomm/mib.c
+++ b/drivers/net/dsa/motorcomm/mib.c
@@ -74,6 +74,8 @@ static const struct yt921x_mib_desc yt921x_mib_descs[] = {
MIB_DESC(1, YT921X_MIB_DATA_TX_OAM, "TxOAM"),
};
+static_assert(ARRAY_SIZE(yt921x_mib_descs) == YT921X_MIB_STAT_NUM);
+
/* The interval should be small enough to avoid overflow of 32bit MIBs.
*
* Until we can read MIBs from stats64 call directly (i.e. sleep
@@ -89,6 +91,8 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *pm = pp->mib;
struct yt921x_mib_stats *mib;
+ u64 *buf = pm->data;
+ unsigned long flags;
u64 rx_frames;
u64 tx_frames;
int res = 0;
@@ -98,7 +102,6 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i];
u32 reg = YT921X_MIBn_DATA0(port) + desc->offset;
- u64_stats_t *valp = &((u64_stats_t *)mib)[i];
u32 val0;
u64 val;
@@ -107,7 +110,7 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
break;
if (desc->size <= 1) {
- u64 old_val = u64_stats_read(valp);
+ u64 old_val = buf[i];
val = (old_val & ~(u64)U32_MAX) | val0;
if (val < old_val)
@@ -121,9 +124,12 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
val = ((u64)val1 << 32) | val0;
}
- u64_stats_set(valp, val);
+ buf[i] = val;
}
+ flags = u64_stats_update_begin_irqsave(&pm->syncp);
+ for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++)
+ u64_stats_set(&((u64_stats_t *)mib)[i], buf[i]);
rx_frames = u64_stats_read(&mib->rx_64byte) +
u64_stats_read(&mib->rx_65_127byte) +
u64_stats_read(&mib->rx_128_255byte) +
@@ -140,6 +146,7 @@ static int yt921x_mib_read(struct yt921x_priv *priv, int port)
u64_stats_read(&mib->tx_jumbo);
u64_stats_set(&pm->rx_frames, rx_frames);
u64_stats_set(&pm->tx_frames, tx_frames);
+ u64_stats_update_end_irqrestore(&pm->syncp, flags);
if (res)
dev_err(dev, "Failed to %s port %d: %i\n", "read stats for",
@@ -187,16 +194,16 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *pm = pp->mib;
- struct yt921x_mib_stats *mib;
+ u64 *buf;
size_t j;
if (!pm)
return;
- mib = &pm->stats;
+ buf = pm->data;
mutex_lock(&priv->reg_lock);
+
yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
j = 0;
for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) {
@@ -205,9 +212,11 @@ yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
if (!desc->name)
continue;
- data[j] = u64_stats_read(&((u64_stats_t *)mib)[i]);
+ data[j] = buf[i];
j++;
}
+
+ mutex_unlock(&priv->reg_lock);
}
int yt921x_dsa_get_sset_count(struct dsa_switch *ds, int port, int sset)
@@ -241,8 +250,8 @@ yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
mib = &pm->stats;
mutex_lock(&priv->reg_lock);
+
yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
mac_stats->FramesTransmittedOK = u64_stats_read(&pm->tx_frames);
mac_stats->SingleCollisionFrames = u64_stats_read(&mib->tx_single_collisions);
@@ -266,6 +275,8 @@ yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port,
/* mac_stats->InRangeLengthErrors */
/* mac_stats->OutOfRangeLengthField */
mac_stats->FrameTooLongErrors = u64_stats_read(&mib->rx_oversize_errors);
+
+ mutex_unlock(&priv->reg_lock);
}
void
@@ -282,12 +293,14 @@ yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
mib = &pm->stats;
mutex_lock(&priv->reg_lock);
+
yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
ctrl_stats->MACControlFramesTransmitted = u64_stats_read(&mib->tx_pause);
ctrl_stats->MACControlFramesReceived = u64_stats_read(&mib->rx_pause);
/* ctrl_stats->UnsupportedOpcodesReceived */
+
+ mutex_unlock(&priv->reg_lock);
}
static const struct ethtool_rmon_hist_range yt921x_rmon_ranges[] = {
@@ -316,8 +329,8 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
mib = &pm->stats;
mutex_lock(&priv->reg_lock);
+
yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
*ranges = yt921x_rmon_ranges;
@@ -341,6 +354,8 @@ yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port,
rmon_stats->hist_tx[4] = u64_stats_read(&mib->tx_512_1023byte);
rmon_stats->hist_tx[5] = u64_stats_read(&mib->tx_1024_1518byte);
rmon_stats->hist_tx[6] = u64_stats_read(&mib->tx_jumbo);
+
+ mutex_unlock(&priv->reg_lock);
}
void
@@ -351,39 +366,45 @@ yt921x_dsa_get_stats64(struct dsa_switch *ds, int port,
struct yt921x_port *pp = &priv->ports[port];
struct yt921x_mib *pm = pp->mib;
struct yt921x_mib_stats *mib;
+ unsigned int start;
if (!pm)
return;
mib = &pm->stats;
- stats->rx_length_errors = u64_stats_read(&mib->rx_undersize_errors) +
- u64_stats_read(&mib->rx_fragment_errors);
- stats->rx_over_errors = u64_stats_read(&mib->rx_oversize_errors);
- stats->rx_crc_errors = u64_stats_read(&mib->rx_crc_errors);
- stats->rx_frame_errors = u64_stats_read(&mib->rx_alignment_errors);
- /* stats->rx_fifo_errors */
- /* stats->rx_missed_errors */
-
- stats->tx_aborted_errors = u64_stats_read(&mib->tx_aborted_errors);
- /* stats->tx_carrier_errors */
- stats->tx_fifo_errors = u64_stats_read(&mib->tx_undersize_errors);
- /* stats->tx_heartbeat_errors */
- stats->tx_window_errors = u64_stats_read(&mib->tx_late_collisions);
-
- stats->rx_packets = u64_stats_read(&pm->rx_frames);
- stats->tx_packets = u64_stats_read(&pm->tx_frames);
- stats->rx_bytes = u64_stats_read(&mib->rx_good_bytes) -
- ETH_FCS_LEN * stats->rx_packets;
- stats->tx_bytes = u64_stats_read(&mib->tx_good_bytes) -
- ETH_FCS_LEN * stats->tx_packets;
+ do {
+ start = u64_stats_fetch_begin(&pm->syncp);
+
+ stats->rx_length_errors = u64_stats_read(&mib->rx_undersize_errors) +
+ u64_stats_read(&mib->rx_fragment_errors);
+ stats->rx_over_errors = u64_stats_read(&mib->rx_oversize_errors);
+ stats->rx_crc_errors = u64_stats_read(&mib->rx_crc_errors);
+ stats->rx_frame_errors = u64_stats_read(&mib->rx_alignment_errors);
+ /* stats->rx_fifo_errors */
+ /* stats->rx_missed_errors */
+
+ stats->tx_aborted_errors = u64_stats_read(&mib->tx_aborted_errors);
+ /* stats->tx_carrier_errors */
+ stats->tx_fifo_errors = u64_stats_read(&mib->tx_undersize_errors);
+ /* stats->tx_heartbeat_errors */
+ stats->tx_window_errors = u64_stats_read(&mib->tx_late_collisions);
+
+ stats->rx_packets = u64_stats_read(&pm->rx_frames);
+ stats->tx_packets = u64_stats_read(&pm->tx_frames);
+ stats->rx_bytes = u64_stats_read(&mib->rx_good_bytes) -
+ ETH_FCS_LEN * stats->rx_packets;
+ stats->tx_bytes = u64_stats_read(&mib->tx_good_bytes) -
+ ETH_FCS_LEN * stats->tx_packets;
+ stats->rx_dropped = u64_stats_read(&mib->rx_dropped);
+ /* stats->tx_dropped */
+ stats->multicast = u64_stats_read(&mib->rx_multicast);
+ stats->collisions = u64_stats_read(&mib->tx_collisions);
+ } while (u64_stats_fetch_retry(&pm->syncp, start));
+
stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors +
stats->rx_crc_errors + stats->rx_frame_errors;
stats->tx_errors = stats->tx_aborted_errors + stats->tx_fifo_errors +
stats->tx_window_errors;
- stats->rx_dropped = u64_stats_read(&mib->rx_dropped);
- /* stats->tx_dropped */
- stats->multicast = u64_stats_read(&mib->rx_multicast);
- stats->collisions = u64_stats_read(&mib->tx_collisions);
}
void
@@ -400,9 +421,11 @@ yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port,
mib = &pm->stats;
mutex_lock(&priv->reg_lock);
+
yt921x_mib_read(priv, port);
- mutex_unlock(&priv->reg_lock);
pause_stats->tx_pause_frames = u64_stats_read(&mib->tx_pause);
pause_stats->rx_pause_frames = u64_stats_read(&mib->rx_pause);
+
+ mutex_unlock(&priv->reg_lock);
}
diff --git a/drivers/net/dsa/motorcomm/mib.h b/drivers/net/dsa/motorcomm/mib.h
index d84ae2f449ac..9c24a52d46cc 100644
--- a/drivers/net/dsa/motorcomm/mib.h
+++ b/drivers/net/dsa/motorcomm/mib.h
@@ -125,13 +125,19 @@ struct yt921x_mib_stats {
u64_stats_t tx_oam;
};
+#define YT921X_MIB_STAT_NUM (sizeof(struct yt921x_mib_stats) / sizeof(u64_stats_t))
+
struct yt921x_mib {
struct yt921x_port *port;
struct delayed_work work;
+ struct u64_stats_sync syncp;
+ /* writers: priv->reg_lock + syncp; readers: priv->reg_lock or syncp */
struct yt921x_mib_stats stats;
u64_stats_t rx_frames;
u64_stats_t tx_frames;
+ /* protected by priv->reg_lock */
+ u64 data[YT921X_MIB_STAT_NUM];
};
void yt921x_mib_poll(struct work_struct *work);
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-04 16:06 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-04 16:06 [PATCH net-next v5 0/6] net: dsa: motorcomm: MIB fixup David Yang
2026-10-04 16:06 ` [PATCH net-next v5 1/6] net: dsa: motorcomm: Hoist type casting helper into chip.h David Yang
2026-10-04 16:06 ` [PATCH net-next v5 2/6] net: dsa: motorcomm: Rename MIB stuff David Yang
2026-10-04 16:06 ` [PATCH net-next v5 3/6] net: dsa: motorcomm: Split MIB buffers David Yang
2026-10-04 16:06 ` [PATCH net-next v5 4/6] net: dsa: motorcomm: Split MIB module David Yang
2026-10-04 16:06 ` [PATCH net-next v5 5/6] net: dsa: motorcomm: Use u64_stats_t for MIB stats David Yang
2026-10-04 16:06 ` [PATCH net-next v5 6/6] net: dsa: motorcomm: Fix MIB synchronization David Yang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®