summaryrefslogtreecommitdiff
path: root/target/linux/generic/backport-5.10/774-v5.15-net-dsa-mv88e6xxx-keep-the-pvid-at-0-when-VLAN-unawa.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/backport-5.10/774-v5.15-net-dsa-mv88e6xxx-keep-the-pvid-at-0-when-VLAN-unawa.patch')
-rw-r--r--target/linux/generic/backport-5.10/774-v5.15-net-dsa-mv88e6xxx-keep-the-pvid-at-0-when-VLAN-unawa.patch225
1 files changed, 0 insertions, 225 deletions
diff --git a/target/linux/generic/backport-5.10/774-v5.15-net-dsa-mv88e6xxx-keep-the-pvid-at-0-when-VLAN-unawa.patch b/target/linux/generic/backport-5.10/774-v5.15-net-dsa-mv88e6xxx-keep-the-pvid-at-0-when-VLAN-unawa.patch
deleted file mode 100644
index 13cc8f3d69..0000000000
--- a/target/linux/generic/backport-5.10/774-v5.15-net-dsa-mv88e6xxx-keep-the-pvid-at-0-when-VLAN-unawa.patch
+++ /dev/null
@@ -1,225 +0,0 @@
-From 675992be6f7b603b8cfda4678f173e1021fc1ab6 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Thu, 7 Oct 2021 19:47:10 +0300
-Subject: [PATCH] net: dsa: mv88e6xxx: keep the pvid at 0 when VLAN-unaware
-
-The VLAN support in mv88e6xxx has a loaded history. Commit 2ea7a679ca2a
-("net: dsa: Don't add vlans when vlan filtering is disabled") noticed
-some issues with VLAN and decided the best way to deal with them was to
-make the DSA core ignore VLANs added by the bridge while VLAN awareness
-is turned off. Those issues were never explained, just presented as
-"at least one corner case".
-
-That approach had problems of its own, presented by
-commit 54a0ed0df496 ("net: dsa: provide an option for drivers to always
-receive bridge VLANs") for the DSA core, followed by
-commit 1fb74191988f ("net: dsa: mv88e6xxx: fix vlan setup") which
-applied ds->configure_vlan_while_not_filtering = true for mv88e6xxx in
-particular.
-
-We still don't know what corner case Andrew saw when he wrote
-commit 2ea7a679ca2a ("net: dsa: Don't add vlans when vlan filtering is
-disabled"), but Tobias now reports that when we use TX forwarding
-offload, pinging an external station from the bridge device is broken if
-the front-facing DSA user port has flooding turned off. The full
-description is in the link below, but for short, when a mv88e6xxx port
-is under a VLAN-unaware bridge, it inherits that bridge's pvid.
-So packets ingressing a user port will be classified to e.g. VID 1
-(assuming that value for the bridge_default_pvid), whereas when
-tag_dsa.c xmits towards a user port, it always sends packets using a VID
-of 0 if that port is standalone or under a VLAN-unaware bridge - or at
-least it did so prior to commit d82f8ab0d874 ("net: dsa: tag_dsa:
-offload the bridge forwarding process").
-
-In any case, when there is a conversation between the CPU and a station
-connected to a user port, the station's MAC address is learned in VID 1
-but the CPU tries to transmit through VID 0. The packets reach the
-intended station, but via flooding and not by virtue of matching the
-existing ATU entry.
-
-DSA has established (and enforced in other drivers: sja1105, felix,
-mt7530) that a VLAN-unaware port should use a private pvid, and not
-inherit the one from the bridge. The bridge's pvid should only be
-inherited when that bridge is VLAN-aware, so all state transitions need
-to be handled. On the other hand, all bridge VLANs should sit in the VTU
-starting with the moment when the bridge offloads them via switchdev,
-they are just not used.
-
-This solves the problem that Tobias sees because packets ingressing on
-VLAN-unaware user ports now get classified to VID 0, which is also the
-VID used by tag_dsa.c on xmit.
-
-Fixes: d82f8ab0d874 ("net: dsa: tag_dsa: offload the bridge forwarding process")
-Link: https://patchwork.kernel.org/project/netdevbpf/patch/20211003222312.284175-2-vladimir.oltean@nxp.com/#24491503
-Reported-by: Tobias Waldekranz <tobias@waldekranz.com>
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
----
- drivers/net/dsa/mv88e6xxx/chip.c | 56 +++++++++++++++++++++++++++++---
- drivers/net/dsa/mv88e6xxx/chip.h | 6 ++++
- drivers/net/dsa/mv88e6xxx/port.c | 21 ++++++++++++
- drivers/net/dsa/mv88e6xxx/port.h | 2 ++
- 4 files changed, 81 insertions(+), 4 deletions(-)
-
---- a/drivers/net/dsa/mv88e6xxx/chip.c
-+++ b/drivers/net/dsa/mv88e6xxx/chip.c
-@@ -1590,6 +1590,26 @@ static int mv88e6xxx_port_check_hw_vlan(
- return 0;
- }
-
-+static int mv88e6xxx_port_commit_pvid(struct mv88e6xxx_chip *chip, int port)
-+{
-+ struct dsa_port *dp = dsa_to_port(chip->ds, port);
-+ struct mv88e6xxx_port *p = &chip->ports[port];
-+ bool drop_untagged = false;
-+ u16 pvid = 0;
-+ int err;
-+
-+ if (dp->bridge_dev && br_vlan_enabled(dp->bridge_dev)) {
-+ pvid = p->bridge_pvid.vid;
-+ drop_untagged = !p->bridge_pvid.valid;
-+ }
-+
-+ err = mv88e6xxx_port_set_pvid(chip, port, pvid);
-+ if (err)
-+ return err;
-+
-+ return mv88e6xxx_port_drop_untagged(chip, port, drop_untagged);
-+}
-+
- static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
- bool vlan_filtering,
- struct switchdev_trans *trans)
-@@ -1603,7 +1623,16 @@ static int mv88e6xxx_port_vlan_filtering
- return chip->info->max_vid ? 0 : -EOPNOTSUPP;
-
- mv88e6xxx_reg_lock(chip);
-+
- err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
-+ if (err)
-+ goto unlock;
-+
-+ err = mv88e6xxx_port_commit_pvid(chip, port);
-+ if (err)
-+ goto unlock;
-+
-+unlock:
- mv88e6xxx_reg_unlock(chip);
-
- return err;
-@@ -1986,8 +2015,10 @@ static void mv88e6xxx_port_vlan_add(stru
- struct mv88e6xxx_chip *chip = ds->priv;
- bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
- bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
-+ struct mv88e6xxx_port *p = &chip->ports[port];
- bool warn;
- u8 member;
-+ int err;
- u16 vid;
-
- if (!chip->info->max_vid)
-@@ -2012,9 +2043,23 @@ static void mv88e6xxx_port_vlan_add(stru
- dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port,
- vid, untagged ? 'u' : 't');
-
-- if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
-- dev_err(ds->dev, "p%d: failed to set PVID %d\n", port,
-- vlan->vid_end);
-+ if (pvid) {
-+ p->bridge_pvid.vid = vlan->vid_end;
-+ p->bridge_pvid.valid = true;
-+
-+ err = mv88e6xxx_port_commit_pvid(chip, port);
-+ if (err)
-+ dev_err(ds->dev, "p%d: failed to set PVID %d", port,
-+ vlan->vid_end);
-+ } else if (vlan->vid_end && p->bridge_pvid.vid == vlan->vid_end) {
-+ /* The old pvid was reinstalled as a non-pvid VLAN */
-+ p->bridge_pvid.valid = false;
-+
-+ err = mv88e6xxx_port_commit_pvid(chip, port);
-+ if (err)
-+ dev_err(ds->dev, "p%d: failed to unset PVID %d", port,
-+ vlan->vid_end);
-+ }
-
- mv88e6xxx_reg_unlock(chip);
- }
-@@ -2065,6 +2110,7 @@ static int mv88e6xxx_port_vlan_del(struc
- const struct switchdev_obj_port_vlan *vlan)
- {
- struct mv88e6xxx_chip *chip = ds->priv;
-+ struct mv88e6xxx_port *p = &chip->ports[port];
- u16 pvid, vid;
- int err = 0;
-
-@@ -2083,7 +2129,9 @@ static int mv88e6xxx_port_vlan_del(struc
- goto unlock;
-
- if (vid == pvid) {
-- err = mv88e6xxx_port_set_pvid(chip, port, 0);
-+ p->bridge_pvid.valid = false;
-+
-+ err = mv88e6xxx_port_commit_pvid(chip, port);
- if (err)
- goto unlock;
- }
---- a/drivers/net/dsa/mv88e6xxx/chip.h
-+++ b/drivers/net/dsa/mv88e6xxx/chip.h
-@@ -224,9 +224,15 @@ struct mv88e6xxx_policy {
- u16 vid;
- };
-
-+struct mv88e6xxx_vlan {
-+ u16 vid;
-+ bool valid;
-+};
-+
- struct mv88e6xxx_port {
- struct mv88e6xxx_chip *chip;
- int port;
-+ struct mv88e6xxx_vlan bridge_pvid;
- u64 serdes_stats[2];
- u64 atu_member_violation;
- u64 atu_miss_violation;
---- a/drivers/net/dsa/mv88e6xxx/port.c
-+++ b/drivers/net/dsa/mv88e6xxx/port.c
-@@ -1062,6 +1062,27 @@ int mv88e6xxx_port_set_8021q_mode(struct
- return 0;
- }
-
-+int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port,
-+ bool drop_untagged)
-+{
-+ u16 old, new;
-+ int err;
-+
-+ err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &old);
-+ if (err)
-+ return err;
-+
-+ if (drop_untagged)
-+ new = old | MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED;
-+ else
-+ new = old & ~MV88E6XXX_PORT_CTL2_DISCARD_UNTAGGED;
-+
-+ if (new == old)
-+ return 0;
-+
-+ return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, new);
-+}
-+
- int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
- {
- u16 reg;
---- a/drivers/net/dsa/mv88e6xxx/port.h
-+++ b/drivers/net/dsa/mv88e6xxx/port.h
-@@ -364,6 +364,8 @@ int mv88e6390x_port_set_cmode(struct mv8
- phy_interface_t mode);
- int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
- int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
-+int mv88e6xxx_port_drop_untagged(struct mv88e6xxx_chip *chip, int port,
-+ bool drop_untagged);
- int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port);
- int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
- int upstream_port);