[openwrt/openwrt] generic: 6.12: backport b53 patches from netdev-next

LEDE Commits lede-commits at lists.infradead.org
Fri Nov 21 12:43:29 PST 2025


noltari pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/08964109beb25127936b1d3e5729c208bb79a7b4

commit 08964109beb25127936b1d3e5729c208bb79a7b4
Author: Álvaro Fernández Rojas <noltari at gmail.com>
AuthorDate: Wed Nov 19 09:42:20 2025 +0100

    generic: 6.12: backport b53 patches from netdev-next
    
    These patches have been accepted in netdev-next for linux v6.19.
    
    2b3013ac0302 net: dsa: b53: add support for bcm63xx ARL entry format
    300f78e8b6b7 net: dsa: b53: add support for 5389/5397/5398 ARL entry format
    a7e73339ad46 net: dsa: b53: move ARL entry functions into ops struct
    e0c476f325a8 net: dsa: b53: split reading search entry into their own functions
    1716be6db04a net: dsa: b53: provide accessors for accessing ARL_SRCH_CTL
    bf6e9d2ae1db net: dsa: b53: move writing ARL entries into their own functions
    4a291fe72267 net: dsa: b53: move reading ARL entries into their own function
    a6e4fd38bf2f net: dsa: b53: b53_arl_read{,25}(): use the entry for comparision
    
    Signed-off-by: Álvaro Fernández Rojas <noltari at gmail.com>
---
 ...arl_read-25-use-the-entry-for-comparision.patch |  85 +++++
 ...ading-ARL-entries-into-their-own-function.patch | 117 +++++++
 ...ting-ARL-entries-into-their-own-functions.patch |  93 ++++++
 ...vide-accessors-for-accessing-ARL_SRCH_CTL.patch |  85 +++++
 ...ing-search-entry-into-their-own-functions.patch |  86 +++++
 ...-move-ARL-entry-functions-into-ops-struct.patch | 348 +++++++++++++++++++++
 ...pport-for-5389-5397-5398-ARL-entry-format.patch | 221 +++++++++++++
 ...-add-support-for-bcm63xx-ARL-entry-format.patch | 177 +++++++++++
 8 files changed, 1212 insertions(+)

