]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: lan966x: Make sure to insert the vlan tags also in host mode
authorHoratiu Vultur <horatiu.vultur@microchip.com>
Wed, 28 May 2025 09:36:19 +0000 (11:36 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2025 10:07:17 +0000 (11:07 +0100)
[ Upstream commit 27eab4c644236a9324084a70fe79e511cbd07393 ]

When running these commands on DUT (and similar at the other end)
ip link set dev eth0 up
ip link add link eth0 name eth0.10 type vlan id 10
ip addr add 10.0.0.1/24 dev eth0.10
ip link set dev eth0.10 up
ping 10.0.0.2

The ping will fail.

The reason why is failing is because, the network interfaces for lan966x
have a flag saying that the HW can insert the vlan tags into the
frames(NETIF_F_HW_VLAN_CTAG_TX). Meaning that the frames that are
transmitted don't have the vlan tag inside the skb data, but they have
it inside the skb. We already get that vlan tag and put it in the IFH
but the problem is that we don't configure the HW to rewrite the frame
when the interface is in host mode.
The fix consists in actually configuring the HW to insert the vlan tag
if it is different than 0.

Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Fixes: 6d2c186afa5d ("net: lan966x: Add vlan support.")
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Link: https://patch.msgid.link/20250528093619.3738998-1-horatiu.vultur@microchip.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
drivers/net/ethernet/microchip/lan966x/lan966x_switchdev.c
drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c

index 9ce46588aaf0371ed31b82e8410daf3db67aea86..8c048ffde23d6bcafd6f6b8f38235ca0b14cc38b 100644 (file)
@@ -811,6 +811,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
        lan966x_vlan_port_set_vlan_aware(port, 0);
        lan966x_vlan_port_set_vid(port, HOST_PVID, false, false);
        lan966x_vlan_port_apply(port);
+       lan966x_vlan_port_rew_host(port);
 
        return 0;
 }
index 4ec33999e4df60e7ac6afda2717c5ac62e48af5c..ff5736d2c7a6bdfad48a4ad5e19f9847546da627 100644 (file)
@@ -388,6 +388,7 @@ void lan966x_vlan_port_apply(struct lan966x_port *port);
 bool lan966x_vlan_cpu_member_cpu_vlan_mask(struct lan966x *lan966x, u16 vid);
 void lan966x_vlan_port_set_vlan_aware(struct lan966x_port *port,
                                      bool vlan_aware);
+void lan966x_vlan_port_rew_host(struct lan966x_port *port);
 int lan966x_vlan_port_set_vid(struct lan966x_port *port,
                              u16 vid,
                              bool pvid,
index 1c88120eb291a2bc8efc7982c09af4fab5975c0e..bcb4db76b75cd5c39559f7db7e579d1bf709068d 100644 (file)
@@ -297,6 +297,7 @@ static void lan966x_port_bridge_leave(struct lan966x_port *port,
        lan966x_vlan_port_set_vlan_aware(port, false);
        lan966x_vlan_port_set_vid(port, HOST_PVID, false, false);
        lan966x_vlan_port_apply(port);
+       lan966x_vlan_port_rew_host(port);
 }
 
 int lan966x_port_changeupper(struct net_device *dev,
index 3c44660128daedada078e565419542dce2f5bd8e..ffb245fb7d678639710defac3c7e74e68c00d0c8 100644 (file)
@@ -149,6 +149,27 @@ void lan966x_vlan_port_set_vlan_aware(struct lan966x_port *port,
        port->vlan_aware = vlan_aware;
 }
 
+/* When the interface is in host mode, the interface should not be vlan aware
+ * but it should insert all the tags that it gets from the network stack.
+ * The tags are not in the data of the frame but actually in the skb and the ifh
+ * is configured already to get this tag. So what we need to do is to update the
+ * rewriter to insert the vlan tag for all frames which have a vlan tag
+ * different than 0.
+ */
+void lan966x_vlan_port_rew_host(struct lan966x_port *port)
+{
+       struct lan966x *lan966x = port->lan966x;
+       u32 val;
+
+       /* Tag all frames except when VID=0*/
+       val = REW_TAG_CFG_TAG_CFG_SET(2);
+
+       /* Update only some bits in the register */
+       lan_rmw(val,
+               REW_TAG_CFG_TAG_CFG,
+               lan966x, REW_TAG_CFG(port->chip_port));
+}
+
 void lan966x_vlan_port_apply(struct lan966x_port *port)
 {
        struct lan966x *lan966x = port->lan966x;