ath25: switch default kernel to 5.15
[openwrt/staging/wigyori.git] / target / linux / realtek / files-5.10 / drivers / net / dsa / rtl83xx / dsa.c
index f08ede730b83cc3412095ce5df501704d1d3d747..bff42b088ad67cf9154d625f6bd6e1d730aacdc9 100644 (file)
@@ -162,11 +162,20 @@ static void rtl83xx_setup_bpdu_traps(struct rtl838x_switch_priv *priv)
                priv->r->set_receive_management_action(i, BPDU, COPY2CPU);
 }
 
+static void rtl83xx_port_set_salrn(struct rtl838x_switch_priv *priv,
+                                  int port, bool enable)
+{
+       int shift = SALRN_PORT_SHIFT(port);
+       int val = enable ? SALRN_MODE_HARDWARE : SALRN_MODE_DISABLED;
+
+       sw_w32_mask(SALRN_MODE_MASK << shift, val << shift,
+                   priv->r->l2_port_new_salrn(port));
+}
+
 static int rtl83xx_setup(struct dsa_switch *ds)
 {
        int i;
        struct rtl838x_switch_priv *priv = ds->priv;
-       u64 port_bitmap = BIT_ULL(priv->cpu_port);
 
        pr_debug("%s called\n", __func__);
 
@@ -177,18 +186,24 @@ static int rtl83xx_setup(struct dsa_switch *ds)
                priv->ports[i].enable = false;
        priv->ports[priv->cpu_port].enable = true;
 
-       /* Isolate ports from each other: traffic only CPU <-> port */
-       /* Setting bit j in register RTL838X_PORT_ISO_CTRL(i) allows
-        * traffic from source port i to destination port j
+       /* Configure ports so they are disabled by default, but once enabled
+        * they will work in isolated mode (only traffic between port and CPU).
         */
        for (i = 0; i < priv->cpu_port; i++) {
                if (priv->ports[i].phy) {
-                       priv->r->set_port_reg_be(BIT_ULL(priv->cpu_port) | BIT_ULL(i),
-                                             priv->r->port_iso_ctrl(i));
-                       port_bitmap |= BIT_ULL(i);
+                       priv->ports[i].pm = BIT_ULL(priv->cpu_port);
+                       priv->r->traffic_set(i, BIT_ULL(i));
                }
        }
-       priv->r->set_port_reg_be(port_bitmap, priv->r->port_iso_ctrl(priv->cpu_port));
+       priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
+
+       /* For standalone ports, forward packets even if a static fdb
+        * entry for the source address exists on another port.
+        */
+       if (priv->r->set_static_move_action) {
+               for (i = 0; i <= priv->cpu_port; i++)
+                       priv->r->set_static_move_action(i, true);
+       }
 
        if (priv->family_id == RTL8380_FAMILY_ID)
                rtl838x_print_matrix();
@@ -205,6 +220,9 @@ static int rtl83xx_setup(struct dsa_switch *ds)
 
        priv->r->l2_learning_setup();
 
+       rtl83xx_port_set_salrn(priv, priv->cpu_port, false);
+       ds->assisted_learning_on_cpu_port = true;
+
        /*
         *  Make sure all frames sent to the switch's MAC are trapped to the CPU-port
         *  0: FWD, 1: DROP, 2: TRAP2CPU
@@ -227,7 +245,6 @@ static int rtl93xx_setup(struct dsa_switch *ds)
 {
        int i;
        struct rtl838x_switch_priv *priv = ds->priv;
-       u32 port_bitmap = BIT(priv->cpu_port);
 
        pr_info("%s called\n", __func__);
 
@@ -245,13 +262,16 @@ static int rtl93xx_setup(struct dsa_switch *ds)
                priv->ports[i].enable = false;
        priv->ports[priv->cpu_port].enable = true;
 
+       /* Configure ports so they are disabled by default, but once enabled
+        * they will work in isolated mode (only traffic between port and CPU).
+        */
        for (i = 0; i < priv->cpu_port; i++) {
                if (priv->ports[i].phy) {
-                       priv->r->traffic_set(i, BIT_ULL(priv->cpu_port) | BIT_ULL(i));
-                       port_bitmap |= BIT_ULL(i);
+                       priv->ports[i].pm = BIT_ULL(priv->cpu_port);
+                       priv->r->traffic_set(i, BIT_ULL(i));
                }
        }
-       priv->r->traffic_set(priv->cpu_port, port_bitmap);
+       priv->r->traffic_set(priv->cpu_port, BIT_ULL(priv->cpu_port));
 
        rtl930x_print_matrix();
 
@@ -263,6 +283,9 @@ static int rtl93xx_setup(struct dsa_switch *ds)
 
        priv->r->l2_learning_setup();
 
+       rtl83xx_port_set_salrn(priv, priv->cpu_port, false);
+       ds->assisted_learning_on_cpu_port = true;
+
        rtl83xx_enable_phy_polling(priv);
 
        priv->r->pie_init(priv);
@@ -864,17 +887,12 @@ static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port,
                                     phy_interface_t interface)
 {
        struct rtl838x_switch_priv *priv = ds->priv;
-       u32 v;
 
        /* Stop TX/RX to port */
        sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port));
 
        // No longer force link