diff --git a/target/linux/generic/backport-6.12/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch b/target/linux/generic/backport-6.12/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch
new file mode 100644
index 0000000000..2b6cff796f
--- /dev/null
+++ b/target/linux/generic/backport-6.12/612-01-v6.19-net-dsa-b53-b53_arl_read-25-use-the-entry-for-comparision.patch
@@ -0,0 +1,85 @@
+From a6e4fd38bf2f2e2363b61c27f4e6c49b14e4bb07 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski at gmail.com>
+Date: Fri, 7 Nov 2025 09:07:42 +0100
+Subject: [PATCH] net: dsa: b53: b53_arl_read{,25}(): use the entry for
+ comparision
+
+Align the b53_arl_read{,25}() functions by consistently using the
+parsed arl entry instead of parsing the raw registers again.
+
+Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/20251107080749.26936-2-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 22 ++++++++++------------
+ 1 file changed, 10 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -1830,7 +1830,7 @@ static int b53_arl_rw_op(struct b53_devi
+ 	return b53_arl_op_wait(dev);
+ }
+ 
+-static int b53_arl_read(struct b53_device *dev, u64 mac,
++static int b53_arl_read(struct b53_device *dev, const u8 *mac,
+ 			u16 vid, struct b53_arl_entry *ent, u8 *idx)
+ {
+ 	DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
+@@ -1854,14 +1854,13 @@ static int b53_arl_read(struct b53_devic
+ 			   B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);
+ 		b53_arl_to_entry(ent, mac_vid, fwd_entry);
+ 
+-		if (!(fwd_entry & ARLTBL_VALID)) {
++		if (!ent->is_valid) {
+ 			set_bit(i, free_bins);
+ 			continue;
+ 		}
+-		if ((mac_vid & ARLTBL_MAC_MASK) != mac)
++		if (!ether_addr_equal(ent->mac, mac))
+ 			continue;
+-		if (dev->vlan_enabled &&
+-		    ((mac_vid >> ARLTBL_VID_S) & ARLTBL_VID_MASK) != vid)
++		if (dev->vlan_enabled && ent->vid != vid)
+ 			continue;
+ 		*idx = i;
+ 		return 0;
+@@ -1871,7 +1870,7 @@ static int b53_arl_read(struct b53_devic
+ 	return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT;
+ }
+ 
+-static int b53_arl_read_25(struct b53_device *dev, u64 mac,
++static int b53_arl_read_25(struct b53_device *dev, const u8 *mac,
+ 			   u16 vid, struct b53_arl_entry *ent, u8 *idx)
+ {
+ 	DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
+@@ -1893,14 +1892,13 @@ static int b53_arl_read_25(struct b53_de
+ 
+ 		b53_arl_to_entry_25(ent, mac_vid);
+ 
+-		if (!(mac_vid & ARLTBL_VALID_25)) {
++		if (!ent->is_valid) {
+ 			set_bit(i, free_bins);
+ 			continue;
+ 		}
+-		if ((mac_vid & ARLTBL_MAC_MASK) != mac)
++		if (!ether_addr_equal(ent->mac, mac))
+ 			continue;
+-		if (dev->vlan_enabled &&
+-		    ((mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25) != vid)
++		if (dev->vlan_enabled && ent->vid != vid)
+ 			continue;
+ 		*idx = i;
+ 		return 0;
+@@ -1933,9 +1931,9 @@ static int b53_arl_op(struct b53_device
+ 		return ret;
+ 
+ 	if (is5325(dev) || is5365(dev))
+-		ret = b53_arl_read_25(dev, mac, vid, &ent, &idx);
++		ret = b53_arl_read_25(dev, addr, vid, &ent, &idx);
+ 	else
+-		ret = b53_arl_read(dev, mac, vid, &ent, &idx);
++		ret = b53_arl_read(dev, addr, vid, &ent, &idx);
+ 
+ 	/* If this is a read, just finish now */
+ 	if (op)
diff --git a/target/linux/generic/backport-6.12/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch b/target/linux/generic/backport-6.12/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch
new file mode 100644
index 0000000000..8cf85ce7ad
--- /dev/null
+++ b/target/linux/generic/backport-6.12/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch
@@ -0,0 +1,117 @@
+From 4a291fe7226736a465ddb3fa93c21fcef7162ec7 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski at gmail.com>
+Date: Fri, 7 Nov 2025 09:07:43 +0100
+Subject: [PATCH] net: dsa: b53: move reading ARL entries into their own
+ function
+
+Instead of duplicating the whole code iterating over all bins for
+BCM5325, factor out reading and parsing the entry into its own
+functions, and name it the modern one after the first chip with that ARL
+format, (BCM53)95.
+
+Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/20251107080749.26936-3-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 69 +++++++++++---------------------
+ 1 file changed, 23 insertions(+), 46 deletions(-)
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -1830,48 +1830,30 @@ static int b53_arl_rw_op(struct b53_devi
+ 	return b53_arl_op_wait(dev);
+ }
+ 
+-static int b53_arl_read(struct b53_device *dev, const u8 *mac,
+-			u16 vid, struct b53_arl_entry *ent, u8 *idx)
++static void b53_arl_read_entry_25(struct b53_device *dev,
++				  struct b53_arl_entry *ent, u8 idx)
+ {
+-	DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
+-	unsigned int i;
+-	int ret;
+-
+-	ret = b53_arl_op_wait(dev);
+-	if (ret)
+-		return ret;
++	u64 mac_vid;
+ 
+-	bitmap_zero(free_bins, dev->num_arl_bins);
+-
+-	/* Read the bins */
+-	for (i = 0; i < dev->num_arl_bins; i++) {
+-		u64 mac_vid;
+-		u32 fwd_entry;
+-
+-		b53_read64(dev, B53_ARLIO_PAGE,
+-			   B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid);
+-		b53_read32(dev, B53_ARLIO_PAGE,
+-			   B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);
+-		b53_arl_to_entry(ent, mac_vid, fwd_entry);
++	b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx),
++		   &mac_vid);
++	b53_arl_to_entry_25(ent, mac_vid);
++}
+ 
+-		if (!ent->is_valid) {
+-			set_bit(i, free_bins);
+-			continue;
+-		}
+-		if (!ether_addr_equal(ent->mac, mac))
+-			continue;
+-		if (dev->vlan_enabled && ent->vid != vid)
+-			continue;
+-		*idx = i;
+-		return 0;
+-	}
++static void b53_arl_read_entry_95(struct b53_device *dev,
++				  struct b53_arl_entry *ent, u8 idx)
++{
++	u32 fwd_entry;
++	u64 mac_vid;
+ 
+-	*idx = find_first_bit(free_bins, dev->num_arl_bins);
+-	return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT;
++	b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx),
++		   &mac_vid);
++	b53_read32(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx), &fwd_entry);
++	b53_arl_to_entry(ent, mac_vid, fwd_entry);
+ }
+ 
+-static int b53_arl_read_25(struct b53_device *dev, const u8 *mac,
+-			   u16 vid, struct b53_arl_entry *ent, u8 *idx)
++static int b53_arl_read(struct b53_device *dev, const u8 *mac,
++			u16 vid, struct b53_arl_entry *ent, u8 *idx)
+ {
+ 	DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
+ 	unsigned int i;
+@@ -1885,12 +1867,10 @@ static int b53_arl_read_25(struct b53_de
+ 
+ 	/* Read the bins */
+ 	for (i = 0; i < dev->num_arl_bins; i++) {
+-		u64 mac_vid;
+-
+-		b53_read64(dev, B53_ARLIO_PAGE,
+-			   B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid);
+-
+-		b53_arl_to_entry_25(ent, mac_vid);
++		if (is5325(dev) || is5365(dev))
++			b53_arl_read_entry_25(dev, ent, i);
++		else
++			b53_arl_read_entry_95(dev, ent, i);
+ 
+ 		if (!ent->is_valid) {
+ 			set_bit(i, free_bins);
+@@ -1930,10 +1910,7 @@ static int b53_arl_op(struct b53_device
+ 	if (ret)
+ 		return ret;
+ 
+-	if (is5325(dev) || is5365(dev))
+-		ret = b53_arl_read_25(dev, addr, vid, &ent, &idx);
+-	else
+-		ret = b53_arl_read(dev, addr, vid, &ent, &idx);
++	ret = b53_arl_read(dev, addr, vid, &ent, &idx);
+ 
+ 	/* If this is a read, just finish now */
+ 	if (op)
diff --git a/target/linux/generic/backport-6.12/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch b/target/linux/generic/backport-6.12/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch
new file mode 100644
index 0000000000..a171232d49
--- /dev/null
+++ b/target/linux/generic/backport-6.12/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch
@@ -0,0 +1,93 @@
+From bf6e9d2ae1dbafee53ec4ccd126595172e1e5278 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski at gmail.com>
+Date: Fri, 7 Nov 2025 09:07:44 +0100
+Subject: [PATCH] net: dsa: b53: move writing ARL entries into their own
+ functions
+
+Move writing ARL entries into individual functions for each format.
+
+Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/20251107080749.26936-4-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 38 ++++++++++++++++++++++----------
+ 1 file changed, 26 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -1840,6 +1840,16 @@ static void b53_arl_read_entry_25(struct
+ 	b53_arl_to_entry_25(ent, mac_vid);
+ }
+ 
++static void b53_arl_write_entry_25(struct b53_device *dev,
++				   const struct b53_arl_entry *ent, u8 idx)
++{
++	u64 mac_vid;
++
++	b53_arl_from_entry_25(&mac_vid, ent);
++	b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx),
++		    mac_vid);
++}
++
+ static void b53_arl_read_entry_95(struct b53_device *dev,
+ 				  struct b53_arl_entry *ent, u8 idx)
+ {
+@@ -1852,6 +1862,19 @@ static void b53_arl_read_entry_95(struct
+ 	b53_arl_to_entry(ent, mac_vid, fwd_entry);
+ }
+ 
++static void b53_arl_write_entry_95(struct b53_device *dev,
++				   const struct b53_arl_entry *ent, u8 idx)
++{
++	u32 fwd_entry;
++	u64 mac_vid;
++
++	b53_arl_from_entry(&mac_vid, &fwd_entry, ent);
++	b53_write64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx),
++		    mac_vid);
++	b53_write32(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx),
++		    fwd_entry);
++}
++
+ static int b53_arl_read(struct b53_device *dev, const u8 *mac,
+ 			u16 vid, struct b53_arl_entry *ent, u8 *idx)
+ {
+@@ -1892,9 +1915,8 @@ static int b53_arl_op(struct b53_device
+ 		      const unsigned char *addr, u16 vid, bool is_valid)
+ {
+ 	struct b53_arl_entry ent;
+-	u32 fwd_entry;
+-	u64 mac, mac_vid = 0;
+ 	u8 idx = 0;
++	u64 mac;
+ 	int ret;
+ 
+ 	/* Convert the array into a 64-bit MAC */
+@@ -1927,7 +1949,6 @@ static int b53_arl_op(struct b53_device
+ 		/* We could not find a matching MAC, so reset to a new entry */
+ 		dev_dbg(dev->dev, "{%pM,%.4d} not found, using idx: %d\n",
+ 			addr, vid, idx);
+-		fwd_entry = 0;
+ 		break;
+ 	default:
+ 		dev_dbg(dev->dev, "{%pM,%.4d} found, using idx: %d\n",
+@@ -1955,16 +1976,9 @@ static int b53_arl_op(struct b53_device
+ 	ent.is_age = false;
+ 	memcpy(ent.mac, addr, ETH_ALEN);
+ 	if (is5325(dev) || is5365(dev))
+-		b53_arl_from_entry_25(&mac_vid, &ent);
++		b53_arl_write_entry_25(dev, &ent, idx);
+ 	else
+-		b53_arl_from_entry(&mac_vid, &fwd_entry, &ent);
+-
+-	b53_write64(dev, B53_ARLIO_PAGE,
+-		    B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid);
+-
+-	if (!is5325(dev) && !is5365(dev))
+-		b53_write32(dev, B53_ARLIO_PAGE,
+-			    B53_ARLTBL_DATA_ENTRY(idx), fwd_entry);
++		b53_arl_write_entry_95(dev, &ent, idx);
+ 
+ 	return b53_arl_rw_op(dev, 0);
+ }
diff --git a/target/linux/generic/backport-6.12/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch b/target/linux/generic/backport-6.12/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch
new file mode 100644
index 0000000000..2ed88e4605
--- /dev/null
+++ b/target/linux/generic/backport-6.12/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch
@@ -0,0 +1,85 @@
+From 1716be6db04af53bac9b869f01156a460595cf41 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski at gmail.com>
+Date: Fri, 7 Nov 2025 09:07:45 +0100
+Subject: [PATCH] net: dsa: b53: provide accessors for accessing ARL_SRCH_CTL
+
+In order to more easily support more formats, move accessing
+ARL_SRCH_CTL into helper functions to contain the differences.
+
+Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/20251107080749.26936-5-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 37 +++++++++++++++++++++-----------
+ 1 file changed, 24 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -2013,18 +2013,37 @@ int b53_fdb_del(struct dsa_switch *ds, i
+ }
+ EXPORT_SYMBOL(b53_fdb_del);
+ 
+-static int b53_arl_search_wait(struct b53_device *dev)
++static void b53_read_arl_srch_ctl(struct b53_device *dev, u8 *val)
+ {
+-	unsigned int timeout = 1000;
+-	u8 reg, offset;
++	u8 offset;
++
++	if (is5325(dev) || is5365(dev))
++		offset = B53_ARL_SRCH_CTL_25;
++	else
++		offset = B53_ARL_SRCH_CTL;
++
++	b53_read8(dev, B53_ARLIO_PAGE, offset, val);
++}
++
++static void b53_write_arl_srch_ctl(struct b53_device *dev, u8 val)
++{
++	u8 offset;
+ 
+ 	if (is5325(dev) || is5365(dev))
+ 		offset = B53_ARL_SRCH_CTL_25;
+ 	else
+ 		offset = B53_ARL_SRCH_CTL;
+ 
++	b53_write8(dev, B53_ARLIO_PAGE, offset, val);
++}
++
++static int b53_arl_search_wait(struct b53_device *dev)
++{
++	unsigned int timeout = 1000;
++	u8 reg;
++
+ 	do {
+-		b53_read8(dev, B53_ARLIO_PAGE, offset, &reg);
++		b53_read_arl_srch_ctl(dev, &reg);
+ 		if (!(reg & ARL_SRCH_STDN))
+ 			return -ENOENT;
+ 
+@@ -2079,23 +2098,15 @@ int b53_fdb_dump(struct dsa_switch *ds,
+ 	unsigned int count = 0, results_per_hit = 1;
+ 	struct b53_device *priv = ds->priv;
+ 	struct b53_arl_entry results[2];
+-	u8 offset;
+ 	int ret;
+-	u8 reg;
+ 
+ 	if (priv->num_arl_bins > 2)
+ 		results_per_hit = 2;
+ 
+ 	mutex_lock(&priv->arl_mutex);
+ 
+-	if (is5325(priv) || is5365(priv))
+-		offset = B53_ARL_SRCH_CTL_25;
+-	else
+-		offset = B53_ARL_SRCH_CTL;
+-
+ 	/* Start search operation */
+-	reg = ARL_SRCH_STDN;
+-	b53_write8(priv, B53_ARLIO_PAGE, offset, reg);
++	b53_write_arl_srch_ctl(priv, ARL_SRCH_STDN);
+ 
+ 	do {
+ 		ret = b53_arl_search_wait(priv);
diff --git a/target/linux/generic/backport-6.12/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch b/target/linux/generic/backport-6.12/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch
new file mode 100644
index 0000000000..3e263f8cfb
--- /dev/null
+++ b/target/linux/generic/backport-6.12/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch
@@ -0,0 +1,86 @@
+From e0c476f325a8c9b961a3d446c24d3c8ecae7d186 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski at gmail.com>
+Date: Fri, 7 Nov 2025 09:07:46 +0100
+Subject: [PATCH] net: dsa: b53: split reading search entry into their own
+ functions
+
+Split reading search entries into a function for each format.
+
+Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/20251107080749.26936-6-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 56 ++++++++++++++++++++++----------
+ 1 file changed, 38 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -2056,28 +2056,48 @@ static int b53_arl_search_wait(struct b5
+ 	return -ETIMEDOUT;
+ }
+ 
+-static void b53_arl_search_rd(struct b53_device *dev, u8 idx,
+-			      struct b53_arl_entry *ent)
++static void b53_arl_search_read_25(struct b53_device *dev, u8 idx,
++				   struct b53_arl_entry *ent)
+ {
+ 	u64 mac_vid;
+ 
+-	if (is5325(dev)) {
+-		b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25,
+-			   &mac_vid);
+-		b53_arl_to_entry_25(ent, mac_vid);
+-	} else if (is5365(dev)) {
+-		b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65,
+-			   &mac_vid);
+-		b53_arl_to_entry_25(ent, mac_vid);
+-	} else {
+-		u32 fwd_entry;
+-
+-		b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx),
+-			   &mac_vid);
+-		b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx),
+-			   &fwd_entry);
+-		b53_arl_to_entry(ent, mac_vid, fwd_entry);
+-	}
++	b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25,
++		   &mac_vid);
++	b53_arl_to_entry_25(ent, mac_vid);
++}
++
++static void b53_arl_search_read_65(struct b53_device *dev, u8 idx,
++				   struct b53_arl_entry *ent)
++{
++	u64 mac_vid;
++
++	b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65,
++		   &mac_vid);
++	b53_arl_to_entry_25(ent, mac_vid);
++}
++
++static void b53_arl_search_read_95(struct b53_device *dev, u8 idx,
++				   struct b53_arl_entry *ent)
++{
++	u32 fwd_entry;
++	u64 mac_vid;
++
++	b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx),
++		   &mac_vid);
++	b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx),
++		   &fwd_entry);
++	b53_arl_to_entry(ent, mac_vid, fwd_entry);
++}
++
++static void b53_arl_search_rd(struct b53_device *dev, u8 idx,
++			      struct b53_arl_entry *ent)
++{
++	if (is5325(dev))
++		b53_arl_search_read_25(dev, idx, ent);
++	else if (is5365(dev))
++		b53_arl_search_read_65(dev, idx, ent);
++	else
++		b53_arl_search_read_95(dev, idx, ent);
+ }
+ 
+ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
diff --git a/target/linux/generic/backport-6.12/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch b/target/linux/generic/backport-6.12/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch
new file mode 100644
index 0000000000..dfa902d048
--- /dev/null
+++ b/target/linux/generic/backport-6.12/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch
@@ -0,0 +1,348 @@
+From a7e73339ad46ade76d29fb6cc7d7854222608c26 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski at gmail.com>
+Date: Fri, 7 Nov 2025 09:07:47 +0100
+Subject: [PATCH] net: dsa: b53: move ARL entry functions into ops struct
+
+Now that the differences in ARL entry formats are neatly contained into
+functions per chip family, wrap them into an ops struct and add wrapper
+functions to access them.
+
+Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/20251107080749.26936-7-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 67 ++++++++++++++++++++++----------
+ drivers/net/dsa/b53/b53_priv.h   | 30 ++++++++++++++
+ 2 files changed, 76 insertions(+), 21 deletions(-)
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -1890,10 +1890,7 @@ static int b53_arl_read(struct b53_devic
+ 
+ 	/* Read the bins */
+ 	for (i = 0; i < dev->num_arl_bins; i++) {
+-		if (is5325(dev) || is5365(dev))
+-			b53_arl_read_entry_25(dev, ent, i);
+-		else
+-			b53_arl_read_entry_95(dev, ent, i);
++		b53_arl_read_entry(dev, ent, i);
+ 
+ 		if (!ent->is_valid) {
+ 			set_bit(i, free_bins);
+@@ -1975,10 +1972,7 @@ static int b53_arl_op(struct b53_device
+ 	ent.is_static = true;
+ 	ent.is_age = false;
+ 	memcpy(ent.mac, addr, ETH_ALEN);
+-	if (is5325(dev) || is5365(dev))
+-		b53_arl_write_entry_25(dev, &ent, idx);
+-	else
+-		b53_arl_write_entry_95(dev, &ent, idx);
++	b53_arl_write_entry(dev, &ent, idx);
+ 
+ 	return b53_arl_rw_op(dev, 0);
+ }
+@@ -2089,17 +2083,6 @@ static void b53_arl_search_read_95(struc
+ 	b53_arl_to_entry(ent, mac_vid, fwd_entry);
+ }
+ 
+-static void b53_arl_search_rd(struct b53_device *dev, u8 idx,
+-			      struct b53_arl_entry *ent)
+-{
+-	if (is5325(dev))
+-		b53_arl_search_read_25(dev, idx, ent);
+-	else if (is5365(dev))
+-		b53_arl_search_read_65(dev, idx, ent);
+-	else
+-		b53_arl_search_read_95(dev, idx, ent);
+-}
+-
+ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
+ 			dsa_fdb_dump_cb_t *cb, void *data)
+ {
+@@ -2133,13 +2116,13 @@ int b53_fdb_dump(struct dsa_switch *ds,
+ 		if (ret)
+ 			break;
+ 
+-		b53_arl_search_rd(priv, 0, &results[0]);
++		b53_arl_search_read(priv, 0, &results[0]);
+ 		ret = b53_fdb_copy(port, &results[0], cb, data);
+ 		if (ret)
+ 			break;
+ 
+ 		if (results_per_hit == 2) {
+-			b53_arl_search_rd(priv, 1, &results[1]);
++			b53_arl_search_read(priv, 1, &results[1]);
+ 			ret = b53_fdb_copy(port, &results[1], cb, data);
+ 			if (ret)
+ 				break;
+@@ -2672,6 +2655,24 @@ static const struct dsa_switch_ops b53_s
+ 	.port_change_mtu	= b53_change_mtu,
+ };
+ 
++static const struct b53_arl_ops b53_arl_ops_25 = {
++	.arl_read_entry = b53_arl_read_entry_25,
++	.arl_write_entry = b53_arl_write_entry_25,
++	.arl_search_read = b53_arl_search_read_25,
++};
++
++static const struct b53_arl_ops b53_arl_ops_65 = {
++	.arl_read_entry = b53_arl_read_entry_25,
++	.arl_write_entry = b53_arl_write_entry_25,
++	.arl_search_read = b53_arl_search_read_65,
++};
++
++static const struct b53_arl_ops b53_arl_ops_95 = {
++	.arl_read_entry = b53_arl_read_entry_95,
++	.arl_write_entry = b53_arl_write_entry_95,
++	.arl_search_read = b53_arl_search_read_95,
++};
++
+ struct b53_chip_data {
+ 	u32 chip_id;
+ 	const char *dev_name;
+@@ -2685,6 +2686,7 @@ struct b53_chip_data {
+ 	u8 duplex_reg;
+ 	u8 jumbo_pm_reg;
+ 	u8 jumbo_size_reg;
++	const struct b53_arl_ops *arl_ops;
+ };
+ 
+ #define B53_VTA_REGS	\
+@@ -2704,6 +2706,7 @@ static const struct b53_chip_data b53_sw
+ 		.arl_buckets = 1024,
+ 		.imp_port = 5,
+ 		.duplex_reg = B53_DUPLEX_STAT_FE,
++		.arl_ops = &b53_arl_ops_25,
+ 	},
+ 	{
+ 		.chip_id = BCM5365_DEVICE_ID,
+@@ -2714,6 +2717,7 @@ static const struct b53_chip_data b53_sw
+ 		.arl_buckets = 1024,
+ 		.imp_port = 5,
+ 		.duplex_reg = B53_DUPLEX_STAT_FE,
++		.arl_ops = &b53_arl_ops_65,
+ 	},
+ 	{
+ 		.chip_id = BCM5389_DEVICE_ID,
+@@ -2727,6 +2731,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM5395_DEVICE_ID,
+@@ -2740,6 +2745,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM5397_DEVICE_ID,
+@@ -2753,6 +2759,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM5398_DEVICE_ID,
+@@ -2766,6 +2773,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53101_DEVICE_ID,
+@@ -2779,6 +2787,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53115_DEVICE_ID,
+@@ -2792,6 +2801,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53125_DEVICE_ID,
+@@ -2805,6 +2815,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53128_DEVICE_ID,
+@@ -2818,6 +2829,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM63XX_DEVICE_ID,
+@@ -2831,6 +2843,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_63XX,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53010_DEVICE_ID,
+@@ -2844,6 +2857,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53011_DEVICE_ID,
+@@ -2857,6 +2871,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53012_DEVICE_ID,
+@@ -2870,6 +2885,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53018_DEVICE_ID,
+@@ -2883,6 +2899,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53019_DEVICE_ID,
+@@ -2896,6 +2913,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM58XX_DEVICE_ID,
+@@ -2909,6 +2927,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM583XX_DEVICE_ID,
+@@ -2922,6 +2941,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	/* Starfighter 2 */
+ 	{
+@@ -2936,6 +2956,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM7445_DEVICE_ID,
+@@ -2949,6 +2970,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM7278_DEVICE_ID,
+@@ -2962,6 +2984,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ 	{
+ 		.chip_id = BCM53134_DEVICE_ID,
+@@ -2976,6 +2999,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
++		.arl_ops = &b53_arl_ops_95,
+ 	},
+ };
+ 
+@@ -3004,6 +3028,7 @@ static int b53_switch_init(struct b53_de
+ 			dev->num_vlans = chip->vlans;
+ 			dev->num_arl_bins = chip->arl_bins;
+ 			dev->num_arl_buckets = chip->arl_buckets;
++			dev->arl_ops = chip->arl_ops;
+ 			break;
+ 		}
+ 	}
+--- a/drivers/net/dsa/b53/b53_priv.h
++++ b/drivers/net/dsa/b53/b53_priv.h
+@@ -58,6 +58,17 @@ struct b53_io_ops {
+ 				bool link_up);
+ };
+ 
++struct b53_arl_entry;
++
++struct b53_arl_ops {
++	void (*arl_read_entry)(struct b53_device *dev,
++			       struct b53_arl_entry *ent, u8 idx);
++	void (*arl_write_entry)(struct b53_device *dev,
++				const struct b53_arl_entry *ent, u8 idx);
++	void (*arl_search_read)(struct b53_device *dev, u8 idx,
++				struct b53_arl_entry *ent);
++};
++
+ #define B53_INVALID_LANE	0xff
+ 
+ enum {
+@@ -127,6 +138,7 @@ struct b53_device {
+ 	struct mutex stats_mutex;
+ 	struct mutex arl_mutex;
+ 	const struct b53_io_ops *ops;
++	const struct b53_arl_ops *arl_ops;
+ 
+ 	/* chip specific data */
+ 	u32 chip_id;
+@@ -371,6 +383,24 @@ static inline void b53_arl_from_entry_25
+ 		*mac_vid |= ARLTBL_AGE_25;
+ }
+ 
++static inline void b53_arl_read_entry(struct b53_device *dev,
++				      struct b53_arl_entry *ent, u8 idx)
++{
++	dev->arl_ops->arl_read_entry(dev, ent, idx);
++}
++
++static inline void b53_arl_write_entry(struct b53_device *dev,
++				       const struct b53_arl_entry *ent, u8 idx)
++{
++	dev->arl_ops->arl_write_entry(dev, ent, idx);
++}
++
++static inline void b53_arl_search_read(struct b53_device *dev, u8 idx,
++				       struct b53_arl_entry *ent)
++{
++	dev->arl_ops->arl_search_read(dev, idx, ent);
++}
++
+ #ifdef CONFIG_BCM47XX
+ 
+ #include <linux/bcm47xx_nvram.h>
diff --git a/target/linux/generic/backport-6.12/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch b/target/linux/generic/backport-6.12/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch
new file mode 100644
index 0000000000..f87a78355e
--- /dev/null
+++ b/target/linux/generic/backport-6.12/612-07-v6.19-net-dsa-b53-add-support-for-5389-5397-5398-ARL-entry-format.patch
@@ -0,0 +1,221 @@
+From 300f78e8b6b7be17c2c78afeded75be68acb1aa7 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski at gmail.com>
+Date: Fri, 7 Nov 2025 09:07:48 +0100
+Subject: [PATCH] net: dsa: b53: add support for 5389/5397/5398 ARL entry
+ format
+
+BCM5389, BCM5397 and BCM5398 use a different ARL entry format with just
+a 16 bit fwdentry register, as well as different search control and data
+offsets.
+
+So add appropriate ops for them and switch those chips to use them.
+
+Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/20251107080749.26936-8-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 53 ++++++++++++++++++++++++++++++--
+ drivers/net/dsa/b53/b53_priv.h   | 26 ++++++++++++++++
+ drivers/net/dsa/b53/b53_regs.h   | 13 ++++++++
+ 3 files changed, 89 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -1850,6 +1850,31 @@ static void b53_arl_write_entry_25(struc
+ 		    mac_vid);
+ }
+ 
++static void b53_arl_read_entry_89(struct b53_device *dev,
++				  struct b53_arl_entry *ent, u8 idx)
++{
++	u64 mac_vid;
++	u16 fwd_entry;
++
++	b53_read64(dev, B53_ARLIO_PAGE, B53_ARLTBL_MAC_VID_ENTRY(idx),
++		   &mac_vid);
++	b53_read16(dev, B53_ARLIO_PAGE, B53_ARLTBL_DATA_ENTRY(idx), &fwd_entry);
++	b53_arl_to_entry_89(ent, mac_vid, fwd_entry);
++}
++
++static void b53_arl_write_entry_89(struct b53_device *dev,
++				   const struct b53_arl_entry *ent, u8 idx)
++{
++	u32 fwd_entry;
++	u64 mac_vid;
++
++	b53_arl_from_entry_89(&mac_vid, &fwd_entry, ent);
++	b53_write64(dev, B53_ARLIO_PAGE,
++		    B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid);
++	b53_write16(dev, B53_ARLIO_PAGE,
++		    B53_ARLTBL_DATA_ENTRY(idx), fwd_entry);
++}
++
+ static void b53_arl_read_entry_95(struct b53_device *dev,
+ 				  struct b53_arl_entry *ent, u8 idx)
+ {
+@@ -2013,6 +2038,8 @@ static void b53_read_arl_srch_ctl(struct
+ 
+ 	if (is5325(dev) || is5365(dev))
+ 		offset = B53_ARL_SRCH_CTL_25;
++	else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev))
++		offset = B53_ARL_SRCH_CTL_89;
+ 	else
+ 		offset = B53_ARL_SRCH_CTL;
+ 
+@@ -2025,6 +2052,8 @@ static void b53_write_arl_srch_ctl(struc
+ 
+ 	if (is5325(dev) || is5365(dev))
+ 		offset = B53_ARL_SRCH_CTL_25;
++	else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev))
++		offset = B53_ARL_SRCH_CTL_89;
+ 	else
+ 		offset = B53_ARL_SRCH_CTL;
+ 
+@@ -2070,6 +2099,18 @@ static void b53_arl_search_read_65(struc
+ 	b53_arl_to_entry_25(ent, mac_vid);
+ }
+ 
++static void b53_arl_search_read_89(struct b53_device *dev, u8 idx,
++				   struct b53_arl_entry *ent)
++{
++	u16 fwd_entry;
++	u64 mac_vid;
++
++	b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_MACVID_89,
++		   &mac_vid);
++	b53_read16(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_89, &fwd_entry);
++	b53_arl_to_entry_89(ent, mac_vid, fwd_entry);
++}
++
+ static void b53_arl_search_read_95(struct b53_device *dev, u8 idx,
+ 				   struct b53_arl_entry *ent)
+ {
+@@ -2667,6 +2708,12 @@ static const struct b53_arl_ops b53_arl_
+ 	.arl_search_read = b53_arl_search_read_65,
+ };
+ 
++static const struct b53_arl_ops b53_arl_ops_89 = {
++	.arl_read_entry = b53_arl_read_entry_89,
++	.arl_write_entry = b53_arl_write_entry_89,
++	.arl_search_read = b53_arl_search_read_89,
++};
++
+ static const struct b53_arl_ops b53_arl_ops_95 = {
+ 	.arl_read_entry = b53_arl_read_entry_95,
+ 	.arl_write_entry = b53_arl_write_entry_95,
+@@ -2731,7 +2778,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
+-		.arl_ops = &b53_arl_ops_95,
++		.arl_ops = &b53_arl_ops_89,
+ 	},
+ 	{
+ 		.chip_id = BCM5395_DEVICE_ID,
+@@ -2759,7 +2806,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
+-		.arl_ops = &b53_arl_ops_95,
++		.arl_ops = &b53_arl_ops_89,
+ 	},
+ 	{
+ 		.chip_id = BCM5398_DEVICE_ID,
+@@ -2773,7 +2820,7 @@ static const struct b53_chip_data b53_sw
+ 		.duplex_reg = B53_DUPLEX_STAT_GE,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
+-		.arl_ops = &b53_arl_ops_95,
++		.arl_ops = &b53_arl_ops_89,
+ 	},
+ 	{
+ 		.chip_id = BCM53101_DEVICE_ID,
+--- a/drivers/net/dsa/b53/b53_priv.h
++++ b/drivers/net/dsa/b53/b53_priv.h
+@@ -353,6 +353,18 @@ static inline void b53_arl_to_entry_25(s
+ 	ent->vid = mac_vid >> ARLTBL_VID_S_65;
+ }
+ 
++static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent,
++				       u64 mac_vid, u16 fwd_entry)
++{
++	memset(ent, 0, sizeof(*ent));
++	ent->port = fwd_entry & ARLTBL_DATA_PORT_ID_MASK_89;
++	ent->is_valid = !!(fwd_entry & ARLTBL_VALID_89);
++	ent->is_age = !!(fwd_entry & ARLTBL_AGE_89);
++	ent->is_static = !!(fwd_entry & ARLTBL_STATIC_89);
++	u64_to_ether_addr(mac_vid, ent->mac);
++	ent->vid = mac_vid >> ARLTBL_VID_S;
++}
++
+ static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
+ 				      const struct b53_arl_entry *ent)
+ {
+@@ -383,6 +395,20 @@ static inline void b53_arl_from_entry_25
+ 		*mac_vid |= ARLTBL_AGE_25;
+ }
+ 
++static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry,
++					 const struct b53_arl_entry *ent)
++{
++	*mac_vid = ether_addr_to_u64(ent->mac);
++	*mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK) << ARLTBL_VID_S;
++	*fwd_entry = ent->port & ARLTBL_DATA_PORT_ID_MASK_89;
++	if (ent->is_valid)
++		*fwd_entry |= ARLTBL_VALID_89;
++	if (ent->is_static)
++		*fwd_entry |= ARLTBL_STATIC_89;
++	if (ent->is_age)
++		*fwd_entry |= ARLTBL_AGE_89;
++}
++
+ static inline void b53_arl_read_entry(struct b53_device *dev,
+ 				      struct b53_arl_entry *ent, u8 idx)
+ {
+--- a/drivers/net/dsa/b53/b53_regs.h
++++ b/drivers/net/dsa/b53/b53_regs.h
+@@ -342,12 +342,20 @@
+ #define   ARLTBL_STATIC			BIT(15)
+ #define   ARLTBL_VALID			BIT(16)
+ 
++/* BCM5389 ARL Table Data Entry N Register format (16 bit) */
++#define   ARLTBL_DATA_PORT_ID_MASK_89	GENMASK(8, 0)
++#define   ARLTBL_TC_MASK_89		GENMASK(12, 10)
++#define   ARLTBL_AGE_89			BIT(13)
++#define   ARLTBL_STATIC_89		BIT(14)
++#define   ARLTBL_VALID_89		BIT(15)
++
+ /* Maximum number of bin entries in the ARL for all switches */
+ #define B53_ARLTBL_MAX_BIN_ENTRIES	4
+ 
+ /* ARL Search Control Register (8 bit) */
+ #define B53_ARL_SRCH_CTL		0x50
+ #define B53_ARL_SRCH_CTL_25		0x20
++#define B53_ARL_SRCH_CTL_89		0x30
+ #define   ARL_SRCH_VLID			BIT(0)
+ #define   ARL_SRCH_STDN			BIT(7)
+ 
+@@ -355,10 +363,12 @@
+ #define B53_ARL_SRCH_ADDR		0x51
+ #define B53_ARL_SRCH_ADDR_25		0x22
+ #define B53_ARL_SRCH_ADDR_65		0x24
++#define B53_ARL_SRCH_ADDR_89		0x31
+ #define  ARL_ADDR_MASK			GENMASK(14, 0)
+ 
+ /* ARL Search MAC/VID Result (64 bit) */
+ #define B53_ARL_SRCH_RSTL_0_MACVID	0x60
++#define B53_ARL_SRCH_RSLT_MACVID_89	0x33
+ 
+ /* Single register search result on 5325 */
+ #define B53_ARL_SRCH_RSTL_0_MACVID_25	0x24
+@@ -368,6 +378,9 @@
+ /* ARL Search Data Result (32 bit) */
+ #define B53_ARL_SRCH_RSTL_0		0x68
+ 
++/* BCM5389 ARL Search Data Result (16 bit) */
++#define B53_ARL_SRCH_RSLT_89		0x3b
++
+ #define B53_ARL_SRCH_RSTL_MACVID(x)	(B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10))
+ #define B53_ARL_SRCH_RSTL(x)		(B53_ARL_SRCH_RSTL_0 + ((x) * 0x10))
+ 
diff --git a/target/linux/generic/backport-6.12/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch b/target/linux/generic/backport-6.12/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch
new file mode 100644
index 0000000000..33aab1144d
--- /dev/null
+++ b/target/linux/generic/backport-6.12/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch
@@ -0,0 +1,177 @@
+From 2b3013ac03028a2364d8779719bb6bfbc0212435 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski at gmail.com>
+Date: Fri, 7 Nov 2025 09:07:49 +0100
+Subject: [PATCH] net: dsa: b53: add support for bcm63xx ARL entry format
+
+The ARL registers of BCM63XX embedded switches are somewhat unique. The
+normal ARL table access registers have the same format as BCM5389, but
+the ARL search registers differ:
+
+* SRCH_CTL is at the same offset of BCM5389, but 16 bits wide. It does
+  not have more fields, just needs to be accessed by a 16 bit read.
+* SRCH_RSLT_MACVID and SRCH_RSLT are aligned to 32 bit, and have shifted
+  offsets.
+* SRCH_RSLT has a different format than the normal ARL data entry
+  register.
+* There is only one set of ENTRY_N registers, implying a 1 bin layout.
+
+So add appropriate ops for bcm63xx and let it use it.
+
+Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/20251107080749.26936-9-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 44 +++++++++++++++++++++++++++-----
+ drivers/net/dsa/b53/b53_priv.h   | 15 +++++++++++
+ drivers/net/dsa/b53/b53_regs.h   |  9 +++++++
+ 3 files changed, 61 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -2038,12 +2038,20 @@ static void b53_read_arl_srch_ctl(struct
+ 
+ 	if (is5325(dev) || is5365(dev))
+ 		offset = B53_ARL_SRCH_CTL_25;
+-	else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev))
++	else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev) ||
++		 is63xx(dev))
+ 		offset = B53_ARL_SRCH_CTL_89;
+ 	else
+ 		offset = B53_ARL_SRCH_CTL;
+ 
+-	b53_read8(dev, B53_ARLIO_PAGE, offset, val);
++	if (is63xx(dev)) {
++		u16 val16;
++
++		b53_read16(dev, B53_ARLIO_PAGE, offset, &val16);
++		*val = val16 & 0xff;
++	} else {
++		b53_read8(dev, B53_ARLIO_PAGE, offset, val);
++	}
+ }
+ 
+ static void b53_write_arl_srch_ctl(struct b53_device *dev, u8 val)
+@@ -2052,12 +2060,16 @@ static void b53_write_arl_srch_ctl(struc
+ 
+ 	if (is5325(dev) || is5365(dev))
+ 		offset = B53_ARL_SRCH_CTL_25;
+-	else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev))
++	else if (dev->chip_id == BCM5389_DEVICE_ID || is5397_98(dev) ||
++		 is63xx(dev))
+ 		offset = B53_ARL_SRCH_CTL_89;
+ 	else
+ 		offset = B53_ARL_SRCH_CTL;
+ 
+-	b53_write8(dev, B53_ARLIO_PAGE, offset, val);
++	if (is63xx(dev))
++		b53_write16(dev, B53_ARLIO_PAGE, offset, val);
++	else
++		b53_write8(dev, B53_ARLIO_PAGE, offset, val);
+ }
+ 
+ static int b53_arl_search_wait(struct b53_device *dev)
+@@ -2111,6 +2123,18 @@ static void b53_arl_search_read_89(struc
+ 	b53_arl_to_entry_89(ent, mac_vid, fwd_entry);
+ }
+ 
++static void b53_arl_search_read_63xx(struct b53_device *dev, u8 idx,
++				     struct b53_arl_entry *ent)
++{
++	u16 fwd_entry;
++	u64 mac_vid;
++
++	b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_MACVID_63XX,
++		   &mac_vid);
++	b53_read16(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSLT_63XX, &fwd_entry);
++	b53_arl_search_to_entry_63xx(ent, mac_vid, fwd_entry);
++}
++
+ static void b53_arl_search_read_95(struct b53_device *dev, u8 idx,
+ 				   struct b53_arl_entry *ent)
+ {
+@@ -2714,6 +2738,12 @@ static const struct b53_arl_ops b53_arl_
+ 	.arl_search_read = b53_arl_search_read_89,
+ };
+ 
++static const struct b53_arl_ops b53_arl_ops_63xx = {
++	.arl_read_entry = b53_arl_read_entry_89,
++	.arl_write_entry = b53_arl_write_entry_89,
++	.arl_search_read = b53_arl_search_read_63xx,
++};
++
+ static const struct b53_arl_ops b53_arl_ops_95 = {
+ 	.arl_read_entry = b53_arl_read_entry_95,
+ 	.arl_write_entry = b53_arl_write_entry_95,
+@@ -2883,14 +2913,14 @@ static const struct b53_chip_data b53_sw
+ 		.dev_name = "BCM63xx",
+ 		.vlans = 4096,
+ 		.enabled_ports = 0, /* pdata must provide them */
+-		.arl_bins = 4,
+-		.arl_buckets = 1024,
++		.arl_bins = 1,
++		.arl_buckets = 4096,
+ 		.imp_port = 8,
+ 		.vta_regs = B53_VTA_REGS_63XX,
+ 		.duplex_reg = B53_DUPLEX_STAT_63XX,
+ 		.jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX,
+ 		.jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX,
+-		.arl_ops = &b53_arl_ops_95,
++		.arl_ops = &b53_arl_ops_63xx,
+ 	},
+ 	{
+ 		.chip_id = BCM53010_DEVICE_ID,
+--- a/drivers/net/dsa/b53/b53_priv.h
++++ b/drivers/net/dsa/b53/b53_priv.h
+@@ -409,6 +409,21 @@ static inline void b53_arl_from_entry_89
+ 		*fwd_entry |= ARLTBL_AGE_89;
+ }
+ 
++static inline void b53_arl_search_to_entry_63xx(struct b53_arl_entry *ent,
++						u64 mac_vid, u16 fwd_entry)
++{
++	memset(ent, 0, sizeof(*ent));
++	u64_to_ether_addr(mac_vid, ent->mac);
++	ent->vid = mac_vid >> ARLTBL_VID_S;
++
++	ent->port = fwd_entry & ARL_SRST_PORT_ID_MASK_63XX;
++	ent->port >>= 1;
++
++	ent->is_age = !!(fwd_entry & ARL_SRST_AGE_63XX);
++	ent->is_static = !!(fwd_entry & ARL_SRST_STATIC_63XX);
++	ent->is_valid = 1;
++}
++
+ static inline void b53_arl_read_entry(struct b53_device *dev,
+ 				      struct b53_arl_entry *ent, u8 idx)
+ {
+--- a/drivers/net/dsa/b53/b53_regs.h
++++ b/drivers/net/dsa/b53/b53_regs.h
+@@ -364,11 +364,13 @@
+ #define B53_ARL_SRCH_ADDR_25		0x22
+ #define B53_ARL_SRCH_ADDR_65		0x24
+ #define B53_ARL_SRCH_ADDR_89		0x31
++#define B53_ARL_SRCH_ADDR_63XX		0x32
+ #define  ARL_ADDR_MASK			GENMASK(14, 0)
+ 
+ /* ARL Search MAC/VID Result (64 bit) */
+ #define B53_ARL_SRCH_RSTL_0_MACVID	0x60
+ #define B53_ARL_SRCH_RSLT_MACVID_89	0x33
++#define B53_ARL_SRCH_RSLT_MACVID_63XX	0x34
+ 
+ /* Single register search result on 5325 */
+ #define B53_ARL_SRCH_RSTL_0_MACVID_25	0x24
+@@ -384,6 +386,13 @@
+ #define B53_ARL_SRCH_RSTL_MACVID(x)	(B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10))
+ #define B53_ARL_SRCH_RSTL(x)		(B53_ARL_SRCH_RSTL_0 + ((x) * 0x10))
+ 
++/* 63XX ARL Search Data Result (16 bit) */
++#define B53_ARL_SRCH_RSLT_63XX		0x3c
++#define   ARL_SRST_PORT_ID_MASK_63XX	GENMASK(9, 1)
++#define   ARL_SRST_TC_MASK_63XX		GENMASK(13, 11)
++#define   ARL_SRST_AGE_63XX		BIT(14)
++#define   ARL_SRST_STATIC_63XX		BIT(15)
++
+ /*************************************************************************
+  * IEEE 802.1X Registers
+  *************************************************************************/




More information about the lede-commits mailing list