mac80211: Support multiple CSA counters
Support up to IEEE80211_MAX_CSA_COUNTERS_NUM csa counters.
This is defined to be 2 now, to support both CSA and eCSA
counters.
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 263dea5..0d1a42d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2417,10 +2417,9 @@
struct beacon_data *beacon)
{
struct probe_resp *resp;
- int counter_offset_beacon = sdata->csa_counter_offset_beacon;
- int counter_offset_presp = sdata->csa_counter_offset_presp;
u8 *beacon_data;
size_t beacon_data_len;
+ int i;
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
@@ -2438,32 +2437,47 @@
default:
return;
}
- if (WARN_ON(counter_offset_beacon >= beacon_data_len))
- return;
- /* Warn if the driver did not check for/react to csa
- * completeness. A beacon with CSA counter set to 0 should
- * never occur, because a counter of 1 means switch just
- * before the next beacon.
- */
- if (WARN_ON(beacon_data[counter_offset_beacon] == 1))
- return;
+ for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
+ u16 counter_offset_beacon =
+ sdata->csa_counter_offset_beacon[i];
+ u16 counter_offset_presp = sdata->csa_counter_offset_presp[i];
+
+ if (counter_offset_beacon) {
+ if (WARN_ON(counter_offset_beacon >= beacon_data_len))
+ return;
+
+ /* Warn if the driver did not check for/react to csa
+ * completeness. A beacon with CSA counter set to 0
+ * should never occur, because a counter of 1 means
+ * switch just before the next beacon.
+ */
+ if (WARN_ON(beacon_data[counter_offset_beacon] == 1))
+ return;
+
+ beacon_data[counter_offset_beacon] =
+ sdata->csa_current_counter - 1;
+ }
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ counter_offset_presp) {
+ rcu_read_lock();
+ resp = rcu_dereference(sdata->u.ap.probe_resp);
+
+ /* If nl80211 accepted the offset, this should
+ * not happen.
+ */
+ if (WARN_ON(!resp)) {
+ rcu_read_unlock();
+ return;
+ }
+ resp->data[counter_offset_presp] =
+ sdata->csa_current_counter - 1;
+ rcu_read_unlock();
+ }
+ }
sdata->csa_current_counter--;
- beacon_data[counter_offset_beacon] = sdata->csa_current_counter;
-
- if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) {
- rcu_read_lock();
- resp = rcu_dereference(sdata->u.ap.probe_resp);
-
- /* if nl80211 accepted the offset, this should not happen. */
- if (WARN_ON(!resp)) {
- rcu_read_unlock();
- return;
- }
- resp->data[counter_offset_presp] = sdata->csa_current_counter;
- rcu_read_unlock();
- }
}
bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
@@ -2472,7 +2486,7 @@
struct beacon_data *beacon = NULL;
u8 *beacon_data;
size_t beacon_data_len;
- int counter_beacon = sdata->csa_counter_offset_beacon;
+ int counter_beacon = sdata->csa_counter_offset_beacon[0];
int ret = false;
if (!ieee80211_sdata_running(sdata))