aboutsummaryrefslogtreecommitdiffstats
path: root/net/switchdev/switchdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/switchdev/switchdev.c')
-rw-r--r--net/switchdev/switchdev.c100
1 files changed, 80 insertions, 20 deletions
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 5963d7ac1026..eac68c4e57ec 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -362,21 +362,8 @@ static int __switchdev_port_obj_add(struct net_device *dev,
362 return err; 362 return err;
363} 363}
364 364
365/** 365static int switchdev_port_obj_add_now(struct net_device *dev,
366 * switchdev_port_obj_add - Add port object 366 const struct switchdev_obj *obj)
367 *
368 * @dev: port device
369 * @id: object ID
370 * @obj: object to add
371 *
372 * Use a 2-phase prepare-commit transaction model to ensure
373 * system is not left in a partially updated state due to
374 * failure from driver/device.
375 *
376 * rtnl_lock must be held.
377 */
378int switchdev_port_obj_add(struct net_device *dev,
379 const struct switchdev_obj *obj)
380{ 367{
381 struct switchdev_trans trans; 368 struct switchdev_trans trans;
382 int err; 369 int err;
@@ -418,18 +405,53 @@ int switchdev_port_obj_add(struct net_device *dev,
418 405
419 return err; 406 return err;
420} 407}
421EXPORT_SYMBOL_GPL(switchdev_port_obj_add); 408
409static void switchdev_port_obj_add_deferred(struct net_device *dev,
410 const void *data)
411{
412 const struct switchdev_obj *obj = data;
413 int err;
414
415 err = switchdev_port_obj_add_now(dev, obj);
416 if (err && err != -EOPNOTSUPP)
417 netdev_err(dev, "failed (err=%d) to add object (id=%d)\n",
418 err, obj->id);
419}
420
421static int switchdev_port_obj_add_defer(struct net_device *dev,
422 const struct switchdev_obj *obj)
423{
424 return switchdev_deferred_enqueue(dev, obj, sizeof(*obj),
425 switchdev_port_obj_add_deferred);
426}
422 427
423/** 428/**
424 * switchdev_port_obj_del - Delete port object 429 * switchdev_port_obj_add - Add port object
425 * 430 *
426 * @dev: port device 431 * @dev: port device
427 * @id: object ID 432 * @id: object ID
428 * @obj: object to delete 433 * @obj: object to add
434 *
435 * Use a 2-phase prepare-commit transaction model to ensure
436 * system is not left in a partially updated state due to
437 * failure from driver/device.
438 *
439 * rtnl_lock must be held and must not be in atomic section,
440 * in case SWITCHDEV_F_DEFER flag is not set.
429 */ 441 */
430int switchdev_port_obj_del(struct net_device *dev, 442int switchdev_port_obj_add(struct net_device *dev,
431 const struct switchdev_obj *obj) 443 const struct switchdev_obj *obj)
432{ 444{
445 if (obj->flags & SWITCHDEV_F_DEFER)
446 return switchdev_port_obj_add_defer(dev, obj);
447 ASSERT_RTNL();
448 return switchdev_port_obj_add_now(dev, obj);
449}
450EXPORT_SYMBOL_GPL(switchdev_port_obj_add);
451
452static int switchdev_port_obj_del_now(struct net_device *dev,
453 const struct switchdev_obj *obj)
454{
433 const struct switchdev_ops *ops = dev->switchdev_ops; 455 const struct switchdev_ops *ops = dev->switchdev_ops;
434 struct net_device *lower_dev; 456 struct net_device *lower_dev;
435 struct list_head *iter; 457 struct list_head *iter;
@@ -444,13 +466,51 @@ int switchdev_port_obj_del(struct net_device *dev,
444 */ 466 */
445 467
446 netdev_for_each_lower_dev(dev, lower_dev, iter) { 468 netdev_for_each_lower_dev(dev, lower_dev, iter) {
447 err = switchdev_port_obj_del(lower_dev, obj); 469 err = switchdev_port_obj_del_now(lower_dev, obj);
448 if (err) 470 if (err)
449 break; 471 break;
450 } 472 }
451 473
452 return err; 474 return err;
453} 475}
476
477static void switchdev_port_obj_del_deferred(struct net_device *dev,
478 const void *data)
479{
480 const struct switchdev_obj *obj = data;
481 int err;
482
483 err = switchdev_port_obj_del_now(dev, obj);
484 if (err && err != -EOPNOTSUPP)
485 netdev_err(dev, "failed (err=%d) to del object (id=%d)\n",
486 err, obj->id);
487}
488
489static int switchdev_port_obj_del_defer(struct net_device *dev,
490 const struct switchdev_obj *obj)
491{
492 return switchdev_deferred_enqueue(dev, obj, sizeof(*obj),
493 switchdev_port_obj_del_deferred);
494}
495
496/**
497 * switchdev_port_obj_del - Delete port object
498 *
499 * @dev: port device
500 * @id: object ID
501 * @obj: object to delete
502 *
503 * rtnl_lock must be held and must not be in atomic section,
504 * in case SWITCHDEV_F_DEFER flag is not set.
505 */
506int switchdev_port_obj_del(struct net_device *dev,
507 const struct switchdev_obj *obj)
508{
509 if (obj->flags & SWITCHDEV_F_DEFER)
510 return switchdev_port_obj_del_defer(dev, obj);
511 ASSERT_RTNL();
512 return switchdev_port_obj_del_now(dev, obj);
513}
454EXPORT_SYMBOL_GPL(switchdev_port_obj_del); 514EXPORT_SYMBOL_GPL(switchdev_port_obj_del);
455 515
456/** 516/**