net: ethernet: ti: ale: fix allmulti for nu type ale
authorGrygorii Strashko <grygorii.strashko@ti.com>
Sat, 13 Jun 2020 14:54:14 +0000 (17:54 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sat, 13 Jun 2020 22:37:17 +0000 (15:37 -0700)
On AM65xx MCU CPSW2G NUSS and 66AK2E/L NUSS allmulti setting does not allow
unregistered mcast packets to pass.

This happens, because ALE VLAN entries on these SoCs do not contain port
masks for reg/unreg mcast packets, but instead store indexes of
ALE_VLAN_MASK_MUXx_REG registers which intended for store port masks for
reg/unreg mcast packets.
This path was missed by commit 9d1f6447274f ("net: ethernet: ti: ale: fix
seeing unreg mcast packets with promisc and allmulti disabled").

Hence, fix it by taking into account ALE type in cpsw_ale_set_allmulti().

Fixes: 9d1f6447274f ("net: ethernet: ti: ale: fix seeing unreg mcast packets with promisc and allmulti disabled")
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ti/cpsw_ale.c

index 8dc6be1..9ad872b 100644 (file)
@@ -604,10 +604,44 @@ void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
        }
 }
 
+static void cpsw_ale_vlan_set_unreg_mcast(struct cpsw_ale *ale, u32 *ale_entry,
+                                         int allmulti)
+{
+       int unreg_mcast;
+
+       unreg_mcast =
+               cpsw_ale_get_vlan_unreg_mcast(ale_entry,
+                                             ale->vlan_field_bits);
+       if (allmulti)
+               unreg_mcast |= ALE_PORT_HOST;
+       else
+               unreg_mcast &= ~ALE_PORT_HOST;
+       cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
+                                     ale->vlan_field_bits);
+}
+
+static void
+cpsw_ale_vlan_set_unreg_mcast_idx(struct cpsw_ale *ale, u32 *ale_entry,
+                                 int allmulti)
+{
+       int unreg_mcast;
+       int idx;
+
+       idx = cpsw_ale_get_vlan_unreg_mcast_idx(ale_entry);
+
+       unreg_mcast = readl(ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
+
+       if (allmulti)
+               unreg_mcast |= ALE_PORT_HOST;
+       else
+               unreg_mcast &= ~ALE_PORT_HOST;
+
+       writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
+}
+
 void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)
 {
        u32 ale_entry[ALE_ENTRY_WORDS];
-       int unreg_mcast = 0;
        int type, idx;
 
        for (idx = 0; idx < ale->params.ale_entries; idx++) {
@@ -624,15 +658,12 @@ void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)
                if (port != -1 && !(vlan_members & BIT(port)))
                        continue;
 
-               unreg_mcast =
-                       cpsw_ale_get_vlan_unreg_mcast(ale_entry,
-                                                     ale->vlan_field_bits);
-               if (allmulti)
-                       unreg_mcast |= ALE_PORT_HOST;
+               if (!ale->params.nu_switch_ale)
+                       cpsw_ale_vlan_set_unreg_mcast(ale, ale_entry, allmulti);
                else
-                       unreg_mcast &= ~ALE_PORT_HOST;
-               cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
-                                             ale->vlan_field_bits);
+                       cpsw_ale_vlan_set_unreg_mcast_idx(ale, ale_entry,
+                                                         allmulti);
+
                cpsw_ale_write(ale, idx, ale_entry);
        }
 }