 30d2fcffeb
			
		
	
	30d2fcffeb
	
	
	
		
			
			The prerequisite DSA changes for the nice RTL8366RB improvements are already backported so bring back these changes as well. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
		
			
				
	
	
		
			142 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From c9111895fd38dadf125e07be627778a9950d8d77 Mon Sep 17 00:00:00 2001
 | |
| From: DENG Qingfang <dqfext@gmail.com>
 | |
| Date: Sun, 26 Sep 2021 00:59:24 +0200
 | |
| Subject: [PATCH 01/11] net: dsa: rtl8366rb: Support bridge offloading
 | |
| MIME-Version: 1.0
 | |
| Content-Type: text/plain; charset=UTF-8
 | |
| Content-Transfer-Encoding: 8bit
 | |
| 
 | |
| Use port isolation registers to configure bridge offloading.
 | |
| 
 | |
| Tested on the D-Link DIR-685, switching between ports and
 | |
| sniffing ports to make sure no packets leak.
 | |
| 
 | |
| Cc: Vladimir Oltean <olteanv@gmail.com>
 | |
| Cc: Mauri Sandberg <sandberg@mailfence.com>
 | |
| Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
 | |
| Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
 | |
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
 | |
| Signed-off-by: DENG Qingfang <dqfext@gmail.com>
 | |
| Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
 | |
| Signed-off-by: David S. Miller <davem@davemloft.net>
 | |
| ---
 | |
|  drivers/net/dsa/rtl8366rb.c | 86 +++++++++++++++++++++++++++++++++++++
 | |
|  1 file changed, 86 insertions(+)
 | |
| 
 | |
| --- a/drivers/net/dsa/rtl8366rb.c
 | |
| +++ b/drivers/net/dsa/rtl8366rb.c
 | |
| @@ -300,6 +300,13 @@
 | |
|  #define RTL8366RB_INTERRUPT_STATUS_REG	0x0442
 | |
|  #define RTL8366RB_NUM_INTERRUPT		14 /* 0..13 */
 | |
|  
 | |
| +/* Port isolation registers */
 | |
| +#define RTL8366RB_PORT_ISO_BASE		0x0F08
 | |
| +#define RTL8366RB_PORT_ISO(pnum)	(RTL8366RB_PORT_ISO_BASE + (pnum))
 | |
| +#define RTL8366RB_PORT_ISO_EN		BIT(0)
 | |
| +#define RTL8366RB_PORT_ISO_PORTS_MASK	GENMASK(7, 1)
 | |
| +#define RTL8366RB_PORT_ISO_PORTS(pmask)	((pmask) << 1)
 | |
| +
 | |
|  /* bits 0..5 enable force when cleared */
 | |
|  #define RTL8366RB_MAC_FORCE_CTRL_REG	0x0F11
 | |
|  
 | |
| @@ -835,6 +842,21 @@ static int rtl8366rb_setup(struct dsa_sw
 | |
|  	if (ret)
 | |
|  		return ret;
 | |
|  
 | |
| +	/* Isolate all user ports so they can only send packets to itself and the CPU port */
 | |
| +	for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
 | |
| +		ret = regmap_write(smi->map, RTL8366RB_PORT_ISO(i),
 | |
| +				   RTL8366RB_PORT_ISO_PORTS(BIT(RTL8366RB_PORT_NUM_CPU)) |
 | |
| +				   RTL8366RB_PORT_ISO_EN);
 | |
| +		if (ret)
 | |
| +			return ret;
 | |
| +	}
 | |
| +	/* CPU port can send packets to all ports */
 | |
| +	ret = regmap_write(smi->map, RTL8366RB_PORT_ISO(RTL8366RB_PORT_NUM_CPU),
 | |
| +			   RTL8366RB_PORT_ISO_PORTS(dsa_user_ports(ds)) |
 | |
| +			   RTL8366RB_PORT_ISO_EN);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
|  	/* Set up the "green ethernet" feature */
 | |
|  	ret = rtl8366rb_jam_table(rtl8366rb_green_jam,
 | |
|  				  ARRAY_SIZE(rtl8366rb_green_jam), smi, false);
 | |
