Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: lan966x: Make sure to insert the vlan tags also in host mode

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>

authored by

Horatiu Vultur and committed by
Paolo Abeni
27eab4c6 f65dca17

+24
+1
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
··· 879 879 lan966x_vlan_port_set_vlan_aware(port, 0); 880 880 lan966x_vlan_port_set_vid(port, HOST_PVID, false, false); 881 881 lan966x_vlan_port_apply(port); 882 + lan966x_vlan_port_rew_host(port); 882 883 883 884 return 0; 884 885 }
+1
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
··· 497 497 bool lan966x_vlan_cpu_member_cpu_vlan_mask(struct lan966x *lan966x, u16 vid); 498 498 void lan966x_vlan_port_set_vlan_aware(struct lan966x_port *port, 499 499 bool vlan_aware); 500 + void lan966x_vlan_port_rew_host(struct lan966x_port *port); 500 501 int lan966x_vlan_port_set_vid(struct lan966x_port *port, 501 502 u16 vid, 502 503 bool pvid,
+1
drivers/net/ethernet/microchip/lan966x/lan966x_switchdev.c
··· 297 297 lan966x_vlan_port_set_vlan_aware(port, false); 298 298 lan966x_vlan_port_set_vid(port, HOST_PVID, false, false); 299 299 lan966x_vlan_port_apply(port); 300 + lan966x_vlan_port_rew_host(port); 300 301 } 301 302 302 303 int lan966x_port_changeupper(struct net_device *dev,
+21
drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c
··· 149 149 port->vlan_aware = vlan_aware; 150 150 } 151 151 152 + /* When the interface is in host mode, the interface should not be vlan aware 153 + * but it should insert all the tags that it gets from the network stack. 154 + * The tags are not in the data of the frame but actually in the skb and the ifh 155 + * is configured already to get this tag. So what we need to do is to update the 156 + * rewriter to insert the vlan tag for all frames which have a vlan tag 157 + * different than 0. 158 + */ 159 + void lan966x_vlan_port_rew_host(struct lan966x_port *port) 160 + { 161 + struct lan966x *lan966x = port->lan966x; 162 + u32 val; 163 + 164 + /* Tag all frames except when VID=0*/ 165 + val = REW_TAG_CFG_TAG_CFG_SET(2); 166 + 167 + /* Update only some bits in the register */ 168 + lan_rmw(val, 169 + REW_TAG_CFG_TAG_CFG, 170 + lan966x, REW_TAG_CFG(port->chip_port)); 171 + } 172 + 152 173 void lan966x_vlan_port_apply(struct lan966x_port *port) 153 174 { 154 175 struct lan966x *lan966x = port->lan966x;