generic: 6.12: backport b53 patches from netdev-next
authorÁlvaro Fernández Rojas <[email protected]>
Wed, 19 Nov 2025 08:42:20 +0000 (09:42 +0100)
committerÁlvaro Fernández Rojas <[email protected]>
Fri, 21 Nov 2025 20:42:55 +0000 (21:42 +0100)
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 <[email protected]>
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 with mode: 0644]
target/linux/generic/backport-6.12/612-02-v6.19-net-dsa-b53-move-reading-ARL-entries-into-their-own-function.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/612-03-v6.19-net-dsa-b53-move-writing-ARL-entries-into-their-own-functions.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/612-04-v6.19-net-dsa-b53-provide-accessors-for-accessing-ARL_SRCH_CTL.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/612-05-v6.19-net-dsa-b53-split-reading-search-entry-into-their-own-functions.patch [new file with mode: 0644]
target/linux/generic/backport-6.12/612-06-v6.19-net-dsa-b53-move-ARL-entry-functions-into-ops-struct.patch [new file with mode: 0644]
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 with mode: 0644]
target/linux/generic/backport-6.12/612-08-v6.19-net-dsa-b53-add-support-for-bcm63xx-ARL-entry-format.patch [new file with mode: 0644]

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 (file)
index 0000000..2b6cff7
--- /dev/null
@@ -0,0 +1,85 @@
+From a6e4fd38bf2f2e2363b61c27f4e6c49b14e4bb07 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <[email protected]>
+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 <[email protected]>
+Reviewed-by: Florian Fainelli <[email protected]>
+Link: https://patch.msgid.link/[email protected]
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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 (file)
index 0000000..8cf85ce
--- /dev/null
@@ -0,0 +1,117 @@
+From 4a291fe7226736a465ddb3fa93c21fcef7162ec7 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <[email protected]>
+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 <[email protected]>
+Reviewed-by: Florian Fainelli <[email protected]>
+Link: https://patch.msgid.link/[email protected]
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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 (file)
index 0000000..a171232
--- /dev/null
@@ -0,0 +1,93 @@
+From bf6e9d2ae1dbafee53ec4ccd126595172e1e5278 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <[email protected]>
+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 <[email protected]>
+Reviewed-by: Florian Fainelli <[email protected]>
+Link: https://patch.msgid.link/[email protected]
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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 (file)
index 0000000..2ed88e4
--- /dev/null
@@ -0,0 +1,85 @@
+From 1716be6db04af53bac9b869f01156a460595cf41 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <[email protected]>
+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 <[email protected]>
+Reviewed-by: Florian Fainelli <[email protected]>
+Link: https://patch.msgid.link/[email protected]
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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 (file)
index 0000000..3e263f8
--- /dev/null
@@ -0,0 +1,86 @@
+From e0c476f325a8c9b961a3d446c24d3c8ecae7d186 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <[email protected]>
+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 <[email protected]>
+Reviewed-by: Florian Fainelli <[email protected]>
+Link: https://patch.msgid.link/[email protected]
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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 (file)
index 0000000..dfa902d
--- /dev/null
@@ -0,0 +1,348 @@
+From a7e73339ad46ade76d29fb6cc7d7854222608c26 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <[email protected]>
+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 <[email protected]>
+Reviewed-by: Florian Fainelli <[email protected]>
+Link: https://patch.msgid.link/[email protected]
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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 (file)
index 0000000..f87a783
--- /dev/null
@@ -0,0 +1,221 @@
+From 300f78e8b6b7be17c2c78afeded75be68acb1aa7 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <[email protected]>
+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 <[email protected]>
+Reviewed-by: Florian Fainelli <[email protected]>
+Link: https://patch.msgid.link/[email protected]
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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 (file)
index 0000000..33aab11
--- /dev/null
@@ -0,0 +1,177 @@
+From 2b3013ac03028a2364d8779719bb6bfbc0212435 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <[email protected]>
+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 <[email protected]>
+Reviewed-by: Florian Fainelli <[email protected]>
+Link: https://patch.msgid.link/[email protected]
+Signed-off-by: Jakub Kicinski <[email protected]>
+---
+ 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
+  *************************************************************************/