From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit 47c2c0c2312118a478f738503781de1d1a6020d2 ]
On SJA1105P/Q/R/S and SJA1110, the L2 Lookup Table entries contain a maskable "inner/outer tag" bit which means: - when set to 1: match single-outer and double tagged frames - when set to 0: match untagged and single-inner tagged frames - when masked off: match all frames regardless of the type of tag
This driver does not make any meaningful distinction between inner tags (matches on TPID) and outer tags (matches on TPID2). In fact, all VLAN table entries are installed as SJA1110_VLAN_D_TAG, which means that they match on both inner and outer tags.
So it does not make sense that we install FDB entries with the IOTAG bit set to 1.
In VLAN-unaware mode, we set both TPID and TPID2 to 0xdadb, so the switch will see frames as outer-tagged or double-tagged (never inner). So the FDB entries will match if IOTAG is set to 1.
In VLAN-aware mode, we set TPID to 0x8100 and TPID2 to 0x88a8. So the switch will see untagged and 802.1Q-tagged packets as inner-tagged, and 802.1ad-tagged packets as outer-tagged. So untagged and 802.1Q-tagged packets will not match FDB entries if IOTAG is set to 1, but 802.1ad tagged packets will. Strange.
To fix this, simply mask off the IOTAG bit from FDB entries, and make them match regardless of whether the VLAN tag is inner or outer.
Fixes: 1da73821343c ("net: dsa: sja1105: Add FDB operations for P/Q/R/S series") Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/sja1105/sja1105_main.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index e65be1380803..855371fcbf85 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1387,10 +1387,8 @@ int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port, /* Search for an existing entry in the FDB table */ l2_lookup.macaddr = ether_addr_to_u64(addr); l2_lookup.vlanid = vid; - l2_lookup.iotag = SJA1105_S_TAG; l2_lookup.mask_macaddr = GENMASK_ULL(ETH_ALEN * 8 - 1, 0); l2_lookup.mask_vlanid = VLAN_VID_MASK; - l2_lookup.mask_iotag = BIT(0); l2_lookup.destports = BIT(port);
rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP, @@ -1475,10 +1473,8 @@ int sja1105pqrs_fdb_del(struct dsa_switch *ds, int port,
l2_lookup.macaddr = ether_addr_to_u64(addr); l2_lookup.vlanid = vid; - l2_lookup.iotag = SJA1105_S_TAG; l2_lookup.mask_macaddr = GENMASK_ULL(ETH_ALEN * 8 - 1, 0); l2_lookup.mask_vlanid = VLAN_VID_MASK; - l2_lookup.mask_iotag = BIT(0); l2_lookup.destports = BIT(port);
rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,