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