kernel: ar8xxx: get_arl_table now shows all ports of an entry
authorGünther Kelleter <guenther.kelleter@devolo.de>
Mon, 26 Nov 2018 14:44:31 +0000 (15:44 +0100)
committerJo-Philipp Wich <jo@mein.io>
Tue, 18 Dec 2018 16:48:18 +0000 (17:48 +0100)
Multicast ARL entries can have multiple destination ports. Get and dump
all destination ports of each entry, not just the lowest.

Signed-off-by: Günther Kelleter <guenther.kelleter@devolo.de>
(backported from 33878b0a40707a53920ec72a92430ab420b0893f)

target/linux/generic/files/drivers/net/phy/ar8216.c
target/linux/generic/files/drivers/net/phy/ar8216.h
target/linux/generic/files/drivers/net/phy/ar8327.c
target/linux/generic/files/drivers/net/phy/ar8327.h

index 6869e1ff191cbba219a7719fedd94cbc1b8595e4..68754e6096849a2756aba5f4bfffe54161ab08b2 100644 (file)
@@ -749,7 +749,6 @@ static void ar8216_get_arl_entry(struct ar8xxx_priv *priv,
        u16 r2, page;
        u16 r1_func0, r1_func1, r1_func2;
        u32 t, val0, val1, val2;
-       int i;
 
        split_addr(AR8216_REG_ATU_FUNC0, &r1_func0, &r2, &page);
        r2 |= 0x10;
@@ -785,12 +784,7 @@ static void ar8216_get_arl_entry(struct ar8xxx_priv *priv,
                if (!*status)
                        break;
 
-               i = 0;
-               t = AR8216_ATU_PORT0;
-               while (!(val2 & t) && ++i < priv->dev.ports)
-                       t <<= 1;
-
-               a->port = i;
+               a->portmap = (val2 & AR8216_ATU_PORTS) >> AR8216_ATU_PORTS_S;
                a->mac[0] = (val0 & AR8216_ATU_ADDR5) >> AR8216_ATU_ADDR5_S;
                a->mac[1] = (val0 & AR8216_ATU_ADDR4) >> AR8216_ATU_ADDR4_S;
                a->mac[2] = (val1 & AR8216_ATU_ADDR3) >> AR8216_ATU_ADDR3_S;
@@ -1516,8 +1510,12 @@ ar8xxx_sw_get_arl_table(struct switch_dev *dev,
                 */
                for (j = 0; j < i; ++j) {
                        a1 = &priv->arl_table[j];
-                       if (a->port == a1->port && !memcmp(a->mac, a1->mac, sizeof(a->mac)))
-                               goto duplicate;
+                       if (!memcmp(a->mac, a1->mac, sizeof(a->mac))) {
+                               /* ignore ports already seen in former entry */
+                               a->portmap &= ~a1->portmap;
+                               if (!a->portmap)
+                                       goto duplicate;
+                       }
                }
        }
 
@@ -1534,7 +1532,7 @@ ar8xxx_sw_get_arl_table(struct switch_dev *dev,
        for (j = 0; j < priv->dev.ports; ++j) {
                for (k = 0; k < i; ++k) {
                        a = &priv->arl_table[k];
-                       if (a->port != j)
+                       if (!(a->portmap & BIT(j)))
                                continue;
                        len += snprintf(buf + len, sizeof(priv->arl_buf) - len,
                                        "Port %d: MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
index ba0e0ddccda22c4196f7304d6abdc27b81abef69..509818c50d21279111b2e7e2d9f7797e03b7ae4f 100644 (file)
 
 #define AR8216_REG_ATU_FUNC2           0x0058
 #define   AR8216_ATU_PORTS             BITS(0, 6)
+#define   AR8216_ATU_PORTS_S           0
 #define   AR8216_ATU_PORT0             BIT(0)
 #define   AR8216_ATU_PORT1             BIT(1)
 #define   AR8216_ATU_PORT2             BIT(2)
@@ -367,7 +368,7 @@ enum arl_op {
 };
 
 struct arl_entry {
-       u8 port;
+       u16 portmap;
        u8 mac[6];
 };
 
index 74f0a08d76e837dc6576a4be84a976fc86b685ef..803fb3d49f36d5b350debe0cf56c47cab74fcf7c 100644 (file)
@@ -1057,8 +1057,7 @@ static void ar8327_get_arl_entry(struct ar8xxx_priv *priv,
        struct mii_bus *bus = priv->mii_bus;
        u16 r2, page;
        u16 r1_data0, r1_data1, r1_data2, r1_func;
-       u32 t, val0, val1, val2;
-       int i;
+       u32 val0, val1, val2;
 
        split_addr(AR8327_REG_ATU_DATA0, &r1_data0, &r2, &page);
        r2 |= 0x10;
@@ -1095,12 +1094,7 @@ static void ar8327_get_arl_entry(struct ar8xxx_priv *priv,
                if (!*status)
                        break;
 
-               i = 0;
-               t = AR8327_ATU_PORT0;
-               while (!(val1 & t) && ++i < AR8327_NUM_PORTS)
-                       t <<= 1;
-
-               a->port = i;
+               a->portmap = (val1 & AR8327_ATU_PORTS) >> AR8327_ATU_PORTS_S;
                a->mac[0] = (val0 & AR8327_ATU_ADDR0) >> AR8327_ATU_ADDR0_S;
                a->mac[1] = (val0 & AR8327_ATU_ADDR1) >> AR8327_ATU_ADDR1_S;
                a->mac[2] = (val0 & AR8327_ATU_ADDR2) >> AR8327_ATU_ADDR2_S;
index d53ef885b198e2edbd7d8fcb91cd4e3e712985f7..38e33ea57e64464bf33931937b92a269e872e6cb 100644 (file)
 #define   AR8327_ATU_ADDR5                     BITS(8, 8)
 #define   AR8327_ATU_ADDR5_S                   8
 #define   AR8327_ATU_PORTS                     BITS(16, 7)
+#define   AR8327_ATU_PORTS_S                   16
 #define   AR8327_ATU_PORT0                     BIT(16)
 #define   AR8327_ATU_PORT1                     BIT(17)
 #define   AR8327_ATU_PORT2                     BIT(18)