Commit 89153ed6 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: propagate extack to .port_vlan_filtering

Some drivers can't dynamically change the VLAN filtering option, or
impose some restrictions, it would be nice to propagate this info
through netlink instead of printing it to a kernel log that might never
be read. Also netlink extack includes the module that emitted the
message, which means that it's easier to figure out which ones are
driver-generated errors as opposed to command misuse.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 31046a5f
...@@ -1409,7 +1409,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, ...@@ -1409,7 +1409,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
} }
EXPORT_SYMBOL(b53_phylink_mac_link_up); EXPORT_SYMBOL(b53_phylink_mac_link_up);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
struct b53_device *dev = ds->priv; struct b53_device *dev = ds->priv;
......
...@@ -346,7 +346,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port, ...@@ -346,7 +346,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
struct phy_device *phydev, struct phy_device *phydev,
int speed, int duplex, int speed, int duplex,
bool tx_pause, bool rx_pause); bool tx_pause, bool rx_pause);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering); int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
struct netlink_ext_ack *extack);
int b53_vlan_add(struct dsa_switch *ds, int port, int b53_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan, const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
......
...@@ -190,7 +190,8 @@ static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port, ...@@ -190,7 +190,8 @@ static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
} }
static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port, static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
bool vlan_filtering) bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n", dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
__func__, port, vlan_filtering); __func__, port, vlan_filtering);
......
...@@ -875,7 +875,8 @@ static int hellcreek_fdb_dump(struct dsa_switch *ds, int port, ...@@ -875,7 +875,8 @@ static int hellcreek_fdb_dump(struct dsa_switch *ds, int port,
} }
static int hellcreek_vlan_filtering(struct dsa_switch *ds, int port, static int hellcreek_vlan_filtering(struct dsa_switch *ds, int port,
bool vlan_filtering) bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
struct hellcreek *hellcreek = ds->priv; struct hellcreek *hellcreek = ds->priv;
......
...@@ -727,14 +727,18 @@ static int gswip_pce_load_microcode(struct gswip_priv *priv) ...@@ -727,14 +727,18 @@ static int gswip_pce_load_microcode(struct gswip_priv *priv)
} }
static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port, static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port,
bool vlan_filtering) bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev; struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
struct gswip_priv *priv = ds->priv; struct gswip_priv *priv = ds->priv;
/* Do not allow changing the VLAN filtering options while in bridge */ /* Do not allow changing the VLAN filtering options while in bridge */
if (bridge && !!(priv->port_vlan_filter & BIT(port)) != vlan_filtering) if (bridge && !!(priv->port_vlan_filter & BIT(port)) != vlan_filtering) {
NL_SET_ERR_MSG_MOD(extack,
"Dynamic toggling of vlan_filtering not supported");
return -EIO; return -EIO;
}
if (vlan_filtering) { if (vlan_filtering) {
/* Use port based VLAN tag */ /* Use port based VLAN tag */
...@@ -773,7 +777,7 @@ static int gswip_setup(struct dsa_switch *ds) ...@@ -773,7 +777,7 @@ static int gswip_setup(struct dsa_switch *ds)
/* disable port fetch/store dma on all ports */ /* disable port fetch/store dma on all ports */
for (i = 0; i < priv->hw_info->max_ports; i++) { for (i = 0; i < priv->hw_info->max_ports; i++) {
gswip_port_disable(ds, i); gswip_port_disable(ds, i);
gswip_port_vlan_filtering(ds, i, false); gswip_port_vlan_filtering(ds, i, false, NULL);
} }
/* enable Switch */ /* enable Switch */
......
...@@ -783,7 +783,8 @@ static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port) ...@@ -783,7 +783,8 @@ static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
} }
static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port, static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
bool flag) bool flag,
struct netlink_ext_ack *extack)
{ {
struct ksz_device *dev = ds->priv; struct ksz_device *dev = ds->priv;
......
...@@ -493,7 +493,8 @@ static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port) ...@@ -493,7 +493,8 @@ static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
} }
static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port, static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
bool flag) bool flag,
struct netlink_ext_ack *extack)
{ {
struct ksz_device *dev = ds->priv; struct ksz_device *dev = ds->priv;
......
...@@ -1376,8 +1376,8 @@ mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid) ...@@ -1376,8 +1376,8 @@ mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
} }
static int static int
mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
bool vlan_filtering) struct netlink_ext_ack *extack)
{ {
if (vlan_filtering) { if (vlan_filtering) {
/* The port is being kept as VLAN-unaware port when bridge is /* The port is being kept as VLAN-unaware port when bridge is
......
...@@ -1600,7 +1600,8 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, ...@@ -1600,7 +1600,8 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
} }
static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
bool vlan_filtering) bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
struct mv88e6xxx_chip *chip = ds->priv; struct mv88e6xxx_chip *chip = ds->priv;
u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE : u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
......
...@@ -781,7 +781,8 @@ static int felix_vlan_prepare(struct dsa_switch *ds, int port, ...@@ -781,7 +781,8 @@ static int felix_vlan_prepare(struct dsa_switch *ds, int port,
flags & BRIDGE_VLAN_INFO_UNTAGGED); flags & BRIDGE_VLAN_INFO_UNTAGGED);
} }
static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
struct netlink_ext_ack *extack)
{ {
struct ocelot *ocelot = ds->priv; struct ocelot *ocelot = ds->priv;
......
...@@ -1294,7 +1294,8 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port, ...@@ -1294,7 +1294,8 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
} }
static int static int
qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
struct qca8k_priv *priv = ds->priv; struct qca8k_priv *priv = ds->priv;
......
...@@ -130,8 +130,8 @@ int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable); ...@@ -130,8 +130,8 @@ int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable);
int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable); int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable);
int rtl8366_reset_vlan(struct realtek_smi *smi); int rtl8366_reset_vlan(struct realtek_smi *smi);
int rtl8366_init_vlan(struct realtek_smi *smi); int rtl8366_init_vlan(struct realtek_smi *smi);
int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
bool vlan_filtering); struct netlink_ext_ack *extack);
int rtl8366_vlan_add(struct dsa_switch *ds, int port, int rtl8366_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan, const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
......
...@@ -340,7 +340,8 @@ int rtl8366_init_vlan(struct realtek_smi *smi) ...@@ -340,7 +340,8 @@ int rtl8366_init_vlan(struct realtek_smi *smi)
} }
EXPORT_SYMBOL_GPL(rtl8366_init_vlan); EXPORT_SYMBOL_GPL(rtl8366_init_vlan);
int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
struct realtek_smi *smi = ds->priv; struct realtek_smi *smi = ds->priv;
struct rtl8366_vlan_4k vlan4k; struct rtl8366_vlan_4k vlan4k;
......
...@@ -247,7 +247,8 @@ enum sja1105_reset_reason { ...@@ -247,7 +247,8 @@ enum sja1105_reset_reason {
int sja1105_static_config_reload(struct sja1105_private *priv, int sja1105_static_config_reload(struct sja1105_private *priv,
enum sja1105_reset_reason reason); enum sja1105_reset_reason reason);
int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled); int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
struct netlink_ext_ack *extack);
void sja1105_frame_memory_partitioning(struct sja1105_private *priv); void sja1105_frame_memory_partitioning(struct sja1105_private *priv);
/* From sja1105_devlink.c */ /* From sja1105_devlink.c */
......
...@@ -143,7 +143,7 @@ static int sja1105_best_effort_vlan_filtering_set(struct sja1105_private *priv, ...@@ -143,7 +143,7 @@ static int sja1105_best_effort_vlan_filtering_set(struct sja1105_private *priv,
dp = dsa_to_port(ds, port); dp = dsa_to_port(ds, port);
vlan_filtering = dsa_port_is_vlan_filtering(dp); vlan_filtering = dsa_port_is_vlan_filtering(dp);
rc = sja1105_vlan_filtering(ds, port, vlan_filtering); rc = sja1105_vlan_filtering(ds, port, vlan_filtering, NULL);
if (rc) if (rc)
break; break;
} }
......
...@@ -2639,7 +2639,8 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) ...@@ -2639,7 +2639,8 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify)
* which can only be partially reconfigured at runtime (and not the TPID). * which can only be partially reconfigured at runtime (and not the TPID).
* So a switch reset is required. * So a switch reset is required.
*/ */
int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
struct netlink_ext_ack *extack)
{ {
struct sja1105_l2_lookup_params_entry *l2_lookup_params; struct sja1105_l2_lookup_params_entry *l2_lookup_params;
struct sja1105_general_params_entry *general_params; struct sja1105_general_params_entry *general_params;
...@@ -2653,8 +2654,8 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) ...@@ -2653,8 +2654,8 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
list_for_each_entry(rule, &priv->flow_block.rules, list) { list_for_each_entry(rule, &priv->flow_block.rules, list) {
if (rule->type == SJA1105_RULE_VL) { if (rule->type == SJA1105_RULE_VL) {
dev_err(ds->dev, NL_SET_ERR_MSG_MOD(extack,
"Cannot change VLAN filtering with active VL rules\n"); "Cannot change VLAN filtering with active VL rules");
return -EBUSY; return -EBUSY;
} }
} }
...@@ -2736,7 +2737,7 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) ...@@ -2736,7 +2737,7 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
rc = sja1105_static_config_reload(priv, SJA1105_VLAN_FILTERING); rc = sja1105_static_config_reload(priv, SJA1105_VLAN_FILTERING);
if (rc) if (rc)
dev_err(ds->dev, "Failed to change VLAN Ethertype\n"); NL_SET_ERR_MSG_MOD(extack, "Failed to change VLAN Ethertype");
/* Switch port identification based on 802.1Q is only passable /* Switch port identification based on 802.1Q is only passable
* if we are not under a vlan_filtering bridge. So make sure * if we are not under a vlan_filtering bridge. So make sure
......
...@@ -641,7 +641,8 @@ struct dsa_switch_ops { ...@@ -641,7 +641,8 @@ struct dsa_switch_ops {
* VLAN support * VLAN support
*/ */
int (*port_vlan_filtering)(struct dsa_switch *ds, int port, int (*port_vlan_filtering)(struct dsa_switch *ds, int port,
bool vlan_filtering); bool vlan_filtering,
struct netlink_ext_ack *extack);
int (*port_vlan_add)(struct dsa_switch *ds, int port, int (*port_vlan_add)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan, const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
......
...@@ -170,7 +170,8 @@ int dsa_port_lag_change(struct dsa_port *dp, ...@@ -170,7 +170,8 @@ int dsa_port_lag_change(struct dsa_port *dp,
int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev, int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev,
struct netdev_lag_upper_info *uinfo); struct netdev_lag_upper_info *uinfo);
void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev); void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev);
int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering); int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
struct netlink_ext_ack *extack);
bool dsa_port_skip_vlan_configuration(struct dsa_port *dp); bool dsa_port_skip_vlan_configuration(struct dsa_port *dp);
int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock); int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock);
int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu, int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
......
...@@ -294,7 +294,8 @@ void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag) ...@@ -294,7 +294,8 @@ void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag)
/* Must be called under rcu_read_lock() */ /* Must be called under rcu_read_lock() */
static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp, static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
bool vlan_filtering) bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
int err, i; int err, i;
...@@ -324,8 +325,8 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp, ...@@ -324,8 +325,8 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
*/ */
err = br_vlan_get_info(br, vid, &br_info); err = br_vlan_get_info(br, vid, &br_info);
if (err == 0) { if (err == 0) {
dev_err(ds->dev, "Must remove upper %s first\n", NL_SET_ERR_MSG_MOD(extack,
upper_dev->name); "Must first remove VLAN uppers having VIDs also present in bridge");
return false; return false;
} }
} }
...@@ -351,14 +352,16 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp, ...@@ -351,14 +352,16 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
if (other_bridge == dp->bridge_dev) if (other_bridge == dp->bridge_dev)
continue; continue;
if (br_vlan_enabled(other_bridge) != vlan_filtering) { if (br_vlan_enabled(other_bridge) != vlan_filtering) {
dev_err(ds->dev, "VLAN filtering is a global setting\n"); NL_SET_ERR_MSG_MOD(extack,
"VLAN filtering is a global setting");
return false; return false;
} }
} }
return true; return true;
} }
int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering) int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
struct netlink_ext_ack *extack)
{ {
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
bool apply; bool apply;
...@@ -372,7 +375,7 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering) ...@@ -372,7 +375,7 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering)
* dsa_slave_switchdev_event(). * dsa_slave_switchdev_event().
*/ */
rcu_read_lock(); rcu_read_lock();
apply = dsa_port_can_apply_vlan_filtering(dp, vlan_filtering); apply = dsa_port_can_apply_vlan_filtering(dp, vlan_filtering, extack);
rcu_read_unlock(); rcu_read_unlock();
if (!apply) if (!apply)
return -EINVAL; return -EINVAL;
...@@ -380,7 +383,8 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering) ...@@ -380,7 +383,8 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering)
if (dsa_port_is_vlan_filtering(dp) == vlan_filtering) if (dsa_port_is_vlan_filtering(dp) == vlan_filtering)
return 0; return 0;
err = ds->ops->port_vlan_filtering(ds, dp->index, vlan_filtering); err = ds->ops->port_vlan_filtering(ds, dp->index, vlan_filtering,
extack);
if (err) if (err)
return err; return err;
......
...@@ -286,7 +286,8 @@ static int dsa_slave_port_attr_set(struct net_device *dev, ...@@ -286,7 +286,8 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
ret = dsa_port_set_state(dp, attr->u.stp_state); ret = dsa_port_set_state(dp, attr->u.stp_state);
break; break;
case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
ret = dsa_port_vlan_filtering(dp, attr->u.vlan_filtering); ret = dsa_port_vlan_filtering(dp, attr->u.vlan_filtering,
extack);
break; break;
case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
ret = dsa_port_ageing_time(dp, attr->u.ageing_time); ret = dsa_port_ageing_time(dp, attr->u.ageing_time);
......
...@@ -106,6 +106,7 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, ...@@ -106,6 +106,7 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
{ {
bool unset_vlan_filtering = br_vlan_enabled(info->br); bool unset_vlan_filtering = br_vlan_enabled(info->br);
struct dsa_switch_tree *dst = ds->dst; struct dsa_switch_tree *dst = ds->dst;
struct netlink_ext_ack extack = {0};
int err, i; int err, i;
if (dst->index == info->tree_index && ds->index == info->sw_index && if (dst->index == info->tree_index && ds->index == info->sw_index &&
...@@ -137,7 +138,10 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, ...@@ -137,7 +138,10 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
} }
if (unset_vlan_filtering) { if (unset_vlan_filtering) {
err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port), err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port),
false); false, &extack);
if (extack._msg)
dev_err(ds->dev, "port %d: %s\n", info->port,
extack._msg);
if (err && err != EOPNOTSUPP) if (err && err != EOPNOTSUPP)
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment