• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
4  *
5  * Copyright (c) 2008 Marvell Semiconductor
6  * Copyright (c) 2015 CMC Electronics, Inc.
7  * Copyright (c) 2017 Savoir-faire Linux, Inc.
8  */
9 
10 #include <linux/bitfield.h>
11 #include <linux/interrupt.h>
12 #include <linux/irqdomain.h>
13 
14 #include "chip.h"
15 #include "global1.h"
16 
17 /* Offset 0x02: VTU FID Register */
18 
mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)19 static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
20 				     struct mv88e6xxx_vtu_entry *entry)
21 {
22 	u16 val;
23 	int err;
24 
25 	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
26 	if (err)
27 		return err;
28 
29 	entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
30 
31 	return 0;
32 }
33 
mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)34 static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
35 				      struct mv88e6xxx_vtu_entry *entry)
36 {
37 	u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
38 
39 	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
40 }
41 
42 /* Offset 0x03: VTU SID Register */
43 
mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)44 static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
45 				     struct mv88e6xxx_vtu_entry *entry)
46 {
47 	u16 val;
48 	int err;
49 
50 	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
51 	if (err)
52 		return err;
53 
54 	entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
55 
56 	return 0;
57 }
58 
mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)59 static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
60 				      struct mv88e6xxx_vtu_entry *entry)
61 {
62 	u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
63 
64 	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
65 }
66 
67 /* Offset 0x05: VTU Operation Register */
68 
mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip * chip)69 static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
70 {
71 	int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
72 
73 	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
74 }
75 
mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip * chip,u16 op)76 static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
77 {
78 	int err;
79 
80 	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
81 				 MV88E6XXX_G1_VTU_OP_BUSY | op);
82 	if (err)
83 		return err;
84 
85 	return mv88e6xxx_g1_vtu_op_wait(chip);
86 }
87 
88 /* Offset 0x06: VTU VID Register */
89 
mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)90 static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
91 				     struct mv88e6xxx_vtu_entry *entry)
92 {
93 	u16 val;
94 	int err;
95 
96 	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
97 	if (err)
98 		return err;
99 
100 	entry->vid = val & 0xfff;
101 
102 	if (val & MV88E6390_G1_VTU_VID_PAGE)
103 		entry->vid |= 0x1000;
104 
105 	entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
106 
107 	return 0;
108 }
109 
mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)110 static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
111 				      struct mv88e6xxx_vtu_entry *entry)
112 {
113 	u16 val = entry->vid & 0xfff;
114 
115 	if (entry->vid & 0x1000)
116 		val |= MV88E6390_G1_VTU_VID_PAGE;
117 
118 	if (entry->valid)
119 		val |= MV88E6XXX_G1_VTU_VID_VALID;
120 
121 	return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
122 }
123 
124 /* Offset 0x07: VTU/STU Data Register 1
125  * Offset 0x08: VTU/STU Data Register 2
126  * Offset 0x09: VTU/STU Data Register 3
127  */
mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip * chip,u16 * regs)128 static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
129 					  u16 *regs)
130 {
131 	int i;
132 
133 	/* Read all 3 VTU/STU Data registers */
134 	for (i = 0; i < 3; ++i) {
135 		u16 *reg = &regs[i];
136 		int err;
137 
138 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
139 		if (err)
140 			return err;
141 	}
142 
143 	return 0;
144 }
145 
mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)146 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
147 				      struct mv88e6xxx_vtu_entry *entry)
148 {
149 	u16 regs[3];
150 	int err;
151 	int i;
152 
153 	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
154 	if (err)
155 		return err;
156 
157 	/* Extract MemberTag data */
158 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
159 		unsigned int member_offset = (i % 4) * 4;
160 
161 		entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
162 	}
163 
164 	return 0;
165 }
166 
mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)167 static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
168 				      struct mv88e6xxx_vtu_entry *entry)
169 {
170 	u16 regs[3];
171 	int err;
172 	int i;
173 
174 	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
175 	if (err)
176 		return err;
177 
178 	/* Extract PortState data */
179 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
180 		unsigned int state_offset = (i % 4) * 4 + 2;
181 
182 		entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
183 	}
184 
185 	return 0;
186 }
187 
mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)188 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
189 				       struct mv88e6xxx_vtu_entry *entry)
190 {
191 	u16 regs[3] = { 0 };
192 	int i;
193 
194 	/* Insert MemberTag and PortState data */
195 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
196 		unsigned int member_offset = (i % 4) * 4;
197 		unsigned int state_offset = member_offset + 2;
198 
199 		regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
200 		regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
201 	}
202 
203 	/* Write all 3 VTU/STU Data registers */
204 	for (i = 0; i < 3; ++i) {
205 		u16 reg = regs[i];
206 		int err;
207 
208 		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
209 		if (err)
210 			return err;
211 	}
212 
213 	return 0;
214 }
215 
mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip * chip,u8 * data)216 static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
217 {
218 	u16 regs[2];
219 	int i;
220 
221 	/* Read the 2 VTU/STU Data registers */
222 	for (i = 0; i < 2; ++i) {
223 		u16 *reg = &regs[i];
224 		int err;
225 
226 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
227 		if (err)
228 			return err;
229 	}
230 
231 	/* Extract data */
232 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
233 		unsigned int offset = (i % 8) * 2;
234 
235 		data[i] = (regs[i / 8] >> offset) & 0x3;
236 	}
237 
238 	return 0;
239 }
240 
mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip * chip,u8 * data)241 static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
242 {
243 	u16 regs[2] = { 0 };
244 	int i;
245 
246 	/* Insert data */
247 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
248 		unsigned int offset = (i % 8) * 2;
249 
250 		regs[i / 8] |= (data[i] & 0x3) << offset;
251 	}
252 
253 	/* Write the 2 VTU/STU Data registers */
254 	for (i = 0; i < 2; ++i) {
255 		u16 reg = regs[i];
256 		int err;
257 
258 		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
259 		if (err)
260 			return err;
261 	}
262 
263 	return 0;
264 }
265 
266 /* VLAN Translation Unit Operations */
267 
mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)268 static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
269 					struct mv88e6xxx_vtu_entry *entry)
270 {
271 	int err;
272 
273 	err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
274 	if (err)
275 		return err;
276 
277 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
278 	if (err)
279 		return err;
280 
281 	err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
282 	if (err)
283 		return err;
284 
285 	return mv88e6xxx_g1_vtu_vid_read(chip, entry);
286 }
287 
mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * vtu)288 static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
289 				    struct mv88e6xxx_vtu_entry *vtu)
290 {
291 	struct mv88e6xxx_vtu_entry stu;
292 	int err;
293 
294 	err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
295 	if (err)
296 		return err;
297 
298 	stu.sid = vtu->sid - 1;
299 
300 	err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
301 	if (err)
302 		return err;
303 
304 	if (stu.sid != vtu->sid || !stu.valid)
305 		return -EINVAL;
306 
307 	return 0;
308 }
309 
mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)310 static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
311 				    struct mv88e6xxx_vtu_entry *entry)
312 {
313 	int err;
314 
315 	err = mv88e6xxx_g1_vtu_op_wait(chip);
316 	if (err)
317 		return err;
318 
319 	/* To get the next higher active VID, the VTU GetNext operation can be
320 	 * started again without setting the VID registers since it already
321 	 * contains the last VID.
322 	 *
323 	 * To save a few hardware accesses and abstract this to the caller,
324 	 * write the VID only once, when the entry is given as invalid.
325 	 */
326 	if (!entry->valid) {
327 		err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
328 		if (err)
329 			return err;
330 	}
331 
332 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
333 	if (err)
334 		return err;
335 
336 	return mv88e6xxx_g1_vtu_vid_read(chip, entry);
337 }
338 
mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)339 int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
340 			     struct mv88e6xxx_vtu_entry *entry)
341 {
342 	u16 val;
343 	int err;
344 
345 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
346 	if (err)
347 		return err;
348 
349 	if (entry->valid) {
350 		err = mv88e6185_g1_vtu_data_read(chip, entry);
351 		if (err)
352 			return err;
353 
354 		err = mv88e6185_g1_stu_data_read(chip, entry);
355 		if (err)
356 			return err;
357 
358 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
359 		 * VTU DBNum[5:4] are located in VTU Operation 9:8
360 		 */
361 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
362 		if (err)
363 			return err;
364 
365 		entry->fid = val & 0x000f;
366 		entry->fid |= (val & 0x0300) >> 4;
367 	}
368 
369 	return 0;
370 }
371 
mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)372 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
373 			     struct mv88e6xxx_vtu_entry *entry)
374 {
375 	u16 val;
376 	int err;
377 
378 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
379 	if (err)
380 		return err;
381 
382 	if (entry->valid) {
383 		err = mv88e6185_g1_vtu_data_read(chip, entry);
384 		if (err)
385 			return err;
386 
387 		err = mv88e6185_g1_stu_data_read(chip, entry);
388 		if (err)
389 			return err;
390 
391 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
392 		 * VTU DBNum[7:4] are located in VTU Operation 11:8
393 		 */
394 		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
395 		if (err)
396 			return err;
397 
398 		entry->fid = val & 0x000f;
399 		entry->fid |= (val & 0x0f00) >> 4;
400 	}
401 
402 	return 0;
403 }
404 
mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)405 int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
406 			     struct mv88e6xxx_vtu_entry *entry)
407 {
408 	int err;
409 
410 	/* Fetch VLAN MemberTag data from the VTU */
411 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
412 	if (err)
413 		return err;
414 
415 	if (entry->valid) {
416 		err = mv88e6185_g1_vtu_data_read(chip, entry);
417 		if (err)
418 			return err;
419 
420 		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
421 		if (err)
422 			return err;
423 
424 		/* Fetch VLAN PortState data from the STU */
425 		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
426 		if (err)
427 			return err;
428 
429 		err = mv88e6185_g1_stu_data_read(chip, entry);
430 		if (err)
431 			return err;
432 	}
433 
434 	return 0;
435 }
436 
mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)437 int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
438 			     struct mv88e6xxx_vtu_entry *entry)
439 {
440 	int err;
441 
442 	/* Fetch VLAN MemberTag data from the VTU */
443 	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
444 	if (err)
445 		return err;
446 
447 	if (entry->valid) {
448 		err = mv88e6390_g1_vtu_data_read(chip, entry->member);
449 		if (err)
450 			return err;
451 
452 		/* Fetch VLAN PortState data from the STU */
453 		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
454 		if (err)
455 			return err;
456 
457 		err = mv88e6390_g1_vtu_data_read(chip, entry->state);
458 		if (err)
459 			return err;
460 
461 		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
462 		if (err)
463 			return err;
464 	}
465 
466 	return 0;
467 }
468 
mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)469 int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
470 			       struct mv88e6xxx_vtu_entry *entry)
471 {
472 	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
473 	int err;
474 
475 	err = mv88e6xxx_g1_vtu_op_wait(chip);
476 	if (err)
477 		return err;
478 
479 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
480 	if (err)
481 		return err;
482 
483 	if (entry->valid) {
484 		err = mv88e6185_g1_vtu_data_write(chip, entry);
485 		if (err)
486 			return err;
487 
488 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
489 		 * VTU DBNum[5:4] are located in VTU Operation 9:8
490 		 */
491 		op |= entry->fid & 0x000f;
492 		op |= (entry->fid & 0x0030) << 4;
493 	}
494 
495 	return mv88e6xxx_g1_vtu_op(chip, op);
496 }
497 
mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)498 int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
499 			       struct mv88e6xxx_vtu_entry *entry)
500 {
501 	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
502 	int err;
503 
504 	err = mv88e6xxx_g1_vtu_op_wait(chip);
505 	if (err)
506 		return err;
507 
508 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
509 	if (err)
510 		return err;
511 
512 	if (entry->valid) {
513 		err = mv88e6185_g1_vtu_data_write(chip, entry);
514 		if (err)
515 			return err;
516 
517 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
518 		 * VTU DBNum[7:4] are located in VTU Operation 11:8
519 		 */
520 		op |= entry->fid & 0x000f;
521 		op |= (entry->fid & 0x00f0) << 4;
522 	}
523 
524 	return mv88e6xxx_g1_vtu_op(chip, op);
525 }
526 
mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)527 int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
528 			       struct mv88e6xxx_vtu_entry *entry)
529 {
530 	int err;
531 
532 	err = mv88e6xxx_g1_vtu_op_wait(chip);
533 	if (err)
534 		return err;
535 
536 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
537 	if (err)
538 		return err;
539 
540 	if (entry->valid) {
541 		/* Write MemberTag and PortState data */
542 		err = mv88e6185_g1_vtu_data_write(chip, entry);
543 		if (err)
544 			return err;
545 
546 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
547 		if (err)
548 			return err;
549 
550 		/* Load STU entry */
551 		err = mv88e6xxx_g1_vtu_op(chip,
552 					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
553 		if (err)
554 			return err;
555 
556 		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
557 		if (err)
558 			return err;
559 	}
560 
561 	/* Load/Purge VTU entry */
562 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
563 }
564 
mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip * chip,struct mv88e6xxx_vtu_entry * entry)565 int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
566 			       struct mv88e6xxx_vtu_entry *entry)
567 {
568 	int err;
569 
570 	err = mv88e6xxx_g1_vtu_op_wait(chip);
571 	if (err)
572 		return err;
573 
574 	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
575 	if (err)
576 		return err;
577 
578 	if (entry->valid) {
579 		/* Write PortState data */
580 		err = mv88e6390_g1_vtu_data_write(chip, entry->state);
581 		if (err)
582 			return err;
583 
584 		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
585 		if (err)
586 			return err;
587 
588 		/* Load STU entry */
589 		err = mv88e6xxx_g1_vtu_op(chip,
590 					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
591 		if (err)
592 			return err;
593 
594 		/* Write MemberTag data */
595 		err = mv88e6390_g1_vtu_data_write(chip, entry->member);
596 		if (err)
597 			return err;
598 
599 		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
600 		if (err)
601 			return err;
602 	}
603 
604 	/* Load/Purge VTU entry */
605 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
606 }
607 
mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip * chip)608 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
609 {
610 	int err;
611 
612 	err = mv88e6xxx_g1_vtu_op_wait(chip);
613 	if (err)
614 		return err;
615 
616 	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
617 }
618 
mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq,void * dev_id)619 static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
620 {
621 	struct mv88e6xxx_chip *chip = dev_id;
622 	struct mv88e6xxx_vtu_entry entry;
623 	int spid;
624 	int err;
625 	u16 val;
626 
627 	mv88e6xxx_reg_lock(chip);
628 
629 	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
630 	if (err)
631 		goto out;
632 
633 	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
634 	if (err)
635 		goto out;
636 
637 	err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
638 	if (err)
639 		goto out;
640 
641 	spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
642 
643 	if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
644 		dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
645 				    entry.vid, spid);
646 		chip->ports[spid].vtu_member_violation++;
647 	}
648 
649 	if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
650 		dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
651 				    entry.vid, spid);
652 		chip->ports[spid].vtu_miss_violation++;
653 	}
654 
655 	mv88e6xxx_reg_unlock(chip);
656 
657 	return IRQ_HANDLED;
658 
659 out:
660 	mv88e6xxx_reg_unlock(chip);
661 
662 	dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
663 		err);
664 
665 	return IRQ_HANDLED;
666 }
667 
mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip * chip)668 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
669 {
670 	int err;
671 
672 	chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
673 					      MV88E6XXX_G1_STS_IRQ_VTU_PROB);
674 	if (chip->vtu_prob_irq < 0)
675 		return chip->vtu_prob_irq;
676 
677 	snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
678 		 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
679 
680 	err = request_threaded_irq(chip->vtu_prob_irq, NULL,
681 				   mv88e6xxx_g1_vtu_prob_irq_thread_fn,
682 				   IRQF_ONESHOT, chip->vtu_prob_irq_name,
683 				   chip);
684 	if (err)
685 		irq_dispose_mapping(chip->vtu_prob_irq);
686 
687 	return err;
688 }
689 
mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip * chip)690 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
691 {
692 	free_irq(chip->vtu_prob_irq, chip);
693 	irq_dispose_mapping(chip->vtu_prob_irq);
694 }
695