Search Linux Wireless

[PATCH 3/3] mac80211: make csa_currnet_counter atomic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Even it ieee80211_beacon_get() and
ieee80211_csa_update_counter() were to be
guaranteed to be serialized by drivers it still
couldn't be guaranteed to be safe on SMP systems.

Signed-off-by: Michal Kazior <michal.kazior@xxxxxxxxx>
---
 net/mac80211/cfg.c         | 12 +++++++-----
 net/mac80211/ieee80211_i.h |  2 +-
 net/mac80211/tx.c          | 11 ++++++-----
 3 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0518268..aab258b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -938,7 +938,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 	new->tail = new->head + new_head_len;
 	new->head_len = new_head_len;
 	new->tail_len = new_tail_len;
-	new->csa_current_counter = csa_count;
+	atomic_set(&new->csa_current_counter, csa_count);
 	memcpy(new->csa_counter_offset, csa_counter_offset_beacon,
 	       n_csa_counter_offset_beacon * sizeof(*new->csa_counter_offset));
 
@@ -3508,7 +3508,6 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	    (sdata->vif.type == NL80211_IFTYPE_AP ||
 	     sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
 	    params->n_csa_offsets) {
-		int i;
 		struct beacon_data *beacon = NULL;
 
 		rcu_read_lock();
@@ -3520,10 +3519,13 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 		else if (ieee80211_vif_is_mesh(&sdata->vif))
 			beacon = rcu_dereference(sdata->u.mesh.beacon);
 
-		if (beacon)
+		if (beacon) {
+			u8 count = atomic_read(&beacon->csa_current_counter);
+			int i;
+
 			for (i = 0; i < params->n_csa_offsets; i++)
-				data[params->csa_offsets[i]] =
-					beacon->csa_current_counter;
+				data[params->csa_offsets[i]] = count;
+		}
 
 		rcu_read_unlock();
 	}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 71915a2..69da2d6 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -234,7 +234,7 @@ struct beacon_data {
 	int head_len, tail_len;
 	struct ieee80211_meshconf_ie *meshconf;
 	u16 csa_counter_offset[IEEE80211_MAX_CSA_COUNTERS_NUM];
-	u8 csa_current_counter;
+	atomic_t csa_current_counter;
 	struct rcu_head rcu_head;
 };
 
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index eeeafeb..af59877 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2423,7 +2423,7 @@ static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata,
 	u8 *beacon_data;
 	size_t beacon_data_len;
 	int i;
-	u8 count = beacon->csa_current_counter;
+	u8 count = atomic_read(&beacon->csa_current_counter);
 
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_AP:
@@ -2481,11 +2481,12 @@ u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
 	if (!beacon)
 		goto unlock;
 
-	beacon->csa_current_counter--;
-
+	count = atomic_dec_return(&beacon->csa_current_counter);
 	/* the counter should never reach 0 */
-	WARN_ON_ONCE(!beacon->csa_current_counter);
-	count = beacon->csa_current_counter;
+	if (WARN_ON_ONCE(count <= 0)) {
+		/* prevent it from going negative */
+		atomic_inc(&beacon->csa_current_counter);
+	}
 
 unlock:
 	rcu_read_unlock();
-- 
1.8.5.3

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux