2018-02-16 16:13:09

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 00/13] cfg80211/mac80211 patches from our internal tree 2018-02-16

From: Luca Coelho <[email protected]>

Hi,

Some patches with mac80211 and cfg80211 changes from our internal
tree.

Please review, though you have already reviewed most if not all of
them ;)

Cheers,
Luca.


Avraham Stern (1):
cfg80211: clear wep keys after disconnection

Haim Dreyfuss (3):
cfg80211: read wmm rules from regulatory database
mac80211: limit wmm params to comply with ETSI requirements
cfg80211: Add API to allow querying regdb for wmm_rule

Ilan Peer (4):
mac80211: Call mgd_prep_tx before transmitting deauthentication
mac80211: Do not disconnect on invalid operating class
mac80211: Fix sending ADDBA response for an ongoing session
mac80211: agg-rx: Accept ADDBA request update if timeout did not
change

Johannes Berg (1):
mac80211: support reporting A-MPDU EOF bit value/known

Sara Sharon (4):
mac80211: fix a possible leak of station stats
mac80211: ibss: send a probe request instead of allocating station
mac80211: fix calling sleeping function in atomic context
mac80211: add get TID helper

include/linux/ieee80211.h | 12 +++
include/net/cfg80211.h | 28 ++++++
include/net/ieee80211_radiotap.h | 2 +
include/net/mac80211.h | 18 ++++
include/net/regulatory.h | 28 ++++++
net/mac80211/agg-rx.c | 13 ++-
net/mac80211/cfg.c | 3 +
net/mac80211/debugfs.c | 1 +
net/mac80211/ibss.c | 54 +---------
net/mac80211/ieee80211_i.h | 7 +-
net/mac80211/iface.c | 3 +-
net/mac80211/michael.c | 2 +-
net/mac80211/mlme.c | 19 +++-
net/mac80211/rc80211_minstrel_ht.c | 2 +-
net/mac80211/rx.c | 10 +-
net/mac80211/spectmgmt.c | 7 +-
net/mac80211/sta_info.c | 3 +-
net/mac80211/tx.c | 9 +-
net/mac80211/util.c | 40 ++++++++
net/mac80211/wpa.c | 8 +-
net/wireless/reg.c | 200 +++++++++++++++++++++++++++++++++++--
net/wireless/sme.c | 2 +
22 files changed, 380 insertions(+), 91 deletions(-)

--
2.15.1


2018-02-16 16:18:25

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 13/13] cfg80211: Add API to allow querying regdb for wmm_rule

From: Haim Dreyfuss <[email protected]>

In general regulatory self managed devices maintain their own
regulatory profiles thus it doesn't have to query the regulatory database
on country change.

ETSI has recently introduced a new channel access mechanism for 5GHz
that all wlan devices need to comply with.
These values are stored in the regulatory database.
There are self managed devices which can't maintain these
values on their own. Add API to allow self managed regulatory devices
to query the regulatory database for high band wmm rule.

Signed-off-by: Haim Dreyfuss <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/cfg80211.h | 28 ++++++++++++++++++++++++++
net/wireless/reg.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7d49cd0cf92d..647cb33e738a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6,6 +6,7 @@
* Copyright 2006-2010 Johannes Berg <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -4653,6 +4654,33 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
*/
const char *reg_initiator_name(enum nl80211_reg_initiator initiator);

+/**
+ * DOC: Internal regulatory db functions
+ *
+ */
+
+/**
+ * reg_query_regdb_wmm - Query internal regulatory db for wmm rule
+ * Regulatory self-managed driver can use it to proactively
+ *
+ * @alpha2: the ISO/IEC 3166 alpha2 wmm rule to be queried.
+ * @freq: the freqency(in MHz) to be queried.
+ * @dbptr: pointer where the regdb wmm data is to be stored (or %NULL if
+ * irrelevant). This can be used later for deduplication.
+ * @rule: pointer to store the wmm rule from the regulatory db.
+ *
+ * Self-managed wireless drivers can use this function to query
+ * the internal regulatory database to check whether the given
+ * ISO/IEC 3166 alpha2 country and freq have wmm rule limitations.
+ *
+ * Drivers should check the return value, its possible you can get
+ * an -ENODATA.
+ *
+ * Return: 0 on success. -ENODATA.
+ */
+int reg_query_regdb_wmm(char *alpha2, int freq, u32 *ptr,
+ struct ieee80211_wmm_rule *rule);
+
/*
* callbacks for asynchronous cfg80211 methods, notification
* functions and BSS handling helpers
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7c7c0e0f8d9d..1896394c6e7f 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -878,6 +878,60 @@ static void set_wmm_rule(struct ieee80211_wmm_rule *rule,
}
}

+static int __regdb_query_wmm(const struct fwdb_header *db,
+ const struct fwdb_country *country, int freq,
+ u32 *dbptr, struct ieee80211_wmm_rule *rule)
+{
+ unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
+ struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
+ int i;
+
+ for (i = 0; i < coll->n_rules; i++) {
+ __be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
+ unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
+ struct fwdb_rule *rrule = (void *)((u8 *)db + rule_ptr);
+ struct fwdb_wmm_rule *wmm;
+ unsigned int wmm_ptr;
+
+ if (rrule->len < offsetofend(struct fwdb_rule, wmm_ptr))
+ continue;
+
+ if (freq >= KHZ_TO_MHZ(be32_to_cpu(rrule->start)) &&
+ freq <= KHZ_TO_MHZ(be32_to_cpu(rrule->end))) {
+ wmm_ptr = be16_to_cpu(rrule->wmm_ptr) << 2;
+ wmm = (void *)((u8 *)db + wmm_ptr);
+ set_wmm_rule(rule, wmm);
+ if (dbptr)
+ *dbptr = wmm_ptr;
+ return 0;
+ }
+ }
+
+ return -ENODATA;
+}
+
+int reg_query_regdb_wmm(char *alpha2, int freq, u32 *dbptr,
+ struct ieee80211_wmm_rule *rule)
+{
+ const struct fwdb_header *hdr = regdb;
+ const struct fwdb_country *country;
+
+ if (IS_ERR(regdb))
+ return PTR_ERR(regdb);
+
+ country = &hdr->country[0];
+ while (country->coll_ptr) {
+ if (alpha2_equal(alpha2, country->alpha2))
+ return __regdb_query_wmm(regdb, country, freq, dbptr,
+ rule);
+
+ country++;
+ }
+
+ return -ENODATA;
+}
+EXPORT_SYMBOL(reg_query_regdb_wmm);
+
struct wmm_ptrs {
struct ieee80211_wmm_rule *rule;
u32 ptr;
--
2.15.1

2018-02-16 16:13:14

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 06/13] mac80211: add get TID helper

From: Sara Sharon <[email protected]>

Extracting the TID from the QOS header is common enough
to justify helper.

Signed-off-by: Sara Sharon <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/linux/ieee80211.h | 12 ++++++++++++
net/mac80211/iface.c | 3 +--
net/mac80211/michael.c | 2 +-
net/mac80211/mlme.c | 2 +-
net/mac80211/rc80211_minstrel_ht.c | 2 +-
net/mac80211/rx.c | 6 ++----
net/mac80211/tx.c | 9 ++-------
net/mac80211/wpa.c | 8 +++-----
8 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index ee6657a0ed69..b35736c6e85c 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -8,6 +8,7 @@
* Copyright (c) 2006, Michael Wu <[email protected]>
* Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright (c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright (c) 2018 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -2501,6 +2502,17 @@ static inline u8 *ieee80211_get_qos_ctl(struct ieee80211_hdr *hdr)
return (u8 *)hdr + 24;
}

+/**
+ * ieee80211_get_tid - get qos TID
+ * @hdr: the frame
+ */
+static inline u8 ieee80211_get_tid(struct ieee80211_hdr *hdr)
+{
+ u8 *qc = ieee80211_get_qos_ctl(hdr);
+
+ return qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+}
+
/**
* ieee80211_get_SA - get pointer to SA
* @hdr: the frame
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 5fe01f82df12..d13ba064951f 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1324,8 +1324,7 @@ static void ieee80211_iface_work(struct work_struct *work)
mutex_lock(&local->sta_mtx);
sta = sta_info_get_bss(sdata, mgmt->sa);
if (sta) {
- u16 tid = *ieee80211_get_qos_ctl(hdr) &
- IEEE80211_QOS_CTL_TID_MASK;
+ u16 tid = ieee80211_get_tid(hdr);

__ieee80211_stop_rx_ba_session(
sta, tid, WLAN_BACK_RECIPIENT,
diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c
index 408649bd4702..37e172701a63 100644
--- a/net/mac80211/michael.c
+++ b/net/mac80211/michael.c
@@ -35,7 +35,7 @@ static void michael_mic_hdr(struct michael_mic_ctx *mctx, const u8 *key,
da = ieee80211_get_DA(hdr);
sa = ieee80211_get_SA(hdr);
if (ieee80211_is_data_qos(hdr->frame_control))
- tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ tid = ieee80211_get_tid(hdr);
else
tid = 0;

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 39b660b9a908..010b127a3937 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2151,7 +2151,7 @@ static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
u16 tx_time)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- u16 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ u16 tid = ieee80211_get_tid(hdr);
int ac = ieee80211_ac_from_tid(tid);
struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
unsigned long now = jiffies;
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 4a5bdad9f303..fb586b6e5d49 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -669,7 +669,7 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb)
if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
return;

- tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ tid = ieee80211_get_tid(hdr);
if (likely(sta->ampdu_mlme.tid_tx[tid]))
return;

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 478a9c735edb..3dc162ddc3a6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1189,7 +1189,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,

ack_policy = *ieee80211_get_qos_ctl(hdr) &
IEEE80211_QOS_CTL_ACK_POLICY_MASK;
- tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ tid = ieee80211_get_tid(hdr);

tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
if (!tid_agg_rx) {
@@ -1528,9 +1528,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
ieee80211_has_pm(hdr->frame_control) &&
(ieee80211_is_data_qos(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control))) {
- u8 tid;
-
- tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ u8 tid = ieee80211_get_tid(hdr);

ieee80211_sta_uapsd_trigger(&rx->sta->sta, tid);
}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 25904af38839..c3c66c673428 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -797,7 +797,6 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
- u8 *qc;
int tid;

/*
@@ -844,9 +843,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
return TX_CONTINUE;

/* include per-STA, per-TID sequence counter */
-
- qc = ieee80211_get_qos_ctl(hdr);
- tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
+ tid = ieee80211_get_tid(hdr);
tx->sta->tx_stats.msdu[tid]++;

hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid);
@@ -1158,7 +1155,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int tid;
- u8 *qc;

memset(tx, 0, sizeof(*tx));
tx->skb = skb;
@@ -1198,8 +1194,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
!ieee80211_hw_check(&local->hw, TX_AMPDU_SETUP_IN_HW)) {
struct tid_ampdu_tx *tid_tx;

- qc = ieee80211_get_qos_ctl(hdr);
- tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
+ tid = ieee80211_get_tid(hdr);

tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]);
if (tid_tx) {
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 785056cb76f6..58d0b258b684 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -340,7 +340,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
a4_included = ieee80211_has_a4(hdr->frame_control);

if (ieee80211_is_data_qos(hdr->frame_control))
- qos_tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
+ qos_tid = ieee80211_get_tid(hdr);
else
qos_tid = 0;

@@ -601,8 +601,7 @@ static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad)
aad[23] = 0;

if (ieee80211_is_data_qos(hdr->frame_control))
- qos_tid = *ieee80211_get_qos_ctl(hdr) &
- IEEE80211_QOS_CTL_TID_MASK;
+ qos_tid = ieee80211_get_tid(hdr);
else
qos_tid = 0;

@@ -867,8 +866,7 @@ ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx)
return RX_DROP_UNUSABLE;

if (ieee80211_is_data_qos(hdr->frame_control))
- qos_tid = *ieee80211_get_qos_ctl(hdr) &
- IEEE80211_QOS_CTL_TID_MASK;
+ qos_tid = ieee80211_get_tid(hdr);
else
qos_tid = 0;

--
2.15.1

2018-02-16 16:13:11

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 03/13] mac80211: fix calling sleeping function in atomic context

From: Sara Sharon <[email protected]>

sta_info_alloc can be called from atomic paths (such as RX path)
so we need to call pcpu_alloc with the correct gfp.

Fixes: c9c5962b56c1 ("mac80211: enable collecting station statistics per-CPU")
Signed-off-by: Sara Sharon <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
net/mac80211/sta_info.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 8d7e3732bb61..af0b608ee8ed 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -314,7 +314,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,

if (ieee80211_hw_check(hw, USES_RSS)) {
sta->pcpu_rx_stats =
- alloc_percpu(struct ieee80211_sta_rx_stats);
+ alloc_percpu_gfp(struct ieee80211_sta_rx_stats, gfp);
if (!sta->pcpu_rx_stats)
goto free;
}
--
2.15.1

2018-02-19 07:04:27

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 10/13] mac80211: agg-rx: Accept ADDBA request update if timeout did not change

Hi Ilan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mac80211-next/master]
[also build test WARNING on v4.16-rc2 next-20180216]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Luca-Coelho/cfg80211-mac80211-patches-from-our-internal-tree-2018-02-16/20180219-114128
base: https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

>> net/mac80211/agg-rx.c:309:51: sparse: dereference of noderef expression

vim +309 net/mac80211/agg-rx.c

