[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210308150405.3694678-3-tobias@waldekranz.com>
Date: Mon, 8 Mar 2021 16:04:05 +0100
From: Tobias Waldekranz <tobias@...dekranz.com>
To: davem@...emloft.net, kuba@...nel.org
Cc: andrew@...n.ch, vivien.didelot@...il.com, f.fainelli@...il.com,
olteanv@...il.com, netdev@...r.kernel.org
Subject: [PATCH net 2/2] net: dsa: mv88e6xxx: Never apply VLANs on standalone ports to VTU
Standalone ports always have VLAN filtering (Port Control 2, 802.1Q
Mode) disabled. So adding VIDs for any VLAN uppers to the VTU does not
make one bit of difference on the ingress filtering, the CPU will
still receive traffic from all VLANs.
It does however needlessly consume a precious global resource, namely
a VID. Therefore, we refine the requirement for accepting a VLAN on a
port by mandating that the port must be offloading a bridge, in which
case the device will actually make use of the filtering.
Fixes: 061f6a505ac3 ("net: dsa: Add ndo_vlan_rx_{add, kill}_vid implementation")
Signed-off-by: Tobias Waldekranz <tobias@...dekranz.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 40 ++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 903d619e08ed..0ba44bcac7da 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1618,6 +1618,38 @@ static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
return err;
}
+static bool mv88e6xxx_port_offloads_vlans(struct dsa_switch *ds, int port)
+{
+ struct dsa_port *dp = dsa_to_port(ds, port);
+ struct mv88e6xxx_chip *chip = ds->priv;
+
+ if (!mv88e6xxx_max_vid(chip))
+ return false;
+
+ /* There are roughly two scenarios in which VLANs may be added
+ * to a non-bridged port:
+ * (a) (b) br0
+ * /
+ * vlan1 bond0
+ * / / \
+ * swp0 swp0 swp1
+ *
+ * Either (a) a VLAN upper is added to a non-bridged port; or
+ * (b) a port is an indirect lower to a bridge via some
+ * stacked interface that is not offloaded, e.g. a bond in
+ * broadcast mode.
+ *
+ * We still get a callback in these cases as there are other
+ * DSA devices which cannot control VLAN filtering per
+ * port. mv88e6xxx is not one of those, so we can safely
+ * fallback to software VLANs.
+ */
+ if (dsa_is_user_port(ds, port) && !dp->bridge_dev)
+ return false;
+
+ return true;
+}
+
static int
mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
@@ -1625,9 +1657,6 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
struct mv88e6xxx_chip *chip = ds->priv;
int err;
- if (!mv88e6xxx_max_vid(chip))
- return -EOPNOTSUPP;
-
/* If the requested port doesn't belong to the same bridge as the VLAN
* members, do not support it (yet) and fallback to software VLAN.
*/
@@ -1993,6 +2022,9 @@ static int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
u8 member;
int err;
+ if (!mv88e6xxx_port_offloads_vlans(ds, port))
+ return -EOPNOTSUPP;
+
err = mv88e6xxx_port_vlan_prepare(ds, port, vlan);
if (err)
return err;
@@ -2081,7 +2113,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
int err = 0;
u16 pvid;
- if (!mv88e6xxx_max_vid(chip))
+ if (!mv88e6xxx_port_offloads_vlans(ds, port))
return -EOPNOTSUPP;
mv88e6xxx_reg_lock(chip);
--
2.25.1
Powered by blists - more mailing lists