diff mbox series

[RFC,4/4] net: dsa: sja1105: implement shared FDB dump

Message ID 20210821210018.1314952-5-vladimir.oltean@nxp.com (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series Faster ndo_fdb_dump for drivers with shared FDB | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Guessed tree name to be net-next
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cc_maintainers fail 6 maintainers not CCed: f.fainelli@gmail.com davem@davemloft.net olteanv@gmail.com kuba@kernel.org vivien.didelot@gmail.com andrew@lunn.ch
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 85 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/header_inline success Link

Commit Message

Vladimir Oltean Aug. 21, 2021, 9 p.m. UTC
This driver already walks linearly over the FDB in the .port_fdb_dump
method, so the .switch_fdb_dump can reuse the same logic, just call back
a different DSA method when it finds something.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/sja1105/sja1105_main.c | 50 +++++++++++++++++++-------
 1 file changed, 38 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 05ba65042b5f..e1e9e514814e 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -1747,14 +1747,17 @@  static int sja1105_fdb_del(struct dsa_switch *ds, int port,
 }
 
 static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
-			    dsa_fdb_dump_cb_t *cb, void *data)
+			    dsa_fdb_dump_cb_t *port_cb,
+			    dsa_switch_fdb_dump_cb_t *switch_cb,
+			    void *data)
 {
 	struct sja1105_private *priv = ds->priv;
 	struct device *dev = ds->dev;
-	int i;
+	int i, p;
 
 	for (i = 0; i < SJA1105_MAX_L2_LOOKUP_COUNT; i++) {
 		struct sja1105_l2_lookup_entry l2_lookup = {0};
+		unsigned long destports;
 		u8 macaddr[ETH_ALEN];
 		int rc;
 
@@ -1768,13 +1771,12 @@  static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
 			return rc;
 		}
 
-		/* FDB dump callback is per port. This means we have to
-		 * disregard a valid entry if it's not for this port, even if
-		 * only to revisit it later. This is inefficient because the
-		 * 1024-sized FDB table needs to be traversed 4 times through
-		 * SPI during a 'bridge fdb show' command.
+		destports = l2_lookup.destports;
+
+		/* If the FDB dump callback is per port, ignore the entries
+		 * belonging to a different one.
 		 */
-		if (!(l2_lookup.destports & BIT(port)))
+		if (port >= 0 && !(destports & BIT(port)))
 			continue;
 
 		/* We need to hide the FDB entry for unknown multicast */
@@ -1787,13 +1789,36 @@  static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
 		/* We need to hide the dsa_8021q VLANs from the user. */
 		if (!priv->vlan_aware)
 			l2_lookup.vlanid = 0;
-		rc = cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
-		if (rc)
-			return rc;
+
+		if (port_cb) {
+			rc = port_cb(macaddr, l2_lookup.vlanid,
+				     l2_lookup.lockeds, data);
+			if (rc)
+				return rc;
+		} else {
+			for_each_set_bit(p, &destports, ds->num_ports) {
+				rc = switch_cb(ds, p, macaddr, l2_lookup.vlanid,
+					       l2_lookup.lockeds);
+				if (rc)
+					return rc;
+			}
+		}
 	}
 	return 0;
 }
 
+static int sja1105_port_fdb_dump(struct dsa_switch *ds, int port,
+				 dsa_fdb_dump_cb_t *cb, void *data)
+{
+	return sja1105_fdb_dump(ds, port, cb, NULL, data);
+}
+
+static int sja1105_switch_fdb_dump(struct dsa_switch *ds,
+				   dsa_switch_fdb_dump_cb_t *cb)
+{
+	return sja1105_fdb_dump(ds, -1, NULL, cb, NULL);
+}
+
 static void sja1105_fast_age(struct dsa_switch *ds, int port)
 {
 	struct sja1105_private *priv = ds->priv;
@@ -3114,7 +3139,8 @@  const struct dsa_switch_ops sja1105_switch_ops = {
 	.get_sset_count		= sja1105_get_sset_count,
 	.get_ts_info		= sja1105_get_ts_info,
 	.port_disable		= sja1105_port_disable,
-	.port_fdb_dump		= sja1105_fdb_dump,
+	.port_fdb_dump		= sja1105_port_fdb_dump,
+	.switch_fdb_dump	= sja1105_switch_fdb_dump,
 	.port_fdb_add		= sja1105_fdb_add,
 	.port_fdb_del		= sja1105_fdb_del,
 	.port_fast_age		= sja1105_fast_age,