diff options
author | Vivien Didelot <vivien.didelot@savoirfairelinux.com> | 2016-02-26 21:16:08 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-02 00:24:53 +0300 |
commit | 214cdb998739428b09d80b4b152faa7d1e6ad156 (patch) | |
tree | 923ad677a36f4dae005e1f52c1973456fe2b23a9 /drivers/net/dsa | |
parent | 46fbe5e5af772e0533ba3ab3d9977a5b097b88b5 (diff) | |
download | linux-214cdb998739428b09d80b4b152faa7d1e6ad156.tar.xz |
net: dsa: mv88e6xxx: support VLAN filtering
Implement port_vlan_filtering in the driver to toggle the related port
802.1Q mode between DISABLED and SECURE, on user request.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/mv88e6171.c | 1 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6352.c | 1 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.c | 39 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.h | 2 |
4 files changed, 43 insertions, 0 deletions
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index dd1ebaf48077..d72ccbdf53ec 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -106,6 +106,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .port_join_bridge = mv88e6xxx_port_bridge_join, .port_leave_bridge = mv88e6xxx_port_bridge_leave, .port_stp_update = mv88e6xxx_port_stp_update, + .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, .port_vlan_add = mv88e6xxx_port_vlan_add, .port_vlan_del = mv88e6xxx_port_vlan_del, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index bbca36ac4f77..a41fa5043d77 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -327,6 +327,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .port_join_bridge = mv88e6xxx_port_bridge_join, .port_leave_bridge = mv88e6xxx_port_bridge_leave, .port_stp_update = mv88e6xxx_port_stp_update, + .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, .port_vlan_add = mv88e6xxx_port_vlan_add, .port_vlan_del = mv88e6xxx_port_vlan_del, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 27a19dccfd65..d11c9d58cf10 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1712,6 +1712,45 @@ unlock: return err; } +static const char * const mv88e6xxx_port_8021q_mode_names[] = { + [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", + [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", + [PORT_CONTROL_2_8021Q_CHECK] = "Check", + [PORT_CONTROL_2_8021Q_SECURE] = "Secure", +}; + +int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, + bool vlan_filtering) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE : + PORT_CONTROL_2_8021Q_DISABLED; + int ret; + + mutex_lock(&ps->smi_mutex); + + ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_2); + if (ret < 0) + goto unlock; + + old = ret & PORT_CONTROL_2_8021Q_MASK; + + ret &= ~PORT_CONTROL_2_8021Q_MASK; + ret |= new & PORT_CONTROL_2_8021Q_MASK; + + ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_2, ret); + if (ret < 0) + goto unlock; + + netdev_dbg(ds->ports[port], "802.1Q Mode: %s (was %s)\n", + mv88e6xxx_port_8021q_mode_names[new], + mv88e6xxx_port_8021q_mode_names[old]); +unlock: + mutex_unlock(&ps->smi_mutex); + + return ret; +} + int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 85a416620f7c..d7b088dd8e16 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -490,6 +490,8 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *bridge); int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port); int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); +int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, + bool vlan_filtering); int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans); |