|
|
@@ -1450,6 +1450,20 @@ static int rtl83xx_vlan_prepare(struct dsa_switch *ds, int port,
|
|
|
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 void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
|
|
|
const struct switchdev_obj_port_vlan *vlan)
|
|
|
{
|
|
|
@@ -1468,20 +1482,11 @@ static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
|
|
|
|
|
|
mutex_lock(&priv->reg_mutex);
|
|
|
|
|
|
- if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
|
|
|
- for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
|
|
|
- if (!v)
|
|
|
- continue;
|
|
|
- /* Set both inner and outer PVID of the port */
|
|
|
- priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, v);
|
|
|
- priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, v);
|
|
|
- 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 = vlan->vid_end;
|
|
|
- }
|
|
|
+ for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
|
|
|
+ if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
|
|
|
+ rtl83xx_vlan_set_pvid(priv, port, v);
|
|
|
+ else if (priv->ports[port].pvid == v)
|
|
|
+ rtl83xx_vlan_set_pvid(priv, port, 0);
|
|
|
}
|
|
|
|
|
|
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
|
|
|
@@ -1503,6 +1508,8 @@ static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
|
|
|
info.tagged_ports |= BIT_ULL(port);
|
|
|
if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
|
|
|
info.untagged_ports |= BIT_ULL(port);
|
|
|
+ else
|
|
|
+ info.untagged_ports &= ~BIT_ULL(port);
|
|
|
|
|
|
priv->r->vlan_set_untagged(v, info.untagged_ports);
|
|
|
pr_debug("Untagged ports, VLAN %d: %llx\n", v, info.untagged_ports);
|
|
|
@@ -1537,12 +1544,7 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
|
|
|
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
|
|
|
/* Reset to default if removing the current PVID */
|
|
|
if (v == pvid) {
|
|
|
- priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, 0);
|
|
|
- priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, 0);
|
|
|
- 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);
|
|
|
+ rtl83xx_vlan_set_pvid(priv, port, 0);
|
|
|
}
|
|
|
/* Get port memberships of this vlan */
|
|
|
priv->r->vlan_tables_read(v, &info);
|