realtek: 5.15: backport VLAN fix
With commita22d359fa5VLAN handling was fixed for kernel 6.6. This restored network connectivity of the devices. For easy testing backport the fix for 5.15 too. Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de> Link: https://github.com/openwrt/openwrt/pull/16391 Signed-off-by: Robert Marko <robimarko@gmail.com> (cherry picked from commit35e13244aa) Signed-off-by: Goetz Goerisch <ggoerisch@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						Sander Vanheule
					
				
			
			
				
	
			
			
			
						parent
						
							8e75eed617
						
					
				
				
					commit
					ace013101c
				
			@@ -109,6 +109,20 @@ static enum dsa_tag_protocol rtl83xx_get_tag_protocol(struct dsa_switch *ds,
 | 
				
			|||||||
	return DSA_TAG_PROTO_TRAILER;
 | 
						return DSA_TAG_PROTO_TRAILER;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rtl83xx_vlan_set_pvid(struct rtl838x_switch_priv *priv,
 | 
				
			||||||
 | 
									  int port, int pvid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Set both inner and outer PVID of the port */
 | 
				
			||||||
 | 
						priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, pvid);
 | 
				
			||||||
 | 
						priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, pvid);
 | 
				
			||||||
 | 
						priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_INNER,
 | 
				
			||||||
 | 
										PBVLAN_MODE_UNTAG_AND_PRITAG);
 | 
				
			||||||
 | 
						priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
 | 
				
			||||||
 | 
										PBVLAN_MODE_UNTAG_AND_PRITAG);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv->ports[port].pvid = pvid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Initialize all VLANS */
 | 
					/* Initialize all VLANS */
 | 
				
			||||||
static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv)
 | 
					static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -132,17 +146,22 @@ static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv)
 | 
				
			|||||||
		info.l2_tunnel_list_id = -1;
 | 
							info.l2_tunnel_list_id = -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Initialize all vlans 0-4095 */
 | 
						/* Initialize normal VLANs 1-4095 */
 | 
				
			||||||
	for (int i = 0; i < MAX_VLANS; i ++)
 | 
						for (int i = 1; i < MAX_VLANS; i ++)
 | 
				
			||||||
		priv->r->vlan_set_tagged(i, &info);
 | 
							priv->r->vlan_set_tagged(i, &info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* reset PVIDs; defaults to 1 on reset */
 | 
						/*
 | 
				
			||||||
	for (int i = 0; i <= priv->ds->num_ports; i++) {
 | 
						 * Initialize the special VLAN 0 and reset PVIDs. The CPU port PVID
 | 
				
			||||||
		priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_INNER, 0);
 | 
						 * is applied to packets from the CPU for untagged destinations,
 | 
				
			||||||
		priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_OUTER, 0);
 | 
						 * regardless if the actual ingress VID. Any port with untagged
 | 
				
			||||||
		priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_INNER, PBVLAN_MODE_UNTAG_AND_PRITAG);
 | 
						 * egress VLAN(s) must therefore be a member of VLAN 0 to support
 | 
				
			||||||
		priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_OUTER, PBVLAN_MODE_UNTAG_AND_PRITAG);
 | 
						 * CPU port as ingress when VLAN filtering is enabled.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						for (int i = 0; i <= priv->cpu_port; i++) {
 | 
				
			||||||
 | 
							rtl83xx_vlan_set_pvid(priv, i, 0);
 | 
				
			||||||
 | 
							info.tagged_ports |= BIT_ULL(i);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						priv->r->vlan_set_tagged(0, &info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set forwarding action based on inner VLAN tag */
 | 
						/* Set forwarding action based on inner VLAN tag */
 | 
				
			||||||
	for (int i = 0; i < priv->cpu_port; i++)
 | 
						for (int i = 0; i < priv->cpu_port; i++)
 | 
				
			||||||
@@ -1405,20 +1424,6 @@ static int rtl83xx_vlan_prepare(struct dsa_switch *ds, int port,
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rtl83xx_vlan_set_pvid(struct rtl838x_switch_priv *priv,
 | 
					 | 
				
			||||||
				  int port, int pvid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	/* Set both inner and outer PVID of the port */
 | 
					 | 
				
			||||||
	priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, pvid);
 | 
					 | 
				
			||||||
	priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, pvid);
 | 
					 | 
				
			||||||
	priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_INNER,
 | 
					 | 
				
			||||||
					PBVLAN_MODE_UNTAG_AND_PRITAG);
 | 
					 | 
				
			||||||
	priv->r->vlan_port_pvidmode_set(port, PBVLAN_TYPE_OUTER,
 | 
					 | 
				
			||||||
					PBVLAN_MODE_UNTAG_AND_PRITAG);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	priv->ports[port].pvid = pvid;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
 | 
					static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
 | 
				
			||||||
			    const struct switchdev_obj_port_vlan *vlan,
 | 
								    const struct switchdev_obj_port_vlan *vlan,
 | 
				
			||||||
			    struct netlink_ext_ack *extack)
 | 
								    struct netlink_ext_ack *extack)
 | 
				
			||||||