-       if (priv->family_id == RTL9300_FAMILY_ID)
-               v = RTL930X_FORCE_EN | RTL930X_FORCE_LINK_EN;
-       else if (priv->family_id == RTL9310_FAMILY_ID)
-               v = RTL931X_FORCE_EN | RTL931X_FORCE_LINK_EN;
-       sw_w32_mask(v, 0, priv->r->mac_port_ctrl(port));
+       sw_w32_mask(0x3, 0, priv->r->mac_force_mode_ctrl(port));
 }
 
 static void rtl93xx_phylink_mac_link_down(struct dsa_switch *ds, int port,
@@ -882,11 +900,17 @@ static void rtl93xx_phylink_mac_link_down(struct dsa_switch *ds, int port,
                                     phy_interface_t interface)
 {
        struct rtl838x_switch_priv *priv = ds->priv;
+       u32 v = 0;
+
        /* Stop TX/RX to port */
        sw_w32_mask(0x3, 0, priv->r->mac_port_ctrl(port));
 
        // No longer force link
-       sw_w32_mask(3, 0, priv->r->mac_force_mode_ctrl(port));
+       if (priv->family_id == RTL9300_FAMILY_ID)
+               v = RTL930X_FORCE_EN | RTL930X_FORCE_LINK_EN;
+       else if (priv->family_id == RTL9310_FAMILY_ID)
+               v = RTL931X_FORCE_EN | RTL931X_FORCE_LINK_EN;
+       sw_w32_mask(v, 0, priv->r->mac_force_mode_ctrl(port));
 }
 
 static void rtl83xx_phylink_mac_link_up(struct dsa_switch *ds, int port,
@@ -964,14 +988,8 @@ static int rtl83xx_mc_group_alloc(struct rtl838x_switch_priv *priv, int port)
        if (mc_group >= MAX_MC_GROUPS - 1)
                return -1;
 
-       if (priv->is_lagmember[port]) {
-               pr_info("%s: %d is lag slave. ignore\n", __func__, port);
-               return 0;
-       }
-
        set_bit(mc_group, priv->mc_group_bm);
-       mc_group++;  // We cannot use group 0, as this is used for lookup miss flooding
-       portmask = BIT_ULL(port) | BIT_ULL(priv->cpu_port); 
+       portmask = BIT_ULL(port);
        priv->r->write_mcast_pmask(mc_group, portmask);
 
        return mc_group;
@@ -982,10 +1000,7 @@ static u64 rtl83xx_mc_group_add_port(struct rtl838x_switch_priv *priv, int mc_gr
        u64 portmask = priv->r->read_mcast_pmask(mc_group);
 
        pr_debug("%s: %d\n", __func__, port);
-       if (priv->is_lagmember[port]) {
-               pr_info("%s: %d is lag slave. ignore\n", __func__, port);
-               return portmask;
-       }
+
        portmask |= BIT_ULL(port);
        priv->r->write_mcast_pmask(mc_group, portmask);
 
@@ -997,45 +1012,15 @@ static u64 rtl83xx_mc_group_del_port(struct rtl838x_switch_priv *priv, int mc_gr
        u64 portmask = priv->r->read_mcast_pmask(mc_group);
 
        pr_debug("%s: %d\n", __func__, port);
-       if (priv->is_lagmember[port]) {
-               pr_info("%s: %d is lag slave. ignore\n", __func__, port);
-               return portmask;
-       }
+
+       portmask &= ~BIT_ULL(port);
        priv->r->write_mcast_pmask(mc_group, portmask);
-       if (portmask == BIT_ULL(priv->cpu_port)) {
-               portmask &= ~BIT_ULL(priv->cpu_port);
-               priv->r->write_mcast_pmask(mc_group, portmask);
+       if (!portmask)
                clear_bit(mc_group, priv->mc_group_bm);
-       }
 
        return portmask;
 }
 
-static void store_mcgroups(struct rtl838x_switch_priv *priv, int port)
-{
-       int mc_group;
-
-       for (mc_group = 0; mc_group < MAX_MC_GROUPS; mc_group++) {
-               u64 portmask = priv->r->read_mcast_pmask(mc_group);
-               if (portmask & BIT_ULL(port)) {
-                       priv->mc_group_saves[mc_group] = port;
-                       rtl83xx_mc_group_del_port(priv, mc_group, port);
-               }
-       }
-}
-
-static void load_mcgroups(struct rtl838x_switch_priv *priv, int port)
-{
-       int mc_group;
-
-       for (mc_group = 0; mc_group < MAX_MC_GROUPS; mc_group++) {
-               if (priv->mc_group_saves[mc_group] == port) {
-                       rtl83xx_mc_group_add_port(priv, mc_group, port);
-                       priv->mc_group_saves[mc_group] = -1;
-               }
-       }
-}
-
 static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
                                struct phy_device *phydev)
 {
@@ -1046,10 +1031,7 @@ static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
        priv->ports[port].enable = true;
 
        /* enable inner tagging on egress, do not keep any tags */
-       if (priv->family_id == RTL9310_FAMILY_ID)
-               sw_w32(BIT(4), priv->r->vlan_port_tag_sts_ctrl + (port << 2));
-       else
-               sw_w32(1, priv->r->vlan_port_tag_sts_ctrl + (port << 2));
+       priv->r->vlan_port_keep_tag_set(port, 0, 1);
 
        if (dsa_is_cpu_port(ds, port))
                return 0;
@@ -1057,8 +1039,6 @@ static int rtl83xx_port_enable(struct dsa_switch *ds, int port,
        /* add port to switch mask of CPU_PORT */
        priv->r->traffic_enable(priv->cpu_port, port);
 
-       load_mcgroups(priv, port);
-
        if (priv->is_lagmember[port]) {
                pr_debug("%s: %d is lag slave. ignore\n", __func__, port);
                return 0;
@@ -1094,7 +1074,6 @@ static void rtl83xx_port_disable(struct dsa_switch *ds, int port)
        // BUG: This does not work on RTL931X
        /* remove port from switch mask of CPU_PORT */
        priv->r->traffic_disable(priv->cpu_port, port);
-       store_mcgroups(priv, port);
 
        /* remove all other ports in the same bridge from switch mask of port */
        v = priv->r->traffic_get(port);
@@ -1194,7 +1173,6 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
                        port_bitmap |= BIT_ULL(i);
                }
        }
-       load_mcgroups(priv, port);
 
        /* Add all other ports to this port matrix. */
        if (priv->ports[port].enable) {
@@ -1204,6 +1182,10 @@ static int rtl83xx_port_bridge_join(struct dsa_switch *ds, int port,
                priv->r->traffic_set(port, v);
        }
        priv->ports[port].pm |= port_bitmap;
+
+       if (priv->r->set_static_move_action)
+               priv->r->set_static_move_action(port, false);
+
        mutex_unlock(&priv->reg_mutex);
 
        return 0;
@@ -1213,7 +1195,7 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
                                        struct net_device *bridge)
 {
        struct rtl838x_switch_priv *priv = ds->priv;
-       u64 port_bitmap = BIT_ULL(priv->cpu_port), v;
+       u64 port_bitmap = 0, v;
        int i;
 
        pr_debug("%s %x: %d", __func__, (u32)priv, port);
@@ -1231,20 +1213,22 @@ static void rtl83xx_port_bridge_leave(struct dsa_switch *ds, int port,
                        if (priv->ports[i].enable)
                                priv->r->traffic_disable(i, port);
 
-                       priv->ports[i].pm |= BIT_ULL(port);
-                       port_bitmap &= ~BIT_ULL(i);
+                       priv->ports[i].pm &= ~BIT_ULL(port);
+                       port_bitmap |= BIT_ULL(i);
                }
        }
-       store_mcgroups(priv, port);
 
-       /* Add all other ports to this port matrix. */
+       /* Remove all other ports from this port matrix. */
        if (priv->ports[port].enable) {
                v = priv->r->traffic_get(port);
-               v |= port_bitmap;
+               v &= ~port_bitmap;
                priv->r->traffic_set(port, v);
        }
        priv->ports[port].pm &= ~port_bitmap;
 
+       if (priv->r->set_static_move_action)
+               priv->r->set_static_move_action(port, true);
+
        mutex_unlock(&priv->reg_mutex);
 }
 
@@ -1422,6 +1406,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)
 {
@@ -1429,7 +1427,7 @@ static void rtl83xx_vlan_add(struct dsa_switch *ds, int port,
        struct rtl838x_switch_priv *priv = ds->priv;
        int v;
 
-       pr_debug("%s port %d, vid_end %d, vid_end %d, flags %x\n", __func__,
+       pr_debug("%s port %d, vid_begin %d, vid_end %d, flags %x\n", __func__,
                port, vlan->vid_begin, vlan->vid_end, vlan->flags);
 
        if (vlan->vid_begin > 4095 || vlan->vid_end > 4095) {
@@ -1440,20 +1438,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++) {
@@ -1475,6 +1464,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);
@@ -1494,7 +1485,7 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
        int v;
        u16 pvid;
 
-       pr_debug("%s: port %d, vid_end %d, vid_end %d, flags %x\n", __func__,
+       pr_debug("%s: port %d, vid_begin %d, vid_end %d, flags %x\n", __func__,
                port, vlan->vid_begin, vlan->vid_end, vlan->flags);
 
        if (vlan->vid_begin > 4095 || vlan->vid_end > 4095) {
@@ -1509,12 +1500,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);
@@ -1534,47 +1520,34 @@ static int rtl83xx_vlan_del(struct dsa_switch *ds, int port,
        return 0;
 }
 
-static void dump_l2_entry(struct rtl838x_l2_entry *e)
-{
-       pr_info("MAC: %02x:%02x:%02x:%02x:%02x:%02x vid: %d, rvid: %d, port: %d, valid: %d\n",
-               e->mac[0], e->mac[1], e->mac[2], e->mac[3], e->mac[4], e->mac[5],
-               e->vid, e->rvid, e->port, e->valid);
-
-       if (e->type != L2_MULTICAST) {
-               pr_info("Type: %d, is_static: %d, is_ip_mc: %d, is_ipv6_mc: %d, block_da: %d\n",
-                       e->type, e->is_static, e->is_ip_mc, e->is_ipv6_mc, e->block_da);
-               pr_info("  block_sa: %d, susp: %d, nh: %d, age: %d, is_trunk: %d, trunk: %d\n",
-               e->block_sa, e->suspended, e->next_hop, e->age, e->is_trunk, e->trunk);
-       }
-       if (e->type == L2_MULTICAST)
-               pr_info("  L2_MULTICAST mc_portmask_index: %d\n", e->mc_portmask_index);
-       if (e->is_ip_mc || e->is_ipv6_mc)
-               pr_info("  mc_portmask_index: %d, mc_gip: %d, mc_sip: %d\n",
-                       e->mc_portmask_index, e->mc_gip, e->mc_sip);
-       pr_info("  stack_dev: %d\n", e->stack_dev);
-       if (e->next_hop)
-               pr_info("  nh_route_id: %d\n", e->nh_route_id);
-}
-
 static void rtl83xx_setup_l2_uc_entry(struct rtl838x_l2_entry *e, int port, int vid, u64 mac)
 {
-       e->is_ip_mc = e->is_ipv6_mc  = false;
+       memset(e, 0, sizeof(*e));
+
+       e->type = L2_UNICAST;
        e->valid = true;
+
        e->age = 3;
-       e->port = port,
-       e->vid = vid;
+       e->is_static = true;
+
+       e->port = port;
+
+       e->rvid = e->vid = vid;
+       e->is_ip_mc = e->is_ipv6_mc = false;
        u64_to_ether_addr(mac, e->mac);
 }
 
-static void rtl83xx_setup_l2_mc_entry(struct rtl838x_switch_priv *priv,
-                                     struct rtl838x_l2_entry *e, int vid, u64 mac, int mc_group)
+static void rtl83xx_setup_l2_mc_entry(struct rtl838x_l2_entry *e, int vid, u64 mac, int mc_group)
 {
-       e->is_ip_mc = e->is_ipv6_mc  = false;
+       memset(e, 0, sizeof(*e));
+
+       e->type = L2_MULTICAST;
        e->valid = true;
+
        e->mc_portmask_index = mc_group;
-       e->type = L2_MULTICAST;
+
        e->rvid = e->vid = vid;
-       pr_debug("%s: vid: %d, rvid: %d\n", __func__, e->vid, e->rvid);
+       e->is_ip_mc = e->is_ipv6_mc = false;
        u64_to_ether_addr(mac, e->mac);
 }
 
@@ -1661,7 +1634,7 @@ static int rtl83xx_port_fdb_add(struct dsa_switch *ds, int port,
        }
 
        // Hash buckets full, try CAM
-       rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
+       idx = rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
 
        if (idx >= 0) {
                rtl83xx_setup_l2_uc_entry(&e, port, vid, mac);
@@ -1684,21 +1657,20 @@ static int rtl83xx_port_fdb_del(struct dsa_switch *ds, int port,
        int err = 0, idx;
        u64 seed = priv->r->l2_hash_seed(mac, vid);
 
-       pr_info("In %s, mac %llx, vid: %d\n", __func__, mac, vid);
+       pr_debug("In %s, mac %llx, vid: %d\n", __func__, mac, vid);
        mutex_lock(&priv->reg_mutex);
 
        idx = rtl83xx_find_l2_hash_entry(priv, seed, true, &e);
 
        if (idx >= 0) {
-               pr_info("Found entry index %d, key %d and bucket %d\n", idx, idx >> 2, idx & 3);
+               pr_debug("Found entry index %d, key %d and bucket %d\n", idx, idx >> 2, idx & 3);
                e.valid = false;
-               dump_l2_entry(&e);
                priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e);
                goto out;
        }
 
        /* Check CAM for spillover from hash buckets */
-       rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
+       idx = rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
 
        if (idx >= 0) {
                e.valid = false;
@@ -1717,8 +1689,6 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port,
        struct rtl838x_l2_entry e;
        struct rtl838x_switch_priv *priv = ds->priv;
        int i;
-       u32 fid, pkey;
-       u64 mac;
 
        mutex_lock(&priv->reg_mutex);
 
@@ -1728,30 +1698,11 @@ static int rtl83xx_port_fdb_dump(struct dsa_switch *ds, int port,
                if (!e.valid)
                        continue;
 
-               if (e.port == port || e.port == RTL930X_PORT_IGNORE) {
-                       u64 seed;
-                       u32 key;
-
-                       fid = ((i >> 2) & 0x3ff) | (e.rvid & ~0x3ff);
-                       mac = ether_addr_to_u64(&e.mac[0]);
-                       pkey = priv->r->l2_hash_key(priv, priv->r->l2_hash_seed(mac, fid));
-                       fid = (pkey & 0x3ff) | (fid & ~0x3ff);
-                       pr_info("-> index %d, key %x, bucket %d, dmac %016llx, fid: %x rvid: %x\n",
-                               i, i >> 2, i & 0x3, mac, fid, e.rvid);
-                       dump_l2_entry(&e);
-                       seed = priv->r->l2_hash_seed(mac, e.rvid);
-                       key = priv->r->l2_hash_key(priv, seed);
-                       pr_info("seed: %016llx, key based on rvid: %08x\n", seed, key);
+               if (e.port == port || e.port == RTL930X_PORT_IGNORE)
                        cb(e.mac, e.vid, e.is_static, data);
-               }
-               if (e.type == L2_MULTICAST) {
-                       u64 portmask = priv->r->read_mcast_pmask(e.mc_portmask_index);
 
-                       if (portmask & BIT_ULL(port)) {
-                               dump_l2_entry(&e);
-                               pr_info("  PM: %016llx\n", portmask);
-                       }
-               }
+               if (!((i + 1) % 64))
+                       cond_resched();
        }
 
        for (i = 0; i < 64; i++) {
@@ -1814,14 +1765,14 @@ static void rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
                                err = -ENOTSUPP;
                                goto out;
                        }
-                       rtl83xx_setup_l2_mc_entry(priv, &e, vid, mac, mc_group);
+                       rtl83xx_setup_l2_mc_entry(&e, vid, mac, mc_group);
                        priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e);
                }
                goto out;
        }
 
        // Hash buckets full, try CAM
-       rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
+       idx = rtl83xx_find_l2_cam_entry(priv, seed, false, &e);
 
        if (idx >= 0) {
                if (e.valid) {
@@ -1835,7 +1786,7 @@ static void rtl83xx_port_mdb_add(struct dsa_switch *ds, int port,
                                err = -ENOTSUPP;
                                goto out;
                        }
-                       rtl83xx_setup_l2_mc_entry(priv, &e, vid, mac, mc_group);
+                       rtl83xx_setup_l2_mc_entry(&e, vid, mac, mc_group);
                        priv->r->write_cam(idx, &e);
                }
                goto out;
@@ -1875,20 +1826,18 @@ int rtl83xx_port_mdb_del(struct dsa_switch *ds, int port,
                portmask = rtl83xx_mc_group_del_port(priv, e.mc_portmask_index, port);
                if (!portmask) {
                        e.valid = false;
-                       // dump_l2_entry(&e);
                        priv->r->write_l2_entry_using_hash(idx >> 2, idx & 0x3, &e);
                }
                goto out;
        }
 
        /* Check CAM for spillover from hash buckets */
-       rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
+       idx = rtl83xx_find_l2_cam_entry(priv, seed, true, &e);
 
        if (idx >= 0) {
                portmask = rtl83xx_mc_group_del_port(priv, e.mc_portmask_index, port);
                if (!portmask) {
                        e.valid = false;
-                       // dump_l2_entry(&e);
                        priv->r->write_cam(idx, &e);
                }
                goto out;