[PATCH net-next 1/5] dpaa2-switch: rework FDB management on the bridge leave path

From: Ioana Ciornei

Date: Thu May 28 2026 - 13:43:58 EST


On bridge leave, the dpaa2_switch_port_set_fdb() function always
allocates a new FDB for the port which is becoming standalone. In case
no FDB is found, then the port leaving a bridge will continue to use the
current one.

The above logic does not cover the case in which there are multiple
bridges which have ports from the same DPSW instance. In this case, when
the last port leaves bridge #1, it finds an unused FDB to switch to, but
the old FDB is not marked as unused. Since the number of FDBs is equal
to the number of DPSW interfaces, this will eventually lead to multiple
ports sharing the same FDB.

Fix this by changing how we are managing the FDBs on the leave path.
Instead of directly allocating a new FDB, first verify if the current
port is the last one to leave a bridge. If this is the case, then
continue to use the current FDB and only allocate another FDB if there
are other ports remaining in the bridge.

Signed-off-by: Ioana Ciornei <ioana.ciornei@xxxxxxx>
---
.../ethernet/freescale/dpaa2/dpaa2-switch.c | 31 ++++++++++++++-----
1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index 52c1cb9cb7e0..782fef26b78e 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -54,27 +54,44 @@ dpaa2_switch_filter_block_get_unused(struct ethsw_core *ethsw)
static u16 dpaa2_switch_port_set_fdb(struct ethsw_port_priv *port_priv,
struct net_device *bridge_dev)
{
+ struct ethsw_core *ethsw = port_priv->ethsw_data;
struct ethsw_port_priv *other_port_priv = NULL;
struct dpaa2_switch_fdb *fdb;
struct net_device *other_dev;
+ bool last_fdb_user = true;
struct list_head *iter;
+ int i;

/* If we leave a bridge (bridge_dev is NULL), find an unused
* FDB and use that.
*/
if (!bridge_dev) {
- fdb = dpaa2_switch_fdb_get_unused(port_priv->ethsw_data);
-
- /* If there is no unused FDB, we must be the last port that
- * leaves the last bridge, all the others are standalone. We
- * can just keep the FDB that we already have.
- */
+ /* First verify if this is the last port to leave this bridge */
+ for (i = 0; i < ethsw->sw_attr.num_ifs; i++) {
+ if (!ethsw->ports[i] || ethsw->ports[i] == port_priv)
+ continue;
+ if (ethsw->ports[i]->fdb == port_priv->fdb) {
+ last_fdb_user = false;
+ break;
+ }
+ }

- if (!fdb) {
+ /* If this is the last user of the FDB, just keep using it. */
+ if (last_fdb_user) {
port_priv->fdb->bridge_dev = NULL;
return 0;
}

+ /* Since we are not the last port which leaves a bridge,
+ * acquire a new FDB and use it. The number of FDBs is sized to
+ * accommodate all switch ports as standalone, each with its
+ * private FDB, which means that dpaa2_switch_fdb_get_unused()
+ * must succeed here. WARN if not.
+ */
+ fdb = dpaa2_switch_fdb_get_unused(port_priv->ethsw_data);
+ if (WARN_ON(!fdb))
+ return 0;
+
port_priv->fdb = fdb;
port_priv->fdb->in_use = true;
port_priv->fdb->bridge_dev = NULL;
--
2.25.1