bonding: Simplify the xmit function for modes that use xmit_hash
[cascardo/linux.git] / drivers / net / bonding / bond_options.c
index dc73463..b62697f 100644 (file)
@@ -625,6 +625,8 @@ int __bond_opt_set(struct bonding *bond,
 out:
        if (ret)
                bond_opt_error_interpret(bond, opt, ret, val);
+       else
+               call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev);
 
        return ret;
 }
@@ -732,15 +734,13 @@ static int bond_option_active_slave_set(struct bonding *bond,
        }
 
        block_netpoll_tx();
-       write_lock_bh(&bond->curr_slave_lock);
-
        /* check to see if we are clearing active */
        if (!slave_dev) {
                netdev_info(bond->dev, "Clearing current active slave\n");
                RCU_INIT_POINTER(bond->curr_active_slave, NULL);
                bond_select_active_slave(bond);
        } else {
-               struct slave *old_active = bond_deref_active_protected(bond);
+               struct slave *old_active = rtnl_dereference(bond->curr_active_slave);
                struct slave *new_active = bond_slave_get_rtnl(slave_dev);
 
                BUG_ON(!new_active);
@@ -763,8 +763,6 @@ static int bond_option_active_slave_set(struct bonding *bond,
                        }
                }
        }
-
-       write_unlock_bh(&bond->curr_slave_lock);
        unblock_netpoll_tx();
 
        return ret;
@@ -953,14 +951,7 @@ static int _bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
 
 static int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target)
 {
-       int ret;
-
-       /* not to race with bond_arp_rcv */
-       write_lock_bh(&bond->lock);
-       ret = _bond_option_arp_ip_target_add(bond, target);
-       write_unlock_bh(&bond->lock);
-
-       return ret;
+       return _bond_option_arp_ip_target_add(bond, target);
 }
 
 static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
@@ -989,9 +980,6 @@ static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
 
        netdev_info(bond->dev, "Removing ARP target %pI4\n", &target);
 
-       /* not to race with bond_arp_rcv */
-       write_lock_bh(&bond->lock);
-
        bond_for_each_slave(bond, slave, iter) {
                targets_rx = slave->target_last_arp_rx;
                for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++)
@@ -1002,8 +990,6 @@ static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
                targets[i] = targets[i+1];
        targets[i] = 0;
 
-       write_unlock_bh(&bond->lock);
-
        return 0;
 }
 
@@ -1011,11 +997,8 @@ void bond_option_arp_ip_targets_clear(struct bonding *bond)
 {
        int i;
 
-       /* not to race with bond_arp_rcv */
-       write_lock_bh(&bond->lock);
        for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
                _bond_options_arp_ip_target_set(bond, i, 0, 0);
-       write_unlock_bh(&bond->lock);
 }
 
 static int bond_option_arp_ip_targets_set(struct bonding *bond,
@@ -1079,8 +1062,6 @@ static int bond_option_primary_set(struct bonding *bond,
        struct slave *slave;
 
        block_netpoll_tx();
-       read_lock(&bond->lock);
-       write_lock_bh(&bond->curr_slave_lock);
 
        p = strchr(primary, '\n');
        if (p)
@@ -1088,7 +1069,7 @@ static int bond_option_primary_set(struct bonding *bond,
        /* check to see if we are clearing primary */
        if (!strlen(primary)) {
                netdev_info(bond->dev, "Setting primary slave to None\n");
-               bond->primary_slave = NULL;
+               RCU_INIT_POINTER(bond->primary_slave, NULL);
                memset(bond->params.primary, 0, sizeof(bond->params.primary));
                bond_select_active_slave(bond);
                goto out;
@@ -1098,16 +1079,16 @@ static int bond_option_primary_set(struct bonding *bond,
                if (strncmp(slave->dev->name, primary, IFNAMSIZ) == 0) {
                        netdev_info(bond->dev, "Setting %s as primary slave\n",
                                    slave->dev->name);
-                       bond->primary_slave = slave;
+                       rcu_assign_pointer(bond->primary_slave, slave);
                        strcpy(bond->params.primary, slave->dev->name);
                        bond_select_active_slave(bond);
                        goto out;
                }
        }
 
-       if (bond->primary_slave) {
+       if (rtnl_dereference(bond->primary_slave)) {
                netdev_info(bond->dev, "Setting primary slave to None\n");
-               bond->primary_slave = NULL;
+               RCU_INIT_POINTER(bond->primary_slave, NULL);
                bond_select_active_slave(bond);
        }
        strncpy(bond->params.primary, primary, IFNAMSIZ);
@@ -1117,8 +1098,6 @@ static int bond_option_primary_set(struct bonding *bond,
                    primary, bond->dev->name);
 
 out:
-       write_unlock_bh(&bond->curr_slave_lock);
-       read_unlock(&bond->lock);
        unblock_netpoll_tx();
 
        return 0;
@@ -1132,9 +1111,7 @@ static int bond_option_primary_reselect_set(struct bonding *bond,
        bond->params.primary_reselect = newval->value;
 
        block_netpoll_tx();
-       write_lock_bh(&bond->curr_slave_lock);
        bond_select_active_slave(bond);
-       write_unlock_bh(&bond->curr_slave_lock);
        unblock_netpoll_tx();
 
        return 0;