diff options
author | Felix Fietkau <nbd@openwrt.org> | 2015-01-24 19:42:06 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2015-01-24 19:42:06 +0000 |
commit | 4bfb00d02d6537fee9557d989601bc235fa81116 (patch) | |
tree | a0afadd52a96538fee50829f7c06d84fce4b2cb2 /target/linux/generic/files/drivers/net/phy/ar8216.c | |
parent | 95e0b242c20cd8fe135e989cdad76405d38cca25 (diff) | |
download | master-187ad058-4bfb00d02d6537fee9557d989601bc235fa81116.tar.gz master-187ad058-4bfb00d02d6537fee9557d989601bc235fa81116.tar.bz2 master-187ad058-4bfb00d02d6537fee9557d989601bc235fa81116.zip |
ar8216: add swconfig attribute to display ARL table on AR8327/AR8337
Add global read-only swconfig attribute "arl_table" to display the
address resolution table.
So far the chip-specific part is implemented for AR8327/AR8337 only
as I don't have the datasheets for the other AR8XXX chips.
Successfully tested on TL-WDR4300 (AR8327rev2)
and TL-WDR4900 (AR8327rev4).
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@44104 3c298f89-4303-0410-b956-a3cf2f4a3e73
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] = { |