Skip to content

Commit 9230706

Browse files
wkzkuba-moo
authored andcommitted
net: dsa: mv88e6xxx: Avoid VTU corruption on 6097
As soon as you add the second port to a VLAN, all other port membership configuration is overwritten with zeroes. The HW interprets this as all ports being "unmodified members" of the VLAN. In the simple case when all ports belong to the same VLAN, switching will still work. But using multiple VLANs or trying to set multiple ports as tagged members will not work. On the 6352, doing a VTU GetNext op, followed by an STU GetNext op will leave you with both the member- and state- data in the VTU/STU data registers. But on the 6097 (which uses the same implementation), the STU GetNext will override the information gathered from the VTU GetNext. Separate the two stages, parsing the result of the VTU GetNext before doing the STU GetNext. We opt to update the existing implementation for all applicable chips, as opposed to creating a separate callback for 6097, because although the previous implementation did work for (at least) 6352, the datasheet does not mention the masking behavior. Fixes: ef6fcea ("net: dsa: mv88e6xxx: get STU entry on VTU GetNext") Signed-off-by: Tobias Waldekranz <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 3734471 commit 9230706

File tree

1 file changed

+49
-10
lines changed

1 file changed

+49
-10
lines changed

drivers/net/dsa/mv88e6xxx/global1_vtu.c

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,9 @@ static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
125125
* Offset 0x08: VTU/STU Data Register 2
126126
* Offset 0x09: VTU/STU Data Register 3
127127
*/
128-
129-
static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
130-
struct mv88e6xxx_vtu_entry *entry)
128+
static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
129+
u16 *regs)
131130
{
132-
u16 regs[3];
133131
int i;
134132

135133
/* Read all 3 VTU/STU Data registers */
@@ -142,12 +140,45 @@ static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
142140
return err;
143141
}
144142

145-
/* Extract MemberTag and PortState data */
143+
return 0;
144+
}
145+
146+
static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
147+
struct mv88e6xxx_vtu_entry *entry)
148+
{
149+
u16 regs[3];
150+
int err;
151+
int i;
152+
153+
err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
154+
if (err)
155+
return err;
156+
157+
/* Extract MemberTag data */
146158
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
147159
unsigned int member_offset = (i % 4) * 4;
148-
unsigned int state_offset = member_offset + 2;
149160

150161
entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
162+
}
163+
164+
return 0;
165+
}
166+
167+
static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
168+
struct mv88e6xxx_vtu_entry *entry)
169+
{
170+
u16 regs[3];
171+
int err;
172+
int i;
173+
174+
err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
175+
if (err)
176+
return err;
177+
178+
/* Extract PortState data */
179+
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
180+
unsigned int state_offset = (i % 4) * 4 + 2;
181+
151182
entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
152183
}
153184

@@ -349,6 +380,10 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
349380
if (err)
350381
return err;
351382

383+
err = mv88e6185_g1_stu_data_read(chip, entry);
384+
if (err)
385+
return err;
386+
352387
/* VTU DBNum[3:0] are located in VTU Operation 3:0
353388
* VTU DBNum[7:4] are located in VTU Operation 11:8
354389
*/
@@ -374,16 +409,20 @@ int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
374409
return err;
375410

376411
if (entry->valid) {
377-
/* Fetch (and mask) VLAN PortState data from the STU */
378-
err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
412+
err = mv88e6185_g1_vtu_data_read(chip, entry);
379413
if (err)
380414
return err;
381415

382-
err = mv88e6185_g1_vtu_data_read(chip, entry);
416+
err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
383417
if (err)
384418
return err;
385419

386-
err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
420+
/* Fetch VLAN PortState data from the STU */
421+
err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
422+
if (err)
423+
return err;
424+
425+
err = mv88e6185_g1_stu_data_read(chip, entry);
387426
if (err)
388427
return err;
389428
}

0 commit comments

Comments
 (0)