1
1
openwrt/target/linux/generic/pending-6.12/760-15-net-dsa-mxl862xx-support-BR_HAIRPIN_MODE-bridge-flag.patch
Daniel Golle 5b69e6a4a6 generic: 6.12: update MxL862xx DSA switch driver
Update driver to be ready for the upcoming firmware release.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
2026-05-27 19:01:52 +01:00

81 lines
3.3 KiB
Diff

From ba48edffc80f3dd676a9e8cf63aa4778a4ed0f0d Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Wed, 1 Apr 2026 13:43:12 +0100
Subject: [PATCH 15/19] net: dsa: mxl862xx: support BR_HAIRPIN_MODE bridge flag
Implement hairpin mode by including the port's own bridge port ID in
its forwarding portmap. When hairpin is enabled, bridged frames whose
destination resolves to the ingress port are allowed to egress there
instead of being dropped.
For LAG ports, the LAG's dedicated bridge port is added to the
master's portmap, which naturally propagates to the LAG bridge port
via the second loop in sync_bridge_members.
The port_bridge_flags handler toggles the bit directly on the cached
portmap and pushes the update via set_bridge_port, avoiding a full
bridge member rebuild since only the calling port is affected.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/dsa/mxl862xx/mxl862xx.c | 12 ++++++++++--
drivers/net/dsa/mxl862xx/mxl862xx.h | 5 +++++
2 files changed, 15 insertions(+), 2 deletions(-)
--- a/drivers/net/dsa/mxl862xx/mxl862xx.c
+++ b/drivers/net/dsa/mxl862xx/mxl862xx.c
@@ -774,6 +774,10 @@ static int __mxl862xx_set_bridge_port(st
}
mxl862xx_fw_portmap_set_bit(br_port_cfg.bridge_port_map,
mxl862xx_cpu_bridge_port_id(ds, port));
+ if (p->hairpin)
+ mxl862xx_fw_portmap_set_bit(br_port_cfg.bridge_port_map,
+ mxl862xx_lag_bridge_port(priv,
+ port));
} else {
mxl862xx_fw_portmap_set_bit(br_port_cfg.bridge_port_map,
mxl862xx_cpu_bridge_port_id(ds, port));
@@ -3911,7 +3915,7 @@ static int mxl862xx_port_pre_bridge_flag
struct netlink_ext_ack *extack)
{
if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD |
- BR_LEARNING))
+ BR_LEARNING | BR_HAIRPIN_MODE))
return -EINVAL;
return 0;
@@ -3953,7 +3957,11 @@ static int mxl862xx_port_bridge_flags(st
if (flags.mask & BR_LEARNING)
priv->ports[port].learning = !!(flags.val & BR_LEARNING);
- if (block != old_block || (flags.mask & BR_LEARNING)) {
+ if (flags.mask & BR_HAIRPIN_MODE)
+ priv->ports[port].hairpin = !!(flags.val & BR_HAIRPIN_MODE);
+
+ if ((block != old_block) ||
+ (flags.mask & (BR_LEARNING | BR_HAIRPIN_MODE))) {
priv->ports[port].flood_block = block;
ret = mxl862xx_set_bridge_port(ds, port);
if (ret)
--- a/drivers/net/dsa/mxl862xx/mxl862xx.h
+++ b/drivers/net/dsa/mxl862xx/mxl862xx.h
@@ -243,6 +243,10 @@ struct mxl862xx_port_stats {
* @stats_lock: protects accumulator reads in .get_stats64 against
* concurrent updates from the polling work
* @tag_8021q_vid: currently assigned tag_8021q management VID
+ * @hairpin: true when hairpin mode is active (BR_HAIRPIN_MODE);
+ * the port's own bridge port is included in its
+ * portmap so bridged frames can egress the ingress
+ * port
* @ingress_mirror: true when ingress mirroring is active on this port
* @egress_mirror: true when egress mirroring is active on this port
* @lag: non-NULL when port is member of a LAG group;
@@ -272,6 +276,7 @@ struct mxl862xx_port {
struct work_struct host_flood_work;
u16 tag_8021q_vid;
struct mxl862xx_evlan_block cpu_egress_evlan;
+ bool hairpin;
bool ingress_mirror;
bool egress_mirror;
struct dsa_lag *lag;