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:
		
				
					committed by
					
						
						Petr Štetiar
					
				
			
			
				
	
			
			
			
						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[] = {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user