]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: dsa: add tag format for MxL862xx switches
authorDaniel Golle <daniel@makrotopia.org>
Sat, 7 Feb 2026 03:07:11 +0000 (03:07 +0000)
committerPaolo Abeni <pabeni@redhat.com>
Wed, 11 Feb 2026 10:27:57 +0000 (11:27 +0100)
Add proprietary special tag format for the MaxLinear MXL862xx family of
switches. While using the same Ethertype as MaxLinear's GSW1xx switches,
the actual tag format differs significantly, hence we need a dedicated
tag driver for that.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Link: https://patch.msgid.link/c64e6ddb6c93a4fac39f9ab9b2d8bf551a2b118d.1770433307.git.daniel@makrotopia.org
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
MAINTAINERS
include/net/dsa.h
net/dsa/Kconfig
net/dsa/Makefile
net/dsa/tag_mxl862xx.c [new file with mode: 0644]

index 608caa55d7d22b638f6333e4e851237d6966f209..0c9b34eda5acb35fd7d01abf698377c56736a86e 100644 (file)
@@ -15631,6 +15631,7 @@ M:      Daniel Golle <daniel@makrotopia.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/net/dsa/maxlinear,mxl862xx.yaml
+F:     net/dsa/tag_mxl862xx.c
 
 MCAN DEVICE DRIVER
 M:     Markus Schneider-Pargmann <msp@baylibre.com>
index 65699036579874fe287aeb65c54006d8d50d2f37..6c17446f3dcc29682e07a70362bae8d8fa6233b0 100644 (file)
@@ -57,6 +57,7 @@ struct tc_action;
 #define DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE    29
 #define DSA_TAG_PROTO_YT921X_VALUE             30
 #define DSA_TAG_PROTO_MXL_GSW1XX_VALUE         31
+#define DSA_TAG_PROTO_MXL862_VALUE             32
 
 enum dsa_tag_protocol {
        DSA_TAG_PROTO_NONE              = DSA_TAG_PROTO_NONE_VALUE,
@@ -91,6 +92,7 @@ enum dsa_tag_protocol {
        DSA_TAG_PROTO_VSC73XX_8021Q     = DSA_TAG_PROTO_VSC73XX_8021Q_VALUE,
        DSA_TAG_PROTO_YT921X            = DSA_TAG_PROTO_YT921X_VALUE,
        DSA_TAG_PROTO_MXL_GSW1XX        = DSA_TAG_PROTO_MXL_GSW1XX_VALUE,
+       DSA_TAG_PROTO_MXL862            = DSA_TAG_PROTO_MXL862_VALUE,
 };
 
 struct dsa_switch;
index f86b30742122fc32e964080a4bb5b9f7a756fa99..5ed8c704636dd7fc6e35ea0835f8e510eecc3d79 100644 (file)
@@ -104,6 +104,13 @@ config NET_DSA_TAG_MTK
          Say Y or M if you want to enable support for tagging frames for
          Mediatek switches.
 
+config NET_DSA_TAG_MXL_862XX
+       tristate "Tag driver for MaxLinear MxL862xx switches"
+       help
+         Say Y or M if you want to enable support for tagging frames for the
+         MaxLinear MxL86252 and MxL86282 switches using their native 8-byte
+         tagging protocol.
+
 config NET_DSA_TAG_MXL_GSW1XX
        tristate "Tag driver for MaxLinear GSW1xx switches"
        help
index 42d173f5a7013ae7539eb441a872b0fc5d8229cd..bf7247759a64a037d10956f2658dbe286f4223f2 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_NET_DSA_TAG_HELLCREEK) += tag_hellcreek.o
 obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
 obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o
 obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
+obj-$(CONFIG_NET_DSA_TAG_MXL_862XX) += tag_mxl862xx.o
 obj-$(CONFIG_NET_DSA_TAG_MXL_GSW1XX) += tag_mxl-gsw1xx.o
 obj-$(CONFIG_NET_DSA_TAG_NONE) += tag_none.o
 obj-$(CONFIG_NET_DSA_TAG_OCELOT) += tag_ocelot.o
