net: dsa: vsc73xx: introduce tag 8021q for vsc73xx
authorPawel Dembicki <paweldembicki@gmail.com>
Sat, 13 Jul 2024 21:16:13 +0000 (23:16 +0200)
committerJakub Kicinski <kuba@kernel.org>
Mon, 15 Jul 2024 13:55:15 +0000 (06:55 -0700)
This commit introduces a new tagger based on 802.1q tagging.
It's designed for the vsc73xx driver. The VSC73xx family doesn't have
any tag support for the RGMII port, but it could be based on VLANs.

Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://patch.msgid.link/20240713211620.1125910-8-paweldembicki@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/dsa.h
net/dsa/Kconfig
net/dsa/Makefile
net/dsa/tag_vsc73xx_8021q.c [new file with mode: 0644]

index f9ae3ca66b6f19792749367599103244b063c8da..5a5a03a7b4c3ca420a12b7ef8add134681725193 100644 (file)
@@ -53,6 +53,7 @@ struct tc_action;
 #define DSA_TAG_PROTO_RTL8_4T_VALUE            25
 #define DSA_TAG_PROTO_RZN1_A5PSW_VALUE         26
 #define DSA_TAG_PROTO_LAN937X_VALUE            27
+#define DSA_TAG_PROTO_VSC73XX_8021Q_VALUE      28
 
 enum dsa_tag_protocol {
        DSA_TAG_PROTO_NONE              = DSA_TAG_PROTO_NONE_VALUE,
@@ -83,6 +84,7 @@ enum dsa_tag_protocol {
        DSA_TAG_PROTO_RTL8_4T           = DSA_TAG_PROTO_RTL8_4T_VALUE,
        DSA_TAG_PROTO_RZN1_A5PSW        = DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
        DSA_TAG_PROTO_LAN937X           = DSA_TAG_PROTO_LAN937X_VALUE,
+       DSA_TAG_PROTO_VSC73XX_8021Q     = DSA_TAG_PROTO_VSC73XX_8021Q_VALUE,
 };
 
 struct dsa_switch;
index 8d5bf869eb14a15ae4f24d03cd47084bc1ac0600..2dfe9063613feb3251f3ec9f96adc87d2e0cd47a 100644 (file)
@@ -166,6 +166,12 @@ config NET_DSA_TAG_TRAILER
          Say Y or M if you want to enable support for tagging frames at
          with a trailed. e.g. Marvell 88E6060.
 
+config NET_DSA_TAG_VSC73XX_8021Q
+       tristate "Tag driver for Microchip/Vitesse VSC73xx family of switches, using VLAN"
+       help
+         Say Y or M if you want to enable support for tagging frames with a
+         custom VLAN-based header.
+
 config NET_DSA_TAG_XRS700X
        tristate "Tag driver for XRS700x switches"
        help
index 8a1894a4255221deae9e1d129fdb168dc70e9ab5..555c07cfeb71285b1904bb5ffa0ec8702c1267f8 100644 (file)
@@ -37,6 +37,7 @@ obj-$(CONFIG_NET_DSA_TAG_RTL8_4) += tag_rtl8_4.o
 obj-$(CONFIG_NET_DSA_TAG_RZN1_A5PSW) += tag_rzn1_a5psw.o
 obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o
 obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
+obj-$(CONFIG_NET_DSA_TAG_VSC73XX_8021Q) += tag_vsc73xx_8021q.o
 obj-$(CONFIG_NET_DSA_TAG_XRS700X) += tag_xrs700x.o
 
 # for tracing framework to find trace.h
diff --git a/net/dsa/tag_vsc73xx_8021q.c b/net/dsa/tag_vsc73xx_8021q.c
new file mode 100644 (file)
index 0000000..af121a9
--- /dev/null
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/* Copyright (C) 2024 Pawel Dembicki <paweldembicki@gmail.com>
+ */
+#include <linux/dsa/8021q.h>
+
+#include "tag.h"
+#include "tag_8021q.h"
+
+#define VSC73XX_8021Q_NAME "vsc73xx-8021q"
+
+static struct sk_buff *
+vsc73xx_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct dsa_port *dp = dsa_user_to_port(netdev);
+       u16 queue_mapping = skb_get_queue_mapping(skb);
+       u16 tx_vid = dsa_tag_8021q_standalone_vid(dp);
+       u8 pcp;
+
+       if (skb->offload_fwd_mark) {
+               unsigned int bridge_num = dsa_port_bridge_num_get(dp);
+               struct net_device *br = dsa_port_bridge_dev_get(dp);
+
+               if (br_vlan_enabled(br))
+                       return skb;
+
+               tx_vid = dsa_tag_8021q_bridge_vid(bridge_num);
+       }
+
+       pcp = netdev_txq_to_tc(netdev, queue_mapping);
+
+       return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q,
+                             ((pcp << VLAN_PRIO_SHIFT) | tx_vid));
+}
+
+static struct sk_buff *
+vsc73xx_rcv(struct sk_buff *skb, struct net_device *netdev)
+{
+       int src_port = -1, switch_id = -1, vbid = -1, vid = -1;
+
+       dsa_8021q_rcv(skb, &src_port, &switch_id, &vbid, &vid);
+
+       skb->dev = dsa_tag_8021q_find_user(netdev, src_port, switch_id,
+                                          vid, vbid);
+       if (!skb->dev) {
+               dev_warn_ratelimited(&netdev->dev,
+                                    "Couldn't decode source port\n");
+               return NULL;
+       }
+
+       dsa_default_offload_fwd_mark(skb);
+
+       return skb;
+}
+
+static const struct dsa_device_ops vsc73xx_8021q_netdev_ops = {
+       .name                   = VSC73XX_8021Q_NAME,
+       .proto                  = DSA_TAG_PROTO_VSC73XX_8021Q,
+       .xmit                   = vsc73xx_xmit,
+       .rcv                    = vsc73xx_rcv,
+       .needed_headroom        = VLAN_HLEN,
+       .promisc_on_conduit     = true,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DSA tag driver for VSC73XX family of switches, using VLAN");
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_VSC73XX_8021Q, VSC73XX_8021Q_NAME);
+
+module_dsa_tag_driver(vsc73xx_8021q_netdev_ops);