230
231 void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
232 u8 dialog_token, u16 timeout,
233 u16 start_seq_num, u16 ba_policy, u16 tid,
234 u16 buf_size, bool tx, bool auto_seq)
235 {
236 struct ieee80211_local *local = sta->sdata->local;
237 struct tid_ampdu_rx *tid_agg_rx;
238 struct ieee80211_ampdu_params params = {
239 .sta = &sta->sta,
240 .action = IEEE80211_AMPDU_RX_START,
241 .tid = tid,
242 .amsdu = false,
243 .timeout = timeout,
244 .ssn = start_seq_num,
245 };
246 int i, ret = -EOPNOTSUPP;
247 u16 status = WLAN_STATUS_REQUEST_DECLINED;
248
249 if (tid >= IEEE80211_FIRST_TSPEC_TSID) {
250 ht_dbg(sta->sdata,
251 "STA %pM requests BA session on unsupported tid %d\n",
252 sta->sta.addr, tid);
253 goto end;
254 }
255
256 if (!sta->sta.ht_cap.ht_supported) {
257 ht_dbg(sta->sdata,
258 "STA %pM erroneously requests BA session on tid %d w/o QoS\n",
259 sta->sta.addr, tid);
260 /* send a response anyway, it's an error case if we get here */
261 goto end;
262 }
263
264 if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
265 ht_dbg(sta->sdata,
266 "Suspend in progress - Denying ADDBA request (%pM tid %d)\n",
267 sta->sta.addr, tid);
268 goto end;
269 }
270
271 /* sanity check for incoming parameters:
272 * check if configuration can support the BA policy
273 * and if buffer size does not exceeds max value */
274 /* XXX: check own ht delayed BA capability?? */
275 if (((ba_policy != 1) &&
276 (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) ||
277 (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
278 status = WLAN_STATUS_INVALID_QOS_PARAM;
279 ht_dbg_ratelimited(sta->sdata,
280 "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
281 sta->sta.addr, tid, ba_policy, buf_size);
282 goto end;
283 }
284 /* determine default buffer size */
285 if (buf_size == 0)
286 buf_size = IEEE80211_MAX_AMPDU_BUF;
287
288 /* make sure the size doesn't exceed the maximum supported by the hw */
289 if (buf_size > sta->sta.max_rx_aggregation_subframes)
290 buf_size = sta->sta.max_rx_aggregation_subframes;
291 params.buf_size = buf_size;
292
293 ht_dbg(sta->sdata, "AddBA Req buf_size=%d for %pM\n",
294 buf_size, sta->sta.addr);
295
296 /* examine state machine */
297 lockdep_assert_held(&sta->ampdu_mlme.mtx);
298
299 if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
300 if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
301 ht_dbg_ratelimited(sta->sdata,
302 "updated AddBA Req from %pM on tid %u\n",
303 sta->sta.addr, tid);
304 /* We have no API to update the timeout value in the
305 * driver so reject the timeout update if the timeout
306 * changed. If if did not change, i.e., no real update,
307 * just reply with success.
308 */
> 309 if (sta->ampdu_mlme.tid_rx[tid]->timeout == timeout)
310 status = WLAN_STATUS_SUCCESS;
311 else
312 status = WLAN_STATUS_REQUEST_DECLINED;
313 goto end;
314 }
315
316 ht_dbg_ratelimited(sta->sdata,
317 "unexpected AddBA Req from %pM on tid %u\n",
318 sta->sta.addr, tid);
319
320 /* delete existing Rx BA session on the same tid */
321 ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
322 WLAN_STATUS_UNSPECIFIED_QOS,
323 false);
324 }
325
326 if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) {
327 ret = drv_ampdu_action(local, sta->sdata, &params);
328 ht_dbg(sta->sdata,
329 "Rx A-MPDU request on %pM tid %d result %d\n",
330 sta->sta.addr, tid, ret);
331 if (!ret)
332 status = WLAN_STATUS_SUCCESS;
333 goto end;
334 }
335
336 /* prepare A-MPDU MLME for Rx aggregation */
337 tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
338 if (!tid_agg_rx)
339 goto end;
340
341 spin_lock_init(&tid_agg_rx->reorder_lock);
342
343 /* rx timer */
344 timer_setup(&tid_agg_rx->session_timer,
345 sta_rx_agg_session_timer_expired, TIMER_DEFERRABLE);
346
347 /* rx reorder timer */
348 timer_setup(&tid_agg_rx->reorder_timer,
349 sta_rx_agg_reorder_timer_expired, 0);
350
351 /* prepare reordering buffer */
352 tid_agg_rx->reorder_buf =
353 kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL);
354 tid_agg_rx->reorder_time =
355 kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
356 if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
357 kfree(tid_agg_rx->reorder_buf);
358 kfree(tid_agg_rx->reorder_time);
359 kfree(tid_agg_rx);
360 goto end;
361 }
362
363 for (i = 0; i < buf_size; i++)
364 __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
365
366 ret = drv_ampdu_action(local, sta->sdata, &params);
367 ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
368 sta->sta.addr, tid, ret);
369 if (ret) {
370 kfree(tid_agg_rx->reorder_buf);
371 kfree(tid_agg_rx->reorder_time);
372 kfree(tid_agg_rx);
373 goto end;
374 }
375
376 /* update data */
377 tid_agg_rx->ssn = start_seq_num;
378 tid_agg_rx->head_seq_num = start_seq_num;
379 tid_agg_rx->buf_size = buf_size;
380 tid_agg_rx->timeout = timeout;
381 tid_agg_rx->stored_mpdu_num = 0;
382 tid_agg_rx->auto_seq = auto_seq;
383 tid_agg_rx->started = false;
384 tid_agg_rx->reorder_buf_filtered = 0;
385 tid_agg_rx->tid = tid;
386 tid_agg_rx->sta = sta;
387 status = WLAN_STATUS_SUCCESS;
388
389 /* activate it for RX */
390 rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
391
392 if (timeout) {
393 mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
394 tid_agg_rx->last_rx = jiffies;
395 }
396
397 end:
398 if (status == WLAN_STATUS_SUCCESS) {
399 __set_bit(tid, sta->ampdu_mlme.agg_session_valid);
400 __clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
401 sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
402 }
403
404 if (tx)
405 ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
406 dialog_token, status, 1, buf_size,
407 timeout);
408 }
409

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

2018-02-16 16:13:15

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 07/13] mac80211: Call mgd_prep_tx before transmitting deauthentication

From: Ilan Peer <[email protected]>

In multi channel scenarios, when disassociating from the AP before a
beacon was heard from the AP, it is not guaranteed that the virtual
interface is granted air time for the transmission of the
deauthentication frame. This in turn can lead to various issues as
the AP might never get the deauthentication frame.

