summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Greenman <gregory.greenman@intel.com>2018-04-20 13:49:24 +0300
committerJohannes Berg <johannes.berg@intel.com>2018-05-07 20:50:15 +0200
commit03737001e463d458c13510fcb64179b3368aaeee (patch)
treed3806e1452b144726562b5b77ddb09ad4f2e3575
parenta403f3bf6390f085b7864814fb17567718c5a22c (diff)
mac80211: add api to set CSA counter in mac80211
Sometimes the most updated CSA counter values are known only to the device. Add an API to pass this data to mac80211. Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/mac80211.h13
-rw-r--r--net/mac80211/tx.c25
2 files changed, 38 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d2279b2d61aa..52f36c43f35f 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4450,6 +4450,19 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif);
/**
+ * ieee80211_csa_set_counter - request mac80211 to set csa counter
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @counter: the new value for the counter
+ *
+ * The csa counter can be changed by the device, this API should be
+ * used by the device driver to update csa counter in mac80211.
+ *
+ * It should never be used together with ieee80211_csa_update_counter(),
+ * as it will cause a race condition around the counter value.
+ */
+void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter);
+
+/**
* ieee80211_csa_finish - notify mac80211 about channel switch
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
*
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 535de3161a78..062e125a324c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4084,6 +4084,31 @@ unlock:
}
EXPORT_SYMBOL(ieee80211_csa_update_counter);
+void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct beacon_data *beacon = NULL;
+
+ rcu_read_lock();
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ beacon = rcu_dereference(sdata->u.ap.beacon);
+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+ beacon = rcu_dereference(sdata->u.ibss.presp);
+ else if (ieee80211_vif_is_mesh(&sdata->vif))
+ beacon = rcu_dereference(sdata->u.mesh.beacon);
+
+ if (!beacon)
+ goto unlock;
+
+ if (counter < beacon->csa_current_counter)
+ beacon->csa_current_counter = counter;
+
+unlock:
+ rcu_read_unlock();
+}
+EXPORT_SYMBOL(ieee80211_csa_set_counter);
+
bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);