diff options
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.patch | 141 |
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, |