diff --git a/net/dsa/tag_mxl862xx.c b/net/dsa/tag_mxl862xx.c
new file mode 100644 (file)
index 0000000..01f2158
--- /dev/null
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DSA Special Tag for MaxLinear 862xx switch chips
+ *
+ * Copyright (C) 2025 Daniel Golle <daniel@makrotopia.org>
+ * Copyright (C) 2024 MaxLinear Inc.
+ */
+
+#include <linux/bitops.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/dsa.h>
+#include "tag.h"
+
+#define MXL862_NAME    "mxl862xx"
+
+#define MXL862_HEADER_LEN      8
+
+/* Word 0 -> EtherType */
+
+/* Word 2 */
+#define MXL862_SUBIF_ID                GENMASK(4, 0)
+
+/* Word 3 */
+#define MXL862_IGP_EGP         GENMASK(3, 0)
+
+static struct sk_buff *mxl862_tag_xmit(struct sk_buff *skb,
+                                      struct net_device *dev)
+{
+       struct dsa_port *dp = dsa_user_to_port(dev);
+       struct dsa_port *cpu_dp = dp->cpu_dp;
+       unsigned int cpu_port, sub_interface;
+       __be16 *mxl862_tag;
+
+       cpu_port = cpu_dp->index;
+
+       /* target port sub-interface ID relative to the CPU port */
+       sub_interface = dp->index + 16 - cpu_port;
+
+       /* provide additional space 'MXL862_HEADER_LEN' bytes */
+       skb_push(skb, MXL862_HEADER_LEN);
+
+       /* shift MAC address to the beginning of the enlarged buffer,
+        * releasing the space required for DSA tag (between MAC address and
+        * Ethertype)
+        */
+       dsa_alloc_etype_header(skb, MXL862_HEADER_LEN);
+
+       /* special tag ingress (from the perspective of the switch) */
+       mxl862_tag = dsa_etype_header_pos_tx(skb);
+       mxl862_tag[0] = htons(ETH_P_MXLGSW);
+       mxl862_tag[1] = 0;
+       mxl862_tag[2] = htons(FIELD_PREP(MXL862_SUBIF_ID, sub_interface));
+       mxl862_tag[3] = htons(FIELD_PREP(MXL862_IGP_EGP, cpu_port));
+
+       return skb;
+}
+
+static struct sk_buff *mxl862_tag_rcv(struct sk_buff *skb,
+                                     struct net_device *dev)
+{
+       __be16 *mxl862_tag;
+       int port;
+
+       if (unlikely(!pskb_may_pull(skb, MXL862_HEADER_LEN))) {
+               dev_warn_ratelimited(&dev->dev, "Cannot pull SKB, packet dropped\n");
+               return NULL;
+       }
+
+       mxl862_tag = dsa_etype_header_pos_rx(skb);
+
+       if (unlikely(mxl862_tag[0] != htons(ETH_P_MXLGSW))) {
+               dev_warn_ratelimited(&dev->dev,
+                                    "Invalid special tag marker, packet dropped, tag: %8ph\n",
+                                    mxl862_tag);
+               return NULL;
+       }
+
+       /* Get source port information */
+       port = FIELD_GET(MXL862_IGP_EGP, ntohs(mxl862_tag[3]));
+       skb->dev = dsa_conduit_find_user(dev, 0, port);
+       if (unlikely(!skb->dev)) {
+               dev_warn_ratelimited(&dev->dev,
+                                    "Invalid source port, packet dropped, tag: %8ph\n",
+                                    mxl862_tag);
+               return NULL;
+       }
+
+       /* remove the MxL862xx special tag between the MAC addresses and the
+        * current ethertype field.
+        */
+       skb_pull_rcsum(skb, MXL862_HEADER_LEN);
+       dsa_strip_etype_header(skb, MXL862_HEADER_LEN);
+
+       return skb;
+}
+
+static const struct dsa_device_ops mxl862_netdev_ops = {
+       .name = MXL862_NAME,
+       .proto = DSA_TAG_PROTO_MXL862,
+       .xmit = mxl862_tag_xmit,
+       .rcv = mxl862_tag_rcv,
+       .needed_headroom = MXL862_HEADER_LEN,
+};
+
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_MXL862, MXL862_NAME);
+MODULE_DESCRIPTION("DSA tag driver for MaxLinear MxL862xx switches");
+MODULE_LICENSE("GPL");
+
+module_dsa_tag_driver(mxl862_netdev_ops);