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