diff options
author | Jiri Pirko <jpirko@redhat.com> | 2009-05-22 19:22:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-30 01:12:32 -0400 |
commit | ccffad25b5136958d4769ed6de5e87992dd9c65c (patch) | |
tree | cd5f36fe67f4deeae23d76436f7a032a201cba44 /net/core | |
parent | ae63e808f508c38fe65e23a1480c85d5bd00ecbd (diff) |
net: convert unicast addr list
This patch converts unicast address list to standard list_head using
previously introduced struct netdev_hw_addr. It also relaxes the
locking. Original spinlock (still used for multicast addresses) is not
needed and is no longer used for a protection of this list. All
reading and writing takes place under rtnl (with no changes).
I also removed a possibility to specify the length of the address
while adding or deleting unicast address. It's always dev->addr_len.
The convertion touched especially e1000 and ixgbe codes when the
change is not so trivial.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
drivers/net/bnx2.c | 13 +--
drivers/net/e1000/e1000_main.c | 24 +++--
drivers/net/ixgbe/ixgbe_common.c | 14 ++--
drivers/net/ixgbe/ixgbe_common.h | 4 +-
drivers/net/ixgbe/ixgbe_main.c | 6 +-
drivers/net/ixgbe/ixgbe_type.h | 4 +-
drivers/net/macvlan.c | 11 +-
drivers/net/mv643xx_eth.c | 11 +-
drivers/net/niu.c | 7 +-
drivers/net/virtio_net.c | 7 +-
drivers/s390/net/qeth_l2_main.c | 6 +-
drivers/scsi/fcoe/fcoe.c | 16 ++--
include/linux/netdevice.h | 18 ++--
net/8021q/vlan.c | 4 +-
net/8021q/vlan_dev.c | 10 +-
net/core/dev.c | 195 +++++++++++++++++++++++++++-----------
net/dsa/slave.c | 10 +-
net/packet/af_packet.c | 4 +-
18 files changed, 227 insertions(+), 137 deletions(-)
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 195 |
1 files changed, 138 insertions, 57 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 32ceee17896e..e2fcc5f10177 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3473,8 +3473,9 @@ void dev_set_rx_mode(struct net_device *dev) | |||
3473 | 3473 | ||
3474 | /* hw addresses list handling functions */ | 3474 | /* hw addresses list handling functions */ |
3475 | 3475 | ||
3476 | static int __hw_addr_add(struct list_head *list, unsigned char *addr, | 3476 | static int __hw_addr_add(struct list_head *list, int *delta, |
3477 | int addr_len, unsigned char addr_type) | 3477 | unsigned char *addr, int addr_len, |
3478 | unsigned char addr_type) | ||
3478 | { | 3479 | { |
3479 | struct netdev_hw_addr *ha; | 3480 | struct netdev_hw_addr *ha; |
3480 | int alloc_size; | 3481 | int alloc_size; |
@@ -3482,6 +3483,15 @@ static int __hw_addr_add(struct list_head *list, unsigned char *addr, | |||
3482 | if (addr_len > MAX_ADDR_LEN) | 3483 | if (addr_len > MAX_ADDR_LEN) |
3483 | return -EINVAL; | 3484 | return -EINVAL; |
3484 | 3485 | ||
3486 | list_for_each_entry(ha, list, list) { | ||
3487 | if (!memcmp(ha->addr, addr, addr_len) && | ||
3488 | ha->type == addr_type) { | ||
3489 | ha->refcount++; | ||
3490 | return 0; | ||
3491 | } | ||
3492 | } | ||
3493 | |||
3494 | |||
3485 | alloc_size = sizeof(*ha); | 3495 | alloc_size = sizeof(*ha); |
3486 | if (alloc_size < L1_CACHE_BYTES) | 3496 | if (alloc_size < L1_CACHE_BYTES) |
3487 | alloc_size = L1_CACHE_BYTES; | 3497 | alloc_size = L1_CACHE_BYTES; |
@@ -3490,7 +3500,11 @@ static int __hw_addr_add(struct list_head *list, unsigned char *addr, | |||
3490 | return -ENOMEM; | 3500 | return -ENOMEM; |
3491 | memcpy(ha->addr, addr, addr_len); | 3501 | memcpy(ha->addr, addr, addr_len); |
3492 | ha->type = addr_type; | 3502 | ha->type = addr_type; |
3503 | ha->refcount = 1; | ||
3504 | ha->synced = false; | ||
3493 | list_add_tail_rcu(&ha->list, list); | 3505 | list_add_tail_rcu(&ha->list, list); |
3506 | if (delta) | ||
3507 | (*delta)++; | ||
3494 | return 0; | 3508 | return 0; |
3495 | } | 3509 | } |
3496 | 3510 | ||
@@ -3502,29 +3516,30 @@ static void ha_rcu_free(struct rcu_head *head) | |||
3502 | kfree(ha); | 3516 | kfree(ha); |
3503 | } | 3517 | } |
3504 | 3518 | ||
3505 | static int __hw_addr_del_ii(struct list_head *list, unsigned char *addr, | 3519 | static int __hw_addr_del(struct list_head *list, int *delta, |
3506 | int addr_len, unsigned char addr_type, | 3520 | unsigned char *addr, int addr_len, |
3507 | int ignore_index) | 3521 | unsigned char addr_type) |
3508 | { | 3522 | { |
3509 | struct netdev_hw_addr *ha; | 3523 | struct netdev_hw_addr *ha; |
3510 | int i = 0; | ||
3511 | 3524 | ||
3512 | list_for_each_entry(ha, list, list) { | 3525 | list_for_each_entry(ha, list, list) { |
3513 | if (i++ != ignore_index && | 3526 | if (!memcmp(ha->addr, addr, addr_len) && |
3514 | !memcmp(ha->addr, addr, addr_len) && | ||
3515 | (ha->type == addr_type || !addr_type)) { | 3527 | (ha->type == addr_type || !addr_type)) { |
3528 | if (--ha->refcount) | ||
3529 | return 0; | ||
3516 | list_del_rcu(&ha->list); | 3530 | list_del_rcu(&ha->list); |
3517 | call_rcu(&ha->rcu_head, ha_rcu_free); | 3531 | call_rcu(&ha->rcu_head, ha_rcu_free); |
3532 | if (delta) | ||
3533 | (*delta)--; | ||
3518 | return 0; | 3534 | return 0; |
3519 | } | 3535 | } |
3520 | } | 3536 | } |
3521 | return -ENOENT; | 3537 | return -ENOENT; |
3522 | } | 3538 | } |
3523 | 3539 | ||
3524 | static int __hw_addr_add_multiple_ii(struct list_head *to_list, | 3540 | static int __hw_addr_add_multiple(struct list_head *to_list, int *to_delta, |
3525 | struct list_head *from_list, | 3541 | struct list_head *from_list, int addr_len, |
3526 | int addr_len, unsigned char addr_type, | 3542 | unsigned char addr_type) |
3527 | int ignore_index) | ||
3528 | { | 3543 | { |
3529 | int err; | 3544 | int err; |
3530 | struct netdev_hw_addr *ha, *ha2; | 3545 | struct netdev_hw_addr *ha, *ha2; |
@@ -3532,7 +3547,8 @@ static int __hw_addr_add_multiple_ii(struct list_head *to_list, | |||
3532 | 3547 | ||
3533 | list_for_each_entry(ha, from_list, list) { | 3548 | list_for_each_entry(ha, from_list, list) { |
3534 | type = addr_type ? addr_type : ha->type; | 3549 | type = addr_type ? addr_type : ha->type; |
3535 | err = __hw_addr_add(to_list, ha->addr, addr_len, type); | 3550 | err = __hw_addr_add(to_list, to_delta, ha->addr, |
3551 | addr_len, type); | ||
3536 | if (err) | 3552 | if (err) |
3537 | goto unroll; | 3553 | goto unroll; |
3538 | } | 3554 | } |
@@ -3543,27 +3559,69 @@ unroll: | |||
3543 | if (ha2 == ha) | 3559 | if (ha2 == ha) |
3544 | break; | 3560 | break; |
3545 | type = addr_type ? addr_type : ha2->type; | 3561 | type = addr_type ? addr_type : ha2->type; |
3546 | __hw_addr_del_ii(to_list, ha2->addr, addr_len, type, | 3562 | __hw_addr_del(to_list, to_delta, ha2->addr, |
3547 | ignore_index); | 3563 | addr_len, type); |
3548 | } | 3564 | } |
3549 | return err; | 3565 | return err; |
3550 | } | 3566 | } |
3551 | 3567 | ||
3552 | static void __hw_addr_del_multiple_ii(struct list_head *to_list, | 3568 | static void __hw_addr_del_multiple(struct list_head *to_list, int *to_delta, |
3553 | struct list_head *from_list, | 3569 | struct list_head *from_list, int addr_len, |
3554 | int addr_len, unsigned char addr_type, | 3570 | unsigned char addr_type) |
3555 | int ignore_index) | ||
3556 | { | 3571 | { |
3557 | struct netdev_hw_addr *ha; | 3572 | struct netdev_hw_addr *ha; |
3558 | unsigned char type; | 3573 | unsigned char type; |
3559 | 3574 | ||
3560 | list_for_each_entry(ha, from_list, list) { | 3575 | list_for_each_entry(ha, from_list, list) { |
3561 | type = addr_type ? addr_type : ha->type; | 3576 | type = addr_type ? addr_type : ha->type; |
3562 | __hw_addr_del_ii(to_list, ha->addr, addr_len, addr_type, | 3577 | __hw_addr_del(to_list, to_delta, ha->addr, |
3563 | ignore_index); | 3578 | addr_len, addr_type); |
3579 | } | ||
3580 | } | ||
3581 | |||
3582 | static int __hw_addr_sync(struct list_head *to_list, int *to_delta, | ||
3583 | struct list_head *from_list, int *from_delta, | ||
3584 | int addr_len) | ||
3585 | { | ||
3586 | int err = 0; | ||
3587 | struct netdev_hw_addr *ha, *tmp; | ||
3588 | |||
3589 | list_for_each_entry_safe(ha, tmp, from_list, list) { | ||
3590 | if (!ha->synced) { | ||
3591 | err = __hw_addr_add(to_list, to_delta, ha->addr, | ||
3592 | addr_len, ha->type); | ||
3593 | if (err) | ||
3594 | break; | ||
3595 | ha->synced = true; | ||
3596 | ha->refcount++; | ||
3597 | } else if (ha->refcount == 1) { | ||
3598 | __hw_addr_del(to_list, to_delta, ha->addr, | ||
3599 | addr_len, ha->type); | ||
3600 | __hw_addr_del(from_list, from_delta, ha->addr, | ||
3601 | addr_len, ha->type); | ||
3602 | } | ||
3564 | } | 3603 | } |
3604 | return err; | ||
3565 | } | 3605 | } |
3566 | 3606 | ||
3607 | static void __hw_addr_unsync(struct list_head *to_list, int *to_delta, | ||
3608 | struct list_head *from_list, int *from_delta, | ||
3609 | int addr_len) | ||
3610 | { | ||
3611 | struct netdev_hw_addr *ha, *tmp; | ||
3612 | |||
3613 | list_for_each_entry_safe(ha, tmp, from_list, list) { | ||
3614 | if (ha->synced) { | ||
3615 | __hw_addr_del(to_list, to_delta, ha->addr, | ||
3616 | addr_len, ha->type); | ||
3617 | ha->synced = false; | ||
3618 | __hw_addr_del(from_list, from_delta, ha->addr, | ||
3619 | addr_len, ha->type); | ||
3620 | } | ||
3621 | } | ||
3622 | } | ||
3623 | |||
3624 | |||
3567 | static void __hw_addr_flush(struct list_head *list) | 3625 | static void __hw_addr_flush(struct list_head *list) |
3568 | { | 3626 | { |
3569 | struct netdev_hw_addr *ha, *tmp; | 3627 | struct netdev_hw_addr *ha, *tmp; |
@@ -3594,7 +3652,7 @@ static int dev_addr_init(struct net_device *dev) | |||
3594 | 3652 | ||
3595 | INIT_LIST_HEAD(&dev->dev_addr_list); | 3653 | INIT_LIST_HEAD(&dev->dev_addr_list); |
3596 | memset(addr, 0, sizeof(*addr)); | 3654 | memset(addr, 0, sizeof(*addr)); |
3597 | err = __hw_addr_add(&dev->dev_addr_list, addr, sizeof(*addr), | 3655 | err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(*addr), |
3598 | NETDEV_HW_ADDR_T_LAN); | 3656 | NETDEV_HW_ADDR_T_LAN); |
3599 | if (!err) { | 3657 | if (!err) { |
3600 | /* | 3658 | /* |
@@ -3626,7 +3684,7 @@ int dev_addr_add(struct net_device *dev, unsigned char *addr, | |||
3626 | 3684 | ||
3627 | ASSERT_RTNL(); | 3685 | ASSERT_RTNL(); |
3628 | 3686 | ||
3629 | err = __hw_addr_add(&dev->dev_addr_list, addr, dev->addr_len, | 3687 | err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, dev->addr_len, |
3630 | addr_type); | 3688 | addr_type); |
3631 | if (!err) | 3689 | if (!err) |
3632 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 3690 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
@@ -3649,11 +3707,20 @@ int dev_addr_del(struct net_device *dev, unsigned char *addr, | |||
3649 | unsigned char addr_type) | 3707 | unsigned char addr_type) |
3650 | { | 3708 | { |
3651 | int err; | 3709 | int err; |
3710 | struct netdev_hw_addr *ha; | ||
3652 | 3711 | ||
3653 | ASSERT_RTNL(); | 3712 | ASSERT_RTNL(); |
3654 | 3713 | ||
3655 | err = __hw_addr_del_ii(&dev->dev_addr_list, addr, dev->addr_len, | 3714 | /* |
3656 | addr_type, 0); | 3715 | * We can not remove the first address from the list because |
3716 | * dev->dev_addr points to that. | ||
3717 | */ | ||
3718 | ha = list_first_entry(&dev->dev_addr_list, struct netdev_hw_addr, list); | ||
3719 | if (ha->addr == dev->dev_addr && ha->refcount == 1) | ||
3720 | return -ENOENT; | ||
3721 | |||
3722 | err = __hw_addr_del(&dev->dev_addr_list, NULL, addr, dev->addr_len, | ||
3723 | addr_type); | ||
3657 | if (!err) | 3724 | if (!err) |
3658 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 3725 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
3659 | return err; | 3726 | return err; |
@@ -3680,9 +3747,9 @@ int dev_addr_add_multiple(struct net_device *to_dev, | |||
3680 | 3747 | ||
3681 | if (from_dev->addr_len != to_dev->addr_len) | 3748 | if (from_dev->addr_len != to_dev->addr_len) |
3682 | return -EINVAL; | 3749 | return -EINVAL; |
3683 | err = __hw_addr_add_multiple_ii(&to_dev->dev_addr_list, | 3750 | err = __hw_addr_add_multiple(&to_dev->dev_addr_list, NULL, |
3684 | &from_dev->dev_addr_list, | 3751 | &from_dev->dev_addr_list, |
3685 | to_dev->addr_len, addr_type, 0); | 3752 | to_dev->addr_len, addr_type); |
3686 | if (!err) | 3753 | if (!err) |
3687 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); | 3754 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); |
3688 | return err; | 3755 | return err; |
@@ -3707,9 +3774,9 @@ int dev_addr_del_multiple(struct net_device *to_dev, | |||
3707 | 3774 | ||
3708 | if (from_dev->addr_len != to_dev->addr_len) | 3775 | if (from_dev->addr_len != to_dev->addr_len) |
3709 | return -EINVAL; | 3776 | return -EINVAL; |
3710 | __hw_addr_del_multiple_ii(&to_dev->dev_addr_list, | 3777 | __hw_addr_del_multiple(&to_dev->dev_addr_list, NULL, |
3711 | &from_dev->dev_addr_list, | 3778 | &from_dev->dev_addr_list, |
3712 | to_dev->addr_len, addr_type, 0); | 3779 | to_dev->addr_len, addr_type); |
3713 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); | 3780 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); |
3714 | return 0; | 3781 | return 0; |
3715 | } | 3782 | } |
@@ -3779,24 +3846,22 @@ int __dev_addr_add(struct dev_addr_list **list, int *count, | |||
3779 | * dev_unicast_delete - Release secondary unicast address. | 3846 | * dev_unicast_delete - Release secondary unicast address. |
3780 | * @dev: device | 3847 | * @dev: device |
3781 | * @addr: address to delete | 3848 | * @addr: address to delete |
3782 | * @alen: length of @addr | ||
3783 | * | 3849 | * |
3784 | * Release reference to a secondary unicast address and remove it | 3850 | * Release reference to a secondary unicast address and remove it |
3785 | * from the device if the reference count drops to zero. | 3851 | * from the device if the reference count drops to zero. |
3786 | * | 3852 | * |
3787 | * The caller must hold the rtnl_mutex. | 3853 | * The caller must hold the rtnl_mutex. |
3788 | */ | 3854 | */ |
3789 | int dev_unicast_delete(struct net_device *dev, void *addr, int alen) | 3855 | int dev_unicast_delete(struct net_device *dev, void *addr) |
3790 | { | 3856 | { |
3791 | int err; | 3857 | int err; |
3792 | 3858 | ||
3793 | ASSERT_RTNL(); | 3859 | ASSERT_RTNL(); |
3794 | 3860 | ||
3795 | netif_addr_lock_bh(dev); | 3861 | err = __hw_addr_del(&dev->uc_list, &dev->uc_count, addr, |
3796 | err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0); | 3862 | dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); |
3797 | if (!err) | 3863 | if (!err) |
3798 | __dev_set_rx_mode(dev); | 3864 | __dev_set_rx_mode(dev); |
3799 | netif_addr_unlock_bh(dev); | ||
3800 | return err; | 3865 | return err; |
3801 | } | 3866 | } |
3802 | EXPORT_SYMBOL(dev_unicast_delete); | 3867 | EXPORT_SYMBOL(dev_unicast_delete); |
@@ -3805,24 +3870,22 @@ EXPORT_SYMBOL(dev_unicast_delete); | |||
3805 | * dev_unicast_add - add a secondary unicast address | 3870 | * dev_unicast_add - add a secondary unicast address |
3806 | * @dev: device | 3871 | * @dev: device |
3807 | * @addr: address to add | 3872 | * @addr: address to add |
3808 | * @alen: length of @addr | ||
3809 | * | 3873 | * |
3810 | * Add a secondary unicast address to the device or increase | 3874 | * Add a secondary unicast address to the device or increase |
3811 | * the reference count if it already exists. | 3875 | * the reference count if it already exists. |
3812 | * | 3876 | * |
3813 | * The caller must hold the rtnl_mutex. | 3877 | * The caller must hold the rtnl_mutex. |
3814 | */ | 3878 | */ |
3815 | int dev_unicast_add(struct net_device *dev, void *addr, int alen) | 3879 | int dev_unicast_add(struct net_device *dev, void *addr) |
3816 | { | 3880 | { |
3817 | int err; | 3881 | int err; |
3818 | 3882 | ||
3819 | ASSERT_RTNL(); | 3883 | ASSERT_RTNL(); |
3820 | 3884 | ||
3821 | netif_addr_lock_bh(dev); | 3885 | err = __hw_addr_add(&dev->uc_list, &dev->uc_count, addr, |
3822 | err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0); | 3886 | dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); |
3823 | if (!err) | 3887 | if (!err) |
3824 | __dev_set_rx_mode(dev); | 3888 | __dev_set_rx_mode(dev); |
3825 | netif_addr_unlock_bh(dev); | ||
3826 | return err; | 3889 | return err; |
3827 | } | 3890 | } |
3828 | EXPORT_SYMBOL(dev_unicast_add); | 3891 | EXPORT_SYMBOL(dev_unicast_add); |
@@ -3879,8 +3942,7 @@ void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, | |||
3879 | * @from: source device | 3942 | * @from: source device |
3880 | * | 3943 | * |
3881 | * Add newly added addresses to the destination device and release | 3944 | * Add newly added addresses to the destination device and release |
3882 | * addresses that have no users left. The source device must be | 3945 | * addresses that have no users left. |
3883 | * locked by netif_tx_lock_bh. | ||
3884 | * | 3946 | * |
3885 | * This function is intended to be called from the dev->set_rx_mode | 3947 | * This function is intended to be called from the dev->set_rx_mode |
3886 | * function of layered software devices. | 3948 | * function of layered software devices. |
@@ -3889,12 +3951,15 @@ int dev_unicast_sync(struct net_device *to, struct net_device *from) | |||
3889 | { | 3951 | { |
3890 | int err = 0; | 3952 | int err = 0; |
3891 | 3953 | ||
3892 | netif_addr_lock_bh(to); | 3954 | ASSERT_RTNL(); |
3893 | err = __dev_addr_sync(&to->uc_list, &to->uc_count, | 3955 | |
3894 | &from->uc_list, &from->uc_count); | 3956 | if (to->addr_len != from->addr_len) |
3957 | return -EINVAL; | ||
3958 | |||
3959 | err = __hw_addr_sync(&to->uc_list, &to->uc_count, | ||
3960 | &from->uc_list, &from->uc_count, to->addr_len); | ||
3895 | if (!err) | 3961 | if (!err) |
3896 | __dev_set_rx_mode(to); | 3962 | __dev_set_rx_mode(to); |
3897 | netif_addr_unlock_bh(to); | ||
3898 | return err; | 3963 | return err; |
3899 | } | 3964 | } |
3900 | EXPORT_SYMBOL(dev_unicast_sync); | 3965 | EXPORT_SYMBOL(dev_unicast_sync); |
@@ -3910,18 +3975,33 @@ EXPORT_SYMBOL(dev_unicast_sync); | |||
3910 | */ | 3975 | */ |
3911 | void dev_unicast_unsync(struct net_device *to, struct net_device *from) | 3976 | void dev_unicast_unsync(struct net_device *to, struct net_device *from) |
3912 | { | 3977 | { |
3913 | netif_addr_lock_bh(from); | 3978 | ASSERT_RTNL(); |
3914 | netif_addr_lock(to); | ||
3915 | 3979 | ||
3916 | __dev_addr_unsync(&to->uc_list, &to->uc_count, | 3980 | if (to->addr_len != from->addr_len) |
3917 | &from->uc_list, &from->uc_count); | 3981 | return; |
3918 | __dev_set_rx_mode(to); | ||
3919 | 3982 | ||
3920 | netif_addr_unlock(to); | 3983 | __hw_addr_unsync(&to->uc_list, &to->uc_count, |
3921 | netif_addr_unlock_bh(from); | 3984 | &from->uc_list, &from->uc_count, to->addr_len); |
3985 | __dev_set_rx_mode(to); | ||
3922 | } | 3986 | } |
3923 | EXPORT_SYMBOL(dev_unicast_unsync); | 3987 | EXPORT_SYMBOL(dev_unicast_unsync); |
3924 | 3988 | ||
3989 | static void dev_unicast_flush(struct net_device *dev) | ||
3990 | { | ||
3991 | /* rtnl_mutex must be held here */ | ||
3992 | |||
3993 | __hw_addr_flush(&dev->uc_list); | ||
3994 | dev->uc_count = 0; | ||
3995 | } | ||
3996 | |||
3997 | static void dev_unicast_init(struct net_device *dev) | ||
3998 | { | ||
3999 | /* rtnl_mutex must be held here */ | ||
4000 | |||
4001 | INIT_LIST_HEAD(&dev->uc_list); | ||
4002 | } | ||
4003 | |||
4004 | |||
3925 | static void __dev_addr_discard(struct dev_addr_list **list) | 4005 | static void __dev_addr_discard(struct dev_addr_list **list) |
3926 | { | 4006 | { |
3927 | struct dev_addr_list *tmp; | 4007 | struct dev_addr_list *tmp; |
@@ -3940,9 +4020,6 @@ static void dev_addr_discard(struct net_device *dev) | |||
3940 | { | 4020 | { |
3941 | netif_addr_lock_bh(dev); | 4021 | netif_addr_lock_bh(dev); |
3942 | 4022 | ||
3943 | __dev_addr_discard(&dev->uc_list); | ||
3944 | dev->uc_count = 0; | ||
3945 | |||
3946 | __dev_addr_discard(&dev->mc_list); | 4023 | __dev_addr_discard(&dev->mc_list); |
3947 | dev->mc_count = 0; | 4024 | dev->mc_count = 0; |
3948 | 4025 | ||
@@ -4535,6 +4612,7 @@ static void rollback_registered(struct net_device *dev) | |||
4535 | /* | 4612 | /* |
4536 | * Flush the unicast and multicast chains | 4613 | * Flush the unicast and multicast chains |
4537 | */ | 4614 | */ |
4615 | dev_unicast_flush(dev); | ||
4538 | dev_addr_discard(dev); | 4616 | dev_addr_discard(dev); |
4539 | 4617 | ||
4540 | if (dev->netdev_ops->ndo_uninit) | 4618 | if (dev->netdev_ops->ndo_uninit) |
@@ -5020,6 +5098,8 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5020 | if (dev_addr_init(dev)) | 5098 | if (dev_addr_init(dev)) |
5021 | goto free_tx; | 5099 | goto free_tx; |
5022 | 5100 | ||
5101 | dev_unicast_init(dev); | ||
5102 | |||
5023 | dev_net_set(dev, &init_net); | 5103 | dev_net_set(dev, &init_net); |
5024 | 5104 | ||
5025 | dev->_tx = tx; | 5105 | dev->_tx = tx; |
@@ -5223,6 +5303,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
5223 | /* | 5303 | /* |
5224 | * Flush the unicast and multicast chains | 5304 | * Flush the unicast and multicast chains |
5225 | */ | 5305 | */ |
5306 | dev_unicast_flush(dev); | ||
5226 | dev_addr_discard(dev); | 5307 | dev_addr_discard(dev); |
5227 | 5308 | ||
5228 | netdev_unregister_kobject(dev); | 5309 | netdev_unregister_kobject(dev); |