Linux Audio

Check our new training course

Loading...
v6.8
  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 = &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
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 = &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
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}
v5.9
  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
 19static 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
 34static 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
 44static 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
 59static 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
 69static 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
 76static 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
 90static 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
110static 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 */
128
129static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
130				      struct mv88e6xxx_vtu_entry *entry)
131{
132	u16 regs[3];
133	int i;
134
135	/* Read all 3 VTU/STU Data registers */
136	for (i = 0; i < 3; ++i) {
137		u16 *reg = &regs[i];
138		int err;
139
140		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
141		if (err)
142			return err;
143	}
144
145	/* Extract MemberTag and PortState data */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
147		unsigned int member_offset = (i % 4) * 4;
148		unsigned int state_offset = member_offset + 2;
149
150		entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
151		entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
 
 
 
152	}
153
154	return 0;
155}
156
157static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
158				       struct mv88e6xxx_vtu_entry *entry)
159{
160	u16 regs[3] = { 0 };
161	int i;
162
163	/* Insert MemberTag and PortState data */
164	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
165		unsigned int member_offset = (i % 4) * 4;
166		unsigned int state_offset = member_offset + 2;
167
168		regs[i / 4] |= (entry->member[i] & 0x3) << member_offset;
169		regs[i / 4] |= (entry->state[i] & 0x3) << state_offset;
 
 
 
170	}
171
172	/* Write all 3 VTU/STU Data registers */
173	for (i = 0; i < 3; ++i) {
174		u16 reg = regs[i];
175		int err;
176
177		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
178		if (err)
179			return err;
180	}
181
182	return 0;
183}
184
185static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
186{
187	u16 regs[2];
188	int i;
189
190	/* Read the 2 VTU/STU Data registers */
191	for (i = 0; i < 2; ++i) {
192		u16 *reg = &regs[i];
193		int err;
194
195		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
196		if (err)
197			return err;
198	}
199
200	/* Extract data */
201	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
202		unsigned int offset = (i % 8) * 2;
203
204		data[i] = (regs[i / 8] >> offset) & 0x3;
205	}
206
207	return 0;
208}
209
210static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
211{
212	u16 regs[2] = { 0 };
213	int i;
214
215	/* Insert data */
216	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
217		unsigned int offset = (i % 8) * 2;
218
219		regs[i / 8] |= (data[i] & 0x3) << offset;
220	}
221
222	/* Write the 2 VTU/STU Data registers */
223	for (i = 0; i < 2; ++i) {
224		u16 reg = regs[i];
225		int err;
226
227		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
228		if (err)
229			return err;
230	}
231
232	return 0;
233}
234
235/* VLAN Translation Unit Operations */
236
237static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip,
238					struct mv88e6xxx_vtu_entry *entry)
239{
240	int err;
241
242	err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
243	if (err)
244		return err;
245
246	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
247	if (err)
248		return err;
249
250	err = mv88e6xxx_g1_vtu_sid_read(chip, entry);
251	if (err)
252		return err;
253
254	return mv88e6xxx_g1_vtu_vid_read(chip, entry);
255}
256
257static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip,
258				    struct mv88e6xxx_vtu_entry *vtu)
259{
260	struct mv88e6xxx_vtu_entry stu;
261	int err;
262
263	err = mv88e6xxx_g1_vtu_sid_read(chip, vtu);
264	if (err)
265		return err;
266
267	stu.sid = vtu->sid - 1;
268
269	err = mv88e6xxx_g1_vtu_stu_getnext(chip, &stu);
270	if (err)
271		return err;
272
273	if (stu.sid != vtu->sid || !stu.valid)
274		return -EINVAL;
275
276	return 0;
277}
278
279static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
280				    struct mv88e6xxx_vtu_entry *entry)
281{
282	int err;
283
284	err = mv88e6xxx_g1_vtu_op_wait(chip);
285	if (err)
286		return err;
287
288	/* To get the next higher active VID, the VTU GetNext operation can be
289	 * started again without setting the VID registers since it already
290	 * contains the last VID.
291	 *
292	 * To save a few hardware accesses and abstract this to the caller,
293	 * write the VID only once, when the entry is given as invalid.
294	 */
295	if (!entry->valid) {
296		err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
297		if (err)
298			return err;
299	}
300
301	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
302	if (err)
303		return err;
304
305	return mv88e6xxx_g1_vtu_vid_read(chip, entry);
306}
307
308int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
309			     struct mv88e6xxx_vtu_entry *entry)
310{
311	u16 val;
312	int err;
313
314	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
315	if (err)
316		return err;
317
318	if (entry->valid) {
319		err = mv88e6185_g1_vtu_data_read(chip, entry);
320		if (err)
321			return err;
322
323		/* VTU DBNum[3:0] are located in VTU Operation 3:0
324		 * VTU DBNum[5:4] are located in VTU Operation 9:8
325		 */
326		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
327		if (err)
328			return err;
329
330		entry->fid = val & 0x000f;
331		entry->fid |= (val & 0x0300) >> 4;
332	}
333
334	return 0;
335}
336
337int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
338			     struct mv88e6xxx_vtu_entry *entry)
339{
340	u16 val;
341	int err;
342
343	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
344	if (err)
345		return err;
346
347	if (entry->valid) {
348		err = mv88e6185_g1_vtu_data_read(chip, entry);
349		if (err)
350			return err;
351
352		/* VTU DBNum[3:0] are located in VTU Operation 3:0
353		 * VTU DBNum[7:4] are located in VTU Operation 11:8
354		 */
355		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
356		if (err)
357			return err;
358
359		entry->fid = val & 0x000f;
360		entry->fid |= (val & 0x0f00) >> 4;
 
361	}
362
363	return 0;
364}
365
366int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
367			     struct mv88e6xxx_vtu_entry *entry)
368{
369	int err;
370
371	/* Fetch VLAN MemberTag data from the VTU */
372	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
373	if (err)
374		return err;
375
376	if (entry->valid) {
377		/* Fetch (and mask) VLAN PortState data from the STU */
378		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
379		if (err)
380			return err;
381
382		err = mv88e6185_g1_vtu_data_read(chip, entry);
383		if (err)
384			return err;
385
386		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
387		if (err)
388			return err;
389	}
390
391	return 0;
392}
393
394int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
395			     struct mv88e6xxx_vtu_entry *entry)
396{
397	int err;
398
399	/* Fetch VLAN MemberTag data from the VTU */
400	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
401	if (err)
402		return err;
403
404	if (entry->valid) {
405		err = mv88e6390_g1_vtu_data_read(chip, entry->member);
406		if (err)
407			return err;
408
409		/* Fetch VLAN PortState data from the STU */
410		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
411		if (err)
412			return err;
413
414		err = mv88e6390_g1_vtu_data_read(chip, entry->state);
415		if (err)
416			return err;
417
418		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
419		if (err)
420			return err;
421	}
422
423	return 0;
424}
425
426int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
427			       struct mv88e6xxx_vtu_entry *entry)
428{
429	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
430	int err;
431
432	err = mv88e6xxx_g1_vtu_op_wait(chip);
433	if (err)
434		return err;
435
436	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
437	if (err)
438		return err;
439
440	if (entry->valid) {
441		err = mv88e6185_g1_vtu_data_write(chip, entry);
442		if (err)
443			return err;
444
445		/* VTU DBNum[3:0] are located in VTU Operation 3:0
446		 * VTU DBNum[5:4] are located in VTU Operation 9:8
 
 
 
 
447		 */
448		op |= entry->fid & 0x000f;
449		op |= (entry->fid & 0x0030) << 4;
450	}
451
452	return mv88e6xxx_g1_vtu_op(chip, op);
453}
454
455int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
456			       struct mv88e6xxx_vtu_entry *entry)
457{
458	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
459	int err;
460
461	err = mv88e6xxx_g1_vtu_op_wait(chip);
462	if (err)
463		return err;
464
465	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
466	if (err)
467		return err;
468
469	if (entry->valid) {
470		err = mv88e6185_g1_vtu_data_write(chip, entry);
 
 
 
 
 
471		if (err)
472			return err;
473
474		/* VTU DBNum[3:0] are located in VTU Operation 3:0
475		 * VTU DBNum[7:4] are located in VTU Operation 11:8
476		 */
477		op |= entry->fid & 0x000f;
478		op |= (entry->fid & 0x00f0) << 4;
479	}
480
481	return mv88e6xxx_g1_vtu_op(chip, op);
 
482}
483
484int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
485			       struct mv88e6xxx_vtu_entry *entry)
486{
487	int err;
488
489	err = mv88e6xxx_g1_vtu_op_wait(chip);
490	if (err)
491		return err;
492
493	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
494	if (err)
495		return err;
496
497	if (entry->valid) {
498		/* Write MemberTag and PortState data */
499		err = mv88e6185_g1_vtu_data_write(chip, entry);
500		if (err)
501			return err;
502
503		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
504		if (err)
505			return err;
506
507		/* Load STU entry */
508		err = mv88e6xxx_g1_vtu_op(chip,
509					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
510		if (err)
511			return err;
512
513		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
514		if (err)
515			return err;
516	}
517
518	/* Load/Purge VTU entry */
519	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
520}
521
522int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
523			       struct mv88e6xxx_vtu_entry *entry)
524{
525	int err;
526
527	err = mv88e6xxx_g1_vtu_op_wait(chip);
528	if (err)
529		return err;
530
531	err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
 
 
 
 
 
 
 
 
 
 
532	if (err)
533		return err;
534
535	if (entry->valid) {
536		/* Write PortState data */
537		err = mv88e6390_g1_vtu_data_write(chip, entry->state);
 
 
 
 
 
 
538		if (err)
539			return err;
 
 
 
 
 
540
541		err = mv88e6xxx_g1_vtu_sid_write(chip, entry);
 
 
 
 
 
542		if (err)
543			return err;
 
 
 
 
 
 
 
 
 
544
545		/* Load STU entry */
546		err = mv88e6xxx_g1_vtu_op(chip,
547					  MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
548		if (err)
549			return err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
550
551		/* Write MemberTag data */
552		err = mv88e6390_g1_vtu_data_write(chip, entry->member);
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
565int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
 
566{
567	int err;
568
569	err = mv88e6xxx_g1_vtu_op_wait(chip);
570	if (err)
571		return err;
572
573	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574}
575
 
 
576static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
577{
578	struct mv88e6xxx_chip *chip = dev_id;
579	struct mv88e6xxx_vtu_entry entry;
580	int spid;
581	int err;
582	u16 val;
583
584	mv88e6xxx_reg_lock(chip);
585
586	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
587	if (err)
588		goto out;
589
590	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
591	if (err)
592		goto out;
593
594	err = mv88e6xxx_g1_vtu_vid_read(chip, &entry);
595	if (err)
596		goto out;
597
598	spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
599
600	if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
601		dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
602				    entry.vid, spid);
603		chip->ports[spid].vtu_member_violation++;
604	}
605
606	if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
607		dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
608				    entry.vid, spid);
609		chip->ports[spid].vtu_miss_violation++;
610	}
611
612	mv88e6xxx_reg_unlock(chip);
613
614	return IRQ_HANDLED;
615
616out:
617	mv88e6xxx_reg_unlock(chip);
618
619	dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
620		err);
621
622	return IRQ_HANDLED;
623}
624
625int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
626{
627	int err;
628
629	chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
630					      MV88E6XXX_G1_STS_IRQ_VTU_PROB);
631	if (chip->vtu_prob_irq < 0)
632		return chip->vtu_prob_irq;
633
634	snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
635		 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
636
637	err = request_threaded_irq(chip->vtu_prob_irq, NULL,
638				   mv88e6xxx_g1_vtu_prob_irq_thread_fn,
639				   IRQF_ONESHOT, chip->vtu_prob_irq_name,
640				   chip);
641	if (err)
642		irq_dispose_mapping(chip->vtu_prob_irq);
643
644	return err;
645}
646
647void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
648{
649	free_irq(chip->vtu_prob_irq, chip);
650	irq_dispose_mapping(chip->vtu_prob_irq);
651}