To mitigate such possible issues, add a HW flag indicating that the
driver requires mac80211 to call the mgd_prep_tx() driver callback
to make sure that the virtual interface is granted immediate airtime
to be able to transmit the frame, in case that no beacon was heard
from the AP.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/mac80211.h | 13 +++++++++++++
net/mac80211/debugfs.c | 1 +
net/mac80211/mlme.c | 16 +++++++++++++++-
3 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7efac7f98e45..c27c59650da8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6,6 +6,7 @@
* Copyright 2007-2010 Johannes Berg <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -2068,6 +2069,14 @@ struct ieee80211_txq {
* @IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA: Hardware supports buffer STA on
* TDLS links.
*
+ * @IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP: The driver requires the
+ * mgd_prepare_tx() callback to be called before transmission of a
+ * deauthentication frame in case the association was completed but no
+ * beacon was heard. This is required in multi-channel scenarios, where the
+ * virtual interface might not be given air time for the transmission of
+ * the frame, as it is not synced with the AP/P2P GO yet, and thus the
+ * deauthentication frame might not be transmitted.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2111,6 +2120,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_REPORTS_LOW_ACK,
IEEE80211_HW_SUPPORTS_TX_FRAG,
IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA,
+ IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP,

/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
@@ -3355,6 +3365,9 @@ enum ieee80211_reconfig_type {
* management frame prior to having successfully associated to allow the
* driver to give it channel time for the transmission, to get a response
* and to be able to synchronize with the GO.
+ * For drivers that set %IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP, mac80211
+ * would also call this function before transmitting a deauthentication
+ * frame in case that no beacon was heard from the AP/P2P GO.
* The callback will be called before each transmission and upon return
* mac80211 will transmit the frame right away.
* The callback is optional and can (should!) sleep.
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 1f466d12a6bc..a75653affbf7 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -212,6 +212,7 @@ static const char *hw_flag_names[] = {
FLAG(REPORTS_LOW_ACK),
FLAG(SUPPORTS_TX_FRAG),
FLAG(SUPPORTS_TDLS_BUFFER_STA),
+ FLAG(DEAUTH_NEED_MGD_TX_PREP),
#undef FLAG
};

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 010b127a3937..0024eff9bb84 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -7,6 +7,7 @@
* Copyright 2007, Michael Wu <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -2008,9 +2009,22 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_flush_queues(local, sdata, true);

/* deauthenticate/disassociate now */
- if (tx || frame_buf)
+ if (tx || frame_buf) {
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+ /*
+ * In multi channel scenarios guarantee that the virtual
+ * interface is granted immediate airtime to transmit the
+ * deauthentication frame by calling mgd_prepare_tx, if the
+ * driver requested so.
+ */
+ if (ieee80211_hw_check(&local->hw, DEAUTH_NEED_MGD_TX_PREP) &&
+ !ifmgd->have_beacon)
+ drv_mgd_prepare_tx(sdata->local, sdata);
+
ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype,
reason, tx, frame_buf);
+ }

/* flush out frame - make sure the deauth was actually sent */
if (tx)
--
2.15.1

2018-02-16 16:16:45

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 10/13] mac80211: agg-rx: Accept ADDBA request update if timeout did not change

From: Ilan Peer <[email protected]>

As there is no support for updating an existing ADDBA session with
a peer, we decline the request (while keeping the session active).
However, in case that the timeout did not change, there is no need
to decline the request, so modify the code to reply with status success
in such a case (this is useful for interoperability with APs that send an
ADDBA request update without changing the timeout value).

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
net/mac80211/agg-rx.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 1f3188d03840..420710894d6d 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -302,9 +302,14 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
"updated AddBA Req from %pM on tid %u\n",
sta->sta.addr, tid);
/* We have no API to update the timeout value in the
- * driver so reject the timeout update.
+ * driver so reject the timeout update if the timeout
+ * changed. If if did not change, i.e., no real update,
+ * just reply with success.
*/
- status = WLAN_STATUS_REQUEST_DECLINED;
+ if (sta->ampdu_mlme.tid_rx[tid]->timeout == timeout)
+ status = WLAN_STATUS_SUCCESS;
+ else
+ status = WLAN_STATUS_REQUEST_DECLINED;
goto end;
}

--
2.15.1

2018-02-19 12:58:57

by Luca Coelho

[permalink] [raw]
Subject: Re: [PATCH 02/13] mac80211: ibss: send a probe request instead of allocating station

On Mon, 2018-02-19 at 10:02 +0100, Nicolas Cavallari wrote:
> On 16/02/2018 17:12, Luca Coelho wrote:
> > - sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
> > - if (!sta)
> > - return;
> >
> > - /* make sure mandatory rates are always added */
> > - sband = local->hw.wiphy->bands[band];
> > - sta->sta.supp_rates[band] = supp_rates |
> > - ieee80211_mandatory_rates(sband,
> > scan_width);
> > -
> > - spin_lock(&ifibss->incomplete_lock);
> > - list_add(&sta->list, &ifibss->incomplete_stations);
> > - spin_unlock(&ifibss->incomplete_lock);
> > - ieee80211_queue_work(&local->hw, &sdata->work);
> > + ieee80211_send_probe_req(sdata, sdata->vif.addr, addr,
> > + sdata->u.ibss.ssid, sdata-
> > >u.ibss.ssid_len,
> > + NULL, 0, (u32)-1, true, 0,
> > + chanctx_conf->def.chan, false);
> > + rcu_read_unlock();
> > }
>
> Won't that spam the channel with probe request if the traffic from
> the
> other station is heavy ?
>
> And, if the other station is running the same code and didn't know
> about us (e.g. at join time), won't it also spam the channel with
> probe requests after receiving our many probe requests ? (as well as
> the probe responses from both stations)
>
> Obviously it should stop after receiving a probe response... But what
> if the link is badly asymmetric ?

Sari, can you please look into this?

--
Cheers,
Luca.

2018-02-16 16:13:12

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 04/13] cfg80211: clear wep keys after disconnection

From: Avraham Stern <[email protected]>

When a low level driver calls cfg80211_disconnected(), wep keys are
not cleared. As a result, following connection requests will fail
since cfg80211 internal state shows a connection is still in progress.

Fix this by clearing the wep keys when disconnecting.

Signed-off-by: Avraham Stern <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
net/wireless/sme.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index fdb3646274a5..701cfd7acc1b 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -1032,6 +1032,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
wdev->current_bss = NULL;
wdev->ssid_len = 0;
wdev->conn_owner_nlportid = 0;
+ kzfree(wdev->connect_keys);
+ wdev->connect_keys = NULL;

nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);

--
2.15.1

2018-02-16 16:13:16

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 09/13] mac80211: Fix sending ADDBA response for an ongoing session

From: Ilan Peer <[email protected]>

In case an ADDBA request is received while there is already
an ongoing BA sessions with the same parameters, i.e., update
flow, an ADBBA response with decline status was sent twice. Fix it.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
net/mac80211/agg-rx.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index a8b1616cec41..1f3188d03840 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -8,6 +8,7 @@
* Copyright 2007, Michael Wu <[email protected]>
* Copyright 2007-2010, Intel Corporation
* Copyright(c) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -304,9 +305,6 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
* driver so reject the timeout update.
*/
status = WLAN_STATUS_REQUEST_DECLINED;
- ieee80211_send_addba_resp(sta->sdata, sta->sta.addr,
- tid, dialog_token, status,
- 1, buf_size, timeout);
goto end;
}

--
2.15.1

2018-02-19 06:35:56

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 12/13] mac80211: limit wmm params to comply with ETSI requirements

