aboutsummaryrefslogtreecommitdiff
path: root/pkgs/patches-linux-5.15/774-v5.16-01-net-dsa-rtl8366rb-Support-bridge-offloading.patch
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/patches-linux-5.15/774-v5.16-01-net-dsa-rtl8366rb-Support-bridge-offloading.patch')
-rw-r--r--pkgs/patches-linux-5.15/774-v5.16-01-net-dsa-rtl8366rb-Support-bridge-offloading.patch141
1 files changed, 141 insertions, 0 deletions
diff --git a/pkgs/patches-linux-5.15/774-v5.16-01-net-dsa-rtl8366rb-Support-bridge-offloading.patch b/pkgs/patches-linux-5.15/774-v5.16-01-net-dsa-rtl8366rb-Support-bridge-offloading.patch
new file mode 100644
index 0000000..78570c5
--- /dev/null
+++ b/pkgs/patches-linux-5.15/774-v5.16-01-net-dsa-rtl8366rb-Support-bridge-offloading.patch
@@ -0,0 +1,141 @@
+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,