]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/bonding/bond_main.c
Merge branch 'msm/fixes' into next/late
[karo-tx-linux.git] / drivers / net / bonding / bond_main.c
index 29b846cbfb48d3380fa8dae7e87782e641e2519b..02d9ae7d527e14894d71e67e93372773ad9e5ea0 100644 (file)
@@ -764,8 +764,8 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
        struct net_device *bond_dev, *vlan_dev, *upper_dev;
        struct vlan_entry *vlan;
 
-       rcu_read_lock();
        read_lock(&bond->lock);
+       rcu_read_lock();
 
        bond_dev = bond->dev;
 
@@ -787,12 +787,19 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
                if (vlan_dev)
                        __bond_resend_igmp_join_requests(vlan_dev);
        }
+       rcu_read_unlock();
 
-       if (--bond->igmp_retrans > 0)
+       /* We use curr_slave_lock to protect against concurrent access to
+        * igmp_retrans from multiple running instances of this function and
+        * bond_change_active_slave
+        */
+       write_lock_bh(&bond->curr_slave_lock);
+       if (bond->igmp_retrans > 1) {
+               bond->igmp_retrans--;
                queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5);
-
+       }
+       write_unlock_bh(&bond->curr_slave_lock);
        read_unlock(&bond->lock);
-       rcu_read_unlock();
 }
 
 static void bond_resend_igmp_join_requests_delayed(struct work_struct *work)
@@ -1957,6 +1964,10 @@ err_free:
 
 err_undo_flags:
        bond_compute_features(bond);
+       /* Enslave of first slave has failed and we need to fix master's mac */
+       if (bond->slave_cnt == 0 &&
+           ether_addr_equal(bond_dev->dev_addr, slave_dev->dev_addr))
+               eth_hw_addr_random(bond_dev);
 
        return res;
 }