@@ -1430,6 +1435,9 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
 | 
				
			|||||||
	pr_debug("%s port %d, vid %d, flags %x\n",
 | 
						pr_debug("%s port %d, vid %d, flags %x\n",
 | 
				
			||||||
		__func__, port, vlan->vid, vlan->flags);
 | 
							__func__, port, vlan->vid, vlan->flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Let no one mess with our special VLAN 0 */
 | 
				
			||||||
 | 
						if (!vlan->vid) return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (vlan->vid > 4095) {
 | 
						if (vlan->vid > 4095) {
 | 
				
			||||||
		dev_err(priv->dev, "VLAN out of range: %d", vlan->vid);
 | 
							dev_err(priv->dev, "VLAN out of range: %d", vlan->vid);
 | 
				
			||||||
		return -ENOTSUPP;
 | 
							return -ENOTSUPP;
 | 
				
			||||||
@@ -1441,10 +1449,20 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&priv->reg_mutex);
 | 
						mutex_lock(&priv->reg_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Realtek switches copy frames as-is to/from the CPU. For a proper
 | 
				
			||||||
 | 
						 * VLAN handling the 12 bit RVID field (= VLAN id) for incoming traffic
 | 
				
			||||||
 | 
						 * and the 1 bit RVID_SEL field (0 = use inner tag, 1 = use outer tag)
 | 
				
			||||||
 | 
						 * for outgoing traffic of the CPU tag structure need to be handled. As
 | 
				
			||||||
 | 
						 * of now no such logic is in place. So for the CPU port keep the fixed
 | 
				
			||||||
 | 
						 * PVID=0 from initial setup in place and ignore all subsequent settings.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (port != priv->cpu_port) {
 | 
				
			||||||
		if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
 | 
							if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
 | 
				
			||||||
			rtl83xx_vlan_set_pvid(priv, port, vlan->vid);
 | 
								rtl83xx_vlan_set_pvid(priv, port, vlan->vid);
 | 
				
			||||||
		else if (priv->ports[port].pvid == vlan->vid)
 | 
							else if (priv->ports[port].pvid == vlan->vid)
 | 
				
			||||||
			rtl83xx_vlan_set_pvid(priv, port, 0);
 | 
								rtl83xx_vlan_set_pvid(priv, port, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get port memberships of this vlan */
 | 
						/* Get port memberships of this vlan */
 | 
				
			||||||
	priv->r->vlan_tables_read(vlan->vid, &info);
 | 
						priv->r->vlan_tables_read(vlan->vid, &info);
 | 
				
			||||||
@@ -1488,6 +1506,9 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
 | 
				
			|||||||
	pr_debug("%s: port %d, vid %d, flags %x\n",
 | 
						pr_debug("%s: port %d, vid %d, flags %x\n",
 | 
				
			||||||
		__func__, port, vlan->vid, vlan->flags);
 | 
							__func__, port, vlan->vid, vlan->flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Let no one mess with our special VLAN 0 */
 | 
				
			||||||
 | 
						if (!vlan->vid) return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (vlan->vid > 4095) {
 | 
						if (vlan->vid > 4095) {
 | 
				
			||||||
		dev_err(priv->dev, "VLAN out of range: %d", vlan->vid);
 | 
							dev_err(priv->dev, "VLAN out of range: %d", vlan->vid);
 | 
				
			||||||
		return -ENOTSUPP;
 | 
							return -ENOTSUPP;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user