aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-04-07 02:53:30 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-07 02:53:30 -0400
commit4a35ecf8bf1c4b039503fa554100fe85c761de76 (patch)
tree9b75f5d5636004d9a9aa496924377379be09aa1f /drivers/net/bonding
parentb4d562e3c3553ac58c7120555c4e4aefbb090a2a (diff)
parentfb9e2d887243499b8d28efcf80821c4f6a092395 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/bonding/bond_main.c drivers/net/via-velocity.c drivers/net/wireless/iwlwifi/iwl-agn.c
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_main.c66
1 files changed, 46 insertions, 20 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 22682f1c8473..85e813c7762b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1162,6 +1162,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
1162 write_lock_bh(&bond->curr_slave_lock); 1162 write_lock_bh(&bond->curr_slave_lock);
1163 } 1163 }
1164 } 1164 }
1165
1166 /* resend IGMP joins since all were sent on curr_active_slave */
1167 if (bond->params.mode == BOND_MODE_ROUNDROBIN) {
1168 bond_resend_igmp_join_requests(bond);
1169 }
1165} 1170}
1166 1171
1167/** 1172/**
@@ -4096,22 +4101,41 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
4096 struct bonding *bond = netdev_priv(bond_dev); 4101 struct bonding *bond = netdev_priv(bond_dev);
4097 struct slave *slave, *start_at; 4102 struct slave *slave, *start_at;
4098 int i, slave_no, res = 1; 4103 int i, slave_no, res = 1;
4104 struct iphdr *iph = ip_hdr(skb);
4099 4105
4100 read_lock(&bond->lock); 4106 read_lock(&bond->lock);
4101 4107
4102 if (!BOND_IS_OK(bond)) 4108 if (!BOND_IS_OK(bond))
4103 goto out; 4109 goto out;
4104
4105 /* 4110 /*
4106 * Concurrent TX may collide on rr_tx_counter; we accept that 4111 * Start with the curr_active_slave that joined the bond as the
4107 * as being rare enough not to justify using an atomic op here 4112 * default for sending IGMP traffic. For failover purposes one
4113 * needs to maintain some consistency for the interface that will
4114 * send the join/membership reports. The curr_active_slave found
4115 * will send all of this type of traffic.
4108 */ 4116 */
4109 slave_no = bond->rr_tx_counter++ % bond->slave_cnt; 4117 if ((iph->protocol == IPPROTO_IGMP) &&
4118 (skb->protocol == htons(ETH_P_IP))) {
4110 4119
4111 bond_for_each_slave(bond, slave, i) { 4120 read_lock(&bond->curr_slave_lock);
4112 slave_no--; 4121 slave = bond->curr_active_slave;
4113 if (slave_no < 0) 4122 read_unlock(&bond->curr_slave_lock);
4114 break; 4123
4124 if (!slave)
4125 goto out;
4126 } else {
4127 /*
4128 * Concurrent TX may collide on rr_tx_counter; we accept
4129 * that as being rare enough not to justify using an
4130 * atomic op here.
4131 */
4132 slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
4133
4134 bond_for_each_slave(bond, slave, i) {
4135 slave_no--;
4136 if (slave_no < 0)
4137 break;
4138 }
4115 } 4139 }
4116 4140
4117 start_at = slave; 4141 start_at = slave;
@@ -4384,6 +4408,14 @@ static const struct net_device_ops bond_netdev_ops = {
4384 .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid, 4408 .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
4385}; 4409};
4386 4410
4411static void bond_destructor(struct net_device *bond_dev)
4412{
4413 struct bonding *bond = netdev_priv(bond_dev);
4414 if (bond->wq)
4415 destroy_workqueue(bond->wq);
4416 free_netdev(bond_dev);
4417}
4418
4387static void bond_setup(struct net_device *bond_dev) 4419static void bond_setup(struct net_device *bond_dev)
4388{ 4420{
4389 struct bonding *bond = netdev_priv(bond_dev); 4421 struct bonding *bond = netdev_priv(bond_dev);
@@ -4404,7 +4436,7 @@ static void bond_setup(struct net_device *bond_dev)
4404 bond_dev->ethtool_ops = &bond_ethtool_ops; 4436 bond_dev->ethtool_ops = &bond_ethtool_ops;
4405 bond_set_mode_ops(bond, bond->params.mode); 4437 bond_set_mode_ops(bond, bond->params.mode);
4406 4438
4407 bond_dev->destructor = free_netdev; 4439 bond_dev->destructor = bond_destructor;
4408 4440
4409 /* Initialize the device options */ 4441 /* Initialize the device options */
4410 bond_dev->tx_queue_len = 0; 4442 bond_dev->tx_queue_len = 0;
@@ -4476,9 +4508,6 @@ static void bond_uninit(struct net_device *bond_dev)
4476 4508
4477 bond_remove_proc_entry(bond); 4509 bond_remove_proc_entry(bond);
4478 4510
4479 if (bond->wq)
4480 destroy_workqueue(bond->wq);
4481
4482 __hw_addr_flush(&bond->mc_list); 4511 __hw_addr_flush(&bond->mc_list);
4483} 4512}
4484 4513
@@ -4890,8 +4919,8 @@ int bond_create(struct net *net, const char *name)
4890 bond_setup); 4919 bond_setup);
4891 if (!bond_dev) { 4920 if (!bond_dev) {
4892 pr_err("%s: eek! can't alloc netdev!\n", name); 4921 pr_err("%s: eek! can't alloc netdev!\n", name);
4893 res = -ENOMEM; 4922 rtnl_unlock();
4894 goto out; 4923 return -ENOMEM;
4895 } 4924 }
4896 4925
4897 dev_net_set(bond_dev, net); 4926 dev_net_set(bond_dev, net);
@@ -4900,19 +4929,16 @@ int bond_create(struct net *net, const char *name)
4900 if (!name) { 4929 if (!name) {
4901 res = dev_alloc_name(bond_dev, "bond%d"); 4930 res = dev_alloc_name(bond_dev, "bond%d");
4902 if (res < 0) 4931 if (res < 0)
4903 goto out_netdev; 4932 goto out;
4904 } 4933 }
4905 4934
4906 res = register_netdevice(bond_dev); 4935 res = register_netdevice(bond_dev);
4907 if (res < 0)
4908 goto out_netdev;
4909 4936
4910out: 4937out:
4911 rtnl_unlock(); 4938 rtnl_unlock();
4939 if (res < 0)
4940 bond_destructor(bond_dev);
4912 return res; 4941 return res;
4913out_netdev:
4914 free_netdev(bond_dev);
4915 goto out;
4916} 4942}
4917 4943
4918static int __net_init bond_net_init(struct net *net) 4944static int __net_init bond_net_init(struct net *net)