[RFC PATCH net-next 08/10] net: dsa: introduce a robust form of MTU cross-chip notifiers
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Date: 2022-08-18 15:50:49
Subsystem:
networking [dsa], networking [general], the rest · Maintainers:
Andrew Lunn, Vladimir Oltean, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Add rollback to the MTU cross-chip change procedure, which allows us to leave the tree in a consistent state at all times. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> --- net/dsa/dsa_priv.h | 3 ++- net/dsa/port.c | 19 +++++++++++++++++-- net/dsa/slave.c | 7 ++++--- 3 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index b4545b9ebb64..6c935f151864 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h@@ -230,7 +230,8 @@ int dsa_port_mst_enable(struct dsa_port *dp, bool on, struct netlink_ext_ack *extack); int dsa_port_vlan_msti(struct dsa_port *dp, const struct switchdev_vlan_msti *msti); -int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu); +void dsa_port_mtu_change(struct dsa_port *dp, int new_mtu); +int dsa_port_mtu_change_robust(struct dsa_port *dp, int new_mtu, int old_mtu); int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, u16 vid); int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 2fec3df65643..4095592c4790 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c@@ -962,14 +962,29 @@ int dsa_port_vlan_msti(struct dsa_port *dp, return ds->ops->vlan_msti_set(ds, *dp->bridge, msti); } -int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu) +void dsa_port_mtu_change(struct dsa_port *dp, int new_mtu) { struct dsa_notifier_mtu_info info = { .dp = dp, .mtu = new_mtu, }; - return dsa_port_notify(dp, DSA_NOTIFIER_MTU, &info); + dsa_port_notify(dp, DSA_NOTIFIER_MTU, &info); +} + +int dsa_port_mtu_change_robust(struct dsa_port *dp, int new_mtu, int old_mtu) +{ + struct dsa_notifier_mtu_info old_info = { + .dp = dp, + .mtu = old_mtu, + }; + struct dsa_notifier_mtu_info info = { + .dp = dp, + .mtu = new_mtu, + }; + + return dsa_port_notify_robust(dp, DSA_NOTIFIER_MTU, &info, + DSA_NOTIFIER_MTU, &old_info); } int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index ad6a6663feeb..02cc1774888a 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c@@ -1810,6 +1810,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) int largest_mtu = 0; int new_master_mtu; int old_master_mtu; + int old_cpu_mtu; int mtu_limit; int cpu_mtu; int err;
@@ -1849,6 +1850,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) * MTU, since that surely isn't either. */ cpu_mtu = largest_mtu; + old_cpu_mtu = old_master_mtu - dsa_tag_protocol_overhead(cpu_dp->tag_ops); /* Start applying stuff */ if (new_master_mtu != old_master_mtu) {
@@ -1859,7 +1861,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) /* We only need to propagate the MTU of the CPU port to * upstream switches, so emit a notifier which updates them. */ - err = dsa_port_mtu_change(cpu_dp, cpu_mtu); + err = dsa_port_mtu_change_robust(cpu_dp, cpu_mtu, old_cpu_mtu); if (err) goto out_cpu_failed; }
@@ -1876,8 +1878,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu) out_port_failed: if (new_master_mtu != old_master_mtu) - dsa_port_mtu_change(cpu_dp, old_master_mtu - - dsa_tag_protocol_overhead(cpu_dp->tag_ops)); + dsa_port_mtu_change(cpu_dp, old_cpu_mtu); out_cpu_failed: if (new_master_mtu != old_master_mtu) dev_set_mtu(master, old_master_mtu);
--
2.34.1