Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[linux-2.6-microblaze.git] / drivers / net / bonding / bond_3ad.c
index 9fd1d6c..a86b1f7 100644 (file)
@@ -225,7 +225,7 @@ static inline int __check_agg_selection_timer(struct port *port)
        if (bond == NULL)
                return 0;
 
-       return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0;
+       return atomic_read(&BOND_AD_INFO(bond).agg_select_timer) ? 1 : 0;
 }
 
 /**
@@ -1995,7 +1995,7 @@ static void ad_marker_response_received(struct bond_marker *marker,
  */
 void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
 {
-       BOND_AD_INFO(bond).agg_select_timer = timeout;
+       atomic_set(&BOND_AD_INFO(bond).agg_select_timer, timeout);
 }
 
 /**
@@ -2278,6 +2278,28 @@ void bond_3ad_update_ad_actor_settings(struct bonding *bond)
        spin_unlock_bh(&bond->mode_lock);
 }
 
+/**
+ * bond_agg_timer_advance - advance agg_select_timer
+ * @bond:  bonding structure
+ *
+ * Return true when agg_select_timer reaches 0.
+ */
+static bool bond_agg_timer_advance(struct bonding *bond)
+{
+       int val, nval;
+
+       while (1) {
+               val = atomic_read(&BOND_AD_INFO(bond).agg_select_timer);
+               if (!val)
+                       return false;
+               nval = val - 1;
+               if (atomic_cmpxchg(&BOND_AD_INFO(bond).agg_select_timer,
+                                  val, nval) == val)
+                       break;
+       }
+       return nval == 0;
+}
+
 /**
  * bond_3ad_state_machine_handler - handle state machines timeout
  * @work: work context to fetch bonding struct to work on from
@@ -2313,9 +2335,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
        if (!bond_has_slaves(bond))
                goto re_arm;
 
-       /* check if agg_select_timer timer after initialize is timed out */
-       if (BOND_AD_INFO(bond).agg_select_timer &&
-           !(--BOND_AD_INFO(bond).agg_select_timer)) {
+       if (bond_agg_timer_advance(bond)) {
                slave = bond_first_slave_rcu(bond);
                port = slave ? &(SLAVE_AD_INFO(slave)->port) : NULL;