Skip to content

Commit 5033d5e

Browse files
bwh-mindgregkh
authored andcommitted
net: dsa: microchip: ksz8795: Reject unsupported VLAN configuration
commit 8f4f58f upstream. The switches supported by ksz8795 only have a per-port flag for Tag Removal. This means it is not possible to support both tagged and untagged VLANs on the same port. Reject attempts to add a VLAN that requires the flag to be changed, unless there are no VLANs currently configured. VID 0 is excluded from this check since it is untagged regardless of the state of the flag. On the CPU port we could support tagged and untagged VLANs at the same time. This will be enabled by a later patch. 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> [bwh: Backport to 5.10: - This configuration has to be detected and rejected in the port_vlan_prepare operation - ksz8795_port_vlan_add() has to check again to decide whether to change the Tag Removal flag, so put the common condition in a separate function - Handle VID ranges] Signed-off-by: Ben Hutchings <ben.hutchings@mind.be> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 60c007b commit 5033d5e

2 files changed

Lines changed: 54 additions & 2 deletions

File tree

drivers/net/dsa/microchip/ksz8795.c

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,15 +801,66 @@ static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
801801
return 0;
802802
}
803803

804+
static bool ksz8795_port_vlan_changes_remove_tag(
805+
struct dsa_switch *ds, int port,
806+
const struct switchdev_obj_port_vlan *vlan)
807+
{
808+
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
809+
struct ksz_device *dev = ds->priv;
810+
struct ksz_port *p = &dev->ports[port];
811+
812+
/* If a VLAN is added with untagged flag different from the
813+
* port's Remove Tag flag, we need to change the latter.
814+
* Ignore VID 0, which is always untagged.
815+
*/
816+
return untagged != p->remove_tag &&
817+
!(vlan->vid_begin == 0 && vlan->vid_end == 0);
818+
}
819+
820+
int ksz8795_port_vlan_prepare(struct dsa_switch *ds, int port,
821+
const struct switchdev_obj_port_vlan *vlan)
822+
{
823+
struct ksz_device *dev = ds->priv;
824+
825+
/* Reject attempts to add a VLAN that requires the Remove Tag
826+
* flag to be changed, unless there are no other VLANs
827+
* currently configured.
828+
*/
829+
if (ksz8795_port_vlan_changes_remove_tag(ds, port, vlan)) {
830+
unsigned int vid;
831+
832+
for (vid = 1; vid < dev->num_vlans; ++vid) {
833+
u8 fid, member, valid;
834+
835+
/* Skip the VIDs we are going to add or reconfigure */
836+
if (vid == vlan->vid_begin) {
837+
vid = vlan->vid_end;
838+
continue;
839+
}
840+
841+
ksz8795_from_vlan(dev->vlan_cache[vid].table[0],
842+
&fid, &member, &valid);
843+
if (valid && (member & BIT(port)))
844+
return -EINVAL;
845+
}
846+
}
847+
848+
return ksz_port_vlan_prepare(ds, port, vlan);
849+
}
850+
804851
static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port,
805852
const struct switchdev_obj_port_vlan *vlan)
806853
{
807854
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
808855
struct ksz_device *dev = ds->priv;
856+
struct ksz_port *p = &dev->ports[port];
809857
u16 data, vid, new_pvid = 0;
810858
u8 fid, member, valid;
811859

812-
ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
860+
if (ksz8795_port_vlan_changes_remove_tag(ds, port, vlan)) {
861+
ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
862+
p->remove_tag = untagged;
863+
}
813864

814865
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
815866
ksz8795_r_vlan_table(dev, vid, &data);
@@ -1128,7 +1179,7 @@ static const struct dsa_switch_ops ksz8795_switch_ops = {
11281179
.port_stp_state_set = ksz8795_port_stp_state_set,
11291180
.port_fast_age = ksz_port_fast_age,
11301181
.port_vlan_filtering = ksz8795_port_vlan_filtering,
1131-
.port_vlan_prepare = ksz_port_vlan_prepare,
1182+
.port_vlan_prepare = ksz8795_port_vlan_prepare,
11321183
.port_vlan_add = ksz8795_port_vlan_add,
11331184
.port_vlan_del = ksz8795_port_vlan_del,
11341185
.port_fdb_dump = ksz_port_fdb_dump,

drivers/net/dsa/microchip/ksz_common.h

Lines changed: 1 addition & 0 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

0 commit comments

Comments
 (0)