kernel: ar8xxx: get_arl_table now shows all ports of an entry
[openwrt/openwrt.git] / target / linux / generic / files / drivers / net / phy / ar8216.c
index 61811370de6029c86c1a69a1629e2635de29813f..68754e6096849a2756aba5f4bfffe54161ab08b2 100644 (file)
@@ -355,6 +355,7 @@ ar8xxx_reg_wait(struct ar8xxx_priv *priv, u32 reg, u32 mask, u32 val,
                        return 0;
 
                usleep_range(1000, 2000);
+               cond_resched();
        }
 
        return -ETIMEDOUT;
@@ -426,6 +427,7 @@ ar8xxx_mib_fetch_port_stat(struct ar8xxx_priv *priv, int port, bool flush)
                        mib_stats[i] = 0;
                else
                        mib_stats[i] += t;
+               cond_resched();
        }
 }
 
@@ -565,6 +567,7 @@ ar8216_wait_bit(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val)
                        break;
 
                udelay(10);
+               cond_resched();
        }
 
        pr_err("ar8216: timeout on reg %08x: %08x & %08x != %08x\n",
@@ -730,8 +733,10 @@ ar8216_wait_atu_ready(struct ar8xxx_priv *priv, u16 r2, u16 r1)
 {
        int timeout = 20;
 
-       while (ar8xxx_mii_read32(priv, r2, r1) & AR8216_ATU_ACTIVE && --timeout)
-                udelay(10);
+       while (ar8xxx_mii_read32(priv, r2, r1) & AR8216_ATU_ACTIVE && --timeout) {
+               udelay(10);
+               cond_resched();
+       }
 
        if (!timeout)
                pr_err("ar8216: timeout waiting for atu to become ready\n");
@@ -744,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;
@@ -780,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;
@@ -1511,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;
+                       }
                }
        }
 
@@ -1529,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",
@@ -2099,7 +2102,8 @@ ar8xxx_phy_read_status(struct phy_device *phydev)
 
        phydev->state = PHY_RUNNING;
        netif_carrier_on(phydev->attached_dev);
-       phydev->adjust_link(phydev->attached_dev);
+       if (phydev->adjust_link)
+               phydev->adjust_link(phydev->attached_dev);
 
        return 0;
 }