mirror of
https://github.com/hanwckf/immortalwrt-mt798x.git
synced 2025-01-09 02:43:53 +08:00
ramips: add arl_table support for MT7530
Use switch.h API to expose MT7530's ARL table to user space. Signed-off-by: Salvatore Mesoraca <salvatore@samknows.com>
This commit is contained in:
parent
cc66580293
commit
2a43ab4a18
@ -31,6 +31,7 @@
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "mt7530.h"
|
||||
|
||||
@ -43,6 +44,8 @@
|
||||
#endif
|
||||
#define MT7530_MAX_VID 4095
|
||||
#define MT7530_MIN_VID 0
|
||||
#define MT7530_NUM_ARL_RECORDS 2048
|
||||
#define ARL_LINE_LENGTH 30
|
||||
|
||||
#define MT7530_PORT_MIB_TXB_ID 2 /* TxGOC */
|
||||
#define MT7530_PORT_MIB_RXB_ID 6 /* RxGOC */
|
||||
@ -61,6 +64,20 @@
|
||||
#define REG_ESW_VLAN_VAWD2 0x98
|
||||
#define REG_ESW_VLAN_VTIM(x) (0x100 + 4 * ((x) / 2))
|
||||
|
||||
#define REG_ESW_WT_MAC_ATC 0x80
|
||||
#define REG_ESW_TABLE_ATRD 0x8C
|
||||
#define REG_ESW_TABLE_TSRA1 0x84
|
||||
#define REG_ESW_TABLE_TSRA2 0x88
|
||||
|
||||
#define REG_MAC_ATC_START 0x8004
|
||||
#define REG_MAC_ATC_NEXT 0x8005
|
||||
|
||||
#define REG_MAC_ATC_BUSY 0x8000U
|
||||
#define REG_MAC_ATC_SRCH_HIT 0x2000U
|
||||
#define REG_MAC_ATC_SRCH_END 0x4000U
|
||||
#define REG_ATRD_VALID 0xff000000U
|
||||
#define REG_ATRD_PORT_MASK 0xff0U
|
||||
|
||||
#define REG_ESW_VLAN_VAWD1_IVL_MAC BIT(30)
|
||||
#define REG_ESW_VLAN_VAWD1_VTAG_EN BIT(28)
|
||||
#define REG_ESW_VLAN_VAWD1_VALID BIT(0)
|
||||
@ -212,6 +229,7 @@ struct mt7530_priv {
|
||||
bool global_vlan_enable;
|
||||
struct mt7530_vlan_entry vlan_entries[MT7530_NUM_VLANS];
|
||||
struct mt7530_port_entry port_entries[MT7530_NUM_PORTS];
|
||||
char arl_buf[MT7530_NUM_ARL_RECORDS * ARL_LINE_LENGTH + 1];
|
||||
};
|
||||
|
||||
struct mt7530_mapping {
|
||||
@ -865,6 +883,100 @@ static int mt7530_sw_get_mib(struct switch_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *mt7530_print_arl_table_row(u32 atrd,
|
||||
u32 mac1,
|
||||
u32 mac2,
|
||||
char *buf,
|
||||
size_t *size)
|
||||
{
|
||||
int ret;
|
||||
size_t port;
|
||||
size_t i;
|
||||
u8 port_map;
|
||||
u8 mac[ETH_ALEN];
|
||||
|
||||
mac1 = ntohl(mac1);
|
||||
mac2 = ntohl(mac2);
|
||||
port_map = (u8)((atrd & REG_ATRD_PORT_MASK) >> 4);
|
||||
memcpy(mac, &mac1, sizeof(mac1));
|
||||
memcpy(mac + sizeof(mac1), &mac2, sizeof(mac) - sizeof(mac1));
|
||||
for (port = 0, i = 1; port < MT7530_NUM_PORTS; ++port, i <<= 1) {
|
||||
if (port_map & i) {
|
||||
ret = snprintf(buf, *size, "Port %d: MAC %pM\n", port, mac);
|
||||
if (ret >= *size || ret <= 0) {
|
||||
*buf = 0;
|
||||
buf = NULL;
|
||||
goto out;
|
||||
}
|
||||
buf += ret;
|
||||
*size = *size - ret;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int mt7530_get_arl_table(struct switch_dev *dev,
|
||||
const struct switch_attr *attr,
|
||||
struct switch_val *val)
|
||||
{
|
||||
struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev);
|
||||
char *buf = priv->arl_buf;
|
||||
size_t size = sizeof(priv->arl_buf);
|
||||
size_t count = 0;
|
||||
size_t retry_times = 100;
|
||||
int ret;
|
||||
u32 atc;
|
||||
|
||||
ret = snprintf(buf, size, "address resolution table\n");
|
||||
if (ret >= size || ret <= 0) {
|
||||
priv->arl_buf[0] = 0;
|
||||
goto out;
|
||||
}
|
||||
buf += ret;
|
||||
size = size - ret;
|
||||
|
||||
mt7530_w32(priv, REG_ESW_WT_MAC_ATC, REG_MAC_ATC_START);
|
||||
|
||||
do {
|
||||
atc = mt7530_r32(priv, REG_ESW_WT_MAC_ATC);
|
||||
if (atc & REG_MAC_ATC_SRCH_HIT && !(atc & REG_MAC_ATC_BUSY)) {
|
||||
u32 atrd;
|
||||
|
||||
++count;
|
||||
atrd = mt7530_r32(priv, REG_ESW_TABLE_ATRD);
|
||||
if (atrd & REG_ATRD_VALID) {
|
||||
u32 mac1;
|
||||
u32 mac2;
|
||||
|
||||
mac1 = mt7530_r32(priv, REG_ESW_TABLE_TSRA1);
|
||||
mac2 = mt7530_r32(priv, REG_ESW_TABLE_TSRA2);
|
||||
|
||||
if (!(atc & REG_MAC_ATC_SRCH_END))
|
||||
mt7530_w32(priv, REG_ESW_WT_MAC_ATC, REG_MAC_ATC_NEXT);
|
||||
|
||||
buf = mt7530_print_arl_table_row(atrd, mac1, mac2, buf, &size);
|
||||
if (!buf) {
|
||||
pr_warn("%s: too many addresses\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
} else if (!(atc & REG_MAC_ATC_SRCH_END)) {
|
||||
mt7530_w32(priv, REG_ESW_WT_MAC_ATC, REG_MAC_ATC_NEXT);
|
||||
}
|
||||
} else {
|
||||
--retry_times;
|
||||
usleep_range(1000, 5000);
|
||||
}
|
||||
} while (!(atc & REG_MAC_ATC_SRCH_END) &&
|
||||
count < MT7530_NUM_ARL_RECORDS &&
|
||||
retry_times > 0);
|
||||
out:
|
||||
val->value.s = priv->arl_buf;
|
||||
val->len = strlen(priv->arl_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7530_sw_get_port_mib(struct switch_dev *dev,
|
||||
const struct switch_attr *attr,
|
||||
struct switch_val *val)
|
||||
@ -944,6 +1056,13 @@ static const struct switch_attr mt7530_global[] = {
|
||||
.get = mt7530_get_mirror_monitor_port,
|
||||
.max = MT7530_NUM_PORTS - 1
|
||||
},
|
||||
{
|
||||
.type = SWITCH_TYPE_STRING,
|
||||
.name = "arl_table",
|
||||
.description = "Get ARL table",
|
||||
.set = NULL,
|
||||
.get = mt7530_get_arl_table,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct switch_attr mt7621_port[] = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user