diff options
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 404 |
1 files changed, 286 insertions, 118 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 5c713f2239cc..25ab6fe80da2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -4373,42 +4373,40 @@ struct netdev_adjacent { | |||
| 4373 | /* upper master flag, there can only be one master device per list */ | 4373 | /* upper master flag, there can only be one master device per list */ |
| 4374 | bool master; | 4374 | bool master; |
| 4375 | 4375 | ||
| 4376 | /* indicates that this dev is our first-level lower/upper device */ | ||
| 4377 | bool neighbour; | ||
| 4378 | |||
| 4379 | /* counter for the number of times this device was added to us */ | 4376 | /* counter for the number of times this device was added to us */ |
| 4380 | u16 ref_nr; | 4377 | u16 ref_nr; |
| 4381 | 4378 | ||
| 4379 | /* private field for the users */ | ||
| 4380 | void *private; | ||
| 4381 | |||
| 4382 | struct list_head list; | 4382 | struct list_head list; |
| 4383 | struct rcu_head rcu; | 4383 | struct rcu_head rcu; |
| 4384 | }; | 4384 | }; |
| 4385 | 4385 | ||
| 4386 | static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev, | 4386 | static struct netdev_adjacent *__netdev_find_adj_rcu(struct net_device *dev, |
| 4387 | struct net_device *adj_dev, | 4387 | struct net_device *adj_dev, |
| 4388 | bool upper) | 4388 | struct list_head *adj_list) |
| 4389 | { | 4389 | { |
| 4390 | struct netdev_adjacent *adj; | 4390 | struct netdev_adjacent *adj; |
| 4391 | struct list_head *dev_list; | ||
| 4392 | 4391 | ||
| 4393 | dev_list = upper ? &dev->upper_dev_list : &dev->lower_dev_list; | 4392 | list_for_each_entry_rcu(adj, adj_list, list) { |
| 4394 | |||
| 4395 | list_for_each_entry(adj, dev_list, list) { | ||
| 4396 | if (adj->dev == adj_dev) | 4393 | if (adj->dev == adj_dev) |
| 4397 | return adj; | 4394 | return adj; |
| 4398 | } | 4395 | } |
| 4399 | return NULL; | 4396 | return NULL; |
| 4400 | } | 4397 | } |
| 4401 | 4398 | ||
| 4402 | static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev, | 4399 | static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev, |
| 4403 | struct net_device *udev) | 4400 | struct net_device *adj_dev, |
| 4401 | struct list_head *adj_list) | ||
| 4404 | { | 4402 | { |
| 4405 | return __netdev_find_adj(dev, udev, true); | 4403 | struct netdev_adjacent *adj; |
| 4406 | } | ||
| 4407 | 4404 | ||
| 4408 | static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev, | 4405 | list_for_each_entry(adj, adj_list, list) { |
| 4409 | struct net_device *ldev) | 4406 | if (adj->dev == adj_dev) |
| 4410 | { | 4407 | return adj; |
| 4411 | return __netdev_find_adj(dev, ldev, false); | 4408 | } |
| 4409 | return NULL; | ||
| 4412 | } | 4410 | } |
| 4413 | 4411 | ||
| 4414 | /** | 4412 | /** |
| @@ -4425,7 +4423,7 @@ bool netdev_has_upper_dev(struct net_device *dev, | |||
| 4425 | { | 4423 | { |
| 4426 | ASSERT_RTNL(); | 4424 | ASSERT_RTNL(); |
| 4427 | 4425 | ||
| 4428 | return __netdev_find_upper(dev, upper_dev); | 4426 | return __netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper); |
| 4429 | } | 4427 | } |
| 4430 | EXPORT_SYMBOL(netdev_has_upper_dev); | 4428 | EXPORT_SYMBOL(netdev_has_upper_dev); |
| 4431 | 4429 | ||
| @@ -4440,7 +4438,7 @@ bool netdev_has_any_upper_dev(struct net_device *dev) | |||
| 4440 | { | 4438 | { |
| 4441 | ASSERT_RTNL(); | 4439 | ASSERT_RTNL(); |
| 4442 | 4440 | ||
| 4443 | return !list_empty(&dev->upper_dev_list); | 4441 | return !list_empty(&dev->all_adj_list.upper); |
| 4444 | } | 4442 | } |
| 4445 | EXPORT_SYMBOL(netdev_has_any_upper_dev); | 4443 | EXPORT_SYMBOL(netdev_has_any_upper_dev); |
| 4446 | 4444 | ||
| @@ -4457,10 +4455,10 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev) | |||
| 4457 | 4455 | ||
| 4458 | ASSERT_RTNL(); | 4456 | ASSERT_RTNL(); |
| 4459 | 4457 | ||
| 4460 | if (list_empty(&dev->upper_dev_list)) | 4458 | if (list_empty(&dev->adj_list.upper)) |
| 4461 | return NULL; | 4459 | return NULL; |
| 4462 | 4460 | ||
| 4463 | upper = list_first_entry(&dev->upper_dev_list, | 4461 | upper = list_first_entry(&dev->adj_list.upper, |
| 4464 | struct netdev_adjacent, list); | 4462 | struct netdev_adjacent, list); |
| 4465 | if (likely(upper->master)) | 4463 | if (likely(upper->master)) |
| 4466 | return upper->dev; | 4464 | return upper->dev; |
| @@ -4468,15 +4466,26 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev) | |||
| 4468 | } | 4466 | } |
| 4469 | EXPORT_SYMBOL(netdev_master_upper_dev_get); | 4467 | EXPORT_SYMBOL(netdev_master_upper_dev_get); |
| 4470 | 4468 | ||
| 4471 | /* netdev_upper_get_next_dev_rcu - Get the next dev from upper list | 4469 | void *netdev_adjacent_get_private(struct list_head *adj_list) |
| 4470 | { | ||
| 4471 | struct netdev_adjacent *adj; | ||
| 4472 | |||
| 4473 | adj = list_entry(adj_list, struct netdev_adjacent, list); | ||
| 4474 | |||
| 4475 | return adj->private; | ||
| 4476 | } | ||
| 4477 | EXPORT_SYMBOL(netdev_adjacent_get_private); | ||
| 4478 | |||
| 4479 | /** | ||
| 4480 | * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list | ||
| 4472 | * @dev: device | 4481 | * @dev: device |
| 4473 | * @iter: list_head ** of the current position | 4482 | * @iter: list_head ** of the current position |
| 4474 | * | 4483 | * |
| 4475 | * Gets the next device from the dev's upper list, starting from iter | 4484 | * Gets the next device from the dev's upper list, starting from iter |
| 4476 | * position. The caller must hold RCU read lock. | 4485 | * position. The caller must hold RCU read lock. |
| 4477 | */ | 4486 | */ |
| 4478 | struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, | 4487 | struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev, |
| 4479 | struct list_head **iter) | 4488 | struct list_head **iter) |
| 4480 | { | 4489 | { |
| 4481 | struct netdev_adjacent *upper; | 4490 | struct netdev_adjacent *upper; |
| 4482 | 4491 | ||
| @@ -4484,14 +4493,71 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, | |||
| 4484 | 4493 | ||
| 4485 | upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); | 4494 | upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); |
| 4486 | 4495 | ||
| 4487 | if (&upper->list == &dev->upper_dev_list) | 4496 | if (&upper->list == &dev->all_adj_list.upper) |
| 4488 | return NULL; | 4497 | return NULL; |
| 4489 | 4498 | ||
| 4490 | *iter = &upper->list; | 4499 | *iter = &upper->list; |
| 4491 | 4500 | ||
| 4492 | return upper->dev; | 4501 | return upper->dev; |
| 4493 | } | 4502 | } |
| 4494 | EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu); | 4503 | EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu); |
| 4504 | |||
| 4505 | /** | ||
| 4506 | * netdev_lower_get_next_private - Get the next ->private from the | ||
| 4507 | * lower neighbour list | ||
| 4508 | * @dev: device | ||
| 4509 | * @iter: list_head ** of the current position | ||
| 4510 | * | ||
| 4511 | * Gets the next netdev_adjacent->private from the dev's lower neighbour | ||
| 4512 | * list, starting from iter position. The caller must hold either hold the | ||
| 4513 | * RTNL lock or its own locking that guarantees that the neighbour lower | ||
| 4514 | * list will remain unchainged. | ||
| 4515 | */ | ||
| 4516 | void *netdev_lower_get_next_private(struct net_device *dev, | ||
| 4517 | struct list_head **iter) | ||
| 4518 | { | ||
| 4519 | struct netdev_adjacent *lower; | ||
| 4520 | |||
| 4521 | lower = list_entry(*iter, struct netdev_adjacent, list); | ||
| 4522 | |||
| 4523 | if (&lower->list == &dev->adj_list.lower) | ||
| 4524 | return NULL; | ||
| 4525 | |||
| 4526 | if (iter) | ||
| 4527 | *iter = lower->list.next; | ||
| 4528 | |||
| 4529 | return lower->private; | ||
| 4530 | } | ||
| 4531 | EXPORT_SYMBOL(netdev_lower_get_next_private); | ||
| 4532 | |||
| 4533 | /** | ||
| 4534 | * netdev_lower_get_next_private_rcu - Get the next ->private from the | ||
| 4535 | * lower neighbour list, RCU | ||
| 4536 | * variant | ||
| 4537 | * @dev: device | ||
| 4538 | * @iter: list_head ** of the current position | ||
| 4539 | * | ||
| 4540 | * Gets the next netdev_adjacent->private from the dev's lower neighbour | ||
| 4541 | * list, starting from iter position. The caller must hold RCU read lock. | ||
| 4542 | */ | ||
| 4543 | void *netdev_lower_get_next_private_rcu(struct net_device *dev, | ||
| 4544 | struct list_head **iter) | ||
| 4545 | { | ||
| 4546 | struct netdev_adjacent *lower; | ||
| 4547 | |||
| 4548 | WARN_ON_ONCE(!rcu_read_lock_held()); | ||
| 4549 | |||
| 4550 | lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); | ||
| 4551 | |||
| 4552 | if (&lower->list == &dev->adj_list.lower) | ||
| 4553 | return NULL; | ||
| 4554 | |||
| 4555 | if (iter) | ||
| 4556 | *iter = &lower->list; | ||
| 4557 | |||
| 4558 | return lower->private; | ||
| 4559 | } | ||
| 4560 | EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); | ||
| 4495 | 4561 | ||
| 4496 | /** | 4562 | /** |
| 4497 | * netdev_master_upper_dev_get_rcu - Get master upper device | 4563 | * netdev_master_upper_dev_get_rcu - Get master upper device |
| @@ -4504,7 +4570,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev) | |||
| 4504 | { | 4570 | { |
| 4505 | struct netdev_adjacent *upper; | 4571 | struct netdev_adjacent *upper; |
| 4506 | 4572 | ||
| 4507 | upper = list_first_or_null_rcu(&dev->upper_dev_list, | 4573 | upper = list_first_or_null_rcu(&dev->adj_list.upper, |
| 4508 | struct netdev_adjacent, list); | 4574 | struct netdev_adjacent, list); |
| 4509 | if (upper && likely(upper->master)) | 4575 | if (upper && likely(upper->master)) |
| 4510 | return upper->dev; | 4576 | return upper->dev; |
| @@ -4514,15 +4580,16 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu); | |||
| 4514 | 4580 | ||
| 4515 | static int __netdev_adjacent_dev_insert(struct net_device *dev, | 4581 | static int __netdev_adjacent_dev_insert(struct net_device *dev, |
| 4516 | struct net_device *adj_dev, | 4582 | struct net_device *adj_dev, |
| 4517 | bool neighbour, bool master, | 4583 | struct list_head *dev_list, |
| 4518 | bool upper) | 4584 | void *private, bool master) |
| 4519 | { | 4585 | { |
| 4520 | struct netdev_adjacent *adj; | 4586 | struct netdev_adjacent *adj; |
| 4587 | char linkname[IFNAMSIZ+7]; | ||
| 4588 | int ret; | ||
| 4521 | 4589 | ||
| 4522 | adj = __netdev_find_adj(dev, adj_dev, upper); | 4590 | adj = __netdev_find_adj(dev, adj_dev, dev_list); |
| 4523 | 4591 | ||
| 4524 | if (adj) { | 4592 | if (adj) { |
| 4525 | BUG_ON(neighbour); | ||
| 4526 | adj->ref_nr++; | 4593 | adj->ref_nr++; |
| 4527 | return 0; | 4594 | return 0; |
| 4528 | } | 4595 | } |
| @@ -4533,124 +4600,178 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, | |||
| 4533 | 4600 | ||
| 4534 | adj->dev = adj_dev; | 4601 | adj->dev = adj_dev; |
| 4535 | adj->master = master; | 4602 | adj->master = master; |
| 4536 | adj->neighbour = neighbour; | ||
| 4537 | adj->ref_nr = 1; | 4603 | adj->ref_nr = 1; |
| 4538 | 4604 | adj->private = private; | |
| 4539 | dev_hold(adj_dev); | 4605 | dev_hold(adj_dev); |
| 4540 | pr_debug("dev_hold for %s, because of %s link added from %s to %s\n", | ||
| 4541 | adj_dev->name, upper ? "upper" : "lower", dev->name, | ||
| 4542 | adj_dev->name); | ||
| 4543 | 4606 | ||
| 4544 | if (!upper) { | 4607 | pr_debug("dev_hold for %s, because of link added from %s to %s\n", |
| 4545 | list_add_tail_rcu(&adj->list, &dev->lower_dev_list); | 4608 | adj_dev->name, dev->name, adj_dev->name); |
| 4546 | return 0; | 4609 | |
| 4610 | if (dev_list == &dev->adj_list.lower) { | ||
| 4611 | sprintf(linkname, "lower_%s", adj_dev->name); | ||
| 4612 | ret = sysfs_create_link(&(dev->dev.kobj), | ||
| 4613 | &(adj_dev->dev.kobj), linkname); | ||
| 4614 | if (ret) | ||
| 4615 | goto free_adj; | ||
| 4616 | } else if (dev_list == &dev->adj_list.upper) { | ||
| 4617 | sprintf(linkname, "upper_%s", adj_dev->name); | ||
| 4618 | ret = sysfs_create_link(&(dev->dev.kobj), | ||
| 4619 | &(adj_dev->dev.kobj), linkname); | ||
| 4620 | if (ret) | ||
| 4621 | goto free_adj; | ||
| 4547 | } | 4622 | } |
| 4548 | 4623 | ||
| 4549 | /* Ensure that master upper link is always the first item in list. */ | 4624 | /* Ensure that master link is always the first item in list. */ |
| 4550 | if (master) | 4625 | if (master) { |
| 4551 | list_add_rcu(&adj->list, &dev->upper_dev_list); | 4626 | ret = sysfs_create_link(&(dev->dev.kobj), |
| 4552 | else | 4627 | &(adj_dev->dev.kobj), "master"); |
| 4553 | list_add_tail_rcu(&adj->list, &dev->upper_dev_list); | 4628 | if (ret) |
| 4629 | goto remove_symlinks; | ||
| 4630 | |||
| 4631 | list_add_rcu(&adj->list, dev_list); | ||
| 4632 | } else { | ||
| 4633 | list_add_tail_rcu(&adj->list, dev_list); | ||
| 4634 | } | ||
| 4554 | 4635 | ||
| 4555 | return 0; | 4636 | return 0; |
| 4556 | } | ||
| 4557 | 4637 | ||
| 4558 | static inline int __netdev_upper_dev_insert(struct net_device *dev, | 4638 | remove_symlinks: |
| 4559 | struct net_device *udev, | 4639 | if (dev_list == &dev->adj_list.lower) { |
| 4560 | bool master, bool neighbour) | 4640 | sprintf(linkname, "lower_%s", adj_dev->name); |
| 4561 | { | 4641 | sysfs_remove_link(&(dev->dev.kobj), linkname); |
| 4562 | return __netdev_adjacent_dev_insert(dev, udev, neighbour, master, | 4642 | } else if (dev_list == &dev->adj_list.upper) { |
| 4563 | true); | 4643 | sprintf(linkname, "upper_%s", adj_dev->name); |
| 4564 | } | 4644 | sysfs_remove_link(&(dev->dev.kobj), linkname); |
| 4645 | } | ||
| 4565 | 4646 | ||
| 4566 | static inline int __netdev_lower_dev_insert(struct net_device *dev, | 4647 | free_adj: |
| 4567 | struct net_device *ldev, | 4648 | kfree(adj); |
| 4568 | bool neighbour) | 4649 | |
| 4569 | { | 4650 | return ret; |
| 4570 | return __netdev_adjacent_dev_insert(dev, ldev, neighbour, false, | ||
| 4571 | false); | ||
| 4572 | } | 4651 | } |
| 4573 | 4652 | ||
| 4574 | void __netdev_adjacent_dev_remove(struct net_device *dev, | 4653 | void __netdev_adjacent_dev_remove(struct net_device *dev, |
| 4575 | struct net_device *adj_dev, bool upper) | 4654 | struct net_device *adj_dev, |
| 4655 | struct list_head *dev_list) | ||
| 4576 | { | 4656 | { |
| 4577 | struct netdev_adjacent *adj; | 4657 | struct netdev_adjacent *adj; |
| 4658 | char linkname[IFNAMSIZ+7]; | ||
| 4578 | 4659 | ||
| 4579 | if (upper) | 4660 | adj = __netdev_find_adj(dev, adj_dev, dev_list); |
| 4580 | adj = __netdev_find_upper(dev, adj_dev); | ||
| 4581 | else | ||
| 4582 | adj = __netdev_find_lower(dev, adj_dev); | ||
| 4583 | 4661 | ||
| 4584 | if (!adj) | 4662 | if (!adj) { |
| 4663 | pr_err("tried to remove device %s from %s\n", | ||
| 4664 | dev->name, adj_dev->name); | ||
| 4585 | BUG(); | 4665 | BUG(); |
| 4666 | } | ||
| 4586 | 4667 | ||
| 4587 | if (adj->ref_nr > 1) { | 4668 | if (adj->ref_nr > 1) { |
| 4669 | pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name, | ||
| 4670 | adj->ref_nr-1); | ||
| 4588 | adj->ref_nr--; | 4671 | adj->ref_nr--; |
| 4589 | return; | 4672 | return; |
| 4590 | } | 4673 | } |
| 4591 | 4674 | ||
| 4675 | if (adj->master) | ||
| 4676 | sysfs_remove_link(&(dev->dev.kobj), "master"); | ||
| 4677 | |||
| 4678 | if (dev_list == &dev->adj_list.lower) { | ||
| 4679 | sprintf(linkname, "lower_%s", adj_dev->name); | ||
| 4680 | sysfs_remove_link(&(dev->dev.kobj), linkname); | ||
| 4681 | } else if (dev_list == &dev->adj_list.upper) { | ||
| 4682 | sprintf(linkname, "upper_%s", adj_dev->name); | ||
| 4683 | sysfs_remove_link(&(dev->dev.kobj), linkname); | ||
| 4684 | } | ||
| 4685 | |||
| 4592 | list_del_rcu(&adj->list); | 4686 | list_del_rcu(&adj->list); |
| 4593 | pr_debug("dev_put for %s, because of %s link removed from %s to %s\n", | 4687 | pr_debug("dev_put for %s, because link removed from %s to %s\n", |
| 4594 | adj_dev->name, upper ? "upper" : "lower", dev->name, | 4688 | adj_dev->name, dev->name, adj_dev->name); |
| 4595 | adj_dev->name); | ||
| 4596 | dev_put(adj_dev); | 4689 | dev_put(adj_dev); |
| 4597 | kfree_rcu(adj, rcu); | 4690 | kfree_rcu(adj, rcu); |
| 4598 | } | 4691 | } |
| 4599 | 4692 | ||
| 4600 | static inline void __netdev_upper_dev_remove(struct net_device *dev, | 4693 | int __netdev_adjacent_dev_link_lists(struct net_device *dev, |
| 4601 | struct net_device *udev) | 4694 | struct net_device *upper_dev, |
| 4602 | { | 4695 | struct list_head *up_list, |
| 4603 | return __netdev_adjacent_dev_remove(dev, udev, true); | 4696 | struct list_head *down_list, |
| 4604 | } | 4697 | void *private, bool master) |
| 4605 | |||
| 4606 | static inline void __netdev_lower_dev_remove(struct net_device *dev, | ||
| 4607 | struct net_device *ldev) | ||
| 4608 | { | ||
| 4609 | return __netdev_adjacent_dev_remove(dev, ldev, false); | ||
| 4610 | } | ||
| 4611 | |||
| 4612 | int __netdev_adjacent_dev_insert_link(struct net_device *dev, | ||
| 4613 | struct net_device *upper_dev, | ||
| 4614 | bool master, bool neighbour) | ||
| 4615 | { | 4698 | { |
| 4616 | int ret; | 4699 | int ret; |
| 4617 | 4700 | ||
| 4618 | ret = __netdev_upper_dev_insert(dev, upper_dev, master, neighbour); | 4701 | ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private, |
| 4702 | master); | ||
| 4619 | if (ret) | 4703 | if (ret) |
| 4620 | return ret; | 4704 | return ret; |
| 4621 | 4705 | ||
| 4622 | ret = __netdev_lower_dev_insert(upper_dev, dev, neighbour); | 4706 | ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private, |
| 4707 | false); | ||
| 4623 | if (ret) { | 4708 | if (ret) { |
| 4624 | __netdev_upper_dev_remove(dev, upper_dev); | 4709 | __netdev_adjacent_dev_remove(dev, upper_dev, up_list); |
| 4625 | return ret; | 4710 | return ret; |
| 4626 | } | 4711 | } |
| 4627 | 4712 | ||
| 4628 | return 0; | 4713 | return 0; |
| 4629 | } | 4714 | } |
| 4630 | 4715 | ||
| 4631 | static inline int __netdev_adjacent_dev_link(struct net_device *dev, | 4716 | int __netdev_adjacent_dev_link(struct net_device *dev, |
| 4632 | struct net_device *udev) | 4717 | struct net_device *upper_dev) |
| 4633 | { | 4718 | { |
| 4634 | return __netdev_adjacent_dev_insert_link(dev, udev, false, false); | 4719 | return __netdev_adjacent_dev_link_lists(dev, upper_dev, |
| 4720 | &dev->all_adj_list.upper, | ||
| 4721 | &upper_dev->all_adj_list.lower, | ||
| 4722 | NULL, false); | ||
| 4635 | } | 4723 | } |
| 4636 | 4724 | ||
| 4637 | static inline int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, | 4725 | void __netdev_adjacent_dev_unlink_lists(struct net_device *dev, |
| 4638 | struct net_device *udev, | 4726 | struct net_device *upper_dev, |
| 4639 | bool master) | 4727 | struct list_head *up_list, |
| 4728 | struct list_head *down_list) | ||
| 4640 | { | 4729 | { |
| 4641 | return __netdev_adjacent_dev_insert_link(dev, udev, master, true); | 4730 | __netdev_adjacent_dev_remove(dev, upper_dev, up_list); |
| 4731 | __netdev_adjacent_dev_remove(upper_dev, dev, down_list); | ||
| 4642 | } | 4732 | } |
| 4643 | 4733 | ||
| 4644 | void __netdev_adjacent_dev_unlink(struct net_device *dev, | 4734 | void __netdev_adjacent_dev_unlink(struct net_device *dev, |
| 4645 | struct net_device *upper_dev) | 4735 | struct net_device *upper_dev) |
| 4646 | { | 4736 | { |
| 4647 | __netdev_upper_dev_remove(dev, upper_dev); | 4737 | __netdev_adjacent_dev_unlink_lists(dev, upper_dev, |
| 4648 | __netdev_lower_dev_remove(upper_dev, dev); | 4738 | &dev->all_adj_list.upper, |
| 4739 | &upper_dev->all_adj_list.lower); | ||
| 4740 | } | ||
| 4741 | |||
| 4742 | int __netdev_adjacent_dev_link_neighbour(struct net_device *dev, | ||
| 4743 | struct net_device *upper_dev, | ||
| 4744 | void *private, bool master) | ||
| 4745 | { | ||
| 4746 | int ret = __netdev_adjacent_dev_link(dev, upper_dev); | ||
| 4747 | |||
| 4748 | if (ret) | ||
| 4749 | return ret; | ||
| 4750 | |||
| 4751 | ret = __netdev_adjacent_dev_link_lists(dev, upper_dev, | ||
| 4752 | &dev->adj_list.upper, | ||
| 4753 | &upper_dev->adj_list.lower, | ||
| 4754 | private, master); | ||
| 4755 | if (ret) { | ||
| 4756 | __netdev_adjacent_dev_unlink(dev, upper_dev); | ||
| 4757 | return ret; | ||
| 4758 | } | ||
| 4759 | |||
| 4760 | return 0; | ||
| 4649 | } | 4761 | } |
| 4650 | 4762 | ||
| 4763 | void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, | ||
| 4764 | struct net_device *upper_dev) | ||
| 4765 | { | ||
| 4766 | __netdev_adjacent_dev_unlink(dev, upper_dev); | ||
| 4767 | __netdev_adjacent_dev_unlink_lists(dev, upper_dev, | ||
| 4768 | &dev->adj_list.upper, | ||
| 4769 | &upper_dev->adj_list.lower); | ||
| 4770 | } | ||
| 4651 | 4771 | ||
| 4652 | static int __netdev_upper_dev_link(struct net_device *dev, | 4772 | static int __netdev_upper_dev_link(struct net_device *dev, |
| 4653 | struct net_device *upper_dev, bool master) | 4773 | struct net_device *upper_dev, bool master, |
| 4774 | void *private) | ||
| 4654 | { | 4775 | { |
| 4655 | struct netdev_adjacent *i, *j, *to_i, *to_j; | 4776 | struct netdev_adjacent *i, *j, *to_i, *to_j; |
| 4656 | int ret = 0; | 4777 | int ret = 0; |
| @@ -4661,26 +4782,29 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
| 4661 | return -EBUSY; | 4782 | return -EBUSY; |
| 4662 | 4783 | ||
| 4663 | /* To prevent loops, check if dev is not upper device to upper_dev. */ | 4784 | /* To prevent loops, check if dev is not upper device to upper_dev. */ |
| 4664 | if (__netdev_find_upper(upper_dev, dev)) | 4785 | if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper)) |
| 4665 | return -EBUSY; | 4786 | return -EBUSY; |
| 4666 | 4787 | ||
| 4667 | if (__netdev_find_upper(dev, upper_dev)) | 4788 | if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper)) |
| 4668 | return -EEXIST; | 4789 | return -EEXIST; |
| 4669 | 4790 | ||
| 4670 | if (master && netdev_master_upper_dev_get(dev)) | 4791 | if (master && netdev_master_upper_dev_get(dev)) |
| 4671 | return -EBUSY; | 4792 | return -EBUSY; |
| 4672 | 4793 | ||
| 4673 | ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master); | 4794 | ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private, |
| 4795 | master); | ||
| 4674 | if (ret) | 4796 | if (ret) |
| 4675 | return ret; | 4797 | return ret; |
| 4676 | 4798 | ||
| 4677 | /* Now that we linked these devs, make all the upper_dev's | 4799 | /* Now that we linked these devs, make all the upper_dev's |
| 4678 | * upper_dev_list visible to every dev's lower_dev_list and vice | 4800 | * all_adj_list.upper visible to every dev's all_adj_list.lower an |
| 4679 | * versa, and don't forget the devices itself. All of these | 4801 | * versa, and don't forget the devices itself. All of these |
| 4680 | * links are non-neighbours. | 4802 | * links are non-neighbours. |
| 4681 | */ | 4803 | */ |
| 4682 | list_for_each_entry(i, &dev->lower_dev_list, list) { | 4804 | list_for_each_entry(i, &dev->all_adj_list.lower, list) { |
| 4683 | list_for_each_entry(j, &upper_dev->upper_dev_list, list) { | 4805 | list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { |
| 4806 | pr_debug("Interlinking %s with %s, non-neighbour\n", | ||
| 4807 | i->dev->name, j->dev->name); | ||
| 4684 | ret = __netdev_adjacent_dev_link(i->dev, j->dev); | 4808 | ret = __netdev_adjacent_dev_link(i->dev, j->dev); |
| 4685 | if (ret) | 4809 | if (ret) |
| 4686 | goto rollback_mesh; | 4810 | goto rollback_mesh; |
| @@ -4688,14 +4812,18 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
| 4688 | } | 4812 | } |
| 4689 | 4813 | ||
| 4690 | /* add dev to every upper_dev's upper device */ | 4814 | /* add dev to every upper_dev's upper device */ |
| 4691 | list_for_each_entry(i, &upper_dev->upper_dev_list, list) { | 4815 | list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { |
| 4816 | pr_debug("linking %s's upper device %s with %s\n", | ||
| 4817 | upper_dev->name, i->dev->name, dev->name); | ||
| 4692 | ret = __netdev_adjacent_dev_link(dev, i->dev); | 4818 | ret = __netdev_adjacent_dev_link(dev, i->dev); |
| 4693 | if (ret) | 4819 | if (ret) |
| 4694 | goto rollback_upper_mesh; | 4820 | goto rollback_upper_mesh; |
| 4695 | } | 4821 | } |
| 4696 | 4822 | ||
| 4697 | /* add upper_dev to every dev's lower device */ | 4823 | /* add upper_dev to every dev's lower device */ |
| 4698 | list_for_each_entry(i, &dev->lower_dev_list, list) { | 4824 | list_for_each_entry(i, &dev->all_adj_list.lower, list) { |
| 4825 | pr_debug("linking %s's lower device %s with %s\n", dev->name, | ||
| 4826 | i->dev->name, upper_dev->name); | ||
| 4699 | ret = __netdev_adjacent_dev_link(i->dev, upper_dev); | 4827 | ret = __netdev_adjacent_dev_link(i->dev, upper_dev); |
| 4700 | if (ret) | 4828 | if (ret) |
| 4701 | goto rollback_lower_mesh; | 4829 | goto rollback_lower_mesh; |
| @@ -4706,7 +4834,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, | |||
| 4706 | 4834 | ||
| 4707 | rollback_lower_mesh: | 4835 | rollback_lower_mesh: |
| 4708 | to_i = i; | 4836 | to_i = i; |
| 4709 | list_for_each_entry(i, &dev->lower_dev_list, list) { | 4837 | list_for_each_entry(i, &dev->all_adj_list.lower, list) { |
| 4710 | if (i == to_i) | 4838 | if (i == to_i) |
| 4711 | break; | 4839 | break; |
| 4712 | __netdev_adjacent_dev_unlink(i->dev, upper_dev); | 4840 | __netdev_adjacent_dev_unlink(i->dev, upper_dev); |
| @@ -4716,7 +4844,7 @@ rollback_lower_mesh: | |||
| 4716 | 4844 | ||
| 4717 | rollback_upper_mesh: | 4845 | rollback_upper_mesh: |
| 4718 | to_i = i; | 4846 | to_i = i; |
| 4719 | list_for_each_entry(i, &upper_dev->upper_dev_list, list) { | 4847 | list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) { |
| 4720 | if (i == to_i) | 4848 | if (i == to_i) |
| 4721 | break; | 4849 | break; |
| 4722 | __netdev_adjacent_dev_unlink(dev, i->dev); | 4850 | __netdev_adjacent_dev_unlink(dev, i->dev); |
| @@ -4727,8 +4855,8 @@ rollback_upper_mesh: | |||
| 4727 | rollback_mesh: | 4855 | rollback_mesh: |
| 4728 | to_i = i; | 4856 | to_i = i; |
| 4729 | to_j = j; | 4857 | to_j = j; |
| 4730 | list_for_each_entry(i, &dev->lower_dev_list, list) { | 4858 | list_for_each_entry(i, &dev->all_adj_list.lower, list) { |
| 4731 | list_for_each_entry(j, &upper_dev->upper_dev_list, list) { | 4859 | list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) { |
| 4732 | if (i == to_i && j == to_j) | 4860 | if (i == to_i && j == to_j) |
| 4733 | break; | 4861 | break; |
| 4734 | __netdev_adjacent_dev_unlink(i->dev, j->dev); | 4862 | __netdev_adjacent_dev_unlink(i->dev, j->dev); |
| @@ -4737,7 +4865,7 @@ rollback_mesh: | |||
| 4737 | break; | 4865 | break; |
| 4738 | } | 4866 | } |
| 4739 | 4867 | ||
| 4740 | __netdev_adjacent_dev_unlink(dev, upper_dev); | 4868 | __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); |
| 4741 | 4869 | ||
| 4742 | return ret; | 4870 | return ret; |
| 4743 | } | 4871 | } |
| @@ -4755,7 +4883,7 @@ rollback_mesh: | |||
| 4755 | int netdev_upper_dev_link(struct net_device *dev, | 4883 | int netdev_upper_dev_link(struct net_device *dev, |
| 4756 | struct net_device *upper_dev) | 4884 | struct net_device *upper_dev) |
| 4757 | { | 4885 | { |
| 4758 | return __netdev_upper_dev_link(dev, upper_dev, false); | 4886 | return __netdev_upper_dev_link(dev, upper_dev, false, NULL); |
| 4759 | } | 4887 | } |
| 4760 | EXPORT_SYMBOL(netdev_upper_dev_link); | 4888 | EXPORT_SYMBOL(netdev_upper_dev_link); |
| 4761 | 4889 | ||
| @@ -4773,10 +4901,18 @@ EXPORT_SYMBOL(netdev_upper_dev_link); | |||
| 4773 | int netdev_master_upper_dev_link(struct net_device *dev, | 4901 | int netdev_master_upper_dev_link(struct net_device *dev, |
| 4774 | struct net_device *upper_dev) | 4902 | struct net_device *upper_dev) |
| 4775 | { | 4903 | { |
| 4776 | return __netdev_upper_dev_link(dev, upper_dev, true); | 4904 | return __netdev_upper_dev_link(dev, upper_dev, true, NULL); |
| 4777 | } | 4905 | } |
| 4778 | EXPORT_SYMBOL(netdev_master_upper_dev_link); | 4906 | EXPORT_SYMBOL(netdev_master_upper_dev_link); |
| 4779 | 4907 | ||
| 4908 | int netdev_master_upper_dev_link_private(struct net_device *dev, | ||
| 4909 | struct net_device *upper_dev, | ||
| 4910 | void *private) | ||
| 4911 | { | ||
| 4912 | return __netdev_upper_dev_link(dev, upper_dev, true, private); | ||
| 4913 | } | ||
| 4914 | EXPORT_SYMBOL(netdev_master_upper_dev_link_private); | ||
| 4915 | |||
| 4780 | /** | 4916 | /** |
| 4781 | * netdev_upper_dev_unlink - Removes a link to upper device | 4917 | * netdev_upper_dev_unlink - Removes a link to upper device |
| 4782 | * @dev: device | 4918 | * @dev: device |
| @@ -4791,29 +4927,59 @@ void netdev_upper_dev_unlink(struct net_device *dev, | |||
| 4791 | struct netdev_adjacent *i, *j; | 4927 | struct netdev_adjacent *i, *j; |
| 4792 | ASSERT_RTNL(); | 4928 | ASSERT_RTNL(); |
| 4793 | 4929 | ||
| 4794 | __netdev_adjacent_dev_unlink(dev, upper_dev); | 4930 | __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); |
| 4795 | 4931 | ||
| 4796 | /* Here is the tricky part. We must remove all dev's lower | 4932 | /* Here is the tricky part. We must remove all dev's lower |
| 4797 | * devices from all upper_dev's upper devices and vice | 4933 | * devices from all upper_dev's upper devices and vice |
| 4798 | * versa, to maintain the graph relationship. | 4934 | * versa, to maintain the graph relationship. |
| 4799 | */ | 4935 | */ |
| 4800 | list_for_each_entry(i, &dev->lower_dev_list, list) | 4936 | list_for_each_entry(i, &dev->all_adj_list.lower, list) |
| 4801 | list_for_each_entry(j, &upper_dev->upper_dev_list, list) | 4937 | list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) |
| 4802 | __netdev_adjacent_dev_unlink(i->dev, j->dev); | 4938 | __netdev_adjacent_dev_unlink(i->dev, j->dev); |
| 4803 | 4939 | ||
| 4804 | /* remove also the devices itself from lower/upper device | 4940 | /* remove also the devices itself from lower/upper device |
| 4805 | * list | 4941 | * list |
| 4806 | */ | 4942 | */ |
| 4807 | list_for_each_entry(i, &dev->lower_dev_list, list) | 4943 | list_for_each_entry(i, &dev->all_adj_list.lower, list) |
| 4808 | __netdev_adjacent_dev_unlink(i->dev, upper_dev); | 4944 | __netdev_adjacent_dev_unlink(i->dev, upper_dev); |
| 4809 | 4945 | ||
| 4810 | list_for_each_entry(i, &upper_dev->upper_dev_list, list) | 4946 | list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) |
| 4811 | __netdev_adjacent_dev_unlink(dev, i->dev); | 4947 | __netdev_adjacent_dev_unlink(dev, i->dev); |
| 4812 | 4948 | ||
| 4813 | call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); | 4949 | call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); |
| 4814 | } | 4950 | } |
| 4815 | EXPORT_SYMBOL(netdev_upper_dev_unlink); | 4951 | EXPORT_SYMBOL(netdev_upper_dev_unlink); |
| 4816 | 4952 | ||
| 4953 | void *netdev_lower_dev_get_private_rcu(struct net_device *dev, | ||
| 4954 | struct net_device *lower_dev) | ||
| 4955 | { | ||
| 4956 | struct netdev_adjacent *lower; | ||
| 4957 | |||
| 4958 | if (!lower_dev) | ||
| 4959 | return NULL; | ||
| 4960 | lower = __netdev_find_adj_rcu(dev, lower_dev, &dev->adj_list.lower); | ||
| 4961 | if (!lower) | ||
| 4962 | return NULL; | ||
| 4963 | |||
| 4964 | return lower->private; | ||
| 4965 | } | ||
| 4966 | EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu); | ||
| 4967 | |||
| 4968 | void *netdev_lower_dev_get_private(struct net_device *dev, | ||
| 4969 | struct net_device *lower_dev) | ||
| 4970 | { | ||
| 4971 | struct netdev_adjacent *lower; | ||
| 4972 | |||
| 4973 | if (!lower_dev) | ||
| 4974 | return NULL; | ||
| 4975 | lower = __netdev_find_adj(dev, lower_dev, &dev->adj_list.lower); | ||
| 4976 | if (!lower) | ||
| 4977 | return NULL; | ||
| 4978 | |||
| 4979 | return lower->private; | ||
| 4980 | } | ||
| 4981 | EXPORT_SYMBOL(netdev_lower_dev_get_private); | ||
| 4982 | |||
| 4817 | static void dev_change_rx_flags(struct net_device *dev, int flags) | 4983 | static void dev_change_rx_flags(struct net_device *dev, int flags) |
| 4818 | { | 4984 | { |
| 4819 | const struct net_device_ops *ops = dev->netdev_ops; | 4985 | const struct net_device_ops *ops = dev->netdev_ops; |
| @@ -6069,8 +6235,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | |||
| 6069 | INIT_LIST_HEAD(&dev->napi_list); | 6235 | INIT_LIST_HEAD(&dev->napi_list); |
| 6070 | INIT_LIST_HEAD(&dev->unreg_list); | 6236 | INIT_LIST_HEAD(&dev->unreg_list); |
| 6071 | INIT_LIST_HEAD(&dev->link_watch_list); | 6237 | INIT_LIST_HEAD(&dev->link_watch_list); |
| 6072 | INIT_LIST_HEAD(&dev->upper_dev_list); | 6238 | INIT_LIST_HEAD(&dev->adj_list.upper); |
| 6073 | INIT_LIST_HEAD(&dev->lower_dev_list); | 6239 | INIT_LIST_HEAD(&dev->adj_list.lower); |
| 6240 | INIT_LIST_HEAD(&dev->all_adj_list.upper); | ||
| 6241 | INIT_LIST_HEAD(&dev->all_adj_list.lower); | ||
| 6074 | dev->priv_flags = IFF_XMIT_DST_RELEASE; | 6242 | dev->priv_flags = IFF_XMIT_DST_RELEASE; |
| 6075 | setup(dev); | 6243 | setup(dev); |
| 6076 | 6244 | ||
