rtl83xx_init_stats(priv);
+ ds->configure_vlan_while_not_filtering = true;
+
/* Enable MAC Polling PHY again */
rtl83xx_enable_phy_polling(priv);
pr_debug("Please wait until PHY is settled\n");
pr_debug("%s: %x %d", __func__, (u32) priv, port);
priv->ports[port].enable = true;
+ /* enable inner tagging on egress, do not keep any tags */
+ sw_w32(1, priv->r->vlan_port_tag_sts_ctrl(port));
+
if (dsa_is_cpu_port(ds, port))
return 0;
struct rtl838x_vlan_info info = {};
struct rtl838x_switch_priv *priv = ds->priv;
int v;
- u64 portmask;
pr_debug("%s port %d, vid_end %d, vid_end %d, flags %x\n", __func__,
port, vlan->vid_begin, vlan->vid_end, vlan->flags);
mutex_lock(&priv->reg_mutex);
if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
- for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
- /* Set both inner and outer PVID of the port */
- sw_w32((v << 16) | v, priv->r->vlan_port_pb(port));
- }
+ /* Set both inner and outer PVID of the port */
+ sw_w32((vlan->vid_end << 16) | vlan->vid_end << 2, priv->r->vlan_port_pb(port));
+ priv->ports[port].pvid = vlan->vid_end;
}
- if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED) {
- for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
- /* Get untagged port memberships of this vlan */
- priv->r->vlan_tables_read(v, &info);
- portmask = info.untagged_ports | BIT(port);
- pr_debug("Untagged ports, VLAN %d: %llx\n", v, portmask);
- priv->r->vlan_set_untagged(v, portmask);
- }
- } else {
- for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
- /* Get tagged port memberships of this vlan */
- priv->r->vlan_tables_read(v, &info);
- info.tagged_ports |= BIT(port);
- pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports);
- priv->r->vlan_set_tagged(v, &info);
+ for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
+ /* Get port memberships of this vlan */
+ priv->r->vlan_tables_read(v, &info);
+
+ /* new VLAN? */
+ if (!info.tagged_ports) {
+ info.fid = 0;
+ info.hash_mc_fid = false;
+ info.hash_uc_fid = false;
+ info.profile_id = 0;
}
+
+ /* sanitize untagged_ports - must be a subset */
+ if (info.untagged_ports & ~info.tagged_ports)
+ info.untagged_ports = 0;
+
+ info.tagged_ports |= BIT_ULL(port);
+ if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED)
+ 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);
+
+ priv->r->vlan_set_tagged(v, &info);
+ pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports);
}
mutex_unlock(&priv->reg_mutex);
struct rtl838x_vlan_info info;
struct rtl838x_switch_priv *priv = ds->priv;
int v;
- u64 portmask;
+ u16 pvid;
pr_debug("%s: port %d, vid_end %d, vid_end %d, flags %x\n", __func__,
port, vlan->vid_begin, vlan->vid_end, vlan->flags);
}
mutex_lock(&priv->reg_mutex);
+ pvid = priv->ports[port].pvid;
for (v = vlan->vid_begin; v <= vlan->vid_end; v++) {
- /* Reset both inner and out PVID of the port */
- sw_w32(0, priv->r->vlan_port_pb(port));
-
- if (vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED) {
- /* Get untagged port memberships of this vlan */
- priv->r->vlan_tables_read(v, &info);
- portmask = info.untagged_ports & (~(1ULL << port));
- pr_debug("Untagged ports, VLAN %d: %llx\n", v, portmask);
- priv->r->vlan_set_untagged(v, portmask);
- }
+ /* Reset to default if removing the current PVID */
+ if (v == pvid)
+ sw_w32(0, priv->r->vlan_port_pb(port));
- /* Get tagged port memberships of this vlan */
+ /* Get port memberships of this vlan */
priv->r->vlan_tables_read(v, &info);
- info.tagged_ports &= (~(1ULL << port));
- pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports);
+
+ /* remove port from both tables */
+ info.untagged_ports &= (~BIT_ULL(port));
+ /* always leave vid 1 */
+ if (v != 1)
+ info.tagged_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);
+
priv->r->vlan_set_tagged(v, &info);
+ pr_debug("Tagged ports, VLAN %d: %llx\n", v, info.tagged_ports);
}
mutex_unlock(&priv->reg_mutex);