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 = ®s[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 = ®s[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