On Mon, 2018-02-19 at 07:54 +0200, Kalle Valo wrote:
> Luca Coelho <[email protected]> writes:
>
> > From: Haim Dreyfuss <[email protected]>
> >
> > ETSI has recently restricted the WMM parameters values for
> > 5GHz frequencies. There are two scenarios which may cause
> > to violate ETSI requirements.
> > 1. Using mac80211 default values.
> > 2. Userspace entity tries to configure its own values
> > 2. Associating to AP which advertises WWM IE.
>
> Only two? Also the numbering is interesting :)
>
> > In the latter case
>
> In the last case?

Huh, how did I miss this stuff? Johannes, do you want me to resend or
will you fix it when you take this?

--
Cheers,
Luca.

2018-02-16 16:13:09

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 01/13] mac80211: fix a possible leak of station stats

From: Sara Sharon <[email protected]>

If sta_info_alloc fails after allocating the per CPU statistics,
they are not properly freed.

Fixes: c9c5962b56c1 ("mac80211: enable collecting station statistics per-CPU")
Signed-off-by: Sara Sharon <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
net/mac80211/sta_info.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 0c5627f8a104..8d7e3732bb61 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -433,6 +433,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
if (sta->sta.txq[0])
kfree(to_txq_info(sta->sta.txq[0]));
free:
+ free_percpu(sta->pcpu_rx_stats);
#ifdef CONFIG_MAC80211_MESH
kfree(sta->mesh);
#endif
--
2.15.1

2018-02-16 16:15:04

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 11/13] cfg80211: read wmm rules from regulatory database

From: Haim Dreyfuss <[email protected]>

ETSI EN 301 893 v211 (2017-05) standard defines a new channel access
mechanism that all devices (WLAN and LAA) need to comply with.
The regulatory database can now be loaded into the kernel and also
has the option to load optional data.
In order to be able to comply with ETSI standard, we add wmm_rule into
regulatory rule and add the option to read its value from the regulatory
database.

Signed-off-by: Haim Dreyfuss <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/regulatory.h | 28 +++++++++
net/wireless/reg.c | 146 ++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 167 insertions(+), 7 deletions(-)

diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index ebc5a2ed8631..355b23ad146c 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -4,6 +4,7 @@
* regulatory support structures
*
* Copyright 2008-2009 Luis R. Rodriguez <[email protected]>
+ * Copyright (C) 2018 Intel Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -188,9 +189,35 @@ struct ieee80211_power_rule {
u32 max_eirp;
};

+/**
+ * struct ieee80211_wmm_ac - used to store per ac wmm regulatory limitation
+ *
+ * The information provided in this structure is required for QoS
+ * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
+ *
+ * @cw_min: minimum contention window [a value of the form
+ * 2^n-1 in the range 1..32767]
+ * @cw_max: maximum contention window [like @cw_min]
+ * @cot: maximum burst time in units of 32 usecs, 0 meaning disabled
+ * @aifsn: arbitration interframe space [0..255]
+ *
+ */
+struct ieee80211_wmm_ac {
+ u16 cw_min;
+ u16 cw_max;
+ u16 cot;
+ u8 aifsn;
+};
+
+struct ieee80211_wmm_rule {
+ struct ieee80211_wmm_ac client[IEEE80211_NUM_ACS];
+ struct ieee80211_wmm_ac ap[IEEE80211_NUM_ACS];
+};
+
struct ieee80211_reg_rule {
struct ieee80211_freq_range freq_range;
struct ieee80211_power_rule power_rule;
+ struct ieee80211_wmm_rule *wmm_rule;
u32 flags;
u32 dfs_cac_ms;
};
@@ -198,6 +225,7 @@ struct ieee80211_reg_rule {
struct ieee80211_regdomain {
struct rcu_head rcu_head;
u32 n_reg_rules;
+ u32 n_wmm_rules;
char alpha2[3];
enum nl80211_dfs_regions dfs_region;
struct ieee80211_reg_rule reg_rules[];
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7b42f0bacfd8..7c7c0e0f8d9d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -5,6 +5,7 @@
* Copyright 2008-2011 Luis R. Rodriguez <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -424,23 +425,36 @@ static const struct ieee80211_regdomain *
reg_copy_regd(const struct ieee80211_regdomain *src_regd)
{
struct ieee80211_regdomain *regd;
- int size_of_regd;
+ int size_of_regd, size_of_wmms;
unsigned int i;
+ struct ieee80211_wmm_rule *d_wmm, *s_wmm;

size_of_regd =
sizeof(struct ieee80211_regdomain) +
src_regd->n_reg_rules * sizeof(struct ieee80211_reg_rule);
+ size_of_wmms = src_regd->n_wmm_rules *
+ sizeof(struct ieee80211_wmm_rule);

- regd = kzalloc(size_of_regd, GFP_KERNEL);
+ regd = kzalloc(size_of_regd + size_of_wmms, GFP_KERNEL);
if (!regd)
return ERR_PTR(-ENOMEM);

memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain));

- for (i = 0; i < src_regd->n_reg_rules; i++)
+ d_wmm = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd);
+ s_wmm = (struct ieee80211_wmm_rule *)((u8 *)src_regd + size_of_regd);
+ memcpy(d_wmm, s_wmm, size_of_wmms);
+
+ for (i = 0; i < src_regd->n_reg_rules; i++) {
memcpy(&regd->reg_rules[i], &src_regd->reg_rules[i],
sizeof(struct ieee80211_reg_rule));
+ if (!src_regd->reg_rules[i].wmm_rule)
+ continue;

+ regd->reg_rules[i].wmm_rule = d_wmm +
+ (src_regd->reg_rules[i].wmm_rule - s_wmm) /
+ sizeof(struct ieee80211_wmm_rule);
+ }
return regd;
}

@@ -595,6 +609,17 @@ enum fwdb_flags {
FWDB_FLAG_AUTO_BW = BIT(4),
};

+struct fwdb_wmm_ac {
+ u8 ecw;
+ u8 aifsn;
+ __be16 cot;
+} __packed;
+
+struct fwdb_wmm_rule {
+ struct fwdb_wmm_ac client[IEEE80211_NUM_ACS];
+ struct fwdb_wmm_ac ap[IEEE80211_NUM_ACS];
+} __packed;
+
struct fwdb_rule {
u8 len;
u8 flags;
@@ -602,6 +627,7 @@ struct fwdb_rule {
__be32 start, end, max_bw;
/* start of optional data */
__be16 cac_timeout;
+ __be16 wmm_ptr;
} __packed __aligned(4);

#define FWDB_MAGIC 0x52474442
@@ -613,6 +639,31 @@ struct fwdb_header {
struct fwdb_country country[];
} __packed __aligned(4);

+static int ecw2cw(int ecw)
+{
+ return (1 << ecw) - 1;
+}
+
+static bool valid_wmm(struct fwdb_wmm_rule *rule)
+{
+ struct fwdb_wmm_ac *ac = (struct fwdb_wmm_ac *)rule;
+ int i;
+
+ for (i = 0; i < IEEE80211_NUM_ACS * 2; i++) {
+ u16 cw_min = ecw2cw((ac[i].ecw & 0xf0) >> 4);
+ u16 cw_max = ecw2cw(ac[i].ecw & 0x0f);
+ u8 aifsn = ac[i].aifsn;
+
+ if (cw_min >= cw_max)
+ return false;
+
+ if (aifsn < 1)
+ return false;
+ }
+
+ return true;
+}
+
static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
{
struct fwdb_rule *rule = (void *)(data + (rule_ptr << 2));
@@ -623,7 +674,18 @@ static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
/* mandatory fields */
if (rule->len < offsetofend(struct fwdb_rule, max_bw))
return false;
+ if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) {
+ u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
+ struct fwdb_wmm_rule *wmm;

+ if (wmm_ptr + sizeof(struct fwdb_wmm_rule) > size)
+ return false;
+
+ wmm = (void *)(data + wmm_ptr);
+
+ if (!valid_wmm(wmm))
+ return false;
+ }
return true;
}

