[PATCH] net: dsa: b53: Enable IGMP and MLD control packet CPU copies
From: Florian Fainelli
Date: Mon Oct 26 2026 - 13:26:12 EST
IGMPv2 reports and MLDv1 reports are addressed to the multicast group
itself. Once the first listener is installed in the ARL table, subsequent
reports can follow that entry without reaching the CPU. The bridge then
fails to learn additional listeners, although static MDB forwarding works.
Enable the high-level protocol classifiers so that IGMP and MLD control
packets are copied to the CPU independently of the multicast ARL lookup.
Retain normal L2 forwarding by clearing the CPU-only forwarding modes,
and preserve unrelated protocol-control fields.
Handle the BCM5395's 16-bit register and different classifier fields
separately from the 32-bit layout on the BCM531xx, BCM5301x and newer
integrated RoboSwitch families. Leave older devices with different IGMP
controls untouched, and propagate register access failures during setup.
Fixes: 5d65b64a3d97 ("net: dsa: b53: Add support for MDB")
Signed-off-by: Florian Fainelli <florian.fainelli@xxxxxxxxxxxx>
---
drivers/net/dsa/b53/b53_common.c | 50 ++++++++++++++++++++++++++++++++
drivers/net/dsa/b53/b53_regs.h | 17 +++++++++++
2 files changed, 67 insertions(+)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 0880310c9ce3..54844cfadf01 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -836,6 +836,52 @@ void b53_brcm_hdr_setup(struct dsa_switch *ds, int port)
}
EXPORT_SYMBOL(b53_brcm_hdr_setup);
+static int b53_enable_mcast_snooping(struct b53_device *dev)
+{
+ u32 val;
+ u16 val16;
+ int ret;
+
+ /* BCM5395 has a narrower register and a single IGMP classifier.
+ * Its ICMPv6 classifier also covers MLD.
+ */
+ if (dev->chip_id == BCM5395_DEVICE_ID) {
+ ret = b53_read16(dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL, &val16);
+ if (ret)
+ return ret;
+
+ val16 |= HL_PRTC_IGMP_IP_EN_5395 | HL_PRTC_ICMPV6_EN;
+ val16 &= ~(HL_PRTC_IGMP_FWD_MODE_5395 |
+ HL_PRTC_ICMPV6_FWD_MODE);
+
+ return b53_write16(dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL,
+ val16);
+ }
+
+ /* Older switches use different IGMP controls, not HL_PRTC_CTRL. */
+ if (!is531x5(dev) && !is5301x(dev) && !is58xx(dev))
+ return 0;
+
+ ret = b53_read32(dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL, &val);
+ if (ret)
+ return ret;
+
+ /* IGMPv2 and MLDv1 reports use the group's destination MAC. Once
+ * the first listener is offloaded, ordinary multicast forwarding
+ * can keep subsequent reports from reaching the bridge CPU.
+ * Copy control traffic to the CPU independently of the ARL lookup,
+ * retaining L2 forwarding rather than selecting CPU-only traps.
+ */
+ val |= HL_PRTC_IGMP_RPTLVE_EN | HL_PRTC_IGMP_QRY_EN |
+ HL_PRTC_IGMP_UKN_EN | HL_PRTC_MLD_RPTDONE_EN |
+ HL_PRTC_MLD_QRY_EN;
+ val &= ~(HL_PRTC_IGMP_RPTLVE_FWD_MODE | HL_PRTC_IGMP_QRY_FWD_MODE |
+ HL_PRTC_IGMP_UKN_FWD_MODE | HL_PRTC_MLD_RPTDONE_FWD_MODE |
+ HL_PRTC_MLD_QRY_FWD_MODE);
+
+ return b53_write32(dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL, val);
+}
+
static void b53_enable_cpu_port(struct b53_device *dev, int port)
{
u8 port_ctrl;
@@ -1334,6 +1380,10 @@ static int b53_setup(struct dsa_switch *ds)
b53_disable_port(ds, port);
}
+ ret = b53_enable_mcast_snooping(dev);
+ if (ret)
+ return ret;
+
return b53_setup_devlink_resources(ds);
}
diff --git a/drivers/net/dsa/b53/b53_regs.h b/drivers/net/dsa/b53/b53_regs.h
index 54a278db67c9..cfdb5ed38326 100644
--- a/drivers/net/dsa/b53/b53_regs.h
+++ b/drivers/net/dsa/b53/b53_regs.h
@@ -274,6 +274,23 @@
/* Revision ID register (8 bit) */
#define B53_REV_ID 0x40
+/* High-level protocol control (16 bit on BCM5395, otherwise 32 bit) */
+#define B53_HL_PRTC_CTRL 0x50
+#define HL_PRTC_ICMPV6_EN BIT(4)
+#define HL_PRTC_ICMPV6_FWD_MODE BIT(5)
+#define HL_PRTC_IGMP_IP_EN_5395 BIT(6)
+#define HL_PRTC_IGMP_FWD_MODE_5395 BIT(8)
+#define HL_PRTC_IGMP_RPTLVE_EN BIT(9)
+#define HL_PRTC_IGMP_RPTLVE_FWD_MODE BIT(10)
+#define HL_PRTC_IGMP_QRY_EN BIT(11)
+#define HL_PRTC_IGMP_QRY_FWD_MODE BIT(12)
+#define HL_PRTC_IGMP_UKN_EN BIT(13)
+#define HL_PRTC_IGMP_UKN_FWD_MODE BIT(14)
+#define HL_PRTC_MLD_RPTDONE_EN BIT(15)
+#define HL_PRTC_MLD_RPTDONE_FWD_MODE BIT(16)
+#define HL_PRTC_MLD_QRY_EN BIT(17)
+#define HL_PRTC_MLD_QRY_FWD_MODE BIT(18)
+
/* Broadcom header RX control (16 bit) */
#define B53_BRCM_HDR_RX_DIS 0x60
--
2.53.0