|
@@ -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)
|