Commit 56d8bb71 authored by Linus Walleij's avatar Linus Walleij Committed by David S. Miller
Browse files

net: dsa: rtl8366rb: Support disabling learning



The RTL8366RB hardware supports disabling learning per-port
so let's make use of this feature. Rename some unfortunately
named registers in the process.

Suggested-by: default avatarVladimir Oltean <olteanv@gmail.com>
Cc: Alvin Šipraga <alsi@bang-olufsen.dk>
Cc: Mauri Sandberg <sandberg@mailfence.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: DENG Qingfang <dqfext@gmail.com>
Reviewed-by: default avatarVladimir Oltean <olteanv@gmail.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bcb2293d
Loading
Loading
Loading
Loading
+44 −6
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

#include <linux/bitops.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
@@ -42,9 +43,12 @@
/* Port Enable Control register */
#define RTL8366RB_PECR				0x0001

/* Switch Security Control registers */
#define RTL8366RB_SSCR0				0x0002
#define RTL8366RB_SSCR1				0x0003
/* Switch per-port learning disablement register */
#define RTL8366RB_PORT_LEARNDIS_CTRL		0x0002

/* Security control, actually aging register */
#define RTL8366RB_SECURITY_CTRL			0x0003

#define RTL8366RB_SSCR2				0x0004
#define RTL8366RB_SSCR2_DROP_UNKNOWN_DA		BIT(0)

@@ -927,13 +931,14 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
		/* layer 2 size, see rtl8366rb_change_mtu() */
		rb->max_mtu[i] = 1532;

	/* Enable learning for all ports */
	ret = regmap_write(smi->map, RTL8366RB_SSCR0, 0);
	/* Disable learning for all ports */
	ret = regmap_write(smi->map, RTL8366RB_PORT_LEARNDIS_CTRL,
			   RTL8366RB_PORT_ALL);
	if (ret)
		return ret;

	/* Enable auto ageing for all ports */
	ret = regmap_write(smi->map, RTL8366RB_SSCR1, 0);
	ret = regmap_write(smi->map, RTL8366RB_SECURITY_CTRL, 0);
	if (ret)
		return ret;

@@ -1272,6 +1277,37 @@ static int rtl8366rb_vlan_filtering(struct dsa_switch *ds, int port,
	return ret;
}

static int
rtl8366rb_port_pre_bridge_flags(struct dsa_switch *ds, int port,
				struct switchdev_brport_flags flags,
				struct netlink_ext_ack *extack)
{
	/* We support enabling/disabling learning */
	if (flags.mask & ~(BR_LEARNING))
		return -EINVAL;

	return 0;
}

static int
rtl8366rb_port_bridge_flags(struct dsa_switch *ds, int port,
			    struct switchdev_brport_flags flags,
			    struct netlink_ext_ack *extack)
{
	struct realtek_smi *smi = ds->priv;
	int ret;

	if (flags.mask & BR_LEARNING) {
		ret = regmap_update_bits(smi->map, RTL8366RB_PORT_LEARNDIS_CTRL,
					 BIT(port),
					 (flags.val & BR_LEARNING) ? 0 : BIT(port));
		if (ret)
			return ret;
	}

	return 0;
}

static int rtl8366rb_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
	struct realtek_smi *smi = ds->priv;
@@ -1682,6 +1718,8 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops = {
	.port_vlan_del = rtl8366_vlan_del,
	.port_enable = rtl8366rb_port_enable,
	.port_disable = rtl8366rb_port_disable,
	.port_pre_bridge_flags = rtl8366rb_port_pre_bridge_flags,
	.port_bridge_flags = rtl8366rb_port_bridge_flags,
	.port_change_mtu = rtl8366rb_change_mtu,
	.port_max_mtu = rtl8366rb_max_mtu,
};