realtek: dsa: release the LAG table on error paths

rtldsa_93xx_lag_set_group2ports() gets an already locked table handle
from priv->r->lag_table() and releases it only on the success path, so
both error returns leave the mutex held for good.

The lock covers a whole table access register rather than one of its
tables, so the damage is wider than LAG: on RTL930x that register also
carries VLAN, the ingress ACL, spanning tree state, the packet counters
and port isolation, and every later access to any of them blocks. On
RTL931x the LAG table shares its register with port isolation.

Only the -ENOSPC path can be reached today, when a bond has more than
eight member ports; nothing bounds the member count before it.
Callers cannot reach the -EOPNOTSUPP path because
rtldsa_port_lag_join() already rejects any hash type other than
NETDEV_LAG_HASH_L2 and L23 in rtldsa_83xx_lag_can_offload(), and the
remaining callers pass a NULL info, but the missing release is a trap
for whoever changes that guard.

Not reproduced on hardware: the board here has eight ports, one too few
to trigger the reachable path, and no RTL931x is available.
Compile-tested on realtek/rtl930x and realtek/rtl838x.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25036
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
This commit is contained in:
Gennaro Cimmino
2026-09-05 19:26:28 +02:00
committed by Markus Stockhausen
parent 3809dfe5c6
commit a43f44ae3e
@@ -527,6 +527,7 @@ static int rtldsa_93xx_lag_set_group2ports(struct rtl838x_switch_priv *priv, int
pr_err("%s: Number of LAG ports too high: %u", __func__, pr_err("%s: Number of LAG ports too high: %u", __func__,
num_of_lag_ports); num_of_lag_ports);
rtl_table_release(r);
return -ENOSPC; return -ENOSPC;
} }
@@ -574,6 +575,7 @@ static int rtldsa_93xx_lag_set_group2ports(struct rtl838x_switch_priv *priv, int
e.ip4_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L23; e.ip4_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L23;
e.ip6_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L23; e.ip6_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L23;
} else { } else {
rtl_table_release(r);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
} }