Skip to content

Commit 37c86c4

Browse files
committed
Merge branch 'ks8795-vlan-fixes'
Ben Hutchings says: ==================== ksz8795 VLAN fixes This series fixes a number of bugs in the ksz8795 driver that affect VLAN filtering, tag insertion, and tag removal. I've tested these on the KSZ8795CLXD evaluation board, and checked the register usage against the datasheets for the other supported chips. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 31782a0 + 411d466 commit 37c86c4

File tree

3 files changed

+74
-21
lines changed

3 files changed

+74
-21
lines changed

drivers/net/dsa/microchip/ksz8795.c

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -687,8 +687,8 @@ static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
687687
shifts = ksz8->shifts;
688688

689689
ksz8_r_table(dev, TABLE_VLAN, addr, &data);
690-
addr *= dev->phy_port_cnt;
691-
for (i = 0; i < dev->phy_port_cnt; i++) {
690+
addr *= 4;
691+
for (i = 0; i < 4; i++) {
692692
dev->vlan_cache[addr + i].table[0] = (u16)data;
693693
data >>= shifts[VLAN_TABLE];
694694
}
@@ -702,7 +702,7 @@ static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
702702
u64 buf;
703703

704704
data = (u16 *)&buf;
705-
addr = vid / dev->phy_port_cnt;
705+
addr = vid / 4;
706706
index = vid & 3;
707707
ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
708708
*vlan = data[index];
@@ -716,7 +716,7 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
716716
u64 buf;
717717

718718
data = (u16 *)&buf;
719-
addr = vid / dev->phy_port_cnt;
719+
addr = vid / 4;
720720
index = vid & 3;
721721
ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
722722
data[index] = vlan;
@@ -1119,24 +1119,67 @@ static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag,
11191119
if (ksz_is_ksz88x3(dev))
11201120
return -ENOTSUPP;
11211121

1122+
/* Discard packets with VID not enabled on the switch */
11221123
ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag);
11231124

1125+
/* Discard packets with VID not enabled on the ingress port */
1126+
for (port = 0; port < dev->phy_port_cnt; ++port)
1127+
ksz_port_cfg(dev, port, REG_PORT_CTRL_2, PORT_INGRESS_FILTER,
1128+
flag);
1129+
11241130
return 0;
11251131
}
11261132

1133+
static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state)
1134+
{
1135+
if (ksz_is_ksz88x3(dev)) {
1136+
ksz_cfg(dev, REG_SW_INSERT_SRC_PVID,
1137+
0x03 << (4 - 2 * port), state);
1138+
} else {
1139+
ksz_pwrite8(dev, port, REG_PORT_CTRL_12, state ? 0x0f : 0x00);
1140+
}
1141+
}
1142+
11271143
static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
11281144
const struct switchdev_obj_port_vlan *vlan,
11291145
struct netlink_ext_ack *extack)
11301146
{
11311147
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
11321148
struct ksz_device *dev = ds->priv;
1149+
struct ksz_port *p = &dev->ports[port];
11331150
u16 data, new_pvid = 0;
11341151
u8 fid, member, valid;
11351152

11361153
if (ksz_is_ksz88x3(dev))
11371154
return -ENOTSUPP;
11381155

1139-
ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
1156+
/* If a VLAN is added with untagged flag different from the
1157+
* port's Remove Tag flag, we need to change the latter.
1158+
* Ignore VID 0, which is always untagged.
1159+
* Ignore CPU port, which will always be tagged.
1160+
*/
1161+
if (untagged != p->remove_tag && vlan->vid != 0 &&
1162+
port != dev->cpu_port) {
1163+
unsigned int vid;
1164+
1165+
/* Reject attempts to add a VLAN that requires the
1166+
* Remove Tag flag to be changed, unless there are no
1167+
* other VLANs currently configured.
1168+
*/
1169+
for (vid = 1; vid < dev->num_vlans; ++vid) {
1170+
/* Skip the VID we are going to add or reconfigure */
1171+
if (vid == vlan->vid)
1172+
continue;
1173+
1174+
ksz8_from_vlan(dev, dev->vlan_cache[vid].table[0],
1175+
&fid, &member, &valid);
1176+
if (valid && (member & BIT(port)))
1177+
return -EINVAL;
1178+
}
1179+
1180+
ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
1181+
p->remove_tag = untagged;
1182+
}
11401183

11411184
ksz8_r_vlan_table(dev, vlan->vid, &data);
11421185
ksz8_from_vlan(dev, data, &fid, &member, &valid);
@@ -1160,9 +1203,11 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
11601203
u16 vid;
11611204

11621205
ksz_pread16(dev, port, REG_PORT_CTRL_VID, &vid);
1163-
vid &= 0xfff;
1206+
vid &= ~VLAN_VID_MASK;
11641207
vid |= new_pvid;
11651208
ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, vid);
1209+
1210+
ksz8_port_enable_pvid(dev, port, true);
11661211
}
11671212

11681213
return 0;
@@ -1171,9 +1216,8 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
11711216
static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
11721217
const struct switchdev_obj_port_vlan *vlan)
11731218
{
1174-
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
11751219
struct ksz_device *dev = ds->priv;
1176-
u16 data, pvid, new_pvid = 0;
1220+
u16 data, pvid;
11771221
u8 fid, member, valid;
11781222

11791223
if (ksz_is_ksz88x3(dev))
@@ -1182,8 +1226,6 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
11821226
ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid);
11831227
pvid = pvid & 0xFFF;
11841228

1185-
ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
1186-
11871229
ksz8_r_vlan_table(dev, vlan->vid, &data);
11881230
ksz8_from_vlan(dev, data, &fid, &member, &valid);
11891231

@@ -1195,14 +1237,11 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
11951237
valid = 0;
11961238
}
11971239

1198-
if (pvid == vlan->vid)
1199-
new_pvid = 1;
1200-
12011240
ksz8_to_vlan(dev, fid, member, valid, &data);
12021241
ksz8_w_vlan_table(dev, vlan->vid, data);
12031242

1204-
if (new_pvid != pvid)
1205-
ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid);
1243+
if (pvid == vlan->vid)
1244+
ksz8_port_enable_pvid(dev, port, false);
12061245

12071246
return 0;
12081247
}
@@ -1435,6 +1474,9 @@ static int ksz8_setup(struct dsa_switch *ds)
14351474

14361475
ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false);
14371476

1477+
if (!ksz_is_ksz88x3(dev))
1478+
ksz_cfg(dev, REG_SW_CTRL_19, SW_INS_TAG_ENABLE, true);
1479+
14381480
/* set broadcast storm protection 10% rate */
14391481
regmap_update_bits(dev->regmap[1], S_REPLACE_VID_CTRL,
14401482
BROADCAST_STORM_RATE,
@@ -1717,6 +1759,16 @@ static int ksz8_switch_init(struct ksz_device *dev)
17171759
/* set the real number of ports */
17181760
dev->ds->num_ports = dev->port_cnt;
17191761

1762+
/* We rely on software untagging on the CPU port, so that we
1763+
* can support both tagged and untagged VLANs
1764+
*/
1765+
dev->ds->untag_bridge_pvid = true;
1766+
1767+
/* VLAN filtering is partly controlled by the global VLAN
1768+
* Enable flag
1769+
*/
1770+
dev->ds->vlan_filtering_is_global = true;
1771+
17201772
return 0;
17211773
}
17221774

drivers/net/dsa/microchip/ksz8795_reg.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,10 @@
631631
#define REG_PORT_4_OUT_RATE_3 0xEE
632632
#define REG_PORT_5_OUT_RATE_3 0xFE
633633

634+
/* 88x3 specific */
635+
636+
#define REG_SW_INSERT_SRC_PVID 0xC2
637+
634638
/* PME */
635639

636640
#define SW_PME_OUTPUT_ENABLE BIT(1)

drivers/net/dsa/microchip/ksz_common.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct ksz_port_mib {
2727
struct ksz_port {
2828
u16 member;
2929
u16 vid_member;
30+
bool remove_tag; /* Remove Tag flag set, for ksz8795 only */
3031
int stp_state;
3132
struct phy_device phydev;
3233

@@ -205,12 +206,8 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
205206
int ret;
206207

207208
ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
208-
if (!ret) {
209-
/* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */
210-
value[0] = swab32(value[0]);
211-
value[1] = swab32(value[1]);
212-
*val = swab64((u64)*value);
213-
}
209+
if (!ret)
210+
*val = (u64)value[0] << 32 | value[1];
214211

215212
return ret;
216213
}

0 commit comments

Comments
 (0)