OSDN Git Service

net: switchdev: Replace port attr set SDO with a notification
authorFlorian Fainelli <f.fainelli@gmail.com>
Wed, 27 Feb 2019 19:44:31 +0000 (11:44 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 27 Feb 2019 20:39:56 +0000 (12:39 -0800)
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>
net/bridge/br_switchdev.c
net/switchdev/switchdev.c

index af57c4a..921310d 100644 (file)
@@ -67,12 +67,18 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
                .id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS,
                .u.brport_flags = mask,
        };
+       struct switchdev_notifier_port_attr_info info = {
+               .attr = &attr,
+       };
        int err;
 
        if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
                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)
                return 0;
 
index 3560c19..d81cfce 100644 (file)
@@ -174,39 +174,32 @@ static int switchdev_deferred_enqueue(struct net_device *dev,
        return 0;
 }
 
-static int __switchdev_port_attr_set(struct net_device *dev,
-                                    const struct switchdev_attr *attr,
-                                    struct switchdev_trans *trans)
+static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
+                                     struct net_device *dev,
+                                     const struct switchdev_attr *attr,
+                                     struct switchdev_trans *trans)
 {
-       const struct switchdev_ops *ops = dev->switchdev_ops;
-       struct net_device *lower_dev;
-       struct list_head *iter;
-       int err = -EOPNOTSUPP;
-
-       if (ops && ops->switchdev_port_attr_set) {
-               err = ops->switchdev_port_attr_set(dev, attr, trans);
-               goto done;
-       }
-
-       if (attr->flags & SWITCHDEV_F_NO_RECURSE)
-               goto done;
+       int err;
+       int rc;
 
-       /* Switch device port(s) may be stacked under
-        * bond/team/vlan dev, so recurse down to set attr on
-        * each port.
-        */
+       struct switchdev_notifier_port_attr_info attr_info = {
+               .attr = attr,
+               .trans = trans,
+               .handled = false,
+       };
 
-       netdev_for_each_lower_dev(dev, lower_dev, iter) {
-               err = __switchdev_port_attr_set(lower_dev, attr, trans);
-               if (err)
-                       break;
+       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;
        }
 
-done:
-       if (err == -EOPNOTSUPP && attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP)
-               err = 0;
+       if (!attr_info.handled)
+               return -EOPNOTSUPP;
 
-       return err;
+       return 0;
 }
 
 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;
-       err = __switchdev_port_attr_set(dev, attr, &trans);
+       err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr,
+                                        &trans);
        if (err) {
                /* Prepare phase failed: abort the transaction.  Any
                 * 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;
-       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",
             dev->name, attr->id);
        switchdev_trans_items_warn_destroy(dev, &trans);