| @@ -1127,6 +1149,68 @@ rtl8366rb_port_disable(struct dsa_switch
 | |
|  	rb8366rb_set_port_led(smi, port, false);
 | |
|  }
 | |
|  
 | |
| +static int
 | |
| +rtl8366rb_port_bridge_join(struct dsa_switch *ds, int port,
 | |
| +			   struct net_device *bridge)
 | |
| +{
 | |
| +	struct realtek_smi *smi = ds->priv;
 | |
| +	unsigned int port_bitmap = 0;
 | |
| +	int ret, i;
 | |
| +
 | |
| +	/* Loop over all other ports than the current one */
 | |
| +	for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
 | |
| +		/* Current port handled last */
 | |
| +		if (i == port)
 | |
| +			continue;
 | |
| +		/* Not on this bridge */
 | |
| +		if (dsa_to_port(ds, i)->bridge_dev != bridge)
 | |
| +			continue;
 | |
| +		/* Join this port to each other port on the bridge */
 | |
| +		ret = regmap_update_bits(smi->map, RTL8366RB_PORT_ISO(i),
 | |
| +					 RTL8366RB_PORT_ISO_PORTS(BIT(port)),
 | |
| +					 RTL8366RB_PORT_ISO_PORTS(BIT(port)));
 | |
| +		if (ret)
 | |
| +			dev_err(smi->dev, "failed to join port %d\n", port);
 | |
| +
 | |
| +		port_bitmap |= BIT(i);
 | |
| +	}
 | |
| +
 | |
| +	/* Set the bits for the ports we can access */
 | |
| +	return regmap_update_bits(smi->map, RTL8366RB_PORT_ISO(port),
 | |
| +				  RTL8366RB_PORT_ISO_PORTS(port_bitmap),
 | |
| +				  RTL8366RB_PORT_ISO_PORTS(port_bitmap));
 | |
| +}
 | |
| +
 | |
| +static void
 | |
| +rtl8366rb_port_bridge_leave(struct dsa_switch *ds, int port,
 | |
| +			    struct net_device *bridge)
 | |
| +{
 | |
| +	struct realtek_smi *smi = ds->priv;
 | |
| +	unsigned int port_bitmap = 0;
 | |
| +	int ret, i;
 | |
| +
 | |
| +	/* Loop over all other ports than this one */
 | |
| +	for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
 | |
| +		/* Current port handled last */
 | |
| +		if (i == port)
 | |
| +			continue;
 | |
| +		/* Not on this bridge */
 | |
| +		if (dsa_to_port(ds, i)->bridge_dev != bridge)
 | |
| +			continue;
 | |
| +		/* Remove this port from any other port on the bridge */
 | |
| +		ret = regmap_update_bits(smi->map, RTL8366RB_PORT_ISO(i),
 | |
| +					 RTL8366RB_PORT_ISO_PORTS(BIT(port)), 0);
 | |
| +		if (ret)
 | |
| +			dev_err(smi->dev, "failed to leave port %d\n", port);
 | |
| +
 | |
| +		port_bitmap |= BIT(i);
 | |
| +	}
 | |
| +
 | |
| +	/* Clear the bits for the ports we can not access, leave ourselves */
 | |
| +	regmap_update_bits(smi->map, RTL8366RB_PORT_ISO(port),
 | |
| +			   RTL8366RB_PORT_ISO_PORTS(port_bitmap), 0);
 | |
| +}
 | |
| +
 | |
|  static int rtl8366rb_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
 | |
|  {
 | |
|  	struct realtek_smi *smi = ds->priv;
 | |
| @@ -1510,6 +1594,8 @@ static const struct dsa_switch_ops rtl83
 | |
|  	.get_strings = rtl8366_get_strings,
 | |
|  	.get_ethtool_stats = rtl8366_get_ethtool_stats,
 | |
|  	.get_sset_count = rtl8366_get_sset_count,
 | |
| +	.port_bridge_join = rtl8366rb_port_bridge_join,
 | |
| +	.port_bridge_leave = rtl8366rb_port_bridge_leave,
 | |
|  	.port_vlan_filtering = rtl8366_vlan_filtering,
 | |
|  	.port_vlan_add = rtl8366_vlan_add,
 | |
|  	.port_vlan_del = rtl8366_vlan_del,
 |