diff options
Diffstat (limited to 'target/linux/generic/files/drivers/net/phy/ar8216.c')
-rw-r--r-- | target/linux/generic/files/drivers/net/phy/ar8216.c | 96 |
1 files changed, 81 insertions, 15 deletions
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 8a40a322b5..8266003c17 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -134,19 +134,6 @@ const struct ar8xxx_mib_desc ar8236_mibs[39] = { static DEFINE_MUTEX(ar8xxx_dev_list_lock); static LIST_HEAD(ar8xxx_dev_list); -static inline void -split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) -{ - regaddr >>= 1; - *r1 = regaddr & 0x1e; - - regaddr >>= 5; - *r2 = regaddr & 0x7; - - regaddr >>= 3; - *page = regaddr & 0x1ff; -} - /* inspired by phy_poll_reset in drivers/net/phy/phy_device.c */ static int ar8xxx_phy_poll_reset(struct mii_bus *bus) @@ -217,7 +204,7 @@ ar8xxx_phy_init(struct ar8xxx_priv *priv) ar8xxx_phy_poll_reset(bus); } -static u32 +u32 mii_read32(struct ar8xxx_priv *priv, int phy_id, int regnum) { struct mii_bus *bus = priv->mii_bus; @@ -229,7 +216,7 @@ mii_read32(struct ar8xxx_priv *priv, int phy_id, int regnum) return (hi << 16) | lo; } -static void +void mii_write32(struct ar8xxx_priv *priv, int phy_id, int regnum, u32 val) { struct mii_bus *bus = priv->mii_bus; @@ -1291,6 +1278,78 @@ unlock: return ret; } +int +ar8xxx_sw_get_arl_table(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); + struct mii_bus *bus = priv->mii_bus; + const struct ar8xxx_chip *chip = priv->chip; + char *buf = priv->arl_buf; + int i, j, k, len = 0; + struct arl_entry *a, *a1; + u32 status; + + if (!chip->get_arl_entry) + return -EOPNOTSUPP; + + mutex_lock(&priv->reg_mutex); + mutex_lock(&bus->mdio_lock); + + chip->get_arl_entry(priv, NULL, NULL, AR8XXX_ARL_INITIALIZE); + + for(i = 0; i < AR8XXX_NUM_ARL_RECORDS; ++i) { + a = &priv->arl_table[i]; + duplicate: + chip->get_arl_entry(priv, a, &status, AR8XXX_ARL_GET_NEXT); + + if (!status) + break; + + /* avoid duplicates + * ARL table can include multiple valid entries + * per MAC, just with differing status codes + */ + 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; + } + } + + mutex_unlock(&bus->mdio_lock); + + len += snprintf(buf + len, sizeof(priv->arl_buf) - len, + "address resolution table\n"); + + if (i == AR8XXX_NUM_ARL_RECORDS) + len += snprintf(buf + len, sizeof(priv->arl_buf) - len, + "Too many entries found, displaying the first %d only!\n", + AR8XXX_NUM_ARL_RECORDS); + + for (j = 0; j < priv->dev.ports; ++j) { + for (k = 0; k < i; ++k) { + a = &priv->arl_table[k]; + if (a->port != j) + continue; + len += snprintf(buf + len, sizeof(priv->arl_buf) - len, + "Port %d: MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + j, + a->mac[5], a->mac[4], a->mac[3], + a->mac[2], a->mac[1], a->mac[0]); + } + } + + val->value.s = buf; + val->len = len; + + mutex_unlock(&priv->reg_mutex); + + return 0; +} + + static const struct switch_attr ar8xxx_sw_attr_globals[] = { { .type = SWITCH_TYPE_INT, @@ -1338,6 +1397,13 @@ static const struct switch_attr ar8xxx_sw_attr_globals[] = { .get = ar8xxx_sw_get_mirror_source_port, .max = AR8216_NUM_PORTS - 1 }, + { + .type = SWITCH_TYPE_STRING, + .name = "arl_table", + .description = "Get ARL table", + .set = NULL, + .get = ar8xxx_sw_get_arl_table, + }, }; const struct switch_attr ar8xxx_sw_attr_port[2] = { |