realtek: rtl839x: trap slow protocols to the cpu

The switch drops frames to 01-80-C2-00-00-02 (slow protocols). On
RTL839x the RMA action is FORWARD (0) normally and FLOOD (3) with
promisc/allmulti. Neither reaches the CPU. This breaks LACP bonding.

This improved code always sets the action for 01-80-C2-00-00-02 to
TRAP2CPU (2) and always sets the STP and VLAN bypass. So STP and VLAN
filtering do not drop them.

With promisc/allmulti, all RMA addresses are now trapped instead of
flooded, as flooded frames do not reach the CPU either.

The registers are now updated with regmap_update_bits(), so the
reserved bits of RMA_CTRL_0 and the bits above 9 of RMA_CTRL_3 are no
longer cleared. RMA_CTRL_3 is now also set in allmulti mode, so the
promisc bypass bits do not stay set after a change to allmulti.

Authored-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Signed-off-by: Harm Kroon <hhhkroon@hotmail.com>
Link: https://github.com/openwrt/openwrt/pull/25765
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
pull/25765/head
Harm Kroon 2026-10-13 16:43:43 +02:00 committed by Markus Stockhausen
parent 726d8fa101
commit b909154ce2
1 changed files with 30 additions and 26 deletions

View File

@ -858,35 +858,39 @@ static void rteth_838x_set_rx_mode(struct net_device *dev)
static void rteth_839x_set_rx_mode(struct net_device *dev)
{
struct rteth_ctrl *ctrl = netdev_priv(dev);
u32 rma_actions = 0;
u32 bypass = BIT(0) | BIT(6);
u32 rma0;
/* Flood all classes of RMA addresses (01-80-C2-00-00-{01..2F})
* CTRL_0_FULL = GENMASK(31, 2) = 0xFFFFFFFC
* Lower two bits are reserved, corresponding to RMA 01-80-C2-00-00-00
* CTRL_1_FULL = CTRL_2_FULL = GENMASK(31, 0)
*/
if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_0, 0);
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_1, 0);
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_2, 0);
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_3, 0);
}
if (dev->flags & IFF_ALLMULTI) {
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_0, GENMASK(31, 2));
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_1, GENMASK(31, 0));
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_2, GENMASK(31, 0));
}
if (dev->flags & IFF_PROMISC) {
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_0, GENMASK(31, 2));
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_1, GENMASK(31, 0));
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_2, GENMASK(31, 0));
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_3, GENMASK(9, 0));
}
/* Each two-bit RMA action field uses: 0 = forward, 1 = drop, 2 = trap to CPU. */
if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI))
rma_actions = 0xaaaaaaaaU;
/* Slow protocols (01-80-C2-00-00-02, e.g. LACP) are link-local. The
* switch drops them with FORWARD, so always trap them for bonding.
/*
* Always bypass STP and VLAN filtering for slow protocols:
* bit 0: SLOW_PROTO_BYPASS_STP
* bit 6: RMA_02_BYPASS_VLAN
*
* Promiscuous mode additionally enables the other RMA bypasses.
*/
regmap_update_bits(ctrl->map, RTETH_839X_RMA_CTRL_0, GENMASK(5, 4),
RTETH_839X_RMA_CTRL_0_SLOW_TRAP);
if (dev->flags & IFF_PROMISC)
bypass = GENMASK(9, 0);
/*
* Preserve lookup-miss handling (bit 10) and reserved bits.
* Program the bypasses before enabling the traps.
*/
regmap_update_bits(ctrl->map, RTETH_839X_RMA_CTRL_3,
GENMASK(9, 0), bypass);
/* Always trap 01-80-C2-00-00-02. Bits 1:0 of RMA_CTRL_0 are reserved. */
rma0 = (rma_actions & GENMASK(31, 2)) |
RTETH_839X_RMA_CTRL_0_SLOW_TRAP;
regmap_update_bits(ctrl->map, RTETH_839X_RMA_CTRL_0,
GENMASK(31, 2), rma0);
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_1, rma_actions);
regmap_write(ctrl->map, RTETH_839X_RMA_CTRL_2, rma_actions);
}
static void rteth_930x_set_rx_mode(struct net_device *dev)