@@ -798,23 +860,62 @@ static bool valid_regdb(const u8 *data, unsigned int size)
return true;
}

+static void set_wmm_rule(struct ieee80211_wmm_rule *rule,
+ struct fwdb_wmm_rule *wmm)
+{
+ unsigned int i;
+
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ rule->client[i].cw_min =
+ ecw2cw((wmm->client[i].ecw & 0xf0) >> 4);
+ rule->client[i].cw_max = ecw2cw(wmm->client[i].ecw & 0x0f);
+ rule->client[i].aifsn = wmm->client[i].aifsn;
+ rule->client[i].cot = 1000 * be16_to_cpu(wmm->client[i].cot);
+ rule->ap[i].cw_min = ecw2cw((wmm->ap[i].ecw & 0xf0) >> 4);
+ rule->ap[i].cw_max = ecw2cw(wmm->ap[i].ecw & 0x0f);
+ rule->ap[i].aifsn = wmm->ap[i].aifsn;
+ rule->ap[i].cot = 1000 * be16_to_cpu(wmm->ap[i].cot);
+ }
+}
+
+struct wmm_ptrs {
+ struct ieee80211_wmm_rule *rule;
+ u32 ptr;
+};
+
+static struct ieee80211_wmm_rule *find_wmm_ptr(struct wmm_ptrs *wmm_ptrs,
+ u32 wmm_ptr, int n_wmms)
+{
+ int i;
+
+ for (i = 0; i < n_wmms; i++) {
+ if (wmm_ptrs[i].ptr == wmm_ptr)
+ return wmm_ptrs[i].rule;
+ }
+ return NULL;
+}
+
static int regdb_query_country(const struct fwdb_header *db,
const struct fwdb_country *country)
{
unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
struct ieee80211_regdomain *regdom;
- unsigned int size_of_regd;
- unsigned int i;
+ struct ieee80211_regdomain *tmp_rd;
+ unsigned int size_of_regd, i, n_wmms = 0;
+ struct wmm_ptrs *wmm_ptrs;

- size_of_regd =
- sizeof(struct ieee80211_regdomain) +
+ size_of_regd = sizeof(struct ieee80211_regdomain) +
coll->n_rules * sizeof(struct ieee80211_reg_rule);

regdom = kzalloc(size_of_regd, GFP_KERNEL);
if (!regdom)
return -ENOMEM;

+ wmm_ptrs = kcalloc(coll->n_rules, sizeof(*wmm_ptrs), GFP_KERNEL);
+ if (!wmm_ptrs)
+ return -ENOMEM;
+
regdom->n_reg_rules = coll->n_rules;
regdom->alpha2[0] = country->alpha2[0];
regdom->alpha2[1] = country->alpha2[1];
@@ -851,7 +952,38 @@ static int regdb_query_country(const struct fwdb_header *db,
if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout))
rrule->dfs_cac_ms =
1000 * be16_to_cpu(rule->cac_timeout);
+ if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) {
+ u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
+ struct ieee80211_wmm_rule *wmm_pos =
+ find_wmm_ptr(wmm_ptrs, wmm_ptr, n_wmms);
+ struct fwdb_wmm_rule *wmm;
+ struct ieee80211_wmm_rule *wmm_rule;
+
+ if (wmm_pos) {
+ rrule->wmm_rule = wmm_pos;
+ continue;
+ }
+ wmm = (void *)((u8 *)db + wmm_ptr);
+ tmp_rd = krealloc(regdom, size_of_regd + (n_wmms + 1) *
+ sizeof(struct ieee80211_wmm_rule),
+ GFP_KERNEL);
+
+ if (!tmp_rd) {
+ kfree(regdom);
+ return -ENOMEM;
+ }
+ regdom = tmp_rd;
+
+ wmm_rule = (struct ieee80211_wmm_rule *)
+ ((u8 *)regdom + size_of_regd + n_wmms *
+ sizeof(struct ieee80211_wmm_rule));
+
+ set_wmm_rule(wmm_rule, wmm);
+ wmm_ptrs[n_wmms].ptr = wmm_ptr;
+ wmm_ptrs[n_wmms++].rule = wmm_rule;
+ }
}
+ kfree(wmm_ptrs);

return reg_schedule_apply(regdom);
}
--
2.15.1

2018-02-16 16:13:24

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 12/13] mac80211: limit wmm params to comply with ETSI requirements

From: Haim Dreyfuss <[email protected]>

ETSI has recently restricted the WMM parameters values for
5GHz frequencies. There are two scenarios which may cause
to violate ETSI requirements.
1. Using mac80211 default values.
2. Userspace entity tries to configure its own values
2. Associating to AP which advertises WWM IE.

In the latter case, the client configures the data from the WMM IE as
it's WMM parameters. The AP might not comply with ETSI requirements.
Thus we should limit wmm parameters, when the current regulatory rule
implies that, to make sure we comply with ETSI requirements.

Signed-off-by: Haim Dreyfuss <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
net/mac80211/cfg.c | 3 +++
net/mac80211/ieee80211_i.h | 4 ++++
net/mac80211/mlme.c | 1 +
net/mac80211/util.c | 40 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 48 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 46028e12e216..bb22e05075f4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4,6 +4,7 @@
* Copyright 2006-2010 Johannes Berg <[email protected]>
* Copyright 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* This file is GPLv2 as found in COPYING.
*/
@@ -2156,6 +2157,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
*/
p.uapsd = false;

+ ieee80211_regulatory_limit_wmm_params(sdata, &p, params->ac);
+
sdata->tx_conf[params->ac] = p;
if (drv_conf_tx(local, sdata, params->ac, &p)) {
wiphy_debug(local->hw.wiphy,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 536f04d14592..a58e8433fb5e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -4,6 +4,7 @@
* Copyright 2006-2007 Jiri Benc <[email protected]>
* Copyright 2007-2010 Johannes Berg <[email protected]>
* Copyright 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -1862,6 +1863,9 @@ extern const void *const mac80211_wiphy_privid; /* for wiphy privid */
int ieee80211_frame_duration(enum nl80211_band band, size_t len,
int rate, int erp, int short_preamble,
int shift);
+void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_tx_queue_params *qparam,
+ int ac);
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
bool bss_notify, bool enable_qos);
void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0024eff9bb84..23b66c611727 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1792,6 +1792,7 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
params[ac].cw_min, params[ac].cw_max, aci);
return false;
}
+ ieee80211_regulatory_limit_wmm_params(sdata, &params[ac], ac);
}

