Commit 7f6334f7 authored by David S. Miller's avatar David S. Miller

Merge branch 'Propagate-extack-for-switchdev-LANs-from-DSA'

Vladimir Oltean says:

====================
Propagate extack for switchdev VLANs from DSA

This series moves the restriction messages printed by the DSA core, and
by some individual device drivers, into the netlink extended ack
structure, to be communicated to user space where possible, or still
printed to the kernel log from the bridge layer.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c48f8607 89153ed6
......@@ -1409,7 +1409,8 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
}
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;
......@@ -1444,7 +1445,8 @@ static int b53_vlan_prepare(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 b53_device *dev = ds->priv;
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
......
......@@ -346,9 +346,11 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
struct phy_device *phydev,
int speed, int duplex,
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,
const struct switchdev_obj_port_vlan *vlan);
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack);
int b53_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
int b53_fdb_add(struct dsa_switch *ds, int port,
......
......@@ -891,7 +891,7 @@ static int bcm_sf2_cfp_rule_insert(struct dsa_switch *ds, int port,
else
vlan.flags = 0;
ret = ds->ops->port_vlan_add(ds, port_num, &vlan);
ret = ds->ops->port_vlan_add(ds, port_num, &vlan, NULL);
if (ret)
return ret;
}
......
......@@ -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,
bool vlan_filtering)
bool vlan_filtering,
struct netlink_ext_ack *extack)
{
dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
__func__, port, vlan_filtering);
......@@ -199,7 +200,8 @@ static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
}
static int dsa_loop_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)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
......
......@@ -341,7 +341,8 @@ static u16 hellcreek_private_vid(int port)
}
static int hellcreek_vlan_prepare(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 hellcreek *hellcreek = ds->priv;
int i;
......@@ -358,8 +359,10 @@ static int hellcreek_vlan_prepare(struct dsa_switch *ds, int port,
if (!dsa_is_user_port(ds, i))
continue;
if (vlan->vid == restricted_vid)
if (vlan->vid == restricted_vid) {
NL_SET_ERR_MSG_MOD(extack, "VID restricted by driver");
return -EBUSY;
}
}
return 0;
......@@ -445,14 +448,15 @@ static void hellcreek_unapply_vlan(struct hellcreek *hellcreek, int port,
}
static int hellcreek_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)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
struct hellcreek *hellcreek = ds->priv;
int err;
err = hellcreek_vlan_prepare(ds, port, vlan);
err = hellcreek_vlan_prepare(ds, port, vlan, extack);
if (err)
return err;
......@@ -871,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,
bool vlan_filtering)
bool vlan_filtering,
struct netlink_ext_ack *extack)
{
struct hellcreek *hellcreek = ds->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,
bool vlan_filtering)
bool vlan_filtering,
struct netlink_ext_ack *extack)
{
struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
struct gswip_priv *priv = ds->priv;
/* 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;
}
if (vlan_filtering) {
/* Use port based VLAN tag */
......@@ -773,7 +777,7 @@ static int gswip_setup(struct dsa_switch *ds)
/* disable port fetch/store dma on all ports */
for (i = 0; i < priv->hw_info->max_ports; i++) {
gswip_port_disable(ds, i);
gswip_port_vlan_filtering(ds, i, false);
gswip_port_vlan_filtering(ds, i, false, NULL);
}
/* enable Switch */
......@@ -1128,7 +1132,8 @@ static void gswip_port_bridge_leave(struct dsa_switch *ds, int port,
}
static int gswip_port_vlan_prepare(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 gswip_priv *priv = ds->priv;
struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
......@@ -1163,15 +1168,18 @@ static int gswip_port_vlan_prepare(struct dsa_switch *ds, int port,
}
}
if (idx == -1)
if (idx == -1) {
NL_SET_ERR_MSG_MOD(extack, "No slot in VLAN table");
return -ENOSPC;
}
}
return 0;
}
static int gswip_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 gswip_priv *priv = ds->priv;
struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
......@@ -1179,7 +1187,7 @@ static int gswip_port_vlan_add(struct dsa_switch *ds, int port,
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
int err;
err = gswip_port_vlan_prepare(ds, port, vlan);
err = gswip_port_vlan_prepare(ds, port, vlan, extack);
if (err)
return err;
......
......@@ -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,
bool flag)
bool flag,
struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
......@@ -793,7 +794,8 @@ static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
}
static int ksz8795_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)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
struct ksz_device *dev = ds->priv;
......
......@@ -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,
bool flag)
bool flag,
struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
......@@ -511,7 +512,8 @@ static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
}
static int ksz9477_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 ksz_device *dev = ds->priv;
u32 vlan_table[3];
......@@ -520,7 +522,7 @@ static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
err = ksz9477_get_vlan_table(dev, vlan->vid, vlan_table);
if (err) {
dev_dbg(dev->dev, "Failed to get vlan table\n");
NL_SET_ERR_MSG_MOD(extack, "Failed to get vlan table");
return err;
}
......@@ -535,7 +537,7 @@ static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
err = ksz9477_set_vlan_table(dev, vlan->vid, vlan_table);
if (err) {
dev_dbg(dev->dev, "Failed to set vlan table\n");
NL_SET_ERR_MSG_MOD(extack, "Failed to set vlan table");
return err;
}
......
......@@ -1376,8 +1376,8 @@ mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
}
static int
mt7530_port_vlan_filtering(struct dsa_switch *ds, int port,
bool vlan_filtering)
mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
struct netlink_ext_ack *extack)
{
if (vlan_filtering) {
/* The port is being kept as VLAN-unaware port when bridge is
......@@ -1483,7 +1483,8 @@ mt7530_hw_vlan_update(struct mt7530_priv *priv, u16 vid,
static int
mt7530_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)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
......
......@@ -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,
bool vlan_filtering)
bool vlan_filtering,
struct netlink_ext_ack *extack)
{
struct mv88e6xxx_chip *chip = ds->priv;
u16 mode = vlan_filtering ? MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE :
......@@ -1982,7 +1983,8 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
}
static int mv88e6xxx_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 mv88e6xxx_chip *chip = ds->priv;
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
......
......@@ -781,7 +781,8 @@ static int felix_vlan_prepare(struct dsa_switch *ds, int port,
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;
......@@ -789,7 +790,8 @@ static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
}
static int felix_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 ocelot *ocelot = ds->priv;
u16 flags = vlan->flags;
......
......@@ -1294,7 +1294,8 @@ qca8k_port_fdb_dump(struct dsa_switch *ds, int port,
}
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;
......@@ -1313,7 +1314,8 @@ qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
static int
qca8k_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)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
......
......@@ -130,10 +130,11 @@ int rtl8366_enable_vlan4k(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_init_vlan(struct realtek_smi *smi);
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);
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);
int rtl8366_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
......
......@@ -340,7 +340,8 @@ int rtl8366_init_vlan(struct realtek_smi *smi)
}
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 rtl8366_vlan_4k vlan4k;
......@@ -375,7 +376,8 @@ int rtl8366_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
EXPORT_SYMBOL_GPL(rtl8366_vlan_filtering);
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)
{
bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
......@@ -384,16 +386,20 @@ int rtl8366_vlan_add(struct dsa_switch *ds, int port,
u32 untag = 0;
int ret;
if (!smi->ops->is_vlan_valid(smi, vlan->vid))
if (!smi->ops->is_vlan_valid(smi, vlan->vid)) {
NL_SET_ERR_MSG_MOD(extack, "VLAN ID not valid");
return -EINVAL;
}
/* Enable VLAN in the hardware
* FIXME: what's with this 4k business?
* Just rtl8366_enable_vlan() seems inconclusive.
*/
ret = rtl8366_enable_vlan4k(smi, true);
if (ret)
if (ret) {
NL_SET_ERR_MSG_MOD(extack, "Failed to enable VLAN 4K");
return ret;
}
dev_info(smi->dev, "add VLAN %d on port %d, %s, %s\n",
vlan->vid, port, untagged ? "untagged" : "tagged",
......
......@@ -247,7 +247,8 @@ enum sja1105_reset_reason {
int sja1105_static_config_reload(struct sja1105_private *priv,
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);
/* From sja1105_devlink.c */
......
......@@ -143,7 +143,7 @@ static int sja1105_best_effort_vlan_filtering_set(struct sja1105_private *priv,
dp = dsa_to_port(ds, port);
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)
break;
}
......
......@@ -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).
* 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_general_params_entry *general_params;
......@@ -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) {
if (rule->type == SJA1105_RULE_VL) {
dev_err(ds->dev,
"Cannot change VLAN filtering with active VL rules\n");
NL_SET_ERR_MSG_MOD(extack,
"Cannot change VLAN filtering with active VL rules");
return -EBUSY;
}
}
......@@ -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);
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
* if we are not under a vlan_filtering bridge. So make sure
......@@ -2795,7 +2796,8 @@ static int sja1105_vlan_del_one(struct dsa_switch *ds, int port, u16 vid,
}
static int sja1105_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 sja1105_private *priv = ds->priv;
bool vlan_table_changed = false;
......@@ -2807,7 +2809,8 @@ static int sja1105_vlan_add(struct dsa_switch *ds, int port,
*/
if (priv->vlan_state != SJA1105_VLAN_FILTERING_FULL &&
vid_is_dsa_8021q(vlan->vid)) {
dev_err(ds->dev, "Range 1024-3071 reserved for dsa_8021q operation\n");
NL_SET_ERR_MSG_MOD(extack,
"Range 1024-3071 reserved for dsa_8021q operation");
return -EBUSY;
}
......
......@@ -641,9 +641,11 @@ struct dsa_switch_ops {
* VLAN support
*/
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,
const struct switchdev_obj_port_vlan *vlan);
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack);
int (*port_vlan_del)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan);
/*
......
......@@ -247,7 +247,8 @@ switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info)
void switchdev_deferred_process(void);
int switchdev_port_attr_set(struct net_device *dev,
const struct switchdev_attr *attr);
const struct switchdev_attr *attr,
struct netlink_ext_ack *extack);
int switchdev_port_obj_add(struct net_device *dev,
const struct switchdev_obj *obj,
struct netlink_ext_ack *extack);
......
......@@ -178,7 +178,7 @@ int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state)
};
int err;
err = switchdev_port_attr_set(p->dev, &attr);
err = switchdev_port_attr_set(p->dev, &attr, NULL);
if (err && err != -EOPNOTSUPP)
br_warn(p->br, "error setting offload MRP state on port %u(%s)\n",
(unsigned int)p->port_no, p->dev->name);
......@@ -196,7 +196,7 @@ int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
};
int err;
err = switchdev_port_attr_set(p->dev, &attr);
err = switchdev_port_attr_set(p->dev, &attr, NULL);
if (err && err != -EOPNOTSUPP)
return err;
......
......@@ -1381,7 +1381,7 @@ static void br_mc_router_state_change(struct net_bridge *p,
.u.mrouter = is_mc_router,
};
switchdev_port_attr_set(p->dev, &attr);
switchdev_port_attr_set(p->dev, &attr, NULL);
}
static void br_multicast_local_router_expired(struct timer_list *t)
......@@ -1602,7 +1602,7 @@ static void br_mc_disabled_update(struct net_device *dev, bool value)
.u.mc_disabled = !value,
};
switchdev_port_attr_set(dev, &attr);
switchdev_port_attr_set(dev, &attr, NULL);
}
int br_multicast_add_port(struct net_bridge_port *port)
......@@ -2645,7 +2645,7 @@ static void br_port_mc_router_state_change(struct net_bridge_port *p,
.u.mrouter = is_mc_router,
};
switchdev_port_attr_set(p->dev, &attr);
switchdev_port_attr_set(p->dev, &attr, NULL);
}
/*
......
......@@ -1212,7 +1212,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
if (data[IFLA_BR_VLAN_FILTERING]) {
u8 vlan_filter = nla_get_u8(data[IFLA_BR_VLAN_FILTERING]);
err = __br_vlan_filter_toggle(br, vlan_filter);
err = br_vlan_filter_toggle(br, vlan_filter, extack);
if (err)
return err;
}
......@@ -1221,7 +1221,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
if (data[IFLA_BR_VLAN_PROTOCOL]) {
__be16 vlan_proto = nla_get_be16(data[IFLA_BR_VLAN_PROTOCOL]);
err = __br_vlan_set_proto(br, vlan_proto);
err = __br_vlan_set_proto(br, vlan_proto, extack);
if (err)
return err;
}
......
......@@ -1085,14 +1085,17 @@ int br_vlan_delete(struct net_bridge *br, u16 vid);
void br_vlan_flush(struct net_bridge *br);
struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid);
void br_recalculate_fwd_mask(struct net_bridge *br);
int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
int __br_vlan_set_proto(struct net_bridge *br, __be16 proto);
int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack);
int __br_vlan_set_proto(struct net_bridge *br, __be16 proto,
struct netlink_ext_ack *extack);
int br_vlan_set_proto(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack);
int br_vlan_set_stats(struct net_bridge *br, unsigned long val);
int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val);
int br_vlan_init(struct net_bridge *br);
int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack);
int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid,
struct netlink_ext_ack *extack);
int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags,
......@@ -1261,8 +1264,8 @@ static inline u16 br_get_pvid(const struct net_bridge_vlan_group *vg)
return 0;
}
static inline int __br_vlan_filter_toggle(struct net_bridge *br,
unsigned long val)
static inline int br_vlan_filter_toggle(struct net_bridge *br,
unsigned long val)
{
return -EOPNOTSUPP;
}
......
......@@ -43,7 +43,7 @@ void br_set_state(struct net_bridge_port *p, unsigned int state)
return;
p->state = state;
err = switchdev_port_attr_set(p->dev, &attr);
err = switchdev_port_attr_set(p->dev, &attr, NULL);
if (err && err != -EOPNOTSUPP)
br_warn(p->br, "error setting offload STP state on port %u(%s)\n",
(unsigned int) p->port_no, p->dev->name);
......@@ -591,7 +591,7 @@ int __set_ageing_time(struct net_device *dev, unsigned long t)
};
int err;
err = switchdev_port_attr_set(dev, &attr);
err = switchdev_port_attr_set(dev, &attr, NULL);
if (err && err != -EOPNOTSUPP)
return err;
......
......@@ -96,9 +96,11 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS;
attr.flags = SWITCHDEV_F_DEFER;
err = switchdev_port_attr_set(p->dev, &attr);
err = switchdev_port_attr_set(p->dev, &attr, extack);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "error setting offload flag on port");
if (extack && !extack->_msg)
NL_SET_ERR_MSG_MOD(extack,
"error setting offload flag on port");
return err;
}
......
This diff is collapsed.
......@@ -806,7 +806,8 @@ void br_recalculate_fwd_mask(struct net_bridge *br)
~(1u << br->group_addr[5]);
}
int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack)
{
struct switchdev_attr attr = {
.orig_dev = br->dev,
......@@ -819,7 +820,7 @@ int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
if (br_opt_get(br, BROPT_VLAN_ENABLED) == !!val)
return 0;
err = switchdev_port_attr_set(br->dev, &attr);
err = switchdev_port_attr_set(br->dev, &attr, extack);
if (err && err != -EOPNOTSUPP)
return err;
......@@ -831,11 +832,6 @@ int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
return 0;
}
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
{
return __br_vlan_filter_toggle(br, val);
}
bool br_vlan_enabled(const struct net_device *dev)
{
struct net_bridge *br = netdev_priv(dev);
......@@ -854,7 +850,8 @@ int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto)
}
EXPORT_SYMBOL_GPL(br_vlan_get_proto);
int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)
int __br_vlan_set_proto(struct net_bridge *br, __be16 proto,
struct netlink_ext_ack *extack)
{
struct switchdev_attr attr = {
.orig_dev = br->dev,
......@@ -871,7 +868,7 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)
if (br->vlan_proto == proto)
return 0;
err = switchdev_port_attr_set(br->dev, &attr);
err = switchdev_port_attr_set(br->dev, &attr, extack);
if (err && err != -EOPNOTSUPP)
return err;
......@@ -901,7 +898,7 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)
err_filt:
attr.u.vlan_protocol = ntohs(oldproto);
switchdev_port_attr_set(br->dev, &attr);
switchdev_port_attr_set(br->dev, &attr, NULL);
list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist)
vlan_vid_del(p->dev, proto, vlan->vid);
......@@ -915,12 +912,13 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)
return err;
}
int br_vlan_set_proto(struct net_bridge *br, unsigned long val)
int br_vlan_set_proto(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack)
{
if (!eth_type_vlan(htons(val)))
return -EPROTONOSUPPORT;
return __br_vlan_set_proto(br, htons(val));
return __br_vlan_set_proto(br, htons(val), extack);
}
int br_vlan_set_stats(struct net_bridge *br, unsigned long val)
......@@ -1100,7 +1098,8 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid,
goto out;
}
int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack)
{
u16 pvid = val;
int err = 0;
......@@ -1117,7 +1116,7 @@ int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
err = -EPERM;
goto out;
}
err = __br_vlan_set_default_pvid(br, pvid, NULL);
err = __br_vlan_set_default_pvid(br, pvid, extack);
out:
return err;
}
......@@ -1167,7 +1166,7 @@ int nbp_vlan_init(struct net_bridge_port *p, struct netlink_ext_ack *extack)
if (!vg)
goto out;
ret = switchdev_port_attr_set(p->dev, &attr);
ret = switchdev_port_attr_set(p->dev, &attr, extack);
if (ret && ret != -EOPNOTSUPP)
goto err_vlan_enabled;
......
......@@ -75,6 +75,7 @@ struct dsa_notifier_vlan_info {
const struct switchdev_obj_port_vlan *vlan;
int sw_index;
int port;
struct netlink_ext_ack *extack;
};
/* DSA_NOTIFIER_MTU */
......@@ -169,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,
......@@ -192,7 +194,8 @@ int dsa_port_bridge_flags(const struct dsa_port *dp,
int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
struct netlink_ext_ack *extack);
int dsa_port_vlan_add(struct dsa_port *dp,
const struct switchdev_obj_port_vlan *vlan);
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack);
int dsa_port_vlan_del(struct dsa_port *dp,
const struct switchdev_obj_port_vlan *vlan);
int dsa_port_link_register_of(struct dsa_port *dp);
......
......@@ -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;
......@@ -535,12 +539,14 @@ int dsa_port_mdb_del(const struct dsa_port *dp,
}
int dsa_port_vlan_add(struct dsa_port *dp,
const struct switchdev_obj_port_vlan *vlan)
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
struct dsa_notifier_vlan_info info = {
.sw_index = dp->ds->index,
.port = dp->index,
.vlan = vlan,
.extack = extack,
};
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
......
......@@ -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);
......@@ -357,11 +358,14 @@ static int dsa_slave_vlan_add(struct net_device *dev,
rcu_read_lock();
err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan);
rcu_read_unlock();
if (err)
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Port already has a VLAN upper with this VID");
return err;
}
}
err = dsa_port_vlan_add(dp, &vlan);
err = dsa_port_vlan_add(dp, &vlan, extack);
if (err)
return err;
......@@ -371,7 +375,7 @@ static int dsa_slave_vlan_add(struct net_device *dev,
*/
vlan.flags &= ~BRIDGE_VLAN_INFO_PVID;
err = dsa_port_vlan_add(dp->cpu_dp, &vlan);
err = dsa_port_vlan_add(dp->cpu_dp, &vlan, extack);
if (err)
return err;
......@@ -1287,17 +1291,25 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
/* This API only allows programming tagged, non-PVID VIDs */
.flags = 0,
};
struct netlink_ext_ack extack = {0};
int ret;
/* User port... */
ret = dsa_port_vlan_add(dp, &vlan);
if (ret)
ret = dsa_port_vlan_add(dp, &vlan, &extack);
if (ret) {
if (extack._msg)
netdev_err(dev, "%s\n", extack._msg);
return ret;
}
/* And CPU port... */
ret = dsa_port_vlan_add(dp->cpu_dp, &vlan);
if (ret)
ret = dsa_port_vlan_add(dp->cpu_dp, &vlan, &extack);
if (ret) {
if (extack._msg)
netdev_err(dev, "CPU port %d: %s\n", dp->cpu_dp->index,
extack._msg);
return ret;
}
return vlan_vid_add(master, proto, vid);
}
......
......@@ -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;
}
......@@ -291,7 +295,8 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_vlan_match(ds, port, info)) {
err = ds->ops->port_vlan_add(ds, port, info->vlan);
err = ds->ops->port_vlan_add(ds, port, info->vlan,
info->extack);
if (err)
return err;
}
......
......@@ -100,7 +100,8 @@ static int switchdev_deferred_enqueue(struct net_device *dev,
static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
struct net_device *dev,
const struct switchdev_attr *attr)
const struct switchdev_attr *attr,
struct netlink_ext_ack *extack)
{
int err;
int rc;
......@@ -111,7 +112,7 @@ static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
};
rc = call_switchdev_blocking_notifiers(nt, dev,
&attr_info.info, NULL);
&attr_info.info, extack);
err = notifier_to_errno(rc);
if (err) {
WARN_ON(!attr_info.handled);
......@@ -125,9 +126,11 @@ static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
}
static int switchdev_port_attr_set_now(struct net_device *dev,
const struct switchdev_attr *attr)
const struct switchdev_attr *attr,
struct netlink_ext_ack *extack)
{
return switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr);
return switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr,
extack);
}
static void switchdev_port_attr_set_deferred(struct net_device *dev,
......@@ -136,7 +139,7 @@ static void switchdev_port_attr_set_deferred(struct net_device *dev,
const struct switchdev_attr *attr = data;
int err;
err = switchdev_port_attr_set_now(dev, attr);
err = switchdev_port_attr_set_now(dev, attr, NULL);
if (err && err != -EOPNOTSUPP)
netdev_err(dev, "failed (err=%d) to set attribute (id=%d)\n",
err, attr->id);
......@@ -156,17 +159,19 @@ static int switchdev_port_attr_set_defer(struct net_device *dev,
*
* @dev: port device
* @attr: attribute to set
* @extack: netlink extended ack, for error message propagation
*
* rtnl_lock must be held and must not be in atomic section,
* in case SWITCHDEV_F_DEFER flag is not set.
*/
int switchdev_port_attr_set(struct net_device *dev,
const struct switchdev_attr *attr)
const struct switchdev_attr *attr,
struct netlink_ext_ack *extack)
{
if (attr->flags & SWITCHDEV_F_DEFER)
return switchdev_port_attr_set_defer(dev, attr);
ASSERT_RTNL();
return switchdev_port_attr_set_now(dev, attr);
return switchdev_port_attr_set_now(dev, attr, extack);
}
EXPORT_SYMBOL_GPL(switchdev_port_attr_set);
......
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