Skip to content

Commit

Permalink
net: dsa: microchip: ksz8795: Fix PVID tag insertion
Browse files Browse the repository at this point in the history
ksz8795 has never actually enabled PVID tag insertion, and it also
programmed the PVID incorrectly.  To fix this:

* Allow tag insertion to be controlled per ingress port.  On most
  chips, set bit 2 in Global Control 19.  On KSZ88x3 this control
  flag doesn't exist.

* When adding a PVID:
  - Set the appropriate register bits to enable tag insertion on
    egress at every other port if this was the packet's ingress port.
  - Mask *out* the VID from the default tag, before or-ing in the new
    PVID.

* When removing a PVID:
  - Clear the same control bits to disable tag insertion.
  - Don't update the default tag.  This wasn't doing anything useful.

Fixes: e66f840 ("net: dsa: ksz: Add Microchip KSZ8795 DSA driver")
Signed-off-by: Ben Hutchings <ben.hutchings@mind.be>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ben Hutchings authored and David S. Miller committed Aug 10, 2021
1 parent c34f674 commit ef3b02a
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 7 deletions.
26 changes: 19 additions & 7 deletions drivers/net/dsa/microchip/ksz8795.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,16 @@ static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag,
return 0;
}

static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state)
{
if (ksz_is_ksz88x3(dev)) {
ksz_cfg(dev, REG_SW_INSERT_SRC_PVID,
0x03 << (4 - 2 * port), state);
} else {
ksz_pwrite8(dev, port, REG_PORT_CTRL_12, state ? 0x0f : 0x00);
}
}

static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
Expand Down Expand Up @@ -1160,9 +1170,11 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
u16 vid;

ksz_pread16(dev, port, REG_PORT_CTRL_VID, &vid);
vid &= 0xfff;
vid &= ~VLAN_VID_MASK;
vid |= new_pvid;
ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, vid);

ksz8_port_enable_pvid(dev, port, true);
}

return 0;
Expand All @@ -1173,7 +1185,7 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
struct ksz_device *dev = ds->priv;
u16 data, pvid, new_pvid = 0;
u16 data, pvid;
u8 fid, member, valid;

if (ksz_is_ksz88x3(dev))
Expand All @@ -1195,14 +1207,11 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
valid = 0;
}

if (pvid == vlan->vid)
new_pvid = 1;

ksz8_to_vlan(dev, fid, member, valid, &data);
ksz8_w_vlan_table(dev, vlan->vid, data);

if (new_pvid != pvid)
ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid);
if (pvid == vlan->vid)
ksz8_port_enable_pvid(dev, port, false);

return 0;
}
Expand Down Expand Up @@ -1435,6 +1444,9 @@ static int ksz8_setup(struct dsa_switch *ds)

ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false);

if (!ksz_is_ksz88x3(dev))
ksz_cfg(dev, REG_SW_CTRL_19, SW_INS_TAG_ENABLE, true);

/* set broadcast storm protection 10% rate */
regmap_update_bits(dev->regmap[1], S_REPLACE_VID_CTRL,
BROADCAST_STORM_RATE,
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/dsa/microchip/ksz8795_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,10 @@
#define REG_PORT_4_OUT_RATE_3 0xEE
#define REG_PORT_5_OUT_RATE_3 0xFE

/* 88x3 specific */

#define REG_SW_INSERT_SRC_PVID 0xC2

/* PME */

#define SW_PME_OUTPUT_ENABLE BIT(1)
Expand Down

0 comments on commit ef3b02a

Please sign in to comment.