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