[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220818154911.2973417-4-vladimir.oltean@nxp.com>
Date: Thu, 18 Aug 2022 18:49:04 +0300
From: Vladimir Oltean <vladimir.oltean@....com>
To: netdev@...r.kernel.org
Cc: Andrew Lunn <andrew@...n.ch>,
Vivien Didelot <vivien.didelot@...il.com>,
Florian Fainelli <f.fainelli@...il.com>,
Vladimir Oltean <olteanv@...il.com>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
"Rafael J. Wysocki" <rafael@...nel.org>,
Kevin Hilman <khilman@...nel.org>,
Ulf Hansson <ulf.hansson@...aro.org>,
Len Brown <len.brown@...el.com>, Pavel Machek <pavel@....cz>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Subject: [RFC PATCH net-next 03/10] net: dsa: introduce and use robust form of dsa_broadcast()
Introduce dsa_broadcast_robust(), which uses dsa_tree_notify_robust(),
and convert the bridge join and tag_8021q VLAN add procedures to use
this.
Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
---
net/dsa/dsa2.c | 31 +++++++++++++++++++++++++++++++
net/dsa/dsa_priv.h | 2 ++
net/dsa/port.c | 6 ++++--
net/dsa/tag_8021q.c | 8 ++++----
4 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 50b87419342f..40134ed97980 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -94,6 +94,37 @@ int dsa_broadcast(unsigned long e, void *v)
return err;
}
+/**
+ * dsa_broadcast_robust - Notify all DSA trees in the system, with rollback.
+ * @e: event, must be of type DSA_NOTIFIER_*
+ * @v: event-specific value.
+ * @e_rollback: event, must be of type DSA_NOTIFIER_*
+ * @v_rollback: event-specific value.
+ *
+ * Like dsa_broadcast(), except makes sure that switches are restored to the
+ * previous state in case the notifier call chain fails mid way.
+ */
+int dsa_broadcast_robust(unsigned long e, void *v, unsigned long e_rollback,
+ void *v_rollback)
+{
+ struct dsa_switch_tree *dst;
+ int err = 0;
+
+ list_for_each_entry(dst, &dsa_tree_list, list) {
+ err = dsa_tree_notify_robust(dst, e, v, e_rollback, v_rollback);
+ if (err)
+ goto rollback;
+ }
+
+ return 0;
+
+rollback:
+ list_for_each_entry_continue_reverse(dst, &dsa_tree_list, list)
+ dsa_tree_notify(dst, e_rollback, v_rollback);
+
+ return err;
+}
+
/**
* dsa_lag_map() - Map LAG structure to a linear LAG array
* @dst: Tree in which to record the mapping.
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 9db660aeee93..b4545b9ebb64 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -546,6 +546,8 @@ int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v);
int dsa_tree_notify_robust(struct dsa_switch_tree *dst, unsigned long e,
void *v, unsigned long e_rollback, void *v_rollback);
int dsa_broadcast(unsigned long e, void *v);
+int dsa_broadcast_robust(unsigned long e, void *v, unsigned long e_rollback,
+ void *v_rollback);
int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst,
struct net_device *master,
const struct dsa_device_ops *tag_ops,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 2dd76eb1621c..6aa6402d3ed9 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -480,7 +480,8 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br,
brport_dev = dsa_port_to_bridge_port(dp);
info.bridge = *dp->bridge;
- err = dsa_broadcast(DSA_NOTIFIER_BRIDGE_JOIN, &info);
+ err = dsa_broadcast_robust(DSA_NOTIFIER_BRIDGE_JOIN, &info,
+ DSA_NOTIFIER_BRIDGE_LEAVE, &info);
if (err)
goto out_rollback;
@@ -1738,7 +1739,8 @@ int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast)
};
if (broadcast)
- return dsa_broadcast(DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info);
+ return dsa_broadcast_robust(DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info,
+ DSA_NOTIFIER_TAG_8021Q_VLAN_DEL, &info);
return dsa_port_notify(dp, DSA_NOTIFIER_TAG_8021Q_VLAN_ADD, &info);
}
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index 01a427800797..d20b9590a2e5 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -205,10 +205,10 @@ int dsa_switch_tag_8021q_vlan_add(struct dsa_switch *ds,
struct dsa_port *dp;
int err;
- /* Since we use dsa_broadcast(), there might be other switches in other
- * trees which don't support tag_8021q, so don't return an error.
- * Or they might even support tag_8021q but have not registered yet to
- * use it (maybe they use another tagger currently).
+ /* Since we use dsa_broadcast_robust(), there might be other switches
+ * in other trees which don't support tag_8021q, so don't return an
+ * error. Or they might even support tag_8021q but have not registered
+ * yet to use it (maybe they use another tagger currently).
*/
if (!ds->ops->tag_8021q_vlan_add || !ds->tag_8021q_ctx)
return 0;
--
2.34.1
Powered by blists - more mailing lists