diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
| -rw-r--r-- | drivers/net/bonding/bond_main.c | 72 | 
1 files changed, 42 insertions, 30 deletions
| diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5c2febe94428..86d42306aa5e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -865,12 +865,8 @@ static void bond_hw_addr_flush(struct net_device *bond_dev,  	dev_uc_unsync(slave_dev, bond_dev);  	dev_mc_unsync(slave_dev, bond_dev); -	if (BOND_MODE(bond) == BOND_MODE_8023AD) { -		/* del lacpdu mc addr from mc list */ -		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; - -		dev_mc_del(slave_dev, lacpdu_multicast); -	} +	if (BOND_MODE(bond) == BOND_MODE_8023AD) +		dev_mc_del(slave_dev, lacpdu_mcast_addr);  }  /*--------------------------- Active slave change ---------------------------*/ @@ -890,7 +886,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,  		if (bond->dev->flags & IFF_ALLMULTI)  			dev_set_allmulti(old_active->dev, -1); -		bond_hw_addr_flush(bond->dev, old_active->dev); +		if (bond->dev->flags & IFF_UP) +			bond_hw_addr_flush(bond->dev, old_active->dev);  	}  	if (new_active) { @@ -901,10 +898,12 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,  		if (bond->dev->flags & IFF_ALLMULTI)  			dev_set_allmulti(new_active->dev, 1); -		netif_addr_lock_bh(bond->dev); -		dev_uc_sync(new_active->dev, bond->dev); -		dev_mc_sync(new_active->dev, bond->dev); -		netif_addr_unlock_bh(bond->dev); +		if (bond->dev->flags & IFF_UP) { +			netif_addr_lock_bh(bond->dev); +			dev_uc_sync(new_active->dev, bond->dev); +			dev_mc_sync(new_active->dev, bond->dev); +			netif_addr_unlock_bh(bond->dev); +		}  	}  } @@ -2166,16 +2165,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,  			}  		} -		netif_addr_lock_bh(bond_dev); -		dev_mc_sync_multiple(slave_dev, bond_dev); -		dev_uc_sync_multiple(slave_dev, bond_dev); -		netif_addr_unlock_bh(bond_dev); - -		if (BOND_MODE(bond) == BOND_MODE_8023AD) { -			/* add lacpdu mc addr to mc list */ -			u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; +		if (bond_dev->flags & IFF_UP) { +			netif_addr_lock_bh(bond_dev); +			dev_mc_sync_multiple(slave_dev, bond_dev); +			dev_uc_sync_multiple(slave_dev, bond_dev); +			netif_addr_unlock_bh(bond_dev); -			dev_mc_add(slave_dev, lacpdu_multicast); +			if (BOND_MODE(bond) == BOND_MODE_8023AD) +				dev_mc_add(slave_dev, lacpdu_mcast_addr);  		}  	} @@ -2447,7 +2444,8 @@ static int __bond_release_one(struct net_device *bond_dev,  		if (old_flags & IFF_ALLMULTI)  			dev_set_allmulti(slave_dev, -1); -		bond_hw_addr_flush(bond_dev, slave_dev); +		if (old_flags & IFF_UP) +			bond_hw_addr_flush(bond_dev, slave_dev);  	}  	slave_disable_netpoll(slave); @@ -4184,6 +4182,12 @@ static int bond_open(struct net_device *bond_dev)  	struct list_head *iter;  	struct slave *slave; +	if (BOND_MODE(bond) == BOND_MODE_ROUNDROBIN && !bond->rr_tx_counter) { +		bond->rr_tx_counter = alloc_percpu(u32); +		if (!bond->rr_tx_counter) +			return -ENOMEM; +	} +  	/* reset slave->backup and slave->inactive */  	if (bond_has_slaves(bond)) {  		bond_for_each_slave(bond, slave, iter) { @@ -4221,6 +4225,9 @@ static int bond_open(struct net_device *bond_dev)  		/* register to receive LACPDUs */  		bond->recv_probe = bond_3ad_lacpdu_recv;  		bond_3ad_initiate_agg_selection(bond, 1); + +		bond_for_each_slave(bond, slave, iter) +			dev_mc_add(slave->dev, lacpdu_mcast_addr);  	}  	if (bond_mode_can_use_xmit_hash(bond)) @@ -4232,6 +4239,7 @@ static int bond_open(struct net_device *bond_dev)  static int bond_close(struct net_device *bond_dev)  {  	struct bonding *bond = netdev_priv(bond_dev); +	struct slave *slave;  	bond_work_cancel_all(bond);  	bond->send_peer_notif = 0; @@ -4239,6 +4247,19 @@ static int bond_close(struct net_device *bond_dev)  		bond_alb_deinitialize(bond);  	bond->recv_probe = NULL; +	if (bond_uses_primary(bond)) { +		rcu_read_lock(); +		slave = rcu_dereference(bond->curr_active_slave); +		if (slave) +			bond_hw_addr_flush(bond_dev, slave->dev); +		rcu_read_unlock(); +	} else { +		struct list_head *iter; + +		bond_for_each_slave(bond, slave, iter) +			bond_hw_addr_flush(bond_dev, slave->dev); +	} +  	return 0;  } @@ -6228,15 +6249,6 @@ static int bond_init(struct net_device *bond_dev)  	if (!bond->wq)  		return -ENOMEM; -	if (BOND_MODE(bond) == BOND_MODE_ROUNDROBIN) { -		bond->rr_tx_counter = alloc_percpu(u32); -		if (!bond->rr_tx_counter) { -			destroy_workqueue(bond->wq); -			bond->wq = NULL; -			return -ENOMEM; -		} -	} -  	spin_lock_init(&bond->stats_lock);  	netdev_lockdep_set_classes(bond_dev); | 
