[net-next RFC PATCH v2 2/8] net: dsa: Permit dsa driver to configure additional tagger data

From: Ansuel Smith
Date: Tue Dec 07 2021 - 22:41:00 EST


Permit a dsa driver to configure additional tagger data for the current
active tagger. A new ops is introduced tag_proto_connect() that will be
called on every tagger bind event using the
DSA_NOTIFIER_TAG_PROTO_CONNECT event.

This is used if the driver require to set additional driver or some
handler that the tagger should use to handle special packet.

The dsa driver require to provide explicit support for the current
tagger and to understand the current private data set in the dsa ports.

tag_proto_connect() should parse the tagger proto, check if it does
support it and do the required task to each ports.

An example of this is a dsa driver that supports Ethernet mdio and
require to provide to the tagger a handler function to parse these
packets.

Signed-off-by: Ansuel Smith <ansuelsmth@xxxxxxxxx>
---
include/net/dsa.h | 8 ++++++++
net/dsa/dsa2.c | 11 +++++++++++
net/dsa/dsa_priv.h | 1 +
net/dsa/switch.c | 14 ++++++++++++++
4 files changed, 34 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 33391d74be5c..3af8720e0caf 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -946,6 +946,14 @@ struct dsa_switch_ops {
int (*tag_8021q_vlan_add)(struct dsa_switch *ds, int port, u16 vid,
u16 flags);
int (*tag_8021q_vlan_del)(struct dsa_switch *ds, int port, u16 vid);
+
+ /*
+ * Tagger connect operations. Use this to set special data/handler
+ * for the current tagger set. The function require to provide explicit
+ * support for the current tagger.
+ */
+ int (*tag_proto_connect)(struct dsa_switch *ds,
+ const struct dsa_device_ops *tag_ops);
};

#define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 15566c5ae8ae..15d6c52dbf53 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -1046,6 +1046,7 @@ static void dsa_tree_teardown_lags(struct dsa_switch_tree *dst)
static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst)
{
const struct dsa_device_ops *tag_ops = dst->tag_ops;
+ struct dsa_notifier_tag_proto_info info;
int err;

if (tag_ops->connect) {
@@ -1054,6 +1055,16 @@ static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst)
return err;
}

+ info.tag_ops = tag_ops;
+ err = dsa_tree_notify(dst, DSA_NOTIFIER_TAG_PROTO_CONNECT, &info);
+ if (err && err != -EOPNOTSUPP)
+ goto out_disconnect;
+
+ return 0;
+out_disconnect:
+ if (tag_ops->disconnect)
+ tag_ops->disconnect(dst);
+
return 0;
}

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 3fb2c37c9b88..e69843c4aa6d 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -37,6 +37,7 @@ enum {
DSA_NOTIFIER_VLAN_DEL,
DSA_NOTIFIER_MTU,
DSA_NOTIFIER_TAG_PROTO,
+ DSA_NOTIFIER_TAG_PROTO_CONNECT,
DSA_NOTIFIER_MRP_ADD,
DSA_NOTIFIER_MRP_DEL,
DSA_NOTIFIER_MRP_ADD_RING_ROLE,
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index bb155a16d454..4b7434d709fb 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -647,6 +647,17 @@ static int dsa_switch_change_tag_proto(struct dsa_switch *ds,
return 0;
}

+static int dsa_switch_connect_tag_proto(struct dsa_switch *ds,
+ struct dsa_notifier_tag_proto_info *info)
+{
+ const struct dsa_device_ops *tag_ops = info->tag_ops;
+
+ if (!ds->ops->tag_proto_connect)
+ return -EOPNOTSUPP;
+
+ return ds->ops->tag_proto_connect(ds, tag_ops);
+}
+
static int dsa_switch_mrp_add(struct dsa_switch *ds,
struct dsa_notifier_mrp_info *info)
{
@@ -766,6 +777,9 @@ static int dsa_switch_event(struct notifier_block *nb,
case DSA_NOTIFIER_TAG_PROTO:
err = dsa_switch_change_tag_proto(ds, info);
break;
+ case DSA_NOTIFIER_TAG_PROTO_CONNECT:
+ err = dsa_switch_connect_tag_proto(ds, info);
+ break;
case DSA_NOTIFIER_MRP_ADD:
err = dsa_switch_mrp_add(ds, info);
break;
--
2.32.0