net: switchdev: Replace port attr set SDO with a notification
Drop switchdev_ops.switchdev_port_attr_set. Drop the uses of this field from all clients, which were migrated to use switchdev notification in the previous patches. Add a new function switchdev_port_attr_notify() that sends the switchdev notifications SWITCHDEV_PORT_ATTR_SET and calls the blocking (process) notifier chain. We have one odd case within net/bridge/br_switchdev.c with the SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS attribute identifier that requires executing from atomic context, we deal with that one specifically. Drop __switchdev_port_attr_set() and update switchdev_port_attr_set() likewise. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
570b68c8dd
commit
d45224d604
|
@ -67,12 +67,18 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
|
||||||
.id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS,
|
.id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS,
|
||||||
.u.brport_flags = mask,
|
.u.brport_flags = mask,
|
||||||
};
|
};
|
||||||
|
struct switchdev_notifier_port_attr_info info = {
|
||||||
|
.attr = &attr,
|
||||||
|
};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
|
if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = switchdev_port_attr_set(p->dev, &attr);
|
/* We run from atomic context here */
|
||||||
|
err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev,
|
||||||
|
&info.info, NULL);
|
||||||
|
err = notifier_to_errno(err);
|
||||||
if (err == -EOPNOTSUPP)
|
if (err == -EOPNOTSUPP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -174,39 +174,32 @@ static int switchdev_deferred_enqueue(struct net_device *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __switchdev_port_attr_set(struct net_device *dev,
|
static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
|
||||||
const struct switchdev_attr *attr,
|
struct net_device *dev,
|
||||||
struct switchdev_trans *trans)
|
const struct switchdev_attr *attr,
|
||||||
|
struct switchdev_trans *trans)
|
||||||
{
|
{
|
||||||
const struct switchdev_ops *ops = dev->switchdev_ops;
|
int err;
|
||||||
struct net_device *lower_dev;
|
int rc;
|
||||||
struct list_head *iter;
|
|
||||||
int err = -EOPNOTSUPP;
|
|
||||||
|
|
||||||
if (ops && ops->switchdev_port_attr_set) {
|
struct switchdev_notifier_port_attr_info attr_info = {
|
||||||
err = ops->switchdev_port_attr_set(dev, attr, trans);
|
.attr = attr,
|
||||||
goto done;
|
.trans = trans,
|
||||||
|
.handled = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = call_switchdev_blocking_notifiers(nt, dev,
|
||||||
|
&attr_info.info, NULL);
|
||||||
|
err = notifier_to_errno(rc);
|
||||||
|
if (err) {
|
||||||
|
WARN_ON(!attr_info.handled);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr->flags & SWITCHDEV_F_NO_RECURSE)
|
if (!attr_info.handled)
|
||||||
goto done;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/* Switch device port(s) may be stacked under
|
return 0;
|
||||||
* bond/team/vlan dev, so recurse down to set attr on
|
|
||||||
* each port.
|
|
||||||
*/
|
|
||||||
|
|
||||||
netdev_for_each_lower_dev(dev, lower_dev, iter) {
|
|
||||||
err = __switchdev_port_attr_set(lower_dev, attr, trans);
|
|
||||||
if (err)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (err == -EOPNOTSUPP && attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP)
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int switchdev_port_attr_set_now(struct net_device *dev,
|
static int switchdev_port_attr_set_now(struct net_device *dev,
|
||||||
|
@ -225,7 +218,8 @@ static int switchdev_port_attr_set_now(struct net_device *dev,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
trans.ph_prepare = true;
|
trans.ph_prepare = true;
|
||||||
err = __switchdev_port_attr_set(dev, attr, &trans);
|
err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr,
|
||||||
|
&trans);
|
||||||
if (err) {
|
if (err) {
|
||||||
/* Prepare phase failed: abort the transaction. Any
|
/* Prepare phase failed: abort the transaction. Any
|
||||||
* resources reserved in the prepare phase are
|
* resources reserved in the prepare phase are
|
||||||
|
@ -244,7 +238,8 @@ static int switchdev_port_attr_set_now(struct net_device *dev,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
trans.ph_prepare = false;
|
trans.ph_prepare = false;
|
||||||
err = __switchdev_port_attr_set(dev, attr, &trans);
|
err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr,
|
||||||
|
&trans);
|
||||||
WARN(err, "%s: Commit of attribute (id=%d) failed.\n",
|
WARN(err, "%s: Commit of attribute (id=%d) failed.\n",
|
||||||
dev->name, attr->id);
|
dev->name, attr->id);
|
||||||
switchdev_trans_items_warn_destroy(dev, &trans);
|
switchdev_trans_items_warn_destroy(dev, &trans);
|
||||||
|
|
Loading…
Reference in New Issue