mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 15:02:32 +00:00
realtek: handle changed flags in VLAN configuration
The port_vlan_add method may be called while a port is already a member of that VLAN, so it needs to be able to handle changed flags. Fix it to properly handle when the PVID or UNTAGGED flag was previously set, but now no longer is. To reduce duplication, move PVID configuration to a separate function. Signed-off-by: Jan Hoffmann <jan@3e8.eu>
This commit is contained in:
parent
5d34fc92ec
commit
8ea27bb959
@ -1450,6 +1450,20 @@ 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 void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
|
static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
|
||||||
const struct switchdev_obj_port_vlan *vlan)
|
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);
|
mutex_lock(&priv->reg_mutex);
|
||||||
|
|
||||||
if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
|
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
|
||||||
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
|
if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
|
||||||
if (!v)
|
rtl83xx_vlan_set_pvid(priv, port, v);
|
||||||
continue;
|
else if (priv->ports[port].pvid == v)
|
||||||
/* Set both inner and outer PVID of the port */
|
rtl83xx_vlan_set_pvid(priv, port, 0);
|
||||||
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++) {
|
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);
|
info.tagged_ports |= BIT_ULL(port);
|
||||||
if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
|
if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
|
||||||
info.untagged_ports |= BIT_ULL(port);
|
info.untagged_ports |= BIT_ULL(port);
|
||||||
|
else
|
||||||
|
info.untagged_ports &= ~BIT_ULL(port);
|
||||||
|
|
||||||
priv->r->vlan_set_untagged(v, info.untagged_ports);
|
priv->r->vlan_set_untagged(v, info.untagged_ports);
|
||||||
pr_debug("Untagged ports, VLAN %d: %llx\n", 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++) {
|
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
|
||||||
/* Reset to default if removing the current PVID */
|
/* Reset to default if removing the current PVID */
|
||||||
if (v == pvid) {
|
if (v == pvid) {
|
||||||
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, 0);
|
rtl83xx_vlan_set_pvid(priv, port, 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);
|
|
||||||
}
|
}
|
||||||
/* Get port memberships of this vlan */
|
/* Get port memberships of this vlan */
|
||||||
priv->r->vlan_tables_read(v, &info);
|
priv->r->vlan_tables_read(v, &info);
|
||||||
|
@ -1434,6 +1434,20 @@ 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)
|
||||||
@ -1456,17 +1470,10 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
|
|||||||
|
|
||||||
mutex_lock(&priv->reg_mutex);
|
mutex_lock(&priv->reg_mutex);
|
||||||
|
|
||||||
if (vlan->flags & BRIDGE_VLAN_INFO_PVID && vlan->vid) {
|
if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
|
||||||
/* Set both inner and outer PVID of the port */
|
rtl83xx_vlan_set_pvid(priv, port, vlan->vid);
|
||||||
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, vlan->vid);
|
else if (priv->ports[port].pvid == vlan->vid)
|
||||||
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_OUTER, vlan->vid);
|
rtl83xx_vlan_set_pvid(priv, port, 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);
|
|
||||||
|
|
||||||
priv->ports[port].pvid = vlan->vid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
||||||
@ -1486,6 +1493,8 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port,
|
|||||||
info.tagged_ports |= BIT_ULL(port);
|
info.tagged_ports |= BIT_ULL(port);
|
||||||
if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
|
if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
|
||||||
info.untagged_ports |= BIT_ULL(port);
|
info.untagged_ports |= BIT_ULL(port);
|
||||||
|
else
|
||||||
|
info.untagged_ports &= ~BIT_ULL(port);
|
||||||
|
|
||||||
priv->r->vlan_set_untagged(vlan->vid, info.untagged_ports);
|
priv->r->vlan_set_untagged(vlan->vid, info.untagged_ports);
|
||||||
pr_debug("Untagged ports, VLAN %d: %llx\n", vlan->vid, info.untagged_ports);
|
pr_debug("Untagged ports, VLAN %d: %llx\n", vlan->vid, info.untagged_ports);
|
||||||
@ -1518,12 +1527,7 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
|
|||||||
|
|
||||||
/* Reset to default if removing the current PVID */
|
/* Reset to default if removing the current PVID */
|
||||||
if (vlan->vid == pvid) {
|
if (vlan->vid == pvid) {
|
||||||
priv->r->vlan_port_pvid_set(port, PBVLAN_TYPE_INNER, 0);
|
rtl83xx_vlan_set_pvid(priv, port, 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);
|
|
||||||
}
|
}
|
||||||
/* 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);
|
||||||
|
Loading…
Reference in New Issue
Block a user