for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 1f82191ce601..b5b0c943411e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -5,6 +5,7 @@
* Copyright 2007 Johannes Berg <[email protected]>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -1113,6 +1114,44 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
return crc;
}

+void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_tx_queue_params
+ *qparam, int ac)
+{
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ const struct ieee80211_reg_rule *rrule;
+ struct ieee80211_wmm_ac *wmm_ac;
+ u16 center_freq = 0;
+
+ if (sdata->vif.type != NL80211_IFTYPE_AP &&
+ sdata->vif.type != NL80211_IFTYPE_STATION)
+ return;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (chanctx_conf)
+ center_freq = chanctx_conf->def.chan->center_freq;
+ rcu_read_unlock();
+
+ if (!center_freq)
+ return;
+
+ rrule = freq_reg_info(sdata->wdev.wiphy, MHZ_TO_KHZ(center_freq));
+
+ if (IS_ERR_OR_NULL(rrule) || !rrule->wmm_rule)
+ return;
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ wmm_ac = &rrule->wmm_rule->ap[ac];
+ else
+ wmm_ac = &rrule->wmm_rule->client[ac];
+ qparam->cw_min = max_t(u16, qparam->cw_min, wmm_ac->cw_min);
+ qparam->cw_max = max_t(u16, qparam->cw_max, wmm_ac->cw_max);
+ qparam->aifs = max_t(u8, qparam->aifs, wmm_ac->aifsn);
+ qparam->txop = !qparam->txop ? wmm_ac->cot / 32 :
+ min_t(u16, qparam->txop, wmm_ac->cot / 32);
+}
+
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
bool bss_notify, bool enable_qos)
{
@@ -1206,6 +1245,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
break;
}
}
+ ieee80211_regulatory_limit_wmm_params(sdata, &qparam, ac);

qparam.uapsd = false;

--
2.15.1

2018-02-16 16:13:13

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 05/13] mac80211: support reporting A-MPDU EOF bit value/known

From: Johannes Berg <[email protected]>

Support getting the EOF bit value reported from hardware
and writing it out to radiotap.

Signed-off-by: Johannes Berg <[email protected]>
---
include/net/ieee80211_radiotap.h | 2 ++
include/net/mac80211.h | 5 +++++
net/mac80211/rx.c | 4 ++++
3 files changed, 11 insertions(+)

diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index d91f9e7f4d71..960236fb1681 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -149,6 +149,8 @@ enum ieee80211_radiotap_ampdu_flags {
IEEE80211_RADIOTAP_AMPDU_IS_LAST = 0x0008,
IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR = 0x0010,
IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN = 0x0020,
+ IEEE80211_RADIOTAP_AMPDU_EOF = 0x0040,
+ IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN = 0x0080,
};

/* for IEEE80211_RADIOTAP_VHT */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 906e90223066..7efac7f98e45 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1098,6 +1098,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* the first subframe.
* @RX_FLAG_ICV_STRIPPED: The ICV is stripped from this frame. CRC checking must
* be done in the hardware.
+ * @RX_FLAG_AMPDU_EOF_BIT: Value of the EOF bit in the A-MPDU delimiter for this
+ * frame
+ * @RX_FLAG_AMPDU_EOF_BIT_KNOWN: The EOF value is known
*/
enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = BIT(0),
@@ -1124,6 +1127,8 @@ enum mac80211_rx_flags {
RX_FLAG_MIC_STRIPPED = BIT(21),
RX_FLAG_ALLOW_SAME_PN = BIT(22),
RX_FLAG_ICV_STRIPPED = BIT(23),
+ RX_FLAG_AMPDU_EOF_BIT = BIT(24),
+ RX_FLAG_AMPDU_EOF_BIT_KNOWN = BIT(25),
};

/**
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index e755f93ad735..478a9c735edb 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -439,6 +439,10 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR;
if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN;
+ if (status->flag & RX_FLAG_AMPDU_EOF_BIT_KNOWN)
+ flags |= IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN;
+ if (status->flag & RX_FLAG_AMPDU_EOF_BIT)
+ flags |= IEEE80211_RADIOTAP_AMPDU_EOF;
put_unaligned_le16(flags, pos);
pos += 2;
if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
--
2.15.1

2018-02-16 16:13:16

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 08/13] mac80211: Do not disconnect on invalid operating class

From: Ilan Peer <[email protected]>

Some APs include a non global operating class in their extended channel
switch information element. In such a case, as the operating class is not
known, mac80211 would decide to disconnect.

However the specification states that the operating class needs to be
taken from Annex E, but it does not specify from which table it should be
taken, so it is valid for an AP to use a non global operating class.

To avoid possibly unneeded disconnection, in such a case ignore the
operating class and assume that the current band is used, and if the
resulting channel and band configuration is invalid disconnect.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
net/mac80211/spectmgmt.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index ee0181778a42..029334835747 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -8,6 +8,7 @@
* Copyright 2007, Michael Wu <[email protected]>
* Copyright 2007-2008, Intel Corporation
* Copyright 2008, Johannes Berg <[email protected]>
+ * Copyright (C) 2018 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -27,7 +28,7 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
u32 sta_flags, u8 *bssid,
struct ieee80211_csa_ie *csa_ie)
{
- enum nl80211_band new_band;
+ enum nl80211_band new_band = current_band;
int new_freq;
u8 new_chan_no;
struct ieee80211_channel *new_chan;
@@ -55,15 +56,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
elems->ext_chansw_ie->new_operating_class,
&new_band)) {
sdata_info(sdata,
- "cannot understand ECSA IE operating class %d, disconnecting\n",
+ "cannot understand ECSA IE operating class, %d, ignoring\n",
elems->ext_chansw_ie->new_operating_class);
- return -EINVAL;
}
new_chan_no = elems->ext_chansw_ie->new_ch_num;
csa_ie->count = elems->ext_chansw_ie->count;
csa_ie->mode = elems->ext_chansw_ie->mode;
} else if (elems->ch_switch_ie) {
- new_band = current_band;
new_chan_no = elems->ch_switch_ie->new_ch_num;
csa_ie->count = elems->ch_switch_ie->count;
csa_ie->mode = elems->ch_switch_ie->mode;
--
2.15.1

2018-02-19 09:13:41

by Luca Coelho

[permalink] [raw]
Subject: Re: [PATCH 12/13] mac80211: limit wmm params to comply with ETSI requirements

On Mon, 2018-02-19 at 08:35 +0200, Luciano Coelho wrote:
> On Mon, 2018-02-19 at 07:54 +0200, Kalle Valo wrote:
> > Luca Coelho <[email protected]> writes:
> >
> > > From: Haim Dreyfuss <[email protected]>
> > >
> > > ETSI has recently restricted the WMM parameters values for
> > > 5GHz frequencies. There are two scenarios which may cause
> > > to violate ETSI requirements.
> > > 1. Using mac80211 default values.
> > > 2. Userspace entity tries to configure its own values
> > > 2. Associating to AP which advertises WWM IE.
> >
> > Only two? Also the numbering is interesting :)
> >
> > > In the latter case
> >
> > In the last case?
>
> Huh, how did I miss this stuff? Johannes, do you want me to resend or
> will you fix it when you take this?

We also just found an RCU issue with this patch. I'll send v2.

--
Cheers,
Luca.

2018-02-19 05:54:46

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 12/13] mac80211: limit wmm params to comply with ETSI requirements

Luca Coelho <[email protected]> writes:

> From: Haim Dreyfuss <[email protected]>
>
> ETSI has recently restricted the WMM parameters values for
> 5GHz frequencies. There are two scenarios which may cause
> to violate ETSI requirements.
> 1. Using mac80211 default values.
> 2. Userspace entity tries to configure its own values
> 2. Associating to AP which advertises WWM IE.

Only two? Also the numbering is interesting :)

> In the latter case

In the last case?

--
Kalle Valo

2018-02-19 09:03:05

by Nicolas Cavallari

[permalink] [raw]
Subject: Re: [PATCH 02/13] mac80211: ibss: send a probe request instead of allocating station

On 16/02/2018 17:12, Luca Coelho wrote:
> - sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
> - if (!sta)
> - return;
>
> - /* make sure mandatory rates are always added */
> - sband = local->hw.wiphy->bands[band];
> - sta->sta.supp_rates[band] = supp_rates |
> - ieee80211_mandatory_rates(sband, scan_width);
> -
> - spin_lock(&ifibss->incomplete_lock);
> - list_add(&sta->list, &ifibss->incomplete_stations);
> - spin_unlock(&ifibss->incomplete_lock);
> - ieee80211_queue_work(&local->hw, &sdata->work);
> + ieee80211_send_probe_req(sdata, sdata->vif.addr, addr,
> + sdata->u.ibss.ssid, sdata->u.ibss.ssid_len,
> + NULL, 0, (u32)-1, true, 0,
> + chanctx_conf->def.chan, false);
> + rcu_read_unlock();
> }

