diff options
| author | Takashi Iwai <tiwai@suse.de> | 2011-08-08 14:30:29 +0200 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2011-08-08 14:30:29 +0200 | 
| commit | 0a2d31b62dba9b5b92a38c67c9cc42630513662a (patch) | |
| tree | f755d74ec85248de645e10c45ed1a2ed467530f6 /drivers/net/bonding/bond_main.c | |
| parent | 8039290a91c5dc4414093c086987a5d7738fe2fd (diff) | |
| parent | df944f66784e6d4f2f50739263a4947885d8b6ae (diff) | |
Merge branch 'fix/kconfig' into for-linus
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
| -rw-r--r-- | drivers/net/bonding/bond_main.c | 153 | 
1 files changed, 50 insertions, 103 deletions
| diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 17b4dd94da90..38a83acd502e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -98,6 +98,7 @@ static char *mode;  static char *primary;  static char *primary_reselect;  static char *lacp_rate; +static int min_links;  static char *ad_select;  static char *xmit_hash_policy;  static int arp_interval = BOND_LINK_ARP_INTERV; @@ -150,6 +151,9 @@ module_param(ad_select, charp, 0);  MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic; "  			    "0 for stable (default), 1 for bandwidth, "  			    "2 for count"); +module_param(min_links, int, 0); +MODULE_PARM_DESC(min_links, "Minimum number of available links before turning on carrier"); +  module_param(xmit_hash_policy, charp, 0);  MODULE_PARM_DESC(xmit_hash_policy, "balance-xor and 802.3ad hashing method; "  				   "0 for layer 2 (default), 1 for layer 3+4, " @@ -329,16 +333,6 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)  			kfree(vlan); -			if (list_empty(&bond->vlan_list) && -			    (bond->slave_cnt == 0)) { -				/* Last VLAN removed and no slaves, so -				 * restore block on adding VLANs. This will -				 * be removed once new slaves that are not -				 * VLAN challenged will be added. -				 */ -				bond->dev->features |= NETIF_F_VLAN_CHALLENGED; -			} -  			res = 0;  			goto out;  		} @@ -388,6 +382,8 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)  	return next;  } +#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb)) +  /**   * bond_dev_queue_xmit - Prepare skb for xmit.   * @@ -400,6 +396,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,  {  	skb->dev = slave_dev;  	skb->priority = 1; + +	skb->queue_mapping = bond_queue_mapping(skb); +  	if (unlikely(netpoll_tx_running(slave_dev)))  		bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb);  	else @@ -409,9 +408,8 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,  }  /* - * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid - * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a - * lock because: + * In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid, + * We don't protect the slave list iteration with a lock because:   * a. This operation is performed in IOCTL context,   * b. The operation is protected by the RTNL semaphore in the 8021q code,   * c. Holding a lock with BH disabled while directly calling a base driver @@ -427,33 +425,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,  */  /** - * bond_vlan_rx_register - Propagates registration to slaves - * @bond_dev: bonding net device that got called - * @grp: vlan group being registered - */ -static void bond_vlan_rx_register(struct net_device *bond_dev, -				  struct vlan_group *grp) -{ -	struct bonding *bond = netdev_priv(bond_dev); -	struct slave *slave; -	int i; - -	write_lock_bh(&bond->lock); -	bond->vlgrp = grp; -	write_unlock_bh(&bond->lock); - -	bond_for_each_slave(bond, slave, i) { -		struct net_device *slave_dev = slave->dev; -		const struct net_device_ops *slave_ops = slave_dev->netdev_ops; - -		if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && -		    slave_ops->ndo_vlan_rx_register) { -			slave_ops->ndo_vlan_rx_register(slave_dev, grp); -		} -	} -} - -/**   * bond_vlan_rx_add_vid - Propagates adding an id to slaves   * @bond_dev: bonding net device that got called   * @vid: vlan id being added @@ -490,7 +461,6 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)  {  	struct bonding *bond = netdev_priv(bond_dev);  	struct slave *slave; -	struct net_device *vlan_dev;  	int i, res;  	bond_for_each_slave(bond, slave, i) { @@ -499,12 +469,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)  		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&  		    slave_ops->ndo_vlan_rx_kill_vid) { -			/* Save and then restore vlan_dev in the grp array, -			 * since the slave's driver might clear it. -			 */ -			vlan_dev = vlan_group_get_device(bond->vlgrp, vid);  			slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid); -			vlan_group_set_device(bond->vlgrp, vid, vlan_dev);  		}  	} @@ -520,13 +485,6 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla  	struct vlan_entry *vlan;  	const struct net_device_ops *slave_ops = slave_dev->netdev_ops; -	if (!bond->vlgrp) -		return; - -	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && -	    slave_ops->ndo_vlan_rx_register) -		slave_ops->ndo_vlan_rx_register(slave_dev, bond->vlgrp); -  	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||  	    !(slave_ops->ndo_vlan_rx_add_vid))  		return; @@ -540,30 +498,16 @@ static void bond_del_vlans_from_slave(struct bonding *bond,  {  	const struct net_device_ops *slave_ops = slave_dev->netdev_ops;  	struct vlan_entry *vlan; -	struct net_device *vlan_dev; - -	if (!bond->vlgrp) -		return;  	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||  	    !(slave_ops->ndo_vlan_rx_kill_vid)) -		goto unreg; +		return;  	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {  		if (!vlan->vlan_id)  			continue; -		/* Save and then restore vlan_dev in the grp array, -		 * since the slave's driver might clear it. -		 */ -		vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);  		slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id); -		vlan_group_set_device(bond->vlgrp, vlan->vlan_id, vlan_dev);  	} - -unreg: -	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && -	    slave_ops->ndo_vlan_rx_register) -		slave_ops->ndo_vlan_rx_register(slave_dev, NULL);  }  /*------------------------------- Link status -------------------------------*/ @@ -629,15 +573,8 @@ static int bond_update_speed_duplex(struct slave *slave)  		return -1;  	slave_speed = ethtool_cmd_speed(&etool); -	switch (slave_speed) { -	case SPEED_10: -	case SPEED_100: -	case SPEED_1000: -	case SPEED_10000: -		break; -	default: +	if (slave_speed == 0 || slave_speed == ((__u32) -1))  		return -1; -	}  	switch (etool.duplex) {  	case DUPLEX_FULL: @@ -844,13 +781,13 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)  	__bond_resend_igmp_join_requests(bond->dev);  	/* rejoin all groups on vlan devices */ -	if (bond->vlgrp) { -		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { -			vlan_dev = vlan_group_get_device(bond->vlgrp, -							 vlan->vlan_id); -			if (vlan_dev) -				__bond_resend_igmp_join_requests(vlan_dev); -		} +	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { +		rcu_read_lock(); +		vlan_dev = __vlan_find_dev_deep(bond->dev, +						vlan->vlan_id); +		rcu_read_unlock(); +		if (vlan_dev) +			__bond_resend_igmp_join_requests(vlan_dev);  	}  	if (--bond->igmp_retrans > 0) @@ -1292,6 +1229,7 @@ static inline int slave_enable_netpoll(struct slave *slave)  		goto out;  	np->dev = slave->dev; +	strlcpy(np->dev_name, slave->dev->name, IFNAMSIZ);  	err = __netpoll_setup(np);  	if (err) {  		kfree(np); @@ -1422,9 +1360,9 @@ out:  	return features;  } -#define BOND_VLAN_FEATURES	(NETIF_F_ALL_TX_OFFLOADS | \ -				 NETIF_F_SOFT_FEATURES | \ -				 NETIF_F_LRO) +#define BOND_VLAN_FEATURES	(NETIF_F_ALL_CSUM | NETIF_F_SG | \ +				 NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ +				 NETIF_F_HIGHDMA | NETIF_F_LRO)  static void bond_compute_features(struct bonding *bond)  { @@ -1564,7 +1502,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)  	/* no need to lock since we're protected by rtnl_lock */  	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {  		pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); -		if (bond->vlgrp) { +		if (bond_vlan_used(bond)) {  			pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",  			       bond_dev->name, slave_dev->name, bond_dev->name);  			return -EPERM; @@ -1619,8 +1557,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)  			if (slave_dev->type != ARPHRD_ETHER)  				bond_setup_by_slave(bond_dev, slave_dev); -			else +			else {  				ether_setup(bond_dev); +				bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; +			}  			netdev_bonding_change(bond_dev,  					      NETDEV_POST_TYPE_CHANGE); @@ -1850,8 +1790,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)  			/* Initialize AD with the number of times that the AD timer is called in 1 second  			 * can be called only after the mac address of the bond is set  			 */ -			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL, -					    bond->params.lacp_fast); +			bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);  		} else {  			SLAVE_AD_INFO(new_slave).id =  				SLAVE_AD_INFO(new_slave->prev).id + 1; @@ -2073,7 +2012,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)  		 */  		memset(bond_dev->dev_addr, 0, bond_dev->addr_len); -		if (bond->vlgrp) { +		if (bond_vlan_used(bond)) {  			pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",  				   bond_dev->name, bond_dev->name);  			pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n", @@ -2255,7 +2194,7 @@ static int bond_release_all(struct net_device *bond_dev)  	 */  	memset(bond_dev->dev_addr, 0, bond_dev->addr_len); -	if (bond->vlgrp) { +	if (bond_vlan_used(bond)) {  		pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",  			   bond_dev->name, bond_dev->name);  		pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n", @@ -2693,7 +2632,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)  		if (!targets[i])  			break;  		pr_debug("basa: target %x\n", targets[i]); -		if (!bond->vlgrp) { +		if (!bond_vlan_used(bond)) {  			pr_debug("basa: empty vlan: arp_send\n");  			bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],  				      bond->master_ip, 0); @@ -2728,7 +2667,10 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)  		vlan_id = 0;  		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { -			vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); +			rcu_read_lock(); +			vlan_dev = __vlan_find_dev_deep(bond->dev, +							vlan->vlan_id); +			rcu_read_unlock();  			if (vlan_dev == rt->dst.dev) {  				vlan_id = vlan->vlan_id;  				pr_debug("basa: vlan match on %s %d\n", @@ -3389,9 +3331,8 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,  		}  		list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { -			if (!bond->vlgrp) -				continue; -			vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); +			vlan_dev = __vlan_find_dev_deep(bond->dev, +							vlan->vlan_id);  			if (vlan_dev == event_dev) {  				switch (event) {  				case NETDEV_UP: @@ -3450,7 +3391,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)  	int layer4_xor = 0;  	if (skb->protocol == htons(ETH_P_IP)) { -		if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) && +		if (!ip_is_fragment(iph) &&  		    (iph->protocol == IPPROTO_TCP ||  		     iph->protocol == IPPROTO_UDP)) {  			layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1))); @@ -4206,6 +4147,7 @@ static inline int bond_slave_override(struct bonding *bond,  	return res;  } +  static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)  {  	/* @@ -4216,6 +4158,11 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)  	 */  	u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0; +	/* +	 * Save the original txq to restore before passing to the driver +	 */ +	bond_queue_mapping(skb) = skb->queue_mapping; +  	if (unlikely(txq >= dev->real_num_tx_queues)) {  		do {  			txq -= dev->real_num_tx_queues; @@ -4337,10 +4284,9 @@ static const struct net_device_ops bond_netdev_ops = {  	.ndo_do_ioctl		= bond_do_ioctl,  	.ndo_set_multicast_list	= bond_set_multicast_list,  	.ndo_change_mtu		= bond_change_mtu, -	.ndo_set_mac_address 	= bond_set_mac_address, +	.ndo_set_mac_address	= bond_set_mac_address,  	.ndo_neigh_setup	= bond_neigh_setup, -	.ndo_vlan_rx_register	= bond_vlan_rx_register, -	.ndo_vlan_rx_add_vid 	= bond_vlan_rx_add_vid, +	.ndo_vlan_rx_add_vid	= bond_vlan_rx_add_vid,  	.ndo_vlan_rx_kill_vid	= bond_vlan_rx_kill_vid,  #ifdef CONFIG_NET_POLL_CONTROLLER  	.ndo_netpoll_setup	= bond_netpoll_setup, @@ -4386,7 +4332,7 @@ static void bond_setup(struct net_device *bond_dev)  	bond_dev->tx_queue_len = 0;  	bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;  	bond_dev->priv_flags |= IFF_BONDING; -	bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; +	bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);  	/* At first, we block adding VLANs. That's the only way to  	 * prevent problems that occur when adding VLANs over an @@ -4747,7 +4693,7 @@ static int bond_check_params(struct bond_params *params)  		/* miimon and arp_interval not set, we need one so things  		 * work as expected, see bonding.txt for details  		 */ -		pr_warning("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n"); +		pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n");  	}  	if (primary && !USES_PRIMARY(bond_mode)) { @@ -4804,6 +4750,7 @@ static int bond_check_params(struct bond_params *params)  	params->tx_queues = tx_queues;  	params->all_slaves_active = all_slaves_active;  	params->resend_igmp = resend_igmp; +	params->min_links = min_links;  	if (primary) {  		strncpy(params->primary, primary, IFNAMSIZ); | 
