diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2019-02-27 14:44:31 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-02-27 15:39:56 -0500 |
commit | d45224d604c5ba6ac5f9d6fddbe1d058c81dee80 (patch) | |
tree | 1708ef76a424c823156c36c563a242dadcb35c37 | |
parent | 570b68c8dddea16b96730f7d5d732e270b6a9189 (diff) |
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>
-rw-r--r-- | net/bridge/br_switchdev.c | 8 | ||||
-rw-r--r-- | net/switchdev/switchdev.c | 53 |
2 files changed, 31 insertions, 30 deletions
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index af57c4a2b78a..921310d3cbae 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c | |||
@@ -67,12 +67,18 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, | |||
67 | .id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, | 67 | .id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, |
68 | .u.brport_flags = mask, | 68 | .u.brport_flags = mask, |
69 | }; | 69 | }; |
70 | struct switchdev_notifier_port_attr_info info = { | ||
71 | .attr = &attr, | ||
72 | }; | ||
70 | int err; | 73 | int err; |
71 | 74 | ||
72 | if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD) | 75 | if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD) |
73 | return 0; | 76 | return 0; |
74 | 77 | ||
75 | err = switchdev_port_attr_set(p->dev, &attr); | 78 | /* We run from atomic context here */ |
79 | err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev, | ||
80 | &info.info, NULL); | ||
81 | err = notifier_to_errno(err); | ||
76 | if (err == -EOPNOTSUPP) | 82 | if (err == -EOPNOTSUPP) |
77 | return 0; | 83 | return 0; |
78 | 84 | ||
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 3560c19aa7e2..d81cfcee9ad9 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -174,39 +174,32 @@ static int switchdev_deferred_enqueue(struct net_device *dev, | |||
174 | return 0; | 174 | return 0; |
175 | } | 175 | } |
176 | 176 | ||
177 | static int __switchdev_port_attr_set(struct net_device *dev, | 177 | static int switchdev_port_attr_notify(enum switchdev_notifier_type nt, |
178 | const struct switchdev_attr *attr, | 178 | struct net_device *dev, |
179 | struct switchdev_trans *trans) | 179 | const struct switchdev_attr *attr, |
180 | struct switchdev_trans *trans) | ||
180 | { | 181 | { |
181 | const struct switchdev_ops *ops = dev->switchdev_ops; | 182 | int err; |
182 | struct net_device *lower_dev; | 183 | int rc; |
183 | struct list_head *iter; | ||
184 | int err = -EOPNOTSUPP; | ||
185 | |||
186 | if (ops && ops->switchdev_port_attr_set) { | ||
187 | err = ops->switchdev_port_attr_set(dev, attr, trans); | ||
188 | goto done; | ||
189 | } | ||
190 | |||
191 | if (attr->flags & SWITCHDEV_F_NO_RECURSE) | ||
192 | goto done; | ||
193 | 184 | ||
194 | /* Switch device port(s) may be stacked under | 185 | struct switchdev_notifier_port_attr_info attr_info = { |
195 | * bond/team/vlan dev, so recurse down to set attr on | 186 | .attr = attr, |
196 | * each port. | 187 | .trans = trans, |
197 | */ | 188 | .handled = false, |
189 | }; | ||
198 | 190 | ||
199 | netdev_for_each_lower_dev(dev, lower_dev, iter) { | 191 | rc = call_switchdev_blocking_notifiers(nt, dev, |
200 | err = __switchdev_port_attr_set(lower_dev, attr, trans); | 192 | &attr_info.info, NULL); |
201 | if (err) | 193 | err = notifier_to_errno(rc); |
202 | break; | 194 | if (err) { |
195 | WARN_ON(!attr_info.handled); | ||
196 | return err; | ||
203 | } | 197 | } |
204 | 198 | ||
205 | done: | 199 | if (!attr_info.handled) |
206 | if (err == -EOPNOTSUPP && attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP) | 200 | return -EOPNOTSUPP; |
207 | err = 0; | ||
208 | 201 | ||
209 | return err; | 202 | return 0; |
210 | } | 203 | } |
211 | 204 | ||
212 | static int switchdev_port_attr_set_now(struct net_device *dev, | 205 | 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, | |||
225 | */ | 218 | */ |
226 | 219 | ||
227 | trans.ph_prepare = true; | 220 | trans.ph_prepare = true; |
228 | err = __switchdev_port_attr_set(dev, attr, &trans); | 221 | err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr, |
222 | &trans); | ||
229 | if (err) { | 223 | if (err) { |
230 | /* Prepare phase failed: abort the transaction. Any | 224 | /* Prepare phase failed: abort the transaction. Any |
231 | * resources reserved in the prepare phase are | 225 | * resources reserved in the prepare phase are |
@@ -244,7 +238,8 @@ static int switchdev_port_attr_set_now(struct net_device *dev, | |||
244 | */ | 238 | */ |
245 | 239 | ||
246 | trans.ph_prepare = false; | 240 | trans.ph_prepare = false; |
247 | err = __switchdev_port_attr_set(dev, attr, &trans); | 241 | err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr, |
242 | &trans); | ||
248 | WARN(err, "%s: Commit of attribute (id=%d) failed.\n", | 243 | WARN(err, "%s: Commit of attribute (id=%d) failed.\n", |
249 | dev->name, attr->id); | 244 | dev->name, attr->id); |
250 | switchdev_trans_items_warn_destroy(dev, &trans); | 245 | switchdev_trans_items_warn_destroy(dev, &trans); |