[openwrt/openwrt] ramips: add arl_table support for MT7530

LEDE Commits lede-commits at lists.infradead.org
Fri Jul 17 05:00:52 EDT 2020


ynezz pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/2a43ab4a18b4dfe2f4e39b28b87c60b01e6dfd5c

commit 2a43ab4a18b4dfe2f4e39b28b87c60b01e6dfd5c
Author: Salvatore Mesoraca <salvatore at samknows.com>
AuthorDate: Wed Jun 17 14:07:58 2020 +0100

    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 at samknows.com>
---
 .../files/drivers/net/ethernet/ralink/mt7530.c     | 119 +++++++++++++++++++++
 1 file changed, 119 insertions(+)

diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c
index d1e56a76e9..367b8d9ac4 100644
--- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c
+++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c
@@ -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[] = {



More information about the lede-commits mailing list