Won't that spam the channel with probe request if the traffic from the
other station is heavy ?

And, if the other station is running the same code and didn't know
about us (e.g. at join time), won't it also spam the channel with
probe requests after receiving our many probe requests ? (as well as
the probe responses from both stations)

Obviously it should stop after receiving a probe response... But what
if the link is badly asymmetric ?

2018-02-16 16:13:10

by Luca Coelho

[permalink] [raw]
Subject: [PATCH 02/13] mac80211: ibss: send a probe request instead of allocating station

From: Sara Sharon <[email protected]>

When we hear frames from IBSS that we don't have a station
for, we allocate the station in the RX path with incomplete
data.

Instead, send a probe request to the station.

This helps to solve an issue with iwlwifi, which cannot allocate
stations in atomic paths, and has the added values of having full
data of the station and getting rid from some code.

Signed-off-by: Sara Sharon <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
net/mac80211/ibss.c | 54 +++++-----------------------------------------
net/mac80211/ieee80211_i.h | 3 ---
2 files changed, 5 insertions(+), 52 deletions(-)

diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index db07e0de9a03..a89384904c94 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -691,7 +691,6 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
struct cfg80211_bss *cbss;
struct beacon_data *presp;
- struct sta_info *sta;

if (!is_zero_ether_addr(ifibss->bssid)) {
cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan,
@@ -710,18 +709,6 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)

sta_info_flush(sdata);

- spin_lock_bh(&ifibss->incomplete_lock);
- while (!list_empty(&ifibss->incomplete_stations)) {
- sta = list_first_entry(&ifibss->incomplete_stations,
- struct sta_info, list);
- list_del(&sta->list);
- spin_unlock_bh(&ifibss->incomplete_lock);
-
- sta_info_free(local, sta);
- spin_lock_bh(&ifibss->incomplete_lock);
- }
- spin_unlock_bh(&ifibss->incomplete_lock);
-
netif_carrier_off(sdata->dev);

sdata->vif.bss_conf.ibss_joined = false;
@@ -1204,11 +1191,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_supported_band *sband;
- enum nl80211_bss_scan_width scan_width;
- int band;

/*
* XXX: Consider removing the least recently used entry and
@@ -1232,23 +1215,12 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
return;
}
- band = chanctx_conf->def.chan->band;
- scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
- rcu_read_unlock();
-
- sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
- if (!sta)
- return;

- /* make sure mandatory rates are always added */
- sband = local->hw.wiphy->bands[band];
- sta->sta.supp_rates[band] = supp_rates |
- ieee80211_mandatory_rates(sband, scan_width);
-
- spin_lock(&ifibss->incomplete_lock);
- list_add(&sta->list, &ifibss->incomplete_stations);
- spin_unlock(&ifibss->incomplete_lock);
- ieee80211_queue_work(&local->hw, &sdata->work);
+ ieee80211_send_probe_req(sdata, sdata->vif.addr, addr,
+ sdata->u.ibss.ssid, sdata->u.ibss.ssid_len,
+ NULL, 0, (u32)-1, true, 0,
+ chanctx_conf->def.chan, false);
+ rcu_read_unlock();
}

static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata)
@@ -1670,7 +1642,6 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- struct sta_info *sta;

sdata_lock(sdata);

@@ -1682,19 +1653,6 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
if (!ifibss->ssid_len)
goto out;

- spin_lock_bh(&ifibss->incomplete_lock);
- while (!list_empty(&ifibss->incomplete_stations)) {
- sta = list_first_entry(&ifibss->incomplete_stations,
- struct sta_info, list);
- list_del(&sta->list);
- spin_unlock_bh(&ifibss->incomplete_lock);
-
- ieee80211_ibss_finish_sta(sta);
- rcu_read_unlock();
- spin_lock_bh(&ifibss->incomplete_lock);
- }
- spin_unlock_bh(&ifibss->incomplete_lock);
-
switch (ifibss->state) {
case IEEE80211_IBSS_MLME_SEARCH:
ieee80211_sta_find_ibss(sdata);
@@ -1724,8 +1682,6 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;

timer_setup(&ifibss->timer, ieee80211_ibss_timer, 0);
- INIT_LIST_HEAD(&ifibss->incomplete_stations);
- spin_lock_init(&ifibss->incomplete_lock);
INIT_WORK(&ifibss->csa_connection_drop_work,
ieee80211_csa_connection_drop_work);
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 26900025de2f..536f04d14592 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -581,9 +581,6 @@ struct ieee80211_if_ibss {
struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */
struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */

- spinlock_t incomplete_lock;
- struct list_head incomplete_stations;
-
enum {
IEEE80211_IBSS_MLME_SEARCH,
IEEE80211_IBSS_MLME_JOINED,
--
2.15.1