2
0
forked from Ivasoft/openwrt

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>

SVN-Revision: 44104
This commit is contained in:
Felix Fietkau
2015-01-24 19:42:06 +00:00
parent 6ce848f622
commit 3a313a3e11
4 changed files with 220 additions and 15 deletions

View File

@@ -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] = {