switchdev.c (4b4193256c8d3bc3a5397b5cd9494c2ad386317d) | switchdev.c (ffb68fc58e9640762be891f9aebe4f5aac615ab3) |
---|---|
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> --- 207 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, | 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> --- 207 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, |
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, | 224 struct netlink_ext_ack *extack) 225{ 226 int rc; 227 int err; 228 229 struct switchdev_notifier_port_obj_info obj_info = { 230 .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 247static int switchdev_port_obj_add_now(struct net_device *dev, 248 const struct switchdev_obj *obj, 249 struct netlink_ext_ack *extack) 250{ | 231 .handled = false, 232 }; 233 234 rc = call_switchdev_blocking_notifiers(nt, dev, &obj_info.info, extack); 235 err = notifier_to_errno(rc); 236 if (err) { 237 WARN_ON(!obj_info.handled); 238 return err; 239 } 240 if (!obj_info.handled) 241 return -EOPNOTSUPP; 242 return 0; 243} 244 245static int switchdev_port_obj_add_now(struct net_device *dev, 246 const struct switchdev_obj *obj, 247 struct netlink_ext_ack *extack) 248{ |
251 struct switchdev_trans trans; 252 int err; 253 | |
254 ASSERT_RTNL(); 255 | 249 ASSERT_RTNL(); 250 |
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; | 251 return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, 252 dev, obj, extack); |
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 --- 14 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 * | 253} 254 255static void switchdev_port_obj_add_deferred(struct net_device *dev, 256 const void *data) 257{ 258 const struct switchdev_obj *obj = data; 259 int err; 260 --- 14 unchanged lines hidden (view full) --- 275 276/** 277 * switchdev_port_obj_add - Add port object 278 * 279 * @dev: port device 280 * @obj: object to add 281 * @extack: netlink extended ack 282 * |
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(); 324 return switchdev_port_obj_add_now(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, | 283 * rtnl_lock must be held and must not be in atomic section, 284 * in case SWITCHDEV_F_DEFER flag is not set. 285 */ 286int switchdev_port_obj_add(struct net_device *dev, 287 const struct switchdev_obj *obj, 288 struct netlink_ext_ack *extack) 289{ 290 if (obj->flags & SWITCHDEV_F_DEFER) 291 return switchdev_port_obj_add_defer(dev, obj); 292 ASSERT_RTNL(); 293 return switchdev_port_obj_add_now(dev, obj, extack); 294} 295EXPORT_SYMBOL_GPL(switchdev_port_obj_add); 296 297static int switchdev_port_obj_del_now(struct net_device *dev, 298 const struct switchdev_obj *obj) 299{ 300 return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_DEL, |
332 dev, obj, NULL, NULL); | 301 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, | 302} 303 304static void switchdev_port_obj_del_deferred(struct net_device *dev, 305 const void *data) 306{ 307 const struct switchdev_obj *obj = data; 308 int err; 309 --- 103 unchanged lines hidden (view full) --- 413} 414EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers); 415 416static int __switchdev_handle_port_obj_add(struct net_device *dev, 417 struct switchdev_notifier_port_obj_info *port_obj_info, 418 bool (*check_cb)(const struct net_device *dev), 419 int (*add_cb)(struct net_device *dev, 420 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)) { 463 /* This flag is only checked if the return value is success. */ 464 port_obj_info->handled = true; | 421 struct netlink_ext_ack *extack)) 422{ 423 struct netlink_ext_ack *extack; 424 struct net_device *lower_dev; 425 struct list_head *iter; 426 int err = -EOPNOTSUPP; 427 428 extack = switchdev_notifier_info_to_extack(&port_obj_info->info); 429 430 if (check_cb(dev)) { 431 /* This flag is only checked if the return value is success. */ 432 port_obj_info->handled = true; |
465 return add_cb(dev, port_obj_info->obj, port_obj_info->trans, 466 extack); | 433 return add_cb(dev, port_obj_info->obj, extack); |
467 } 468 469 /* Switch ports might be stacked under e.g. a LAG. Ignore the 470 * unsupported devices, another driver might be able to handle them. But 471 * propagate to the callers any hard errors. 472 * 473 * If the driver does its own bookkeeping of stacked ports, it's not 474 * necessary to go through this helper. --- 11 unchanged lines hidden (view full) --- 486 return err; 487} 488 489int switchdev_handle_port_obj_add(struct net_device *dev, 490 struct switchdev_notifier_port_obj_info *port_obj_info, 491 bool (*check_cb)(const struct net_device *dev), 492 int (*add_cb)(struct net_device *dev, 493 const struct switchdev_obj *obj, | 434 } 435 436 /* Switch ports might be stacked under e.g. a LAG. Ignore the 437 * unsupported devices, another driver might be able to handle them. But 438 * propagate to the callers any hard errors. 439 * 440 * If the driver does its own bookkeeping of stacked ports, it's not 441 * necessary to go through this helper. --- 11 unchanged lines hidden (view full) --- 453 return err; 454} 455 456int switchdev_handle_port_obj_add(struct net_device *dev, 457 struct switchdev_notifier_port_obj_info *port_obj_info, 458 bool (*check_cb)(const struct net_device *dev), 459 int (*add_cb)(struct net_device *dev, 460 const struct switchdev_obj *obj, |
494 struct switchdev_trans *trans, | |
495 struct netlink_ext_ack *extack)) 496{ 497 int err; 498 499 err = __switchdev_handle_port_obj_add(dev, port_obj_info, check_cb, 500 add_cb); 501 if (err == -EOPNOTSUPP) 502 err = 0; --- 109 unchanged lines hidden --- | 461 struct netlink_ext_ack *extack)) 462{ 463 int err; 464 465 err = __switchdev_handle_port_obj_add(dev, port_obj_info, check_cb, 466 add_cb); 467 if (err == -EOPNOTSUPP) 468 err = 0; --- 109 unchanged lines hidden --- |