diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2021-02-13 23:43:19 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-02-15 04:38:12 +0300 |
commit | 89153ed6ebc14879b04686f0e3f3066b1b6bef05 (patch) | |
tree | f19ebc63670c0a8997173286a7e682d74f3c7a52 /net | |
parent | 31046a5fd92c57d99e8861f3dc56a2584787b473 (diff) | |
download | linux-89153ed6ebc14879b04686f0e3f3066b1b6bef05.tar.xz |
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: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/dsa/dsa_priv.h | 3 | ||||
-rw-r--r-- | net/dsa/port.c | 18 | ||||
-rw-r--r-- | net/dsa/slave.c | 3 | ||||
-rw-r--r-- | net/dsa/switch.c | 6 |
4 files changed, 20 insertions, 10 deletions
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 17a9f82db937..e9d1e76c42ba 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -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, struct netdev_lag_upper_info *uinfo); 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); 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, diff --git a/net/dsa/port.c b/net/dsa/port.c index 03ecefe1064a..14a1d0d77657 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -294,7 +294,8 @@ void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag) /* Must be called under rcu_read_lock() */ 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; int err, i; @@ -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); if (err == 0) { - dev_err(ds->dev, "Must remove upper %s first\n", - upper_dev->name); + NL_SET_ERR_MSG_MOD(extack, + "Must first remove VLAN uppers having VIDs also present in bridge"); return false; } } @@ -351,14 +352,16 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp, if (other_bridge == dp->bridge_dev) continue; 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 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; bool apply; @@ -372,7 +375,7 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering) * dsa_slave_switchdev_event(). */ 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(); if (!apply) return -EINVAL; @@ -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) 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) return err; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 9ec487b63e13..5ecb43a1b6e0 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -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); break; 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; case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: ret = dsa_port_ageing_time(dp, attr->u.ageing_time); diff --git a/net/dsa/switch.c b/net/dsa/switch.c index c82d201181a5..db2a9b221988 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -106,6 +106,7 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, { bool unset_vlan_filtering = br_vlan_enabled(info->br); struct dsa_switch_tree *dst = ds->dst; + struct netlink_ext_ack extack = {0}; int err, i; 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, } if (unset_vlan_filtering) { 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) return err; } |