diff options
author | David S. Miller <davem@davemloft.net> | 2010-04-07 02:53:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-07 02:53:30 -0400 |
commit | 4a35ecf8bf1c4b039503fa554100fe85c761de76 (patch) | |
tree | 9b75f5d5636004d9a9aa496924377379be09aa1f /drivers/net/bonding | |
parent | b4d562e3c3553ac58c7120555c4e4aefbb090a2a (diff) | |
parent | fb9e2d887243499b8d28efcf80821c4f6a092395 (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.c | 66 |
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 | ||
4411 | static 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 | |||
4387 | static void bond_setup(struct net_device *bond_dev) | 4419 | static 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 | ||
4910 | out: | 4937 | out: |
4911 | rtnl_unlock(); | 4938 | rtnl_unlock(); |
4939 | if (res < 0) | ||
4940 | bond_destructor(bond_dev); | ||
4912 | return res; | 4941 | return res; |
4913 | out_netdev: | ||
4914 | free_netdev(bond_dev); | ||
4915 | goto out; | ||
4916 | } | 4942 | } |
4917 | 4943 | ||
4918 | static int __net_init bond_net_init(struct net *net) | 4944 | static int __net_init bond_net_init(struct net *net) |