switchdev.c (a3251c1a36f595046bea03935ebe37a1e1f1f1d7) | switchdev.c (4c08c586ff29bda47e3db14da096331d84933f48) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * net/switchdev/switchdev.c - Switch device API 4 * Copyright (c) 2014-2015 Jiri Pirko <jiri@resnulli.us> 5 * Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com> 6 */ 7 8#include <linux/kernel.h> --- 86 unchanged lines hidden (view full) --- 95 list_add_tail(&dfitem->list, &deferred); 96 spin_unlock_bh(&deferred_lock); 97 schedule_work(&deferred_process_work); 98 return 0; 99} 100 101static int switchdev_port_attr_notify(enum switchdev_notifier_type nt, 102 struct net_device *dev, | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * net/switchdev/switchdev.c - Switch device API 4 * Copyright (c) 2014-2015 Jiri Pirko <jiri@resnulli.us> 5 * Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com> 6 */ 7 8#include <linux/kernel.h> --- 86 unchanged lines hidden (view full) --- 95 list_add_tail(&dfitem->list, &deferred); 96 spin_unlock_bh(&deferred_lock); 97 schedule_work(&deferred_process_work); 98 return 0; 99} 100 101static int switchdev_port_attr_notify(enum switchdev_notifier_type nt, 102 struct net_device *dev, |
103 const struct switchdev_attr *attr, 104 struct switchdev_trans *trans) | 103 const struct switchdev_attr *attr) |
105{ 106 int err; 107 int rc; 108 109 struct switchdev_notifier_port_attr_info attr_info = { 110 .attr = attr, | 104{ 105 int err; 106 int rc; 107 108 struct switchdev_notifier_port_attr_info attr_info = { 109 .attr = attr, |
111 .trans = trans, | |
112 .handled = false, 113 }; 114 115 rc = call_switchdev_blocking_notifiers(nt, dev, 116 &attr_info.info, NULL); 117 err = notifier_to_errno(rc); 118 if (err) { 119 WARN_ON(!attr_info.handled); --- 4 unchanged lines hidden (view full) --- 124 return -EOPNOTSUPP; 125 126 return 0; 127} 128 129static int switchdev_port_attr_set_now(struct net_device *dev, 130 const struct switchdev_attr *attr) 131{ | 110 .handled = false, 111 }; 112 113 rc = call_switchdev_blocking_notifiers(nt, dev, 114 &attr_info.info, NULL); 115 err = notifier_to_errno(rc); 116 if (err) { 117 WARN_ON(!attr_info.handled); --- 4 unchanged lines hidden (view full) --- 122 return -EOPNOTSUPP; 123 124 return 0; 125} 126 127static int switchdev_port_attr_set_now(struct net_device *dev, 128 const struct switchdev_attr *attr) 129{ |
132 struct switchdev_trans trans; 133 int err; 134 135 /* Phase I: prepare for attr set. Driver/device should fail 136 * here if there are going to be issues in the commit phase, 137 * such as lack of resources or support. The driver/device 138 * should reserve resources needed for the commit phase here, 139 * but should not commit the attr. 140 */ 141 142 trans.ph_prepare = true; 143 err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr, 144 &trans); 145 if (err) 146 return err; 147 148 /* Phase II: commit attr set. This cannot fail as a fault 149 * of driver/device. If it does, it's a bug in the driver/device 150 * because the driver said everythings was OK in phase I. 151 */ 152 153 trans.ph_prepare = false; 154 err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr, 155 &trans); 156 WARN(err, "%s: Commit of attribute (id=%d) failed.\n", 157 dev->name, attr->id); 158 159 return err; | 130 return switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr); |
160} 161 162static void switchdev_port_attr_set_deferred(struct net_device *dev, 163 const void *data) 164{ 165 const struct switchdev_attr *attr = data; 166 int err; 167 --- 13 unchanged lines hidden (view full) --- 181} 182 183/** 184 * switchdev_port_attr_set - Set port attribute 185 * 186 * @dev: port device 187 * @attr: attribute to set 188 * | 131} 132 133static void switchdev_port_attr_set_deferred(struct net_device *dev, 134 const void *data) 135{ 136 const struct switchdev_attr *attr = data; 137 int err; 138 --- 13 unchanged lines hidden (view full) --- 152} 153 154/** 155 * switchdev_port_attr_set - Set port attribute 156 * 157 * @dev: port device 158 * @attr: attribute to set 159 * |
189 * Use a 2-phase prepare-commit transaction model to ensure 190 * system is not left in a partially updated state due to 191 * failure from driver/device. 192 * | |
193 * rtnl_lock must be held and must not be in atomic section, 194 * in case SWITCHDEV_F_DEFER flag is not set. 195 */ 196int switchdev_port_attr_set(struct net_device *dev, 197 const struct switchdev_attr *attr) 198{ 199 if (attr->flags & SWITCHDEV_F_DEFER) 200 return switchdev_port_attr_set_defer(dev, attr); --- 15 unchanged lines hidden (view full) --- 216 BUG(); 217 } 218 return 0; 219} 220 221static int switchdev_port_obj_notify(enum switchdev_notifier_type nt, 222 struct net_device *dev, 223 const struct switchdev_obj *obj, | 160 * rtnl_lock must be held and must not be in atomic section, 161 * in case SWITCHDEV_F_DEFER flag is not set. 162 */ 163int switchdev_port_attr_set(struct net_device *dev, 164 const struct switchdev_attr *attr) 165{ 166 if (attr->flags & SWITCHDEV_F_DEFER) 167 return switchdev_port_attr_set_defer(dev, attr); --- 15 unchanged lines hidden (view full) --- 183 BUG(); 184 } 185 return 0; 186} 187 188static int switchdev_port_obj_notify(enum switchdev_notifier_type nt, 189 struct net_device *dev, 190 const struct switchdev_obj *obj, |
224 struct switchdev_trans *trans, | |
225 struct netlink_ext_ack *extack) 226{ 227 int rc; 228 int err; 229 230 struct switchdev_notifier_port_obj_info obj_info = { 231 .obj = obj, | 191 struct netlink_ext_ack *extack) 192{ 193 int rc; 194 int err; 195 196 struct switchdev_notifier_port_obj_info obj_info = { 197 .obj = obj, |
232 .trans = trans, | |
233 .handled = false, 234 }; 235 236 rc = call_switchdev_blocking_notifiers(nt, dev, &obj_info.info, extack); 237 err = notifier_to_errno(rc); 238 if (err) { 239 WARN_ON(!obj_info.handled); 240 return err; 241 } 242 if (!obj_info.handled) 243 return -EOPNOTSUPP; 244 return 0; 245} 246 | 198 .handled = false, 199 }; 200 201 rc = call_switchdev_blocking_notifiers(nt, dev, &obj_info.info, extack); 202 err = notifier_to_errno(rc); 203 if (err) { 204 WARN_ON(!obj_info.handled); 205 return err; 206 } 207 if (!obj_info.handled) 208 return -EOPNOTSUPP; 209 return 0; 210} 211 |
247static int switchdev_port_obj_add_now(struct net_device *dev, 248 const struct switchdev_obj *obj, 249 struct netlink_ext_ack *extack) 250{ 251 struct switchdev_trans trans; 252 int err; 253 254 ASSERT_RTNL(); 255 256 /* Phase I: prepare for obj add. Driver/device should fail 257 * here if there are going to be issues in the commit phase, 258 * such as lack of resources or support. The driver/device 259 * should reserve resources needed for the commit phase here, 260 * but should not commit the obj. 261 */ 262 263 trans.ph_prepare = true; 264 err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, 265 dev, obj, &trans, extack); 266 if (err) 267 return err; 268 269 /* Phase II: commit obj add. This cannot fail as a fault 270 * of driver/device. If it does, it's a bug in the driver/device 271 * because the driver said everythings was OK in phase I. 272 */ 273 274 trans.ph_prepare = false; 275 err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, 276 dev, obj, &trans, extack); 277 WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); 278 279 return err; 280} 281 | |
282static void switchdev_port_obj_add_deferred(struct net_device *dev, 283 const void *data) 284{ 285 const struct switchdev_obj *obj = data; 286 int err; 287 | 212static void switchdev_port_obj_add_deferred(struct net_device *dev, 213 const void *data) 214{ 215 const struct switchdev_obj *obj = data; 216 int err; 217 |
288 err = switchdev_port_obj_add_now(dev, obj, NULL); | 218 ASSERT_RTNL(); 219 err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, 220 dev, obj, NULL); |
289 if (err && err != -EOPNOTSUPP) 290 netdev_err(dev, "failed (err=%d) to add object (id=%d)\n", 291 err, obj->id); 292 if (obj->complete) 293 obj->complete(dev, err, obj->complete_priv); 294} 295 296static int switchdev_port_obj_add_defer(struct net_device *dev, --- 5 unchanged lines hidden (view full) --- 302 303/** 304 * switchdev_port_obj_add - Add port object 305 * 306 * @dev: port device 307 * @obj: object to add 308 * @extack: netlink extended ack 309 * | 221 if (err && err != -EOPNOTSUPP) 222 netdev_err(dev, "failed (err=%d) to add object (id=%d)\n", 223 err, obj->id); 224 if (obj->complete) 225 obj->complete(dev, err, obj->complete_priv); 226} 227 228static int switchdev_port_obj_add_defer(struct net_device *dev, --- 5 unchanged lines hidden (view full) --- 234 235/** 236 * switchdev_port_obj_add - Add port object 237 * 238 * @dev: port device 239 * @obj: object to add 240 * @extack: netlink extended ack 241 * |
310 * Use a 2-phase prepare-commit transaction model to ensure 311 * system is not left in a partially updated state due to 312 * failure from driver/device. 313 * | |
314 * rtnl_lock must be held and must not be in atomic section, 315 * in case SWITCHDEV_F_DEFER flag is not set. 316 */ 317int switchdev_port_obj_add(struct net_device *dev, 318 const struct switchdev_obj *obj, 319 struct netlink_ext_ack *extack) 320{ 321 if (obj->flags & SWITCHDEV_F_DEFER) 322 return switchdev_port_obj_add_defer(dev, obj); 323 ASSERT_RTNL(); | 242 * rtnl_lock must be held and must not be in atomic section, 243 * in case SWITCHDEV_F_DEFER flag is not set. 244 */ 245int switchdev_port_obj_add(struct net_device *dev, 246 const struct switchdev_obj *obj, 247 struct netlink_ext_ack *extack) 248{ 249 if (obj->flags & SWITCHDEV_F_DEFER) 250 return switchdev_port_obj_add_defer(dev, obj); 251 ASSERT_RTNL(); |
324 return switchdev_port_obj_add_now(dev, obj, extack); | 252 return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, 253 dev, obj, extack); |
325} 326EXPORT_SYMBOL_GPL(switchdev_port_obj_add); 327 328static int switchdev_port_obj_del_now(struct net_device *dev, 329 const struct switchdev_obj *obj) 330{ 331 return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_DEL, | 254} 255EXPORT_SYMBOL_GPL(switchdev_port_obj_add); 256 257static int switchdev_port_obj_del_now(struct net_device *dev, 258 const struct switchdev_obj *obj) 259{ 260 return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_DEL, |
332 dev, obj, NULL, NULL); | 261 dev, obj, NULL); |
333} 334 335static void switchdev_port_obj_del_deferred(struct net_device *dev, 336 const void *data) 337{ 338 const struct switchdev_obj *obj = data; 339 int err; 340 --- 103 unchanged lines hidden (view full) --- 444} 445EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers); 446 447static int __switchdev_handle_port_obj_add(struct net_device *dev, 448 struct switchdev_notifier_port_obj_info *port_obj_info, 449 bool (*check_cb)(const struct net_device *dev), 450 int (*add_cb)(struct net_device *dev, 451 const struct switchdev_obj *obj, | 262} 263 264static void switchdev_port_obj_del_deferred(struct net_device *dev, 265 const void *data) 266{ 267 const struct switchdev_obj *obj = data; 268 int err; 269 --- 103 unchanged lines hidden (view full) --- 373} 374EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers); 375 376static int __switchdev_handle_port_obj_add(struct net_device *dev, 377 struct switchdev_notifier_port_obj_info *port_obj_info, 378 bool (*check_cb)(const struct net_device *dev), 379 int (*add_cb)(struct net_device *dev, 380 const struct switchdev_obj *obj, |
452 struct switchdev_trans *trans, | |
453 struct netlink_ext_ack *extack)) 454{ 455 struct netlink_ext_ack *extack; 456 struct net_device *lower_dev; 457 struct list_head *iter; 458 int err = -EOPNOTSUPP; 459 460 extack = switchdev_notifier_info_to_extack(&port_obj_info->info); 461 462 if (check_cb(dev)) { | 381 struct netlink_ext_ack *extack)) 382{ 383 struct netlink_ext_ack *extack; 384 struct net_device *lower_dev; 385 struct list_head *iter; 386 int err = -EOPNOTSUPP; 387 388 extack = switchdev_notifier_info_to_extack(&port_obj_info->info); 389 390 if (check_cb(dev)) { |
463 err = add_cb(dev, port_obj_info->obj, port_obj_info->trans, 464 extack); | 391 err = add_cb(dev, port_obj_info->obj, extack); |
465 if (err != -EOPNOTSUPP) 466 port_obj_info->handled = true; 467 return err; 468 } 469 470 /* Switch ports might be stacked under e.g. a LAG. Ignore the 471 * unsupported devices, another driver might be able to handle them. But 472 * propagate to the callers any hard errors. --- 14 unchanged lines hidden (view full) --- 487 return err; 488} 489 490int switchdev_handle_port_obj_add(struct net_device *dev, 491 struct switchdev_notifier_port_obj_info *port_obj_info, 492 bool (*check_cb)(const struct net_device *dev), 493 int (*add_cb)(struct net_device *dev, 494 const struct switchdev_obj *obj, | 392 if (err != -EOPNOTSUPP) 393 port_obj_info->handled = true; 394 return err; 395 } 396 397 /* Switch ports might be stacked under e.g. a LAG. Ignore the 398 * unsupported devices, another driver might be able to handle them. But 399 * propagate to the callers any hard errors. --- 14 unchanged lines hidden (view full) --- 414 return err; 415} 416 417int switchdev_handle_port_obj_add(struct net_device *dev, 418 struct switchdev_notifier_port_obj_info *port_obj_info, 419 bool (*check_cb)(const struct net_device *dev), 420 int (*add_cb)(struct net_device *dev, 421 const struct switchdev_obj *obj, |
495 struct switchdev_trans *trans, | |
496 struct netlink_ext_ack *extack)) 497{ 498 int err; 499 500 err = __switchdev_handle_port_obj_add(dev, port_obj_info, check_cb, 501 add_cb); 502 if (err == -EOPNOTSUPP) 503 err = 0; --- 54 unchanged lines hidden (view full) --- 558} 559EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_del); 560 561static int __switchdev_handle_port_attr_set(struct net_device *dev, 562 struct switchdev_notifier_port_attr_info *port_attr_info, 563 bool (*check_cb)(const struct net_device *dev), 564 int (*set_cb)(struct net_device *dev, 565 const struct switchdev_attr *attr, | 422 struct netlink_ext_ack *extack)) 423{ 424 int err; 425 426 err = __switchdev_handle_port_obj_add(dev, port_obj_info, check_cb, 427 add_cb); 428 if (err == -EOPNOTSUPP) 429 err = 0; --- 54 unchanged lines hidden (view full) --- 484} 485EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_del); 486 487static int __switchdev_handle_port_attr_set(struct net_device *dev, 488 struct switchdev_notifier_port_attr_info *port_attr_info, 489 bool (*check_cb)(const struct net_device *dev), 490 int (*set_cb)(struct net_device *dev, 491 const struct switchdev_attr *attr, |
566 struct switchdev_trans *trans)) | 492 struct netlink_ext_ack *extack)) |
567{ | 493{ |
494 struct netlink_ext_ack *extack; |
|
568 struct net_device *lower_dev; 569 struct list_head *iter; 570 int err = -EOPNOTSUPP; 571 | 495 struct net_device *lower_dev; 496 struct list_head *iter; 497 int err = -EOPNOTSUPP; 498 |
499 extack = switchdev_notifier_info_to_extack(&port_attr_info->info); 500 |
|
572 if (check_cb(dev)) { | 501 if (check_cb(dev)) { |
573 err = set_cb(dev, port_attr_info->attr, port_attr_info->trans); | 502 err = set_cb(dev, port_attr_info->attr, extack); |
574 if (err != -EOPNOTSUPP) 575 port_attr_info->handled = true; 576 return err; 577 } 578 579 /* Switch ports might be stacked under e.g. a LAG. Ignore the 580 * unsupported devices, another driver might be able to handle them. But 581 * propagate to the callers any hard errors. --- 14 unchanged lines hidden (view full) --- 596 return err; 597} 598 599int switchdev_handle_port_attr_set(struct net_device *dev, 600 struct switchdev_notifier_port_attr_info *port_attr_info, 601 bool (*check_cb)(const struct net_device *dev), 602 int (*set_cb)(struct net_device *dev, 603 const struct switchdev_attr *attr, | 503 if (err != -EOPNOTSUPP) 504 port_attr_info->handled = true; 505 return err; 506 } 507 508 /* Switch ports might be stacked under e.g. a LAG. Ignore the 509 * unsupported devices, another driver might be able to handle them. But 510 * propagate to the callers any hard errors. --- 14 unchanged lines hidden (view full) --- 525 return err; 526} 527 528int switchdev_handle_port_attr_set(struct net_device *dev, 529 struct switchdev_notifier_port_attr_info *port_attr_info, 530 bool (*check_cb)(const struct net_device *dev), 531 int (*set_cb)(struct net_device *dev, 532 const struct switchdev_attr *attr, |
604 struct switchdev_trans *trans)) | 533 struct netlink_ext_ack *extack)) |
605{ 606 int err; 607 608 err = __switchdev_handle_port_attr_set(dev, port_attr_info, check_cb, 609 set_cb); 610 if (err == -EOPNOTSUPP) 611 err = 0; 612 return err; 613} 614EXPORT_SYMBOL_GPL(switchdev_handle_port_attr_set); | 534{ 535 int err; 536 537 err = __switchdev_handle_port_attr_set(dev, port_attr_info, check_cb, 538 set_cb); 539 if (err == -EOPNOTSUPP) 540 err = 0; 541 return err; 542} 543EXPORT_SYMBOL_GPL(switchdev_handle_port_attr_set); |