xref: /linux/drivers/net/dsa/realtek/rtl8365mb_l2.c (revision 336e3e4a1ab37b6826fae27e53cd2ac43c9a96ca)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Forwarding and multicast database interface for the rtl8365mb switch family
3  *
4  * Copyright (C) 2022 Alvin Šipraga <alsi@bang-olufsen.dk>
5  */
6 
7 #include <linux/etherdevice.h>
8 
9 #include "rtl8365mb_l2.h"
10 #include "rtl8365mb_table.h"
11 #include <linux/regmap.h>
12 
13 #define RTL8365MB_L2_ENTRY_SIZE			6
14 
15 #define RTL8365MB_L2_UC_D0_MAC5_MSK		GENMASK(7, 0)
16 #define RTL8365MB_L2_UC_D0_MAC4_MSK		GENMASK(15, 8)
17 #define RTL8365MB_L2_UC_D1_MAC3_MSK		GENMASK(7, 0)
18 #define RTL8365MB_L2_UC_D1_MAC2_MSK		GENMASK(15, 8)
19 #define RTL8365MB_L2_UC_D2_MAC1_MSK		GENMASK(7, 0)
20 #define RTL8365MB_L2_UC_D2_MAC0_MSK		GENMASK(15, 8)
21 #define RTL8365MB_L2_UC_D3_VID_MSK		GENMASK(11, 0)
22 #define RTL8365MB_L2_UC_D3_IVL_MSK		GENMASK(13, 13)
23 #define RTL8365MB_L2_UC_D3_PORT_EXT_MSK	GENMASK(15, 15)
24 #define   RTL8365MB_L2_UC_PORT_HI_MSK		GENMASK(3, 3)
25 #define RTL8365MB_L2_UC_D4_EFID_MSK		GENMASK(2, 0)
26 #define RTL8365MB_L2_UC_D4_FID_MSK		GENMASK(6, 3)
27 #define RTL8365MB_L2_UC_D4_SA_PRI_MSK		GENMASK(7, 7)
28 #define RTL8365MB_L2_UC_D4_PORT_MSK		GENMASK(10, 8)
29 #define   RTL8365MB_L2_UC_PORT_LO_MSK		GENMASK(2, 0)
30 #define RTL8365MB_L2_UC_D4_AGE_MSK		GENMASK(13, 11)
31 #define RTL8365MB_L2_UC_D4_AUTH_MSK		GENMASK(14, 14)
32 #define RTL8365MB_L2_UC_D4_SA_BLOCK_MSK	GENMASK(15, 15)
33 
34 #define RTL8365MB_L2_UC_D5_DA_BLOCK_MSK	GENMASK(0, 0)
35 #define RTL8365MB_L2_UC_D5_PRIORITY_MSK	GENMASK(3, 1)
36 #define RTL8365MB_L2_UC_D5_FWD_PRI_MSK		GENMASK(4, 4)
37 #define RTL8365MB_L2_UC_D5_STATIC_MSK		GENMASK(5, 5)
38 
39 #define RTL8365MB_L2_MC_D0_MAC5_MSK		GENMASK(7, 0)
40 #define RTL8365MB_L2_MC_D0_MAC4_MSK		GENMASK(15, 8)
41 #define RTL8365MB_L2_MC_D1_MAC3_MSK		GENMASK(7, 0)
42 #define RTL8365MB_L2_MC_D1_MAC2_MSK		GENMASK(15, 8)
43 #define RTL8365MB_L2_MC_D2_MAC1_MSK		GENMASK(7, 0)
44 #define RTL8365MB_L2_MC_D2_MAC0_MSK		GENMASK(15, 8)
45 #define RTL8365MB_L2_MC_D3_VID_MSK		GENMASK(11, 0)
46 #define RTL8365MB_L2_MC_D3_IVL_MSK		GENMASK(13, 13)
47 #define RTL8365MB_L2_MC_D3_MBR_HI1_MSK		GENMASK(15, 14)
48 #define   RTL8365MB_L2_MC_MBR_HI1_MSK		GENMASK(9, 8)
49 
50 #define RTL8365MB_L2_MC_D4_MBR_MSK		GENMASK(7, 0)
51 #define   RTL8365MB_L2_MC_MBR_LO_MSK		GENMASK(7, 0)
52 #define RTL8365MB_L2_MC_D4_IGMPIDX_MSK		GENMASK(15, 8)
53 
54 #define RTL8365MB_L2_MC_D5_IGMP_ASIC_MSK	GENMASK(0, 0)
55 #define RTL8365MB_L2_MC_D5_PRIORITY_MSK	GENMASK(3, 1)
56 #define RTL8365MB_L2_MC_D5_FWD_PRI_MSK		GENMASK(4, 4)
57 #define RTL8365MB_L2_MC_D5_STATIC_MSK		GENMASK(5, 5)
58 #define RTL8365MB_L2_MC_D5_MBR_HI2_MSK		GENMASK(7, 7)
59 #define   RTL8365MB_L2_MC_MBR_HI2_MSK		GENMASK(10, 10)
60 
61 /* Port flush command registers - writing a 1 to the port's MASK bit will
62  * initiate the flush procedure. Completion is signalled when the corresponding
63  * BUSY bit is 0.
64  */
65 #define RTL8365MB_L2_FLUSH_PORT_REG		0x0A36
66 #define   RTL8365MB_L2_FLUSH_PORT_MSK_MSK	GENMASK(7, 0)
67 #define   RTL8365MB_L2_FLUSH_PORT_BUSY_MSK	GENMASK(15, 8)
68 
69 #define RTL8365MB_L2_FLUSH_PORT_EXT_REG		0x0A35
70 #define   RTL8365MB_L2_FLUSH_PORT_EXT_MSK_MSK	GENMASK(2, 0)
71 #define   RTL8365MB_L2_FLUSH_PORT_EXT_BUSY_MSK	GENMASK(5, 3)
72 
73 #define RTL8365MB_L2_FLUSH_CTRL1_REG		0x0A37
74 #define   RTL8365MB_L2_FLUSH_CTRL1_VID_MSK	GENMASK(11, 0)
75 #define   RTL8365MB_L2_FLUSH_CTRL1_FID_MSK	GENMASK(15, 12)
76 
77 #define RTL8365MB_L2_FLUSH_CTRL2_REG		0x0A38
78 #define   RTL8365MB_L2_FLUSH_CTRL2_MODE_MSK	GENMASK(1, 0)
79 #define   RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT	0
80 #define   RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT_VID 1
81 #define   RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT_FID 2
82 #define   RTL8365MB_L2_FLUSH_CTRL2_TYPE_MSK	GENMASK(2, 2)
83 #define   RTL8365MB_L2_FLUSH_CTRL2_TYPE_DYNAMIC	0
84 #define   RTL8365MB_L2_FLUSH_CTRL2_TYPE_BOTH	1
85 
86 /* This flushes the entire LUT, reading it back it will turn 0 when the
87  * operation is complete
88  */
89 #define RTL8365MB_L2_FLUSH_CTRL3_REG		0x0A39
90 #define   RTL8365MB_L2_FLUSH_CTRL3_MSK		GENMASK(0, 0)
91 
92 struct rtl8365mb_l2_uc_key {
93 	u8 mac_addr[ETH_ALEN];
94 	u16 vid;
95 	u16 fid;
96 	bool ivl;
97 	u16 efid;
98 };
99 
100 struct rtl8365mb_l2_uc {
101 	struct rtl8365mb_l2_uc_key key;
102 	u8 port;
103 	u8 age;
104 	u8 priority;
105 
106 	bool sa_block;
107 	bool da_block;
108 	bool auth;
109 	bool is_static;
110 	bool sa_pri;
111 	bool fwd_pri;
112 };
113 
114 struct rtl8365mb_l2_mc_key {
115 	u8 mac_addr[ETH_ALEN];
116 	union {
117 		u16 vid; /* IVL */
118 		u16 fid; /* SVL */
119 	};
120 	bool ivl;
121 };
122 
123 struct rtl8365mb_l2_mc {
124 	struct rtl8365mb_l2_mc_key key;
125 	u16 member;
126 	u8 priority;
127 	u8 igmpidx;
128 
129 	bool is_static;
130 	bool fwd_pri;
131 	bool igmp_asic;
132 };
133 
134 static void rtl8365mb_l2_data_to_uc(const u16 *data, struct rtl8365mb_l2_uc *uc)
135 {
136 	u32 val;
137 
138 	uc->key.mac_addr[5] = FIELD_GET(RTL8365MB_L2_UC_D0_MAC5_MSK, data[0]);
139 	uc->key.mac_addr[4] = FIELD_GET(RTL8365MB_L2_UC_D0_MAC4_MSK, data[0]);
140 	uc->key.mac_addr[3] = FIELD_GET(RTL8365MB_L2_UC_D1_MAC3_MSK, data[1]);
141 	uc->key.mac_addr[2] = FIELD_GET(RTL8365MB_L2_UC_D1_MAC2_MSK, data[1]);
142 	uc->key.mac_addr[1] = FIELD_GET(RTL8365MB_L2_UC_D2_MAC1_MSK, data[2]);
143 	uc->key.mac_addr[0] = FIELD_GET(RTL8365MB_L2_UC_D2_MAC0_MSK, data[2]);
144 	uc->key.efid = FIELD_GET(RTL8365MB_L2_UC_D4_EFID_MSK, data[4]);
145 	uc->key.vid = FIELD_GET(RTL8365MB_L2_UC_D3_VID_MSK, data[3]);
146 	uc->key.ivl = FIELD_GET(RTL8365MB_L2_UC_D3_IVL_MSK, data[3]);
147 	uc->key.fid = FIELD_GET(RTL8365MB_L2_UC_D4_FID_MSK, data[4]);
148 	uc->age = FIELD_GET(RTL8365MB_L2_UC_D4_AGE_MSK, data[4]);
149 	uc->auth = FIELD_GET(RTL8365MB_L2_UC_D4_AUTH_MSK, data[4]);
150 
151 	val = FIELD_GET(RTL8365MB_L2_UC_D4_PORT_MSK, data[4]);
152 	uc->port = FIELD_PREP(RTL8365MB_L2_UC_PORT_LO_MSK, val);
153 	val = FIELD_GET(RTL8365MB_L2_UC_D3_PORT_EXT_MSK, data[3]);
154 	uc->port |= FIELD_PREP(RTL8365MB_L2_UC_PORT_HI_MSK, val);
155 
156 	uc->sa_pri = FIELD_GET(RTL8365MB_L2_UC_D4_SA_PRI_MSK, data[4]);
157 	uc->fwd_pri = FIELD_GET(RTL8365MB_L2_UC_D5_FWD_PRI_MSK, data[5]);
158 	uc->sa_block = FIELD_GET(RTL8365MB_L2_UC_D4_SA_BLOCK_MSK, data[4]);
159 	uc->da_block = FIELD_GET(RTL8365MB_L2_UC_D5_DA_BLOCK_MSK, data[5]);
160 	uc->priority = FIELD_GET(RTL8365MB_L2_UC_D5_PRIORITY_MSK, data[5]);
161 	uc->is_static = FIELD_GET(RTL8365MB_L2_UC_D5_STATIC_MSK, data[5]);
162 }
163 
164 static void rtl8365mb_l2_uc_to_data(const struct rtl8365mb_l2_uc *uc, u16 *data)
165 {
166 	u32 val;
167 
168 	memset(data, 0, RTL8365MB_L2_ENTRY_SIZE * 2);
169 	data[0] |=
170 		FIELD_PREP(RTL8365MB_L2_UC_D0_MAC5_MSK, uc->key.mac_addr[5]);
171 	data[0] |=
172 		FIELD_PREP(RTL8365MB_L2_UC_D0_MAC4_MSK, uc->key.mac_addr[4]);
173 	data[1] |=
174 		FIELD_PREP(RTL8365MB_L2_UC_D1_MAC3_MSK, uc->key.mac_addr[3]);
175 	data[1] |=
176 		FIELD_PREP(RTL8365MB_L2_UC_D1_MAC2_MSK, uc->key.mac_addr[2]);
177 	data[2] |=
178 		FIELD_PREP(RTL8365MB_L2_UC_D2_MAC1_MSK, uc->key.mac_addr[1]);
179 	data[2] |=
180 		FIELD_PREP(RTL8365MB_L2_UC_D2_MAC0_MSK, uc->key.mac_addr[0]);
181 	data[3] |= FIELD_PREP(RTL8365MB_L2_UC_D3_VID_MSK, uc->key.vid);
182 	data[3] |= FIELD_PREP(RTL8365MB_L2_UC_D3_IVL_MSK, uc->key.ivl);
183 
184 	val = FIELD_GET(RTL8365MB_L2_UC_PORT_HI_MSK, uc->port);
185 	data[3] |= FIELD_PREP(RTL8365MB_L2_UC_D3_PORT_EXT_MSK, val);
186 
187 	data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_FID_MSK, uc->key.fid);
188 	data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_EFID_MSK, uc->key.efid);
189 	data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_AGE_MSK, uc->age);
190 	data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_AUTH_MSK, uc->auth);
191 
192 	val = FIELD_GET(RTL8365MB_L2_UC_PORT_LO_MSK, uc->port);
193 	data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_PORT_MSK, val);
194 
195 	data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_SA_PRI_MSK, uc->sa_pri);
196 	data[4] |= FIELD_PREP(RTL8365MB_L2_UC_D4_SA_BLOCK_MSK, uc->sa_block);
197 	data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_FWD_PRI_MSK, uc->fwd_pri);
198 	data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_DA_BLOCK_MSK, uc->da_block);
199 	data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_PRIORITY_MSK, uc->priority);
200 	data[5] |= FIELD_PREP(RTL8365MB_L2_UC_D5_STATIC_MSK, uc->is_static);
201 }
202 
203 static void rtl8365mb_l2_data_to_mc(const u16 *data, struct rtl8365mb_l2_mc *mc)
204 {
205 	u32 val;
206 
207 	mc->key.mac_addr[5] = FIELD_GET(RTL8365MB_L2_MC_D0_MAC5_MSK, data[0]);
208 	mc->key.mac_addr[4] = FIELD_GET(RTL8365MB_L2_MC_D0_MAC4_MSK, data[0]);
209 	mc->key.mac_addr[3] = FIELD_GET(RTL8365MB_L2_MC_D1_MAC3_MSK, data[1]);
210 	mc->key.mac_addr[2] = FIELD_GET(RTL8365MB_L2_MC_D1_MAC2_MSK, data[1]);
211 	mc->key.mac_addr[1] = FIELD_GET(RTL8365MB_L2_MC_D2_MAC1_MSK, data[2]);
212 	mc->key.mac_addr[0] = FIELD_GET(RTL8365MB_L2_MC_D2_MAC0_MSK, data[2]);
213 	/* key.vid,key.fid shares the same memory space */
214 	mc->key.vid = FIELD_GET(RTL8365MB_L2_MC_D3_VID_MSK, data[3]);
215 	mc->key.ivl = FIELD_GET(RTL8365MB_L2_MC_D3_IVL_MSK, data[3]);
216 	mc->priority = FIELD_GET(RTL8365MB_L2_MC_D5_PRIORITY_MSK, data[5]);
217 	mc->fwd_pri = FIELD_GET(RTL8365MB_L2_MC_D5_FWD_PRI_MSK, data[5]);
218 	mc->is_static = FIELD_GET(RTL8365MB_L2_MC_D5_STATIC_MSK, data[5]);
219 
220 	val = FIELD_GET(RTL8365MB_L2_MC_D4_MBR_MSK, data[4]);
221 	mc->member = FIELD_PREP(RTL8365MB_L2_MC_MBR_LO_MSK, val);
222 	val = FIELD_GET(RTL8365MB_L2_MC_D3_MBR_HI1_MSK, data[3]);
223 	mc->member |= FIELD_PREP(RTL8365MB_L2_MC_MBR_HI1_MSK, val);
224 	val = FIELD_GET(RTL8365MB_L2_MC_D5_MBR_HI2_MSK, data[5]);
225 	mc->member |= FIELD_PREP(RTL8365MB_L2_MC_MBR_HI2_MSK, val);
226 
227 	mc->igmpidx = FIELD_GET(RTL8365MB_L2_MC_D4_IGMPIDX_MSK, data[4]);
228 	mc->igmp_asic = FIELD_GET(RTL8365MB_L2_MC_D5_IGMP_ASIC_MSK, data[5]);
229 }
230 
231 static void rtl8365mb_l2_mc_to_data(const struct rtl8365mb_l2_mc *mc, u16 *data)
232 {
233 	u32 val;
234 
235 	memset(data, 0, RTL8365MB_L2_ENTRY_SIZE * 2);
236 	data[0] |= FIELD_PREP(RTL8365MB_L2_MC_D0_MAC5_MSK, mc->key.mac_addr[5]);
237 	data[0] |= FIELD_PREP(RTL8365MB_L2_MC_D0_MAC4_MSK, mc->key.mac_addr[4]);
238 	data[1] |= FIELD_PREP(RTL8365MB_L2_MC_D1_MAC3_MSK, mc->key.mac_addr[3]);
239 	data[1] |= FIELD_PREP(RTL8365MB_L2_MC_D1_MAC2_MSK, mc->key.mac_addr[2]);
240 	data[2] |= FIELD_PREP(RTL8365MB_L2_MC_D2_MAC1_MSK, mc->key.mac_addr[1]);
241 	data[2] |= FIELD_PREP(RTL8365MB_L2_MC_D2_MAC0_MSK, mc->key.mac_addr[0]);
242 	data[3] |= FIELD_PREP(RTL8365MB_L2_MC_D3_VID_MSK, mc->key.vid);
243 	data[3] |= FIELD_PREP(RTL8365MB_L2_MC_D3_IVL_MSK, mc->key.ivl);
244 
245 	val = FIELD_GET(RTL8365MB_L2_MC_MBR_HI1_MSK, mc->member);
246 	data[3] |= FIELD_PREP(RTL8365MB_L2_MC_D3_MBR_HI1_MSK, val);
247 
248 	val = FIELD_GET(RTL8365MB_L2_MC_MBR_LO_MSK, mc->member);
249 	data[4] |= FIELD_PREP(RTL8365MB_L2_MC_D4_MBR_MSK, val);
250 
251 	data[4] |= FIELD_PREP(RTL8365MB_L2_MC_D4_IGMPIDX_MSK, mc->igmpidx);
252 	data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_IGMP_ASIC_MSK, mc->igmp_asic);
253 	data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_PRIORITY_MSK, mc->priority);
254 	data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_FWD_PRI_MSK, mc->fwd_pri);
255 	data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_STATIC_MSK, mc->is_static);
256 
257 	val = FIELD_GET(RTL8365MB_L2_MC_MBR_HI2_MSK, mc->member);
258 	data[5] |= FIELD_PREP(RTL8365MB_L2_MC_D5_MBR_HI2_MSK, val);
259 }
260 
261 /*
262  * rtl8365mb_l2_get_next_uc() - get the next Unicast L2 entry
263  * @priv: realtek_priv pointer
264  * @addr: as input, the table index to start the walk
265  *        as output, the found table index
266  * @port: restrict the walk on entries related to port
267  * @entry: returned L2 Unicast table entry
268  *
269  * This function gets the next unicast L2 table entry starting from @addr
270  * and checking exclusively entries related to @port.
271  *
272  * On success, it returns 0, updates @addr to the index of the found entry,
273  * and populates @entry. If the search reaches the end of the table and
274  * wraps around and @addr will be strictly lower than the input @addr.
275  * Callers must detect this wrap-around condition to prevent infinite loops.
276  *
277  * If the table contains no matching entries at all, it returns -ENOENT
278  * and leaves @addr and @entry unmodified.
279  *
280  * Return: Returns 0 on success, a negative error on failure.
281  **/
282 int rtl8365mb_l2_get_next_uc(struct realtek_priv *priv, u16 *addr, int port,
283 			     struct realtek_fdb_entry *entry)
284 {
285 	u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
286 	struct rtl8365mb_l2_uc uc;
287 	int ret;
288 
289 	ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
290 				    RTL8365MB_TABLE_OP_READ, addr,
291 				    RTL8365MB_TABLE_L2_METHOD_ADDR_NEXT_UC_PORT,
292 				    port, data, RTL8365MB_L2_ENTRY_SIZE);
293 	if (ret)
294 		return ret;
295 
296 	rtl8365mb_l2_data_to_uc(data, &uc);
297 
298 	ether_addr_copy(entry->mac_addr, uc.key.mac_addr);
299 	entry->vid = uc.key.vid;
300 	entry->is_static = uc.is_static;
301 
302 	return 0;
303 }
304 
305 int rtl8365mb_l2_add_uc(struct realtek_priv *priv, int port,
306 			const unsigned char mac_addr[static ETH_ALEN],
307 			u16 efid, u16 vid)
308 {
309 	u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
310 	struct rtl8365mb_l2_uc uc = { 0 };
311 	u16 addr;
312 	int ret;
313 
314 	memcpy(uc.key.mac_addr, mac_addr, ETH_ALEN);
315 	uc.key.efid = efid;
316 	uc.key.fid = 0;
317 	uc.key.ivl = true;
318 	uc.key.vid = vid;
319 
320 	uc.port = port;
321 	/* Entries programmed by DSA (including those dynamically learned by
322 	 * the software bridge and injected into the CPU port via assisted
323 	 * learning) must be static. We do not let HW decrease age behind the
324 	 * OS's back. As a trade-off, these will show up as permanent to users.
325 	 */
326 	uc.is_static = true;
327 	/* age greater than 0 adds/updates entries */
328 	uc.age = 1;
329 	rtl8365mb_l2_uc_to_data(&uc, data);
330 
331 	/* add the new entry or update an existing one */
332 	ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
333 				    RTL8365MB_TABLE_OP_WRITE, &addr,
334 				    0, 0,
335 				    data, RTL8365MB_L2_ENTRY_SIZE);
336 
337 	/* Assume the missing new entry as the table is full */
338 	if (ret == -ENOENT)
339 		return -ENOSPC;
340 
341 	/* addr will hold the table index, but it is not used here */
342 	return ret;
343 }
344 
345 int rtl8365mb_l2_del_uc(struct realtek_priv *priv, int port,
346 			const unsigned char mac_addr[static ETH_ALEN],
347 			u16 efid, u16 vid)
348 {
349 	u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
350 	struct rtl8365mb_l2_uc uc = { 0 };
351 	u16 addr;
352 	int ret;
353 
354 	memcpy(uc.key.mac_addr, mac_addr, ETH_ALEN);
355 	uc.key.efid = efid;
356 	uc.key.fid = 0;
357 	uc.key.ivl = true;
358 	uc.key.vid = vid;
359 	/* age 0 deletes the entry */
360 	uc.age = 0;
361 	rtl8365mb_l2_uc_to_data(&uc, data);
362 
363 	/* it looks like the switch will always add/update the entry,
364 	 * even when age is 0 or uc.key did not match an existing entry,
365 	 * just to immediately drop it because age is zero. You can still
366 	 * get the added/updated address from @addr
367 	 */
368 	ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
369 				    RTL8365MB_TABLE_OP_WRITE, &addr,
370 				    0, 0,
371 				    data, RTL8365MB_L2_ENTRY_SIZE);
372 
373 	if (ret == -ENOENT) {
374 		dev_dbg(priv->dev, "%s: %pM vid=%d efid=%d missing\n",
375 			__func__, mac_addr, vid, efid);
376 		/* Silently return success */
377 		return 0;
378 	}
379 
380 	/* addr will hold the table index, but it is not used here */
381 	return ret;
382 }
383 
384 int rtl8365mb_l2_flush(struct realtek_priv *priv, int port, u16 vid)
385 {
386 	int mode = vid ? RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT_VID :
387 			 RTL8365MB_L2_FLUSH_CTRL2_MODE_PORT;
388 	u32 val, mask;
389 	int ret;
390 
391 	mutex_lock(&priv->map_lock);
392 
393 	/* Configure flushing mode; only flush dynamic entries */
394 	ret = regmap_write(priv->map_nolock, RTL8365MB_L2_FLUSH_CTRL2_REG,
395 			   FIELD_PREP(RTL8365MB_L2_FLUSH_CTRL2_MODE_MSK,
396 				      mode) |
397 			   FIELD_PREP(RTL8365MB_L2_FLUSH_CTRL2_TYPE_MSK,
398 				      RTL8365MB_L2_FLUSH_CTRL2_TYPE_DYNAMIC));
399 	if (ret)
400 		goto out;
401 
402 	ret = regmap_write(priv->map_nolock, RTL8365MB_L2_FLUSH_CTRL1_REG,
403 			   FIELD_PREP(RTL8365MB_L2_FLUSH_CTRL1_VID_MSK, vid));
404 
405 	if (ret)
406 		goto out;
407 	/* Now issue the flush command and wait for its completion. There are
408 	 * two registers for this purpose, and which one to use depends on the
409 	 * port number. The _EXT register is for ports 8 or higher.
410 	 */
411 	if (port < 8) {
412 		val = FIELD_PREP(RTL8365MB_L2_FLUSH_PORT_MSK_MSK,
413 				 BIT(port) & 0xFF);
414 		ret = regmap_write(priv->map_nolock,
415 				   RTL8365MB_L2_FLUSH_PORT_REG, val);
416 		if (ret)
417 			goto out;
418 
419 		mask = FIELD_PREP(RTL8365MB_L2_FLUSH_PORT_BUSY_MSK,
420 				  BIT(port) & 0xFF);
421 		ret = regmap_read_poll_timeout(priv->map_nolock,
422 					       RTL8365MB_L2_FLUSH_PORT_REG,
423 					       val, !(val & mask), 10, 10000);
424 		if (ret)
425 			goto out;
426 	} else {
427 		val = FIELD_PREP(RTL8365MB_L2_FLUSH_PORT_EXT_MSK_MSK,
428 				 BIT(port) >> 8);
429 		ret = regmap_write(priv->map_nolock,
430 				   RTL8365MB_L2_FLUSH_PORT_EXT_REG, val);
431 		if (ret)
432 			goto out;
433 
434 		mask = FIELD_PREP(RTL8365MB_L2_FLUSH_PORT_EXT_BUSY_MSK,
435 				  BIT(port) >> 8);
436 		ret = regmap_read_poll_timeout(priv->map_nolock,
437 					       RTL8365MB_L2_FLUSH_PORT_EXT_REG,
438 					       val, !(val & mask), 10, 10000);
439 		if (ret)
440 			goto out;
441 	}
442 
443 out:
444 	mutex_unlock(&priv->map_lock);
445 
446 	return ret;
447 }
448 
449 int rtl8365mb_l2_add_mc(struct realtek_priv *priv, int port,
450 			const unsigned char mac_addr[static ETH_ALEN],
451 			u16 vid)
452 {
453 	u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
454 	struct rtl8365mb_l2_mc mc = { 0 };
455 	u16 addr;
456 	int ret;
457 
458 	memcpy(mc.key.mac_addr, mac_addr, ETH_ALEN);
459 	mc.key.vid = vid;
460 	mc.key.ivl = true;
461 	/* Already set the port and is_static, although not used in OP_READ,
462 	 * data will be ready for OP_WRITE if it is a new entry.
463 	 */
464 	mc.member |= BIT(port);
465 	mc.is_static = 1;
466 	rtl8365mb_l2_mc_to_data(&mc, data);
467 
468 	/* First look for an existing entry (to get existing port members) */
469 	ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
470 				    RTL8365MB_TABLE_OP_READ, &addr,
471 				    RTL8365MB_TABLE_L2_METHOD_MAC, 0,
472 				    data, RTL8365MB_L2_ENTRY_SIZE);
473 	if (!ret) {
474 		/* There is already an entry... */
475 		rtl8365mb_l2_data_to_mc(data, &mc);
476 		dev_dbg(priv->dev,
477 			"%s: found %pM addr=%d member=0x%x igmpidx=0x%x %s\n",
478 			__func__, mac_addr, addr, mc.member, mc.igmpidx,
479 			mc.is_static ? "static" : "dynamic");
480 		/* the port must be added as a member */
481 		mc.member |= BIT(port);
482 
483 		if (!mc.is_static) {
484 			dev_dbg(priv->dev,
485 				"%s: promoting addr=%d group to static\n",
486 				__func__, addr);
487 			mc.is_static = 1;
488 		}
489 
490 		rtl8365mb_l2_mc_to_data(&mc, data);
491 	} else if (ret == -ENOENT) {
492 		/* New entry, no need to update data again as it already
493 		 * includes the member.
494 		 *
495 		 * Multicast hardware entries do not support EFID (bridge
496 		 * isolation). However, traffic isolation is still maintained
497 		 * because the hardware applies the port isolation masks
498 		 * (pmasks) configured in bridge_join after the L2 lookup.
499 		 * Entries from different bridges will collide on the same
500 		 * MAC+VID slot with an OR'ed member mask, but packets will
501 		 * only exit through ports allowed by the source port's pmask.
502 		 */
503 	} else {
504 		return ret;
505 	}
506 
507 	/* add the new entry or update an existing one */
508 	ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
509 				    RTL8365MB_TABLE_OP_WRITE, &addr,
510 				    0, 0,
511 				    data, RTL8365MB_L2_ENTRY_SIZE);
512 
513 	/* Assume the missing new entry as the table is full */
514 	if (ret == -ENOENT)
515 		return -ENOSPC;
516 
517 	return ret;
518 }
519 
520 int rtl8365mb_l2_del_mc(struct realtek_priv *priv, int port,
521 			const unsigned char mac_addr[static ETH_ALEN],
522 			u16 vid)
523 {
524 	u16 data[RTL8365MB_L2_ENTRY_SIZE] = { 0 };
525 	struct rtl8365mb_l2_mc mc = { 0 };
526 	u16 addr;
527 	int ret;
528 
529 	memcpy(mc.key.mac_addr, mac_addr, ETH_ALEN);
530 	mc.key.vid = vid;
531 	mc.key.ivl = true;
532 	rtl8365mb_l2_mc_to_data(&mc, data);
533 
534 	/* First look for an existing entry (to get existing port members) */
535 	ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
536 				    RTL8365MB_TABLE_OP_READ, &addr,
537 				    RTL8365MB_TABLE_L2_METHOD_MAC, 0,
538 				    data, RTL8365MB_L2_ENTRY_SIZE);
539 	if (ret == -ENOENT) {
540 		dev_dbg(priv->dev, "%s: %pM vid=%d missing\n",
541 			__func__, mac_addr, vid);
542 		/* Silently return success */
543 		return 0;
544 	}
545 
546 	if (ret)
547 		/* Return on any other error */
548 		return ret;
549 
550 	rtl8365mb_l2_data_to_mc(data, &mc);
551 	dev_dbg(priv->dev,
552 		"%s: found %pM addr=%d member=0x%x igmpidx=0x%x %s\n",
553 		__func__, mac_addr, addr, mc.member, mc.igmpidx,
554 		mc.is_static ? "static" : "dynamic");
555 	/* the port must be removed as a member */
556 	mc.member &= ~BIT(port);
557 	if (!mc.member) {
558 		/* Multicast entries do not have an age field. Clearing both
559 		 * the member portmask and is_static flags is the hardware
560 		 * signal to invalidate and reclaim the L2 table slot.
561 		 */
562 		mc.is_static = 0;
563 		mc.igmpidx = 0;
564 		mc.priority = 0;
565 		mc.fwd_pri = 0;
566 		mc.igmp_asic = 0;
567 	}
568 	rtl8365mb_l2_mc_to_data(&mc, data);
569 
570 	/* update the existing entry. */
571 	ret = rtl8365mb_table_query(priv, RTL8365MB_TABLE_L2,
572 				    RTL8365MB_TABLE_OP_WRITE, &addr,
573 				    0, 0,
574 				    data, RTL8365MB_L2_ENTRY_SIZE);
575 	return ret;
576 }
577