113528a6d5a3152ae6d530fe5a85dd6a484794a4
[openwrt/openwrt.git] /
1 From c45655386e532c85ff1d679fc2aa40b3aaff9916 Mon Sep 17 00:00:00 2001
2 From: Florian Fainelli <f.fainelli@gmail.com>
3 Date: Sat, 14 Jun 2025 09:59:51 +0200
4 Subject: [PATCH] net: dsa: b53: add support for FDB operations on 5325/5365
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 BCM5325 and BCM5365 are part of a much older generation of switches which,
10 due to their limited number of ports and VLAN entries (up to 256) allowed
11 a single 64-bit register to hold a full ARL entry.
12 This requires a little bit of massaging when reading, writing and
13 converting ARL entries in both directions.
14
15 Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
16 Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
17 Link: https://patch.msgid.link/20250614080000.1884236-6-noltari@gmail.com
18 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
19 ---
20 drivers/net/dsa/b53/b53_common.c | 101 +++++++++++++++++++++++++------
21 drivers/net/dsa/b53/b53_priv.h | 29 +++++++++
22 drivers/net/dsa/b53/b53_regs.h | 7 ++-
23 3 files changed, 115 insertions(+), 22 deletions(-)
24
25 --- a/drivers/net/dsa/b53/b53_common.c
26 +++ b/drivers/net/dsa/b53/b53_common.c
27 @@ -1802,6 +1802,45 @@ static int b53_arl_read(struct b53_devic
28 return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT;
29 }
30
31 +static int b53_arl_read_25(struct b53_device *dev, u64 mac,
32 + u16 vid, struct b53_arl_entry *ent, u8 *idx)
33 +{
34 + DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
35 + unsigned int i;
36 + int ret;
37 +
38 + ret = b53_arl_op_wait(dev);
39 + if (ret)
40 + return ret;
41 +
42 + bitmap_zero(free_bins, dev->num_arl_bins);
43 +
44 + /* Read the bins */
45 + for (i = 0; i < dev->num_arl_bins; i++) {
46 + u64 mac_vid;
47 +
48 + b53_read64(dev, B53_ARLIO_PAGE,
49 + B53_ARLTBL_MAC_VID_ENTRY(i), &mac_vid);
50 +
51 + b53_arl_to_entry_25(ent, mac_vid);
52 +
53 + if (!(mac_vid & ARLTBL_VALID_25)) {
54 + set_bit(i, free_bins);
55 + continue;
56 + }
57 + if ((mac_vid & ARLTBL_MAC_MASK) != mac)
58 + continue;
59 + if (dev->vlan_enabled &&
60 + ((mac_vid >> ARLTBL_VID_S_65) & ARLTBL_VID_MASK_25) != vid)
61 + continue;
62 + *idx = i;
63 + return 0;
64 + }
65 +
66 + *idx = find_first_bit(free_bins, dev->num_arl_bins);
67 + return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT;
68 +}
69 +
70 static int b53_arl_op(struct b53_device *dev, int op, int port,
71 const unsigned char *addr, u16 vid, bool is_valid)
72 {
73 @@ -1824,7 +1863,10 @@ static int b53_arl_op(struct b53_device
74 if (ret)
75 return ret;
76
77 - ret = b53_arl_read(dev, mac, vid, &ent, &idx);
78 + if (is5325(dev) || is5365(dev))
79 + ret = b53_arl_read_25(dev, mac, vid, &ent, &idx);
80 + else
81 + ret = b53_arl_read(dev, mac, vid, &ent, &idx);
82
83 /* If this is a read, just finish now */
84 if (op)
85 @@ -1868,12 +1910,17 @@ static int b53_arl_op(struct b53_device
86 ent.is_static = true;
87 ent.is_age = false;
88 memcpy(ent.mac, addr, ETH_ALEN);
89 - b53_arl_from_entry(&mac_vid, &fwd_entry, &ent);
90 + if (is5325(dev) || is5365(dev))
91 + b53_arl_from_entry_25(&mac_vid, &ent);
92 + else
93 + b53_arl_from_entry(&mac_vid, &fwd_entry, &ent);
94
95 b53_write64(dev, B53_ARLIO_PAGE,
96 B53_ARLTBL_MAC_VID_ENTRY(idx), mac_vid);
97 - b53_write32(dev, B53_ARLIO_PAGE,
98 - B53_ARLTBL_DATA_ENTRY(idx), fwd_entry);
99 +
100 + if (!is5325(dev) && !is5365(dev))
101 + b53_write32(dev, B53_ARLIO_PAGE,
102 + B53_ARLTBL_DATA_ENTRY(idx), fwd_entry);
103
104 return b53_arl_rw_op(dev, 0);
105 }
106 @@ -1885,12 +1932,6 @@ int b53_fdb_add(struct dsa_switch *ds, i
107 struct b53_device *priv = ds->priv;
108 int ret;
109
110 - /* 5325 and 5365 require some more massaging, but could
111 - * be supported eventually
112 - */
113 - if (is5325(priv) || is5365(priv))
114 - return -EOPNOTSUPP;
115 -
116 mutex_lock(&priv->arl_mutex);
117 ret = b53_arl_op(priv, 0, port, addr, vid, true);
118 mutex_unlock(&priv->arl_mutex);
119 @@ -1917,10 +1958,15 @@ EXPORT_SYMBOL(b53_fdb_del);
120 static int b53_arl_search_wait(struct b53_device *dev)
121 {
122 unsigned int timeout = 1000;
123 - u8 reg;
124 + u8 reg, offset;
125 +
126 + if (is5325(dev) || is5365(dev))
127 + offset = B53_ARL_SRCH_CTL_25;
128 + else
129 + offset = B53_ARL_SRCH_CTL;
130
131 do {
132 - b53_read8(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, &reg);
133 + b53_read8(dev, B53_ARLIO_PAGE, offset, &reg);
134 if (!(reg & ARL_SRCH_STDN))
135 return 0;
136
137 @@ -1937,13 +1983,24 @@ static void b53_arl_search_rd(struct b53
138 struct b53_arl_entry *ent)
139 {
140 u64 mac_vid;
141 - u32 fwd_entry;
142
143 - b53_read64(dev, B53_ARLIO_PAGE,
144 - B53_ARL_SRCH_RSTL_MACVID(idx), &mac_vid);
145 - b53_read32(dev, B53_ARLIO_PAGE,
146 - B53_ARL_SRCH_RSTL(idx), &fwd_entry);
147 - b53_arl_to_entry(ent, mac_vid, fwd_entry);
148 + if (is5325(dev)) {
149 + b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_25,
150 + &mac_vid);
151 + b53_arl_to_entry_25(ent, mac_vid);
152 + } else if (is5365(dev)) {
153 + b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_0_MACVID_65,
154 + &mac_vid);
155 + b53_arl_to_entry_25(ent, mac_vid);
156 + } else {
157 + u32 fwd_entry;
158 +
159 + b53_read64(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL_MACVID(idx),
160 + &mac_vid);
161 + b53_read32(dev, B53_ARLIO_PAGE, B53_ARL_SRCH_RSTL(idx),
162 + &fwd_entry);
163 + b53_arl_to_entry(ent, mac_vid, fwd_entry);
164 + }
165 }
166
167 static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
168 @@ -1964,14 +2021,20 @@ int b53_fdb_dump(struct dsa_switch *ds,
169 struct b53_device *priv = ds->priv;
170 struct b53_arl_entry results[2];
171 unsigned int count = 0;
172 + u8 offset;
173 int ret;
174 u8 reg;
175
176 mutex_lock(&priv->arl_mutex);
177
178 + if (is5325(priv) || is5365(priv))
179 + offset = B53_ARL_SRCH_CTL_25;
180 + else
181 + offset = B53_ARL_SRCH_CTL;
182 +
183 /* Start search operation */
184 reg = ARL_SRCH_STDN;
185 - b53_write8(priv, B53_ARLIO_PAGE, B53_ARL_SRCH_CTL, reg);
186 + b53_write8(priv, offset, B53_ARL_SRCH_CTL, reg);
187
188 do {
189 ret = b53_arl_search_wait(priv);
190 --- a/drivers/net/dsa/b53/b53_priv.h
191 +++ b/drivers/net/dsa/b53/b53_priv.h
192 @@ -317,6 +317,19 @@ static inline void b53_arl_to_entry(stru
193 ent->vid = mac_vid >> ARLTBL_VID_S;
194 }
195
196 +static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent,
197 + u64 mac_vid)
198 +{
199 + memset(ent, 0, sizeof(*ent));
200 + ent->port = (mac_vid >> ARLTBL_DATA_PORT_ID_S_25) &
201 + ARLTBL_DATA_PORT_ID_MASK_25;
202 + ent->is_valid = !!(mac_vid & ARLTBL_VALID_25);
203 + ent->is_age = !!(mac_vid & ARLTBL_AGE_25);
204 + ent->is_static = !!(mac_vid & ARLTBL_STATIC_25);
205 + u64_to_ether_addr(mac_vid, ent->mac);
206 + ent->vid = mac_vid >> ARLTBL_VID_S_65;
207 +}
208 +
209 static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
210 const struct b53_arl_entry *ent)
211 {
212 @@ -331,6 +344,22 @@ static inline void b53_arl_from_entry(u6
213 *fwd_entry |= ARLTBL_AGE;
214 }
215
216 +static inline void b53_arl_from_entry_25(u64 *mac_vid,
217 + const struct b53_arl_entry *ent)
218 +{
219 + *mac_vid = ether_addr_to_u64(ent->mac);
220 + *mac_vid |= (u64)(ent->port & ARLTBL_DATA_PORT_ID_MASK_25) <<
221 + ARLTBL_DATA_PORT_ID_S_25;
222 + *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK_25) <<
223 + ARLTBL_VID_S_65;
224 + if (ent->is_valid)
225 + *mac_vid |= ARLTBL_VALID_25;
226 + if (ent->is_static)
227 + *mac_vid |= ARLTBL_STATIC_25;
228 + if (ent->is_age)
229 + *mac_vid |= ARLTBL_AGE_25;
230 +}
231 +
232 #ifdef CONFIG_BCM47XX
233
234 #include <linux/bcm47xx_nvram.h>
235 --- a/drivers/net/dsa/b53/b53_regs.h
236 +++ b/drivers/net/dsa/b53/b53_regs.h
237 @@ -329,9 +329,10 @@
238 #define ARLTBL_VID_MASK 0xfff
239 #define ARLTBL_DATA_PORT_ID_S_25 48
240 #define ARLTBL_DATA_PORT_ID_MASK_25 0xf
241 -#define ARLTBL_AGE_25 BIT(61)
242 -#define ARLTBL_STATIC_25 BIT(62)
243 -#define ARLTBL_VALID_25 BIT(63)
244 +#define ARLTBL_VID_S_65 53
245 +#define ARLTBL_AGE_25 BIT_ULL(61)
246 +#define ARLTBL_STATIC_25 BIT_ULL(62)
247 +#define ARLTBL_VALID_25 BIT_ULL(63)
248
249 /* ARL Table Data Entry N Registers (32 bit) */
250 #define B53_ARLTBL_DATA_ENTRY(n) ((0x10 * (n)) + 0x18)