]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
mediatek: ethernet: fix offload with incompatible dsa tag 23996/head
authorMieczyslaw Nalewaj <namiltd@yahoo.com>
Fri, 3 Jul 2026 20:15:02 +0000 (22:15 +0200)
committerRobert Marko <robimarko@gmail.com>
Sun, 12 Jul 2026 19:29:45 +0000 (21:29 +0200)
DSA copies the driver features to slave device, including offload
capabilities. Once a packet is sent through a DSA slave interface,
according to its features, the kernel does not calculate checksums,
expecting that the HW will fill the gaps. DSA adds the defined DSA
tag and sends the tagged packet through the master device.

Ethertype DSA tags expect the driver to calculate checksum based on the
csum_start/csum_offset. However, mtk_eth_soc does not use that info.
mtk_eth_soc checks the network header and decides if the HW can manage
that packet, unaware that MAC layer now contains an extra DSA tag. When
that tag is the Mediatek CPU tag, offload will work as expected.
When it is an incompatible DSA tag or if DSA is stacking two incompatible
DSA tags, the driver will still count on the HW offload. In this case,
packets are sent to the network with an incorrect checksum.

This patch adds an extra check that disables offloading only for the
RTL8367S switch's RTL8_4 tag, which is known to break MTK checksum
offload. The RTL8_4T (the trailing-tag variant) is not affected because
its rtl8_4t tagger already checksums the frame in software before appending
the tag, so ip_summed is no longer CHECKSUM_PARTIAL by the time this driver
sees it.

This approach avoids an overly conservative whitelist which would
disable offload for every non-Mediatek tag, regardless of whether
that tag is actually incompatible with MTK checksum offload.

Tags for other DSA-capable switches are left untouched by this fix
and are not claimed to be offload-safe.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Signed-off-by: Schneider Azima <Schneider-Azima12@protonmail.com>
Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
Link: https://github.com/openwrt/openwrt/pull/23996
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/generic/hack-6.12/739-net-ethernet-mtk_eth_soc-fix-offload-with-incompatible-.patch [new file with mode: 0644]
target/linux/generic/hack-6.18/739-net-ethernet-mtk_eth_soc-fix-offload-with-incompatible-.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.18/750-net-ethernet-mtk_eth_soc-add-mt7987-support.patch

diff --git a/target/linux/generic/hack-6.12/739-net-ethernet-mtk_eth_soc-fix-offload-with-incompatible-.patch b/target/linux/generic/hack-6.12/739-net-ethernet-mtk_eth_soc-fix-offload-with-incompatible-.patch
new file mode 100644 (file)
index 0000000..a63543b
--- /dev/null
@@ -0,0 +1,89 @@
+From: Mieczyslaw Nalewaj <namiltd@yahoo.com>
+Date: Fri, 3 Jul 2026 22:15:02 +0200
+Subject: [PATCH] net: ethernet: mtk_eth_soc: fix offload with incompatible dsa
+ tag
+
+DSA copies the driver features to slave device, including offload
+capabilities. Once a packet is sent through a DSA slave interface,
+according to its features, the kernel does not calculate checksums,
+expecting that the HW will fill the gaps. DSA adds the defined DSA
+tag and sends the tagged packet through the master device.
+
+Ethertype DSA tags expect the driver to calculate checksum based on the
+csum_start/csum_offset. However, mtk_eth_soc does not use that info.
+mtk_eth_soc checks the network header and decides if the HW can manage
+that packet, unaware that MAC layer now contains an extra DSA tag. When
+that tag is the Mediatek CPU tag, offload will work as expected.
+When it is an incompatible DSA tag or if DSA is stacking two incompatible
+DSA tags, the driver will still count on the HW offload. In this case,
+packets are sent to the network with an incorrect checksum.
+
+This patch adds an extra check that disables offloading only for the
+RTL8367S switch's RTL8_4 tag, which is known to break MTK checksum
+offload. The RTL8_4T (the trailing-tag variant) is not affected because
+its rtl8_4t tagger already checksums the frame in software before appending
+the tag, so ip_summed is no longer CHECKSUM_PARTIAL by the time this driver
+sees it.
+
+This approach avoids an overly conservative whitelist which would
+disable offload for every non-Mediatek tag, regardless of whether
+that tag is actually incompatible with MTK checksum offload.
+
+Tags for other DSA-capable switches are left untouched by this fix
+and are not claimed to be offload-safe.
+
+Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
+Signed-off-by: Schneider Azima <Schneider-Azima12@protonmail.com>
+Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 32 +++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -5021,6 +5021,35 @@ static u16 mtk_select_queue(struct net_d
+       return queue;
+ }
++#if IS_ENABLED(CONFIG_NET_DSA)
++static netdev_features_t mtk_features_check(struct sk_buff *skb,
++                                         struct net_device *dev,
++                                         netdev_features_t features)
++{
++      /* No point in doing any of this if neither checksum nor GSO are
++       * being requested for this frame. We can rule out both by just
++       * checking for CHECKSUM_PARTIAL
++       */
++      if (skb->ip_summed != CHECKSUM_PARTIAL)
++              return features;
++
++      if (netdev_uses_dsa(dev)) {
++              const struct dsa_device_ops *tag_ops = dev->dsa_ptr->tag_ops;
++
++              /* RTL8_4 hides the L2 ethertype this driver relies on for
++               * offload. RTL8_4T (the trailing-tag variant) is unaffected
++               * because its rtl8_4t tagger already checksums the frame in
++               * software before appending the tag, so ip_summed is no longer
++               * CHECKSUM_PARTIAL by the time this driver sees it.
++               */
++              if (tag_ops->proto == DSA_TAG_PROTO_RTL8_4)
++                      features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
++      }
++
++      return features;
++}
++#endif
++
+ static const struct ethtool_ops mtk_ethtool_ops = {
+       .get_link_ksettings     = mtk_get_link_ksettings,
+       .set_link_ksettings     = mtk_set_link_ksettings,
+@@ -5060,6 +5089,9 @@ static const struct net_device_ops mtk_n
+       .ndo_bpf                = mtk_xdp,
+       .ndo_xdp_xmit           = mtk_xdp_xmit,
+       .ndo_select_queue       = mtk_select_queue,
++#if IS_ENABLED(CONFIG_NET_DSA)
++      .ndo_features_check     = mtk_features_check,
++#endif
+ };
+ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
diff --git a/target/linux/generic/hack-6.18/739-net-ethernet-mtk_eth_soc-fix-offload-with-incompatible-.patch b/target/linux/generic/hack-6.18/739-net-ethernet-mtk_eth_soc-fix-offload-with-incompatible-.patch
new file mode 100644 (file)
index 0000000..14cfa62
--- /dev/null
@@ -0,0 +1,89 @@
+From: Mieczyslaw Nalewaj <namiltd@yahoo.com>
+Date: Fri, 3 Jul 2026 22:15:02 +0200
+Subject: [PATCH] net: ethernet: mtk_eth_soc: fix offload with incompatible dsa
+ tag
+
+DSA copies the driver features to slave device, including offload
+capabilities. Once a packet is sent through a DSA slave interface,
+according to its features, the kernel does not calculate checksums,
+expecting that the HW will fill the gaps. DSA adds the defined DSA
+tag and sends the tagged packet through the master device.
+
+Ethertype DSA tags expect the driver to calculate checksum based on the
+csum_start/csum_offset. However, mtk_eth_soc does not use that info.
+mtk_eth_soc checks the network header and decides if the HW can manage
+that packet, unaware that MAC layer now contains an extra DSA tag. When
+that tag is the Mediatek CPU tag, offload will work as expected.
+When it is an incompatible DSA tag or if DSA is stacking two incompatible
+DSA tags, the driver will still count on the HW offload. In this case,
+packets are sent to the network with an incorrect checksum.
+
+This patch adds an extra check that disables offloading only for the
+RTL8367S switch's RTL8_4 tag, which is known to break MTK checksum
+offload. The RTL8_4T (the trailing-tag variant) is not affected because
+its rtl8_4t tagger already checksums the frame in software before appending
+the tag, so ip_summed is no longer CHECKSUM_PARTIAL by the time this driver
+sees it.
+
+This approach avoids an overly conservative whitelist which would
+disable offload for every non-Mediatek tag, regardless of whether
+that tag is actually incompatible with MTK checksum offload.
+
+Tags for other DSA-capable switches are left untouched by this fix
+and are not claimed to be offload-safe.
+
+Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
+Signed-off-by: Schneider Azima <Schneider-Azima12@protonmail.com>
+Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 32 +++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -5092,6 +5092,35 @@ static u16 mtk_select_queue(struct net_d
+       return queue;
+ }
++#if IS_ENABLED(CONFIG_NET_DSA)
++static netdev_features_t mtk_features_check(struct sk_buff *skb,
++                                         struct net_device *dev,
++                                         netdev_features_t features)
++{
++      /* No point in doing any of this if neither checksum nor GSO are
++       * being requested for this frame. We can rule out both by just
++       * checking for CHECKSUM_PARTIAL
++       */
++      if (skb->ip_summed != CHECKSUM_PARTIAL)
++              return features;
++
++      if (netdev_uses_dsa(dev)) {
++              const struct dsa_device_ops *tag_ops = dev->dsa_ptr->tag_ops;
++
++              /* RTL8_4 hides the L2 ethertype this driver relies on for
++               * offload. RTL8_4T (the trailing-tag variant) is unaffected
++               * because its rtl8_4t tagger already checksums the frame in
++               * software before appending the tag, so ip_summed is no longer
++               * CHECKSUM_PARTIAL by the time this driver sees it.
++               */
++              if (tag_ops->proto == DSA_TAG_PROTO_RTL8_4)
++                      features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
++      }
++
++      return features;
++}
++#endif
++
+ static const struct ethtool_ops mtk_ethtool_ops = {
+       .get_link_ksettings     = mtk_get_link_ksettings,
+       .set_link_ksettings     = mtk_set_link_ksettings,
+@@ -5131,6 +5160,9 @@ static const struct net_device_ops mtk_n
+       .ndo_bpf                = mtk_xdp,
+       .ndo_xdp_xmit           = mtk_xdp_xmit,
+       .ndo_select_queue       = mtk_select_queue,
++#if IS_ENABLED(CONFIG_NET_DSA)
++      .ndo_features_check     = mtk_features_check,
++#endif
+ };
+ static int mtk_fill_available_pcs(struct phylink_config *config,
index e60027b97c2bbb019aee6e3a78b136475c692d8c..89905401481ccbf154afb4da4eacf157ccdef4b5 100644 (file)
@@ -126,7 +126,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
                        if (mtk_is_netsys_v1(eth))
                                val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
                        mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
-@@ -6029,6 +6065,37 @@ static const struct mtk_soc_data mt7986_
+@@ -6061,6 +6097,37 @@ static const struct mtk_soc_data mt7986_
        },
  };
  
@@ -164,7 +164,7 @@ Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
  static const struct mtk_soc_data mt7988_data = {
        .reg_map = &mt7988_reg_map,
        .ana_rgc3 = 0x128,
-@@ -6091,6 +6158,7 @@ const struct of_device_id of_mtk_match[]
+@@ -6123,6 +6190,7 @@ const struct of_device_id of_mtk_match[]
        { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data },
        { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data },
        { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data },