]> Git Repo - J-linux.git/blob - drivers/net/dsa/mv88e6xxx/global1_vtu.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / net / dsa / mv88e6xxx / global1_vtu.c
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
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
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
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
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
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
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
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
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  */
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
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
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
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
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
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
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
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
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
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
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
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
470 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
471 {
472         int err;
473
474         /* As part of the VTU flush, refresh FID map */
475         bitmap_zero(chip->fid_bitmap, MV88E6XXX_N_FID);
476
477         err = mv88e6xxx_g1_vtu_op_wait(chip);
478         if (err)
479                 return err;
480
481         return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
482 }
483
484 /* Spanning Tree Unit Operations */
485
486 int mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip *chip,
487                              struct mv88e6xxx_stu_entry *entry)
488 {
489         int err;
490
491         err = mv88e6xxx_g1_vtu_op_wait(chip);
492         if (err)
493                 return err;
494
495         /* To get the next higher active SID, the STU GetNext operation can be
496          * started again without setting the SID registers since it already
497          * contains the last SID.
498          *
499          * To save a few hardware accesses and abstract this to the caller,
500          * write the SID only once, when the entry is given as invalid.
501          */
502         if (!entry->valid) {
503                 err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
504                 if (err)
505                         return err;
506         }
507
508         err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
509         if (err)
510                 return err;
511
512         err = mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, NULL);
513         if (err)
514                 return err;
515
516         if (entry->valid) {
517                 err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
518                 if (err)
519                         return err;
520         }
521
522         return 0;
523 }
524
525 int mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip *chip,
526                              struct mv88e6xxx_stu_entry *entry)
527 {
528         int err;
529
530         err = mv88e6xxx_g1_stu_getnext(chip, entry);
531         if (err)
532                 return err;
533
534         if (!entry->valid)
535                 return 0;
536
537         return mv88e6185_g1_vtu_data_read(chip, NULL, entry->state);
538 }
539
540 int mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip *chip,
541                              struct mv88e6xxx_stu_entry *entry)
542 {
543         int err;
544
545         err = mv88e6xxx_g1_stu_getnext(chip, entry);
546         if (err)
547                 return err;
548
549         if (!entry->valid)
550                 return 0;
551
552         return mv88e6390_g1_vtu_data_read(chip, entry->state);
553 }
554
555 int mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
556                                struct mv88e6xxx_stu_entry *entry)
557 {
558         int err;
559
560         err = mv88e6xxx_g1_vtu_op_wait(chip);
561         if (err)
562                 return err;
563
564         err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
565         if (err)
566                 return err;
567
568         err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
569         if (err)
570                 return err;
571
572         if (entry->valid) {
573                 err = mv88e6185_g1_vtu_data_write(chip, NULL, entry->state);
574                 if (err)
575                         return err;
576         }
577
578         /* Load/Purge STU entry */
579         return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
580 }
581
582 int mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
583                                struct mv88e6xxx_stu_entry *entry)
584 {
585         int err;
586
587         err = mv88e6xxx_g1_vtu_op_wait(chip);
588         if (err)
589                 return err;
590
591         err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
592         if (err)
593                 return err;
594
595         err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
596         if (err)
597                 return err;
598
599         if (entry->valid) {
600                 err = mv88e6390_g1_vtu_data_write(chip, entry->state);
601                 if (err)
602                         return err;
603         }
604
605         /* Load/Purge STU entry */
606         return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
607 }
608
609 /* VTU Violation Management */
610
611 static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
612 {
613         struct mv88e6xxx_chip *chip = dev_id;
614         u16 val, vid;
615         int spid;
616         int err;
617
618         mv88e6xxx_reg_lock(chip);
619
620         err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
621         if (err)
622                 goto out;
623
624         err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
625         if (err)
626                 goto out;
627
628         err = mv88e6xxx_g1_vtu_vid_read(chip, NULL, &vid);
629         if (err)
630                 goto out;
631
632         spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
633
634         if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
635                 trace_mv88e6xxx_vtu_member_violation(chip->dev, spid, vid);
636                 chip->ports[spid].vtu_member_violation++;
637         }
638
639         if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
640                 trace_mv88e6xxx_vtu_miss_violation(chip->dev, spid, vid);
641                 chip->ports[spid].vtu_miss_violation++;
642         }
643
644         mv88e6xxx_reg_unlock(chip);
645
646         return IRQ_HANDLED;
647
648 out:
649         mv88e6xxx_reg_unlock(chip);
650
651         dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
652                 err);
653
654         return IRQ_HANDLED;
655 }
656
657 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
658 {
659         int err;
660
661         chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
662                                               MV88E6XXX_G1_STS_IRQ_VTU_PROB);
663         if (chip->vtu_prob_irq < 0)
664                 return chip->vtu_prob_irq;
665
666         snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
667                  "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
668
669         err = request_threaded_irq(chip->vtu_prob_irq, NULL,
670                                    mv88e6xxx_g1_vtu_prob_irq_thread_fn,
671                                    IRQF_ONESHOT, chip->vtu_prob_irq_name,
672                                    chip);
673         if (err)
674                 irq_dispose_mapping(chip->vtu_prob_irq);
675
676         return err;
677 }
678
679 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
680 {
681         free_irq(chip->vtu_prob_irq, chip);
682         irq_dispose_mapping(chip->vtu_prob_irq);
683 }
This page took 0.064931 seconds and 4 git commands to generate.