Loading...
1/*
2 * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
3 *
4 * Copyright (c) 2008 Marvell Semiconductor
5 * Copyright (c) 2015 CMC Electronics, Inc.
6 * Copyright (c) 2017 Savoir-faire Linux, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/interrupt.h>
15#include <linux/irqdomain.h>
16
17#include "chip.h"
18#include "global1.h"
19
20/* Offset 0x02: VTU FID Register */
21
22static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
23 struct mv88e6xxx_vtu_entry *entry)
24{
25 u16 val;
26 int err;
27
28 err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
29 if (err)
30 return err;
31
32 entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
33
34 return 0;
35}
36
37static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
38 struct mv88e6xxx_vtu_entry *entry)
39{
40 u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
41
42 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
43}
44
45/* Offset 0x03: VTU SID Register */
46
47static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip,
48 struct mv88e6xxx_vtu_entry *entry)
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 entry->sid = val & MV88E6352_G1_VTU_SID_MASK;
58
59 return 0;
60}
61
62static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip,
63 struct mv88e6xxx_vtu_entry *entry)
64{
65 u16 val = entry->sid & MV88E6352_G1_VTU_SID_MASK;
66
67 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
68}
69
70/* Offset 0x05: VTU Operation Register */
71
72static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
73{
74 return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_VTU_OP,
75 MV88E6XXX_G1_VTU_OP_BUSY);
76}
77
78static 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
92static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
93 struct mv88e6xxx_vtu_entry *entry)
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 entry->vid = val & 0xfff;
103
104 if (val & MV88E6390_G1_VTU_VID_PAGE)
105 entry->vid |= 0x1000;
106
107 entry->valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
108
109 return 0;
110}
111
112static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
113 struct mv88e6xxx_vtu_entry *entry)
114{
115 u16 val = entry->vid & 0xfff;
116
117 if (entry->vid & 0x1000)
118 val |= MV88E6390_G1_VTU_VID_PAGE;
119
120 if (entry->valid)
121 val |= MV88E6XXX_G1_VTU_VID_VALID;
122
123 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
124}
125
126/* Offset 0x07: VTU/STU Data Register 1
127 * Offset 0x08: VTU/STU Data Register 2
128 * Offset 0x09: VTU/STU Data Register 3
129 */
130
131static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
132 struct mv88e6xxx_vtu_entry *entry)
133{
134 u16 regs[3];
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 /* Extract MemberTag and PortState data */
148 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
149 unsigned int member_offset = (i % 4) * 4;
150 unsigned int state_offset = member_offset + 2;
151
152 entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
153 entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
154 }
155
156 return 0;
157}
158
159static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
160 struct mv88e6xxx_vtu_entry *entry)
161{
162 u16 regs[3] = { 0 };
163 int i;
164
165 /* Insert MemberTag and PortState data */
166 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
167 unsigned int member_offset = (i % 4) * 4;
168 unsigned int state_offset = member_offset + 2;
169
170 regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
171 regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
172 }
173
174 /* Write all 3 VTU/STU Data registers */
175 for (i = 0; i < 3; ++i) {
176 u16 reg = regs[i];
177 int err;
178
179 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
180 if (err)
181 return err;
182 }
183
184 return 0;
185}
186
187static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
188{
189 u16 regs[2];
190 int i;
191
192 /* Read the 2 VTU/STU Data registers */
193 for (i = 0; i < 2; ++i) {
194 u16 *reg = ®s[i];
195 int err;
196
197 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
198 if (err)
199 return err;
200 }
201
202 /* Extract data */
203 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
204 unsigned int offset = (i % 8) * 2;
205
206 data[i] = (regs[i / 8] >> offset) & 0x3;
207 }
208
209 return 0;
210}
211
212static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
213{
214 u16 regs[2] = { 0 };
215 int i;
216
217 /* Insert data */
218 for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
219 unsigned int offset = (i % 8) * 2;
220
221 regs[i / 8] |= (data[i] & 0x3) << offset;
222 }
223
224 /* Write the 2 VTU/STU Data registers */
225 for (i = 0; i < 2; ++i) {
226 u16 reg = regs[i];
227 int err;
228
229 err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
230 if (err)
231 return err;
232 }
233
234 return 0;
235}
236
237/* VLAN Translation Unit Operations */
238
239static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
240 struct mv88e6xxx_vtu_entry *entry)
241{
242 int err;
243
244 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
245 if (err)
246 return err;
247
248 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
249 if (err)
250 return err;
251
252 err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
253 if (err)
254 return err;
255
256 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
257}
258
259static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
260 struct mv88e6xxx_vtu_entry *vtu)
261{
262 struct mv88e6xxx_vtu_entry stu;
263 int err;
264
265 err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
266 if (err)
267 return err;
268
269 stu.sid = vtu->sid - 1;
270
271 err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
272 if (err)
273 return err;
274
275 if (stu.sid != vtu->sid || !stu.valid)
276 return -EINVAL;
277
278 return 0;
279}
280
281static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
282 struct mv88e6xxx_vtu_entry *entry)
283{
284 int err;
285
286 err = mv88e6xxx_g1_vtu_op_wait(chip);
287 if (err)
288 return err;
289
290 /* To get the next higher active VID, the VTU GetNext operation can be
291 * started again without setting the VID registers since it already
292 * contains the last VID.
293 *
294 * To save a few hardware accesses and abstract this to the caller,
295 * write the VID only once, when the entry is given as invalid.
296 */
297 if (!entry->valid) {
298 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
299 if (err)
300 return err;
301 }
302
303 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
304 if (err)
305 return err;
306
307 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
308}
309
310int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
311 struct mv88e6xxx_vtu_entry *entry)
312{
313 u16 val;
314 int err;
315
316 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
317 if (err)
318 return err;
319
320 if (entry->valid) {
321 err = mv88e6185_g1_vtu_data_read(chip, entry);
322 if (err)
323 return err;
324
325 /* VTU DBNum[3:0] are located in VTU Operation 3:0
326 * VTU DBNum[7:4] are located in VTU Operation 11:8
327 */
328 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
329 if (err)
330 return err;
331
332 entry->fid = val & 0x000f;
333 entry->fid |= (val & 0x0f00) >> 4;
334 }
335
336 return 0;
337}
338
339int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
340 struct mv88e6xxx_vtu_entry *entry)
341{
342 int err;
343
344 /* Fetch VLAN MemberTag data from the VTU */
345 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
346 if (err)
347 return err;
348
349 if (entry->valid) {
350 /* Fetch (and mask) VLAN PortState data from the STU */
351 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
352 if (err)
353 return err;
354
355 err = mv88e6185_g1_vtu_data_read(chip, entry);
356 if (err)
357 return err;
358
359 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
360 if (err)
361 return err;
362 }
363
364 return 0;
365}
366
367int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
368 struct mv88e6xxx_vtu_entry *entry)
369{
370 int err;
371
372 /* Fetch VLAN MemberTag data from the VTU */
373 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
374 if (err)
375 return err;
376
377 if (entry->valid) {
378 err = mv88e6390_g1_vtu_data_read(chip, entry->member);
379 if (err)
380 return err;
381
382 /* Fetch VLAN PortState data from the STU */
383 err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
384 if (err)
385 return err;
386
387 err = mv88e6390_g1_vtu_data_read(chip, entry->state);
388 if (err)
389 return err;
390
391 err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
392 if (err)
393 return err;
394 }
395
396 return 0;
397}
398
399int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
400 struct mv88e6xxx_vtu_entry *entry)
401{
402 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
403 int err;
404
405 err = mv88e6xxx_g1_vtu_op_wait(chip);
406 if (err)
407 return err;
408
409 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
410 if (err)
411 return err;
412
413 if (entry->valid) {
414 err = mv88e6185_g1_vtu_data_write(chip, entry);
415 if (err)
416 return err;
417
418 /* VTU DBNum[3:0] are located in VTU Operation 3:0
419 * VTU DBNum[7:4] are located in VTU Operation 11:8
420 */
421 op |= entry->fid & 0x000f;
422 op |= (entry->fid & 0x00f0) << 8;
423 }
424
425 return mv88e6xxx_g1_vtu_op(chip, op);
426}
427
428int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
429 struct mv88e6xxx_vtu_entry *entry)
430{
431 int err;
432
433 err = mv88e6xxx_g1_vtu_op_wait(chip);
434 if (err)
435 return err;
436
437 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
438 if (err)
439 return err;
440
441 if (entry->valid) {
442 /* Write MemberTag and PortState data */
443 err = mv88e6185_g1_vtu_data_write(chip, entry);
444 if (err)
445 return err;
446
447 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
448 if (err)
449 return err;
450
451 /* Load STU entry */
452 err = mv88e6xxx_g1_vtu_op(chip,
453 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
454 if (err)
455 return err;
456
457 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
458 if (err)
459 return err;
460 }
461
462 /* Load/Purge VTU entry */
463 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
464}
465
466int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
467 struct mv88e6xxx_vtu_entry *entry)
468{
469 int err;
470
471 err = mv88e6xxx_g1_vtu_op_wait(chip);
472 if (err)
473 return err;
474
475 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
476 if (err)
477 return err;
478
479 if (entry->valid) {
480 /* Write PortState data */
481 err = mv88e6390_g1_vtu_data_write(chip, entry->state);
482 if (err)
483 return err;
484
485 err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
486 if (err)
487 return err;
488
489 /* Load STU entry */
490 err = mv88e6xxx_g1_vtu_op(chip,
491 MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
492 if (err)
493 return err;
494
495 /* Write MemberTag data */
496 err = mv88e6390_g1_vtu_data_write(chip, entry->member);
497 if (err)
498 return err;
499
500 err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
501 if (err)
502 return err;
503 }
504
505 /* Load/Purge VTU entry */
506 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
507}
508
509int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
510{
511 int err;
512
513 err = mv88e6xxx_g1_vtu_op_wait(chip);
514 if (err)
515 return err;
516
517 return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
518}
519
520static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
521{
522 struct mv88e6xxx_chip *chip = dev_id;
523 struct mv88e6xxx_vtu_entry entry;
524 int spid;
525 int err;
526 u16 val;
527
528 mutex_lock(&chip->reg_lock);
529
530 err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
531 if (err)
532 goto out;
533
534 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
535 if (err)
536 goto out;
537
538 err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
539 if (err)
540 goto out;
541
542 spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
543
544 if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
545 dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
546 entry.vid, spid);
547 chip->ports[spid].vtu_member_violation++;
548 }
549
550 if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
551 dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
552 entry.vid, spid);
553 chip->ports[spid].vtu_miss_violation++;
554 }
555
556 mutex_unlock(&chip->reg_lock);
557
558 return IRQ_HANDLED;
559
560out:
561 mutex_unlock(&chip->reg_lock);
562
563 dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
564 err);
565
566 return IRQ_HANDLED;
567}
568
569int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
570{
571 int err;
572
573 chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
574 MV88E6XXX_G1_STS_IRQ_VTU_PROB);
575 if (chip->vtu_prob_irq < 0)
576 return chip->vtu_prob_irq;
577
578 err = request_threaded_irq(chip->vtu_prob_irq, NULL,
579 mv88e6xxx_g1_vtu_prob_irq_thread_fn,
580 IRQF_ONESHOT, "mv88e6xxx-g1-vtu-prob",
581 chip);
582 if (err)
583 irq_dispose_mapping(chip->vtu_prob_irq);
584
585 return err;
586}
587
588void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
589{
590 free_irq(chip->vtu_prob_irq, chip);
591 irq_dispose_mapping(chip->vtu_prob_irq);
592}
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
20static 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
35static 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
48static 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
62static 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
71static 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
78static 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
92static 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
115static 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 */
133static 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 = ®s[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
151static 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
177static 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
208static 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 = ®s[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
233static 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
260int 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
289int 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
319int 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
346int 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
373int 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
406int 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
438int 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
470int 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
483int 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
522int 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
537int 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
552int 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
579int 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
608static 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
645out:
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
654int 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
676void 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}