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

net: bridge: propagate extack through switchdev_port_attr_set

The benefit is the ability to propagate errors from switchdev drivers
for the SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING and
SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL attributes.
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 9e781401
...@@ -247,7 +247,8 @@ switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info) ...@@ -247,7 +247,8 @@ switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info)
void switchdev_deferred_process(void); void switchdev_deferred_process(void);
int switchdev_port_attr_set(struct net_device *dev, 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, int switchdev_port_obj_add(struct net_device *dev,
const struct switchdev_obj *obj, const struct switchdev_obj *obj,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
......
...@@ -178,7 +178,7 @@ int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state) ...@@ -178,7 +178,7 @@ int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state)
}; };
int err; int err;
err = switchdev_port_attr_set(p->dev, &attr); err = switchdev_port_attr_set(p->dev, &attr, NULL);
if (err && err != -EOPNOTSUPP) if (err && err != -EOPNOTSUPP)
br_warn(p->br, "error setting offload MRP state on port %u(%s)\n", br_warn(p->br, "error setting offload MRP state on port %u(%s)\n",
(unsigned int)p->port_no, p->dev->name); (unsigned int)p->port_no, p->dev->name);
...@@ -196,7 +196,7 @@ int br_mrp_port_switchdev_set_role(struct net_bridge_port *p, ...@@ -196,7 +196,7 @@ int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
}; };
int err; int err;
err = switchdev_port_attr_set(p->dev, &attr); err = switchdev_port_attr_set(p->dev, &attr, NULL);
if (err && err != -EOPNOTSUPP) if (err && err != -EOPNOTSUPP)
return err; return err;
......
...@@ -1381,7 +1381,7 @@ static void br_mc_router_state_change(struct net_bridge *p, ...@@ -1381,7 +1381,7 @@ static void br_mc_router_state_change(struct net_bridge *p,
.u.mrouter = is_mc_router, .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) 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) ...@@ -1602,7 +1602,7 @@ static void br_mc_disabled_update(struct net_device *dev, bool value)
.u.mc_disabled = !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) 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, ...@@ -2645,7 +2645,7 @@ static void br_port_mc_router_state_change(struct net_bridge_port *p,
.u.mrouter = is_mc_router, .u.mrouter = is_mc_router,
}; };
switchdev_port_attr_set(p->dev, &attr); switchdev_port_attr_set(p->dev, &attr, NULL);
} }
/* /*
......
...@@ -1221,7 +1221,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], ...@@ -1221,7 +1221,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
if (data[IFLA_BR_VLAN_PROTOCOL]) { if (data[IFLA_BR_VLAN_PROTOCOL]) {
__be16 vlan_proto = nla_get_be16(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) if (err)
return err; return err;
} }
......
...@@ -1087,7 +1087,8 @@ struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid); ...@@ -1087,7 +1087,8 @@ struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid);
void br_recalculate_fwd_mask(struct net_bridge *br); 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,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
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);
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); struct netlink_ext_ack *extack);
int br_vlan_set_stats(struct net_bridge *br, unsigned long val); int br_vlan_set_stats(struct net_bridge *br, unsigned long val);
......
...@@ -43,7 +43,7 @@ void br_set_state(struct net_bridge_port *p, unsigned int state) ...@@ -43,7 +43,7 @@ void br_set_state(struct net_bridge_port *p, unsigned int state)
return; return;
p->state = state; p->state = state;
err = switchdev_port_attr_set(p->dev, &attr); err = switchdev_port_attr_set(p->dev, &attr, NULL);
if (err && err != -EOPNOTSUPP) if (err && err != -EOPNOTSUPP)
br_warn(p->br, "error setting offload STP state on port %u(%s)\n", br_warn(p->br, "error setting offload STP state on port %u(%s)\n",
(unsigned int) p->port_no, p->dev->name); (unsigned int) p->port_no, p->dev->name);
...@@ -591,7 +591,7 @@ int __set_ageing_time(struct net_device *dev, unsigned long t) ...@@ -591,7 +591,7 @@ int __set_ageing_time(struct net_device *dev, unsigned long t)
}; };
int err; int err;
err = switchdev_port_attr_set(dev, &attr); err = switchdev_port_attr_set(dev, &attr, NULL);
if (err && err != -EOPNOTSUPP) if (err && err != -EOPNOTSUPP)
return err; return err;
......
...@@ -96,9 +96,11 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, ...@@ -96,9 +96,11 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS; attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS;
attr.flags = SWITCHDEV_F_DEFER; attr.flags = SWITCHDEV_F_DEFER;
err = switchdev_port_attr_set(p->dev, &attr); err = switchdev_port_attr_set(p->dev, &attr, extack);
if (err) { 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; return err;
} }
......
...@@ -820,7 +820,7 @@ int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val, ...@@ -820,7 +820,7 @@ int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val,
if (br_opt_get(br, BROPT_VLAN_ENABLED) == !!val) if (br_opt_get(br, BROPT_VLAN_ENABLED) == !!val)
return 0; return 0;
err = switchdev_port_attr_set(br->dev, &attr); err = switchdev_port_attr_set(br->dev, &attr, extack);
if (err && err != -EOPNOTSUPP) if (err && err != -EOPNOTSUPP)
return err; return err;
...@@ -850,7 +850,8 @@ int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto) ...@@ -850,7 +850,8 @@ int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto)
} }
EXPORT_SYMBOL_GPL(br_vlan_get_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 = { struct switchdev_attr attr = {
.orig_dev = br->dev, .orig_dev = br->dev,
...@@ -867,7 +868,7 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) ...@@ -867,7 +868,7 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)
if (br->vlan_proto == proto) if (br->vlan_proto == proto)
return 0; return 0;
err = switchdev_port_attr_set(br->dev, &attr); err = switchdev_port_attr_set(br->dev, &attr, extack);
if (err && err != -EOPNOTSUPP) if (err && err != -EOPNOTSUPP)
return err; return err;
...@@ -897,7 +898,7 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) ...@@ -897,7 +898,7 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto)
err_filt: err_filt:
attr.u.vlan_protocol = ntohs(oldproto); 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) list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist)
vlan_vid_del(p->dev, proto, vlan->vid); vlan_vid_del(p->dev, proto, vlan->vid);
...@@ -917,7 +918,7 @@ int br_vlan_set_proto(struct net_bridge *br, unsigned long val, ...@@ -917,7 +918,7 @@ int br_vlan_set_proto(struct net_bridge *br, unsigned long val,
if (!eth_type_vlan(htons(val))) if (!eth_type_vlan(htons(val)))
return -EPROTONOSUPPORT; 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) int br_vlan_set_stats(struct net_bridge *br, unsigned long val)
...@@ -1165,7 +1166,7 @@ int nbp_vlan_init(struct net_bridge_port *p, struct netlink_ext_ack *extack) ...@@ -1165,7 +1166,7 @@ int nbp_vlan_init(struct net_bridge_port *p, struct netlink_ext_ack *extack)
if (!vg) if (!vg)
goto out; goto out;
ret = switchdev_port_attr_set(p->dev, &attr); ret = switchdev_port_attr_set(p->dev, &attr, extack);
if (ret && ret != -EOPNOTSUPP) if (ret && ret != -EOPNOTSUPP)
goto err_vlan_enabled; goto err_vlan_enabled;
......
...@@ -100,7 +100,8 @@ static int switchdev_deferred_enqueue(struct net_device *dev, ...@@ -100,7 +100,8 @@ static int switchdev_deferred_enqueue(struct net_device *dev,
static int switchdev_port_attr_notify(enum switchdev_notifier_type nt, static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
struct net_device *dev, struct net_device *dev,
const struct switchdev_attr *attr) const struct switchdev_attr *attr,
struct netlink_ext_ack *extack)
{ {
int err; int err;
int rc; int rc;
...@@ -111,7 +112,7 @@ static int switchdev_port_attr_notify(enum switchdev_notifier_type nt, ...@@ -111,7 +112,7 @@ static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
}; };
rc = call_switchdev_blocking_notifiers(nt, dev, rc = call_switchdev_blocking_notifiers(nt, dev,
&attr_info.info, NULL); &attr_info.info, extack);
err = notifier_to_errno(rc); err = notifier_to_errno(rc);
if (err) { if (err) {
WARN_ON(!attr_info.handled); WARN_ON(!attr_info.handled);
...@@ -125,9 +126,11 @@ static int switchdev_port_attr_notify(enum switchdev_notifier_type nt, ...@@ -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, 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, 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, ...@@ -136,7 +139,7 @@ static void switchdev_port_attr_set_deferred(struct net_device *dev,
const struct switchdev_attr *attr = data; const struct switchdev_attr *attr = data;
int err; int err;
err = switchdev_port_attr_set_now(dev, attr); err = switchdev_port_attr_set_now(dev, attr, NULL);
if (err && err != -EOPNOTSUPP) if (err && err != -EOPNOTSUPP)
netdev_err(dev, "failed (err=%d) to set attribute (id=%d)\n", netdev_err(dev, "failed (err=%d) to set attribute (id=%d)\n",
err, attr->id); err, attr->id);
...@@ -156,17 +159,19 @@ static int switchdev_port_attr_set_defer(struct net_device *dev, ...@@ -156,17 +159,19 @@ static int switchdev_port_attr_set_defer(struct net_device *dev,
* *
* @dev: port device * @dev: port device
* @attr: attribute to set * @attr: attribute to set
* @extack: netlink extended ack, for error message propagation
* *
* rtnl_lock must be held and must not be in atomic section, * rtnl_lock must be held and must not be in atomic section,
* in case SWITCHDEV_F_DEFER flag is not set. * in case SWITCHDEV_F_DEFER flag is not set.
*/ */
int switchdev_port_attr_set(struct net_device *dev, 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) if (attr->flags & SWITCHDEV_F_DEFER)
return switchdev_port_attr_set_defer(dev, attr); return switchdev_port_attr_set_defer(dev, attr);
ASSERT_RTNL(); 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); 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