aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-09-15 14:51:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-09-15 14:51:23 -0400
commit6bd2bd27baf12fa0f2e6d611509fc0e1bffb0f97 (patch)
tree1aa11eb70af1e43bc122cb516bab264ddda76050 /net
parenteb2eacf77ec4828c9a2e451b06bc6fc44266f4c0 (diff)
parent0d8614b4b926d0f657d15d7eb5125bcb24b9fd41 (diff)
Merge tag 'mac80211-next-for-john-2014-09-12' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg <johannes@sipsolutions.net> says: "This time, I have some rate minstrel improvements, support for a very small feature from CCX that Steinar reverse-engineered, dynamic ACK timeout support, a number of changes for TDLS, early support for radio resource measurement and many fixes. Also, I'm changing a number of places to clear key memory when it's freed and Intel claims copyright for code they developed." Conflicts: net/mac80211/iface.c Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-rx.c5
-rw-r--r--net/mac80211/cfg.c101
-rw-r--r--net/mac80211/debugfs.c6
-rw-r--r--net/mac80211/debugfs_netdev.c4
-rw-r--r--net/mac80211/debugfs_sta.c1
-rw-r--r--net/mac80211/driver-ops.h2
-rw-r--r--net/mac80211/ibss.c1
-rw-r--r--net/mac80211/ieee80211_i.h8
-rw-r--r--net/mac80211/iface.c15
-rw-r--r--net/mac80211/key.c3
-rw-r--r--net/mac80211/main.c1
-rw-r--r--net/mac80211/mlme.c131
-rw-r--r--net/mac80211/rc80211_minstrel.c98
-rw-r--r--net/mac80211/rc80211_minstrel.h43
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c19
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c303
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h41
-rw-r--r--net/mac80211/rc80211_minstrel_ht_debugfs.c10
-rw-r--r--net/mac80211/rx.c11
-rw-r--r--net/mac80211/scan.c1
-rw-r--r--net/mac80211/sta_info.c1
-rw-r--r--net/mac80211/sta_info.h7
-rw-r--r--net/mac80211/status.c22
-rw-r--r--net/mac80211/tdls.c4
-rw-r--r--net/mac80211/trace.h4
-rw-r--r--net/mac80211/tx.c6
-rw-r--r--net/mac80211/util.c26
-rw-r--r--net/mac80211/wme.c1
-rw-r--r--net/mac80211/wpa.c7
-rw-r--r--net/wireless/chan.c1
-rw-r--r--net/wireless/core.c3
-rw-r--r--net/wireless/ibss.c4
-rw-r--r--net/wireless/mlme.c4
-rw-r--r--net/wireless/nl80211.c233
-rw-r--r--net/wireless/nl80211.h3
-rw-r--r--net/wireless/rdev-ops.h31
-rw-r--r--net/wireless/reg.c82
-rw-r--r--net/wireless/scan.c1
-rw-r--r--net/wireless/sme.c6
-rw-r--r--net/wireless/trace.h45
-rw-r--r--net/wireless/util.c3
-rw-r--r--net/wireless/wext-compat.c2
-rw-r--r--net/wireless/wext-sme.c2
43 files changed, 945 insertions, 357 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index f0e84bc48038..a48bad468880 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -227,7 +227,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
227void __ieee80211_start_rx_ba_session(struct sta_info *sta, 227void __ieee80211_start_rx_ba_session(struct sta_info *sta,
228 u8 dialog_token, u16 timeout, 228 u8 dialog_token, u16 timeout,
229 u16 start_seq_num, u16 ba_policy, u16 tid, 229 u16 start_seq_num, u16 ba_policy, u16 tid,
230 u16 buf_size, bool tx) 230 u16 buf_size, bool tx, bool auto_seq)
231{ 231{
232 struct ieee80211_local *local = sta->sdata->local; 232 struct ieee80211_local *local = sta->sdata->local;
233 struct tid_ampdu_rx *tid_agg_rx; 233 struct tid_ampdu_rx *tid_agg_rx;
@@ -326,6 +326,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
326 tid_agg_rx->buf_size = buf_size; 326 tid_agg_rx->buf_size = buf_size;
327 tid_agg_rx->timeout = timeout; 327 tid_agg_rx->timeout = timeout;
328 tid_agg_rx->stored_mpdu_num = 0; 328 tid_agg_rx->stored_mpdu_num = 0;
329 tid_agg_rx->auto_seq = auto_seq;
329 status = WLAN_STATUS_SUCCESS; 330 status = WLAN_STATUS_SUCCESS;
330 331
331 /* activate it for RX */ 332 /* activate it for RX */
@@ -367,7 +368,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
367 368
368 __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, 369 __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
369 start_seq_num, ba_policy, tid, 370 start_seq_num, ba_policy, tid,
370 buf_size, true); 371 buf_size, true, false);
371} 372}
372 373
373void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, 374void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4d8989b87960..fb6a1502b6df 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2,6 +2,7 @@
2 * mac80211 configuration hooks for cfg80211 2 * mac80211 configuration hooks for cfg80211
3 * 3 *
4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
5 * 6 *
6 * This file is GPLv2 as found in COPYING. 7 * This file is GPLv2 as found in COPYING.
7 */ 8 */
@@ -682,8 +683,19 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
682 if (old) 683 if (old)
683 return -EALREADY; 684 return -EALREADY;
684 685
685 /* TODO: make hostapd tell us what it wants */ 686 switch (params->smps_mode) {
686 sdata->smps_mode = IEEE80211_SMPS_OFF; 687 case NL80211_SMPS_OFF:
688 sdata->smps_mode = IEEE80211_SMPS_OFF;
689 break;
690 case NL80211_SMPS_STATIC:
691 sdata->smps_mode = IEEE80211_SMPS_STATIC;
692 break;
693 case NL80211_SMPS_DYNAMIC:
694 sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
695 break;
696 default:
697 return -EINVAL;
698 }
687 sdata->needed_rx_chains = sdata->local->rx_chains; 699 sdata->needed_rx_chains = sdata->local->rx_chains;
688 700
689 mutex_lock(&local->mtx); 701 mutex_lock(&local->mtx);
@@ -1977,8 +1989,13 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1977 return err; 1989 return err;
1978 } 1990 }
1979 1991
1980 if (changed & WIPHY_PARAM_COVERAGE_CLASS) { 1992 if ((changed & WIPHY_PARAM_COVERAGE_CLASS) ||
1981 err = drv_set_coverage_class(local, wiphy->coverage_class); 1993 (changed & WIPHY_PARAM_DYN_ACK)) {
1994 s16 coverage_class;
1995
1996 coverage_class = changed & WIPHY_PARAM_COVERAGE_CLASS ?
1997 wiphy->coverage_class : -1;
1998 err = drv_set_coverage_class(local, coverage_class);
1982 1999
1983 if (err) 2000 if (err)
1984 return err; 2001 return err;
@@ -2351,6 +2368,58 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
2351 return 0; 2368 return 0;
2352} 2369}
2353 2370
2371static bool ieee80211_coalesce_started_roc(struct ieee80211_local *local,
2372 struct ieee80211_roc_work *new_roc,
2373 struct ieee80211_roc_work *cur_roc)
2374{
2375 unsigned long j = jiffies;
2376 unsigned long cur_roc_end = cur_roc->hw_start_time +
2377 msecs_to_jiffies(cur_roc->duration);
2378 struct ieee80211_roc_work *next_roc;
2379 int new_dur;
2380
2381 if (WARN_ON(!cur_roc->started || !cur_roc->hw_begun))
2382 return false;
2383
2384 if (time_after(j + IEEE80211_ROC_MIN_LEFT, cur_roc_end))
2385 return false;
2386
2387 ieee80211_handle_roc_started(new_roc);
2388
2389 new_dur = new_roc->duration - jiffies_to_msecs(cur_roc_end - j);
2390
2391 /* cur_roc is long enough - add new_roc to the dependents list. */
2392 if (new_dur <= 0) {
2393 list_add_tail(&new_roc->list, &cur_roc->dependents);
2394 return true;
2395 }
2396
2397 new_roc->duration = new_dur;
2398
2399 /*
2400 * if cur_roc was already coalesced before, we might
2401 * want to extend the next roc instead of adding
2402 * a new one.
2403 */
2404 next_roc = list_entry(cur_roc->list.next,
2405 struct ieee80211_roc_work, list);
2406 if (&next_roc->list != &local->roc_list &&
2407 next_roc->chan == new_roc->chan &&
2408 next_roc->sdata == new_roc->sdata &&
2409 !WARN_ON(next_roc->started)) {
2410 list_add_tail(&new_roc->list, &next_roc->dependents);
2411 next_roc->duration = max(next_roc->duration,
2412 new_roc->duration);
2413 next_roc->type = max(next_roc->type, new_roc->type);
2414 return true;
2415 }
2416
2417 /* add right after cur_roc */
2418 list_add(&new_roc->list, &cur_roc->list);
2419
2420 return true;
2421}
2422
2354static int ieee80211_start_roc_work(struct ieee80211_local *local, 2423static int ieee80211_start_roc_work(struct ieee80211_local *local,
2355 struct ieee80211_sub_if_data *sdata, 2424 struct ieee80211_sub_if_data *sdata,
2356 struct ieee80211_channel *channel, 2425 struct ieee80211_channel *channel,
@@ -2456,8 +2525,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
2456 2525
2457 /* If it has already started, it's more difficult ... */ 2526 /* If it has already started, it's more difficult ... */
2458 if (local->ops->remain_on_channel) { 2527 if (local->ops->remain_on_channel) {
2459 unsigned long j = jiffies;
2460
2461 /* 2528 /*
2462 * In the offloaded ROC case, if it hasn't begun, add 2529 * In the offloaded ROC case, if it hasn't begun, add
2463 * this new one to the dependent list to be handled 2530 * this new one to the dependent list to be handled
@@ -2480,28 +2547,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
2480 break; 2547 break;
2481 } 2548 }
2482 2549
2483 if (time_before(j + IEEE80211_ROC_MIN_LEFT, 2550 if (ieee80211_coalesce_started_roc(local, roc, tmp))
2484 tmp->hw_start_time +
2485 msecs_to_jiffies(tmp->duration))) {
2486 int new_dur;
2487
2488 ieee80211_handle_roc_started(roc);
2489
2490 new_dur = roc->duration -
2491 jiffies_to_msecs(tmp->hw_start_time +
2492 msecs_to_jiffies(
2493 tmp->duration) -
2494 j);
2495
2496 if (new_dur > 0) {
2497 /* add right after tmp */
2498 list_add(&roc->list, &tmp->list);
2499 } else {
2500 list_add_tail(&roc->list,
2501 &tmp->dependents);
2502 }
2503 queued = true; 2551 queued = true;
2504 }
2505 } else if (del_timer_sync(&tmp->work.timer)) { 2552 } else if (del_timer_sync(&tmp->work.timer)) {
2506 unsigned long new_end; 2553 unsigned long new_end;
2507 2554
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 0e963bc1ceac..54a189f0393e 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -3,6 +3,7 @@
3 * mac80211 debugfs for wireless PHYs 3 * mac80211 debugfs for wireless PHYs
4 * 4 *
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * 7 *
7 * GPLv2 8 * GPLv2
8 * 9 *
@@ -302,11 +303,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
302 sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); 303 sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n");
303 if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) 304 if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE)
304 sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); 305 sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n");
305 if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS)
306 sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n");
307 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
308 sf += scnprintf(buf + sf, mxln - sf,
309 "SUPPORTS_DYNAMIC_SMPS\n");
310 if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) 306 if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
311 sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); 307 sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n");
312 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) 308 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index e205ebabfa50..c68896adfa96 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -226,12 +226,12 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
226 struct ieee80211_local *local = sdata->local; 226 struct ieee80211_local *local = sdata->local;
227 int err; 227 int err;
228 228
229 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) && 229 if (!(local->hw.wiphy->features & NL80211_FEATURE_STATIC_SMPS) &&
230 smps_mode == IEEE80211_SMPS_STATIC) 230 smps_mode == IEEE80211_SMPS_STATIC)
231 return -EINVAL; 231 return -EINVAL;
232 232
233 /* auto should be dynamic if in PS mode */ 233 /* auto should be dynamic if in PS mode */
234 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) && 234 if (!(local->hw.wiphy->features & NL80211_FEATURE_DYNAMIC_SMPS) &&
235 (smps_mode == IEEE80211_SMPS_DYNAMIC || 235 (smps_mode == IEEE80211_SMPS_DYNAMIC ||
236 smps_mode == IEEE80211_SMPS_AUTOMATIC)) 236 smps_mode == IEEE80211_SMPS_AUTOMATIC))
237 return -EINVAL; 237 return -EINVAL;
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 33eb4a43a2f3..bafe48916229 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -2,6 +2,7 @@
2 * Copyright 2003-2005 Devicescape Software, Inc. 2 * Copyright 2003-2005 Devicescape Software, Inc.
3 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 3 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 11423958116a..196d48c68134 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -450,7 +450,7 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local,
450} 450}
451 451
452static inline int drv_set_coverage_class(struct ieee80211_local *local, 452static inline int drv_set_coverage_class(struct ieee80211_local *local,
453 u8 value) 453 s16 value)
454{ 454{
455 int ret = 0; 455 int ret = 0;
456 might_sleep(); 456 might_sleep();
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 5f9654d31a8d..56b53571c807 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -6,6 +6,7 @@
6 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 6 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
7 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 7 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
8 * Copyright 2009, Johannes Berg <johannes@sipsolutions.net> 8 * Copyright 2009, Johannes Berg <johannes@sipsolutions.net>
9 * Copyright 2013-2014 Intel Mobile Communications GmbH
9 * 10 *
10 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ffb20e5e6cf3..c2aaec4dfcf0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -3,6 +3,7 @@
3 * Copyright 2005, Devicescape Software, Inc. 3 * Copyright 2005, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -354,6 +355,7 @@ enum ieee80211_sta_flags {
354 IEEE80211_STA_DISABLE_80P80MHZ = BIT(12), 355 IEEE80211_STA_DISABLE_80P80MHZ = BIT(12),
355 IEEE80211_STA_DISABLE_160MHZ = BIT(13), 356 IEEE80211_STA_DISABLE_160MHZ = BIT(13),
356 IEEE80211_STA_DISABLE_WMM = BIT(14), 357 IEEE80211_STA_DISABLE_WMM = BIT(14),
358 IEEE80211_STA_ENABLE_RRM = BIT(15),
357}; 359};
358 360
359struct ieee80211_mgd_auth_data { 361struct ieee80211_mgd_auth_data {
@@ -1367,6 +1369,7 @@ struct ieee802_11_elems {
1367 const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; 1369 const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
1368 const u8 *country_elem; 1370 const u8 *country_elem;
1369 const u8 *pwr_constr_elem; 1371 const u8 *pwr_constr_elem;
1372 const u8 *cisco_dtpc_elem;
1370 const struct ieee80211_timeout_interval_ie *timeout_int; 1373 const struct ieee80211_timeout_interval_ie *timeout_int;
1371 const u8 *opmode_notif; 1374 const u8 *opmode_notif;
1372 const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; 1375 const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
@@ -1587,7 +1590,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
1587void __ieee80211_start_rx_ba_session(struct sta_info *sta, 1590void __ieee80211_start_rx_ba_session(struct sta_info *sta,
1588 u8 dialog_token, u16 timeout, 1591 u8 dialog_token, u16 timeout,
1589 u16 start_seq_num, u16 ba_policy, u16 tid, 1592 u16 start_seq_num, u16 ba_policy, u16 tid,
1590 u16 buf_size, bool tx); 1593 u16 buf_size, bool tx, bool auto_seq);
1591void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, 1594void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
1592 enum ieee80211_agg_stop_reason reason); 1595 enum ieee80211_agg_stop_reason reason);
1593void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, 1596void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
@@ -1917,7 +1920,7 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
1917 size_t extra_ies_len); 1920 size_t extra_ies_len);
1918int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, 1921int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
1919 const u8 *peer, enum nl80211_tdls_operation oper); 1922 const u8 *peer, enum nl80211_tdls_operation oper);
1920 1923void ieee80211_tdls_peer_del_work(struct work_struct *wk);
1921 1924
1922extern const struct ethtool_ops ieee80211_ethtool_ops; 1925extern const struct ethtool_ops ieee80211_ethtool_ops;
1923 1926
@@ -1928,4 +1931,3 @@ extern const struct ethtool_ops ieee80211_ethtool_ops;
1928#endif 1931#endif
1929 1932
1930#endif /* IEEE80211_I_H */ 1933#endif /* IEEE80211_I_H */
1931void ieee80211_tdls_peer_del_work(struct work_struct *wk);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index f75e5f132c5a..af237223a8cd 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -5,6 +5,7 @@
5 * Copyright 2005-2006, Devicescape Software, Inc. 5 * Copyright 2005-2006, Devicescape Software, Inc.
6 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 6 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
7 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 7 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
8 * Copyright 2013-2014 Intel Mobile Communications GmbH
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
@@ -1172,19 +1173,11 @@ static void ieee80211_iface_work(struct work_struct *work)
1172 rx_agg = (void *)&skb->cb; 1173 rx_agg = (void *)&skb->cb;
1173 mutex_lock(&local->sta_mtx); 1174 mutex_lock(&local->sta_mtx);
1174 sta = sta_info_get_bss(sdata, rx_agg->addr); 1175 sta = sta_info_get_bss(sdata, rx_agg->addr);
1175 if (sta) { 1176 if (sta)
1176 u16 last_seq;
1177
1178 last_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(
1179 sta->last_seq_ctrl[rx_agg->tid]));
1180
1181 __ieee80211_start_rx_ba_session(sta, 1177 __ieee80211_start_rx_ba_session(sta,
1182 0, 0, 1178 0, 0, 0, 1, rx_agg->tid,
1183 ieee80211_sn_inc(last_seq),
1184 1, rx_agg->tid,
1185 IEEE80211_MAX_AMPDU_BUF, 1179 IEEE80211_MAX_AMPDU_BUF,
1186 false); 1180 false, true);
1187 }
1188 mutex_unlock(&local->sta_mtx); 1181 mutex_unlock(&local->sta_mtx);
1189 } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) { 1182 } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
1190 rx_agg = (void *)&skb->cb; 1183 rx_agg = (void *)&skb->cb;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 6429d0e1d4a1..4712150dc210 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -3,6 +3,7 @@
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -421,7 +422,7 @@ static void ieee80211_key_free_common(struct ieee80211_key *key)
421 ieee80211_aes_key_free(key->u.ccmp.tfm); 422 ieee80211_aes_key_free(key->u.ccmp.tfm);
422 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) 423 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
423 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 424 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
424 kfree(key); 425 kzfree(key);
425} 426}
426 427
427static void __ieee80211_key_destroy(struct ieee80211_key *key, 428static void __ieee80211_key_destroy(struct ieee80211_key *key,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index e0ab4320a078..0de7c93bf62b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -2,6 +2,7 @@
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 8a73de6a5f5b..2de88704278b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -5,6 +5,7 @@
5 * Copyright 2005, Devicescape Software, Inc. 5 * Copyright 2005, Devicescape Software, Inc.
6 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 6 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
7 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 7 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
8 * Copyright 2013-2014 Intel Mobile Communications GmbH
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
@@ -172,7 +173,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
172 173
173 if (!(ht_cap->cap_info & 174 if (!(ht_cap->cap_info &
174 cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40))) { 175 cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40))) {
175 ret = IEEE80211_STA_DISABLE_40MHZ | IEEE80211_STA_DISABLE_VHT; 176 ret = IEEE80211_STA_DISABLE_40MHZ;
176 goto out; 177 goto out;
177 } 178 }
178 179
@@ -672,6 +673,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
672 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) 673 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
673 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; 674 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
674 675
676 if (ifmgd->flags & IEEE80211_STA_ENABLE_RRM)
677 capab |= WLAN_CAPABILITY_RADIO_MEASURE;
678
675 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 679 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
676 memset(mgmt, 0, 24); 680 memset(mgmt, 0, 24);
677 memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN); 681 memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN);
@@ -737,16 +741,17 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
737 } 741 }
738 } 742 }
739 743
740 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { 744 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT ||
741 /* 1. power capabilities */ 745 capab & WLAN_CAPABILITY_RADIO_MEASURE) {
742 pos = skb_put(skb, 4); 746 pos = skb_put(skb, 4);
743 *pos++ = WLAN_EID_PWR_CAPABILITY; 747 *pos++ = WLAN_EID_PWR_CAPABILITY;
744 *pos++ = 2; 748 *pos++ = 2;
745 *pos++ = 0; /* min tx power */ 749 *pos++ = 0; /* min tx power */
746 /* max tx power */ 750 /* max tx power */
747 *pos++ = ieee80211_chandef_max_power(&chanctx_conf->def); 751 *pos++ = ieee80211_chandef_max_power(&chanctx_conf->def);
752 }
748 753
749 /* 2. supported channels */ 754 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
750 /* TODO: get this in reg domain format */ 755 /* TODO: get this in reg domain format */
751 pos = skb_put(skb, 2 * sband->n_channels + 2); 756 pos = skb_put(skb, 2 * sband->n_channels + 2);
752 *pos++ = WLAN_EID_SUPPORTED_CHANNELS; 757 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
@@ -1166,19 +1171,21 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1166 TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); 1171 TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
1167} 1172}
1168 1173
1169static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, 1174static bool
1170 struct ieee80211_channel *channel, 1175ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata,
1171 const u8 *country_ie, u8 country_ie_len, 1176 struct ieee80211_channel *channel,
1172 const u8 *pwr_constr_elem) 1177 const u8 *country_ie, u8 country_ie_len,
1178 const u8 *pwr_constr_elem,
1179 int *chan_pwr, int *pwr_reduction)
1173{ 1180{
1174 struct ieee80211_country_ie_triplet *triplet; 1181 struct ieee80211_country_ie_triplet *triplet;
1175 int chan = ieee80211_frequency_to_channel(channel->center_freq); 1182 int chan = ieee80211_frequency_to_channel(channel->center_freq);
1176 int i, chan_pwr, chan_increment, new_ap_level; 1183 int i, chan_increment;
1177 bool have_chan_pwr = false; 1184 bool have_chan_pwr = false;
1178 1185
1179 /* Invalid IE */ 1186 /* Invalid IE */
1180 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) 1187 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
1181 return 0; 1188 return false;
1182 1189
1183 triplet = (void *)(country_ie + 3); 1190 triplet = (void *)(country_ie + 3);
1184 country_ie_len -= 3; 1191 country_ie_len -= 3;
@@ -1206,7 +1213,7 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
1206 for (i = 0; i < triplet->chans.num_channels; i++) { 1213 for (i = 0; i < triplet->chans.num_channels; i++) {
1207 if (first_channel + i * chan_increment == chan) { 1214 if (first_channel + i * chan_increment == chan) {
1208 have_chan_pwr = true; 1215 have_chan_pwr = true;
1209 chan_pwr = triplet->chans.max_power; 1216 *chan_pwr = triplet->chans.max_power;
1210 break; 1217 break;
1211 } 1218 }
1212 } 1219 }
@@ -1218,18 +1225,76 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
1218 country_ie_len -= 3; 1225 country_ie_len -= 3;
1219 } 1226 }
1220 1227
1221 if (!have_chan_pwr) 1228 if (have_chan_pwr)
1229 *pwr_reduction = *pwr_constr_elem;
1230 return have_chan_pwr;
1231}
1232
1233static void ieee80211_find_cisco_dtpc(struct ieee80211_sub_if_data *sdata,
1234 struct ieee80211_channel *channel,
1235 const u8 *cisco_dtpc_ie,
1236 int *pwr_level)
1237{
1238 /* From practical testing, the first data byte of the DTPC element
1239 * seems to contain the requested dBm level, and the CLI on Cisco
1240 * APs clearly state the range is -127 to 127 dBm, which indicates
1241 * a signed byte, although it seemingly never actually goes negative.
1242 * The other byte seems to always be zero.
1243 */
1244 *pwr_level = (__s8)cisco_dtpc_ie[4];
1245}
1246
1247static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
1248 struct ieee80211_channel *channel,
1249 struct ieee80211_mgmt *mgmt,
1250 const u8 *country_ie, u8 country_ie_len,
1251 const u8 *pwr_constr_ie,
1252 const u8 *cisco_dtpc_ie)
1253{
1254 bool has_80211h_pwr = false, has_cisco_pwr = false;
1255 int chan_pwr = 0, pwr_reduction_80211h = 0;
1256 int pwr_level_cisco, pwr_level_80211h;
1257 int new_ap_level;
1258
1259 if (country_ie && pwr_constr_ie &&
1260 mgmt->u.probe_resp.capab_info &
1261 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) {
1262 has_80211h_pwr = ieee80211_find_80211h_pwr_constr(
1263 sdata, channel, country_ie, country_ie_len,
1264 pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h);
1265 pwr_level_80211h =
1266 max_t(int, 0, chan_pwr - pwr_reduction_80211h);
1267 }
1268
1269 if (cisco_dtpc_ie) {
1270 ieee80211_find_cisco_dtpc(
1271 sdata, channel, cisco_dtpc_ie, &pwr_level_cisco);
1272 has_cisco_pwr = true;
1273 }
1274
1275 if (!has_80211h_pwr && !has_cisco_pwr)
1222 return 0; 1276 return 0;
1223 1277
1224 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem); 1278 /* If we have both 802.11h and Cisco DTPC, apply both limits
1279 * by picking the smallest of the two power levels advertised.
1280 */
1281 if (has_80211h_pwr &&
1282 (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) {
1283 sdata_info(sdata,
1284 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
1285 pwr_level_80211h, chan_pwr, pwr_reduction_80211h,
1286 sdata->u.mgd.bssid);
1287 new_ap_level = pwr_level_80211h;
1288 } else { /* has_cisco_pwr is always true here. */
1289 sdata_info(sdata,
1290 "Limiting TX power to %d dBm as advertised by %pM\n",
1291 pwr_level_cisco, sdata->u.mgd.bssid);
1292 new_ap_level = pwr_level_cisco;
1293 }
1225 1294
1226 if (sdata->ap_power_level == new_ap_level) 1295 if (sdata->ap_power_level == new_ap_level)
1227 return 0; 1296 return 0;
1228 1297
1229 sdata_info(sdata,
1230 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
1231 new_ap_level, chan_pwr, *pwr_constr_elem,
1232 sdata->u.mgd.bssid);
1233 sdata->ap_power_level = new_ap_level; 1298 sdata->ap_power_level = new_ap_level;
1234 if (__ieee80211_recalc_txpower(sdata)) 1299 if (__ieee80211_recalc_txpower(sdata))
1235 return BSS_CHANGED_TXPOWER; 1300 return BSS_CHANGED_TXPOWER;
@@ -2752,6 +2817,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2752 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; 2817 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
2753 u16 capab_info, status_code, aid; 2818 u16 capab_info, status_code, aid;
2754 struct ieee802_11_elems elems; 2819 struct ieee802_11_elems elems;
2820 int ac, uapsd_queues = -1;
2755 u8 *pos; 2821 u8 *pos;
2756 bool reassoc; 2822 bool reassoc;
2757 struct cfg80211_bss *bss; 2823 struct cfg80211_bss *bss;
@@ -2821,9 +2887,15 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2821 * is set can cause the interface to go idle 2887 * is set can cause the interface to go idle
2822 */ 2888 */
2823 ieee80211_destroy_assoc_data(sdata, true); 2889 ieee80211_destroy_assoc_data(sdata, true);
2890
2891 /* get uapsd queues configuration */
2892 uapsd_queues = 0;
2893 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
2894 if (sdata->tx_conf[ac].uapsd)
2895 uapsd_queues |= BIT(ac);
2824 } 2896 }
2825 2897
2826 cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len); 2898 cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues);
2827} 2899}
2828 2900
2829static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 2901static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -2893,7 +2965,9 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
2893/* 2965/*
2894 * This is the canonical list of information elements we care about, 2966 * This is the canonical list of information elements we care about,
2895 * the filter code also gives us all changes to the Microsoft OUI 2967 * the filter code also gives us all changes to the Microsoft OUI
2896 * (00:50:F2) vendor IE which is used for WMM which we need to track. 2968 * (00:50:F2) vendor IE which is used for WMM which we need to track,
2969 * as well as the DTPC IE (part of the Cisco OUI) used for signaling
2970 * changes to requested client power.
2897 * 2971 *
2898 * We implement beacon filtering in software since that means we can 2972 * We implement beacon filtering in software since that means we can
2899 * avoid processing the frame here and in cfg80211, and userspace 2973 * avoid processing the frame here and in cfg80211, and userspace
@@ -3199,13 +3273,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3199 rx_status->band, true); 3273 rx_status->band, true);
3200 mutex_unlock(&local->sta_mtx); 3274 mutex_unlock(&local->sta_mtx);
3201 3275
3202 if (elems.country_elem && elems.pwr_constr_elem && 3276 changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
3203 mgmt->u.probe_resp.capab_info & 3277 elems.country_elem,
3204 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) 3278 elems.country_elem_len,
3205 changed |= ieee80211_handle_pwr_constr(sdata, chan, 3279 elems.pwr_constr_elem,
3206 elems.country_elem, 3280 elems.cisco_dtpc_elem);
3207 elems.country_elem_len,
3208 elems.pwr_constr_elem);
3209 3281
3210 ieee80211_bss_info_change_notify(sdata, changed); 3282 ieee80211_bss_info_change_notify(sdata, changed);
3211} 3283}
@@ -3733,7 +3805,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
3733 ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len; 3805 ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
3734 ifmgd->p2p_noa_index = -1; 3806 ifmgd->p2p_noa_index = -1;
3735 3807
3736 if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) 3808 if (sdata->local->hw.wiphy->features & NL80211_FEATURE_DYNAMIC_SMPS)
3737 ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC; 3809 ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
3738 else 3810 else
3739 ifmgd->req_smps = IEEE80211_SMPS_OFF; 3811 ifmgd->req_smps = IEEE80211_SMPS_OFF;
@@ -4408,6 +4480,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4408 ifmgd->flags &= ~IEEE80211_STA_MFP_ENABLED; 4480 ifmgd->flags &= ~IEEE80211_STA_MFP_ENABLED;
4409 } 4481 }
4410 4482
4483 if (req->flags & ASSOC_REQ_USE_RRM)
4484 ifmgd->flags |= IEEE80211_STA_ENABLE_RRM;
4485 else
4486 ifmgd->flags &= ~IEEE80211_STA_ENABLE_RRM;
4487
4411 if (req->crypto.control_port) 4488 if (req->crypto.control_port)
4412 ifmgd->flags |= IEEE80211_STA_CONTROL_PORT; 4489 ifmgd->flags |= IEEE80211_STA_CONTROL_PORT;
4413 else 4490 else
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 1c1469c36dca..2baa7ed8789d 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -75,7 +75,7 @@ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
75{ 75{
76 int j = MAX_THR_RATES; 76 int j = MAX_THR_RATES;
77 77
78 while (j > 0 && mi->r[i].cur_tp > mi->r[tp_list[j - 1]].cur_tp) 78 while (j > 0 && mi->r[i].stats.cur_tp > mi->r[tp_list[j - 1]].stats.cur_tp)
79 j--; 79 j--;
80 if (j < MAX_THR_RATES - 1) 80 if (j < MAX_THR_RATES - 1)
81 memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); 81 memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
@@ -92,7 +92,7 @@ minstrel_set_rate(struct minstrel_sta_info *mi, struct ieee80211_sta_rates *rate
92 ratetbl->rate[offset].idx = r->rix; 92 ratetbl->rate[offset].idx = r->rix;
93 ratetbl->rate[offset].count = r->adjusted_retry_count; 93 ratetbl->rate[offset].count = r->adjusted_retry_count;
94 ratetbl->rate[offset].count_cts = r->retry_count_cts; 94 ratetbl->rate[offset].count_cts = r->retry_count_cts;
95 ratetbl->rate[offset].count_rts = r->retry_count_rtscts; 95 ratetbl->rate[offset].count_rts = r->stats.retry_count_rtscts;
96} 96}
97 97
98static void 98static void
@@ -140,44 +140,46 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
140 140
141 for (i = 0; i < mi->n_rates; i++) { 141 for (i = 0; i < mi->n_rates; i++) {
142 struct minstrel_rate *mr = &mi->r[i]; 142 struct minstrel_rate *mr = &mi->r[i];
143 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
143 144
144 usecs = mr->perfect_tx_time; 145 usecs = mr->perfect_tx_time;
145 if (!usecs) 146 if (!usecs)
146 usecs = 1000000; 147 usecs = 1000000;
147 148
148 if (unlikely(mr->attempts > 0)) { 149 if (unlikely(mrs->attempts > 0)) {
149 mr->sample_skipped = 0; 150 mrs->sample_skipped = 0;
150 mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts); 151 mrs->cur_prob = MINSTREL_FRAC(mrs->success,
151 mr->succ_hist += mr->success; 152 mrs->attempts);
152 mr->att_hist += mr->attempts; 153 mrs->succ_hist += mrs->success;
153 mr->probability = minstrel_ewma(mr->probability, 154 mrs->att_hist += mrs->attempts;
154 mr->cur_prob, 155 mrs->probability = minstrel_ewma(mrs->probability,
155 EWMA_LEVEL); 156 mrs->cur_prob,
157 EWMA_LEVEL);
156 } else 158 } else
157 mr->sample_skipped++; 159 mrs->sample_skipped++;
158 160
159 mr->last_success = mr->success; 161 mrs->last_success = mrs->success;
160 mr->last_attempts = mr->attempts; 162 mrs->last_attempts = mrs->attempts;
161 mr->success = 0; 163 mrs->success = 0;
162 mr->attempts = 0; 164 mrs->attempts = 0;
163 165
164 /* Update throughput per rate, reset thr. below 10% success */ 166 /* Update throughput per rate, reset thr. below 10% success */
165 if (mr->probability < MINSTREL_FRAC(10, 100)) 167 if (mrs->probability < MINSTREL_FRAC(10, 100))
166 mr->cur_tp = 0; 168 mrs->cur_tp = 0;
167 else 169 else
168 mr->cur_tp = mr->probability * (1000000 / usecs); 170 mrs->cur_tp = mrs->probability * (1000000 / usecs);
169 171
170 /* Sample less often below the 10% chance of success. 172 /* Sample less often below the 10% chance of success.
171 * Sample less often above the 95% chance of success. */ 173 * Sample less often above the 95% chance of success. */
172 if (mr->probability > MINSTREL_FRAC(95, 100) || 174 if (mrs->probability > MINSTREL_FRAC(95, 100) ||
173 mr->probability < MINSTREL_FRAC(10, 100)) { 175 mrs->probability < MINSTREL_FRAC(10, 100)) {
174 mr->adjusted_retry_count = mr->retry_count >> 1; 176 mr->adjusted_retry_count = mrs->retry_count >> 1;
175 if (mr->adjusted_retry_count > 2) 177 if (mr->adjusted_retry_count > 2)
176 mr->adjusted_retry_count = 2; 178 mr->adjusted_retry_count = 2;
177 mr->sample_limit = 4; 179 mr->sample_limit = 4;
178 } else { 180 } else {
179 mr->sample_limit = -1; 181 mr->sample_limit = -1;
180 mr->adjusted_retry_count = mr->retry_count; 182 mr->adjusted_retry_count = mrs->retry_count;
181 } 183 }
182 if (!mr->adjusted_retry_count) 184 if (!mr->adjusted_retry_count)
183 mr->adjusted_retry_count = 2; 185 mr->adjusted_retry_count = 2;
@@ -190,11 +192,11 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
190 * choose the maximum throughput rate as max_prob_rate 192 * choose the maximum throughput rate as max_prob_rate
191 * (2) if all success probabilities < 95%, the rate with 193 * (2) if all success probabilities < 95%, the rate with
192 * highest success probability is choosen as max_prob_rate */ 194 * highest success probability is choosen as max_prob_rate */
193 if (mr->probability >= MINSTREL_FRAC(95, 100)) { 195 if (mrs->probability >= MINSTREL_FRAC(95, 100)) {
194 if (mr->cur_tp >= mi->r[tmp_prob_rate].cur_tp) 196 if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp)
195 tmp_prob_rate = i; 197 tmp_prob_rate = i;
196 } else { 198 } else {
197 if (mr->probability >= mi->r[tmp_prob_rate].probability) 199 if (mrs->probability >= mi->r[tmp_prob_rate].stats.probability)
198 tmp_prob_rate = i; 200 tmp_prob_rate = i;
199 } 201 }
200 } 202 }
@@ -240,14 +242,14 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
240 if (ndx < 0) 242 if (ndx < 0)
241 continue; 243 continue;
242 244
243 mi->r[ndx].attempts += ar[i].count; 245 mi->r[ndx].stats.attempts += ar[i].count;
244 246
245 if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) 247 if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
246 mi->r[ndx].success += success; 248 mi->r[ndx].stats.success += success;
247 } 249 }
248 250
249 if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) 251 if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
250 mi->sample_count++; 252 mi->sample_packets++;
251 253
252 if (mi->sample_deferred > 0) 254 if (mi->sample_deferred > 0)
253 mi->sample_deferred--; 255 mi->sample_deferred--;
@@ -265,7 +267,7 @@ minstrel_get_retry_count(struct minstrel_rate *mr,
265 unsigned int retry = mr->adjusted_retry_count; 267 unsigned int retry = mr->adjusted_retry_count;
266 268
267 if (info->control.use_rts) 269 if (info->control.use_rts)
268 retry = max(2U, min(mr->retry_count_rtscts, retry)); 270 retry = max(2U, min(mr->stats.retry_count_rtscts, retry));
269 else if (info->control.use_cts_prot) 271 else if (info->control.use_cts_prot)
270 retry = max(2U, min(mr->retry_count_cts, retry)); 272 retry = max(2U, min(mr->retry_count_cts, retry));
271 return retry; 273 return retry;
@@ -317,15 +319,15 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
317 sampling_ratio = mp->lookaround_rate; 319 sampling_ratio = mp->lookaround_rate;
318 320
319 /* increase sum packet counter */ 321 /* increase sum packet counter */
320 mi->packet_count++; 322 mi->total_packets++;
321 323
322#ifdef CONFIG_MAC80211_DEBUGFS 324#ifdef CONFIG_MAC80211_DEBUGFS
323 if (mp->fixed_rate_idx != -1) 325 if (mp->fixed_rate_idx != -1)
324 return; 326 return;
325#endif 327#endif
326 328
327 delta = (mi->packet_count * sampling_ratio / 100) - 329 delta = (mi->total_packets * sampling_ratio / 100) -
328 (mi->sample_count + mi->sample_deferred / 2); 330 (mi->sample_packets + mi->sample_deferred / 2);
329 331
330 /* delta < 0: no sampling required */ 332 /* delta < 0: no sampling required */
331 prev_sample = mi->prev_sample; 333 prev_sample = mi->prev_sample;
@@ -333,10 +335,10 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
333 if (delta < 0 || (!mrr_capable && prev_sample)) 335 if (delta < 0 || (!mrr_capable && prev_sample))
334 return; 336 return;
335 337
336 if (mi->packet_count >= 10000) { 338 if (mi->total_packets >= 10000) {
337 mi->sample_deferred = 0; 339 mi->sample_deferred = 0;
338 mi->sample_count = 0; 340 mi->sample_packets = 0;
339 mi->packet_count = 0; 341 mi->total_packets = 0;
340 } else if (delta > mi->n_rates * 2) { 342 } else if (delta > mi->n_rates * 2) {
341 /* With multi-rate retry, not every planned sample 343 /* With multi-rate retry, not every planned sample
342 * attempt actually gets used, due to the way the retry 344 * attempt actually gets used, due to the way the retry
@@ -347,7 +349,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
347 * starts getting worse, minstrel would start bursting 349 * starts getting worse, minstrel would start bursting
348 * out lots of sampling frames, which would result 350 * out lots of sampling frames, which would result
349 * in a large throughput loss. */ 351 * in a large throughput loss. */
350 mi->sample_count += (delta - mi->n_rates * 2); 352 mi->sample_packets += (delta - mi->n_rates * 2);
351 } 353 }
352 354
353 /* get next random rate sample */ 355 /* get next random rate sample */
@@ -361,7 +363,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
361 */ 363 */
362 if (mrr_capable && 364 if (mrr_capable &&
363 msr->perfect_tx_time > mr->perfect_tx_time && 365 msr->perfect_tx_time > mr->perfect_tx_time &&
364 msr->sample_skipped < 20) { 366 msr->stats.sample_skipped < 20) {
365 /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark 367 /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
366 * packets that have the sampling rate deferred to the 368 * packets that have the sampling rate deferred to the
367 * second MRR stage. Increase the sample counter only 369 * second MRR stage. Increase the sample counter only
@@ -375,7 +377,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
375 if (!msr->sample_limit != 0) 377 if (!msr->sample_limit != 0)
376 return; 378 return;
377 379
378 mi->sample_count++; 380 mi->sample_packets++;
379 if (msr->sample_limit > 0) 381 if (msr->sample_limit > 0)
380 msr->sample_limit--; 382 msr->sample_limit--;
381 } 383 }
@@ -384,7 +386,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
384 * has a probability of >95%, we shouldn't be attempting 386 * has a probability of >95%, we shouldn't be attempting
385 * to use it, as this only wastes precious airtime */ 387 * to use it, as this only wastes precious airtime */
386 if (!mrr_capable && 388 if (!mrr_capable &&
387 (mi->r[ndx].probability > MINSTREL_FRAC(95, 100))) 389 (mi->r[ndx].stats.probability > MINSTREL_FRAC(95, 100)))
388 return; 390 return;
389 391
390 mi->prev_sample = true; 392 mi->prev_sample = true;
@@ -459,6 +461,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
459 461
460 for (i = 0; i < sband->n_bitrates; i++) { 462 for (i = 0; i < sband->n_bitrates; i++) {
461 struct minstrel_rate *mr = &mi->r[n]; 463 struct minstrel_rate *mr = &mi->r[n];
464 struct minstrel_rate_stats *mrs = &mi->r[n].stats;
462 unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; 465 unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
463 unsigned int tx_time_single; 466 unsigned int tx_time_single;
464 unsigned int cw = mp->cw_min; 467 unsigned int cw = mp->cw_min;
@@ -471,6 +474,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
471 474
472 n++; 475 n++;
473 memset(mr, 0, sizeof(*mr)); 476 memset(mr, 0, sizeof(*mr));
477 memset(mrs, 0, sizeof(*mrs));
474 478
475 mr->rix = i; 479 mr->rix = i;
476 shift = ieee80211_chandef_get_shift(chandef); 480 shift = ieee80211_chandef_get_shift(chandef);
@@ -482,9 +486,9 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
482 /* calculate maximum number of retransmissions before 486 /* calculate maximum number of retransmissions before
483 * fallback (based on maximum segment size) */ 487 * fallback (based on maximum segment size) */
484 mr->sample_limit = -1; 488 mr->sample_limit = -1;
485 mr->retry_count = 1; 489 mrs->retry_count = 1;
486 mr->retry_count_cts = 1; 490 mr->retry_count_cts = 1;
487 mr->retry_count_rtscts = 1; 491 mrs->retry_count_rtscts = 1;
488 tx_time = mr->perfect_tx_time + mi->sp_ack_dur; 492 tx_time = mr->perfect_tx_time + mi->sp_ack_dur;
489 do { 493 do {
490 /* add one retransmission */ 494 /* add one retransmission */
@@ -501,13 +505,13 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
501 (mr->retry_count_cts < mp->max_retry)) 505 (mr->retry_count_cts < mp->max_retry))
502 mr->retry_count_cts++; 506 mr->retry_count_cts++;
503 if ((tx_time_rtscts < mp->segment_size) && 507 if ((tx_time_rtscts < mp->segment_size) &&
504 (mr->retry_count_rtscts < mp->max_retry)) 508 (mrs->retry_count_rtscts < mp->max_retry))
505 mr->retry_count_rtscts++; 509 mrs->retry_count_rtscts++;
506 } while ((tx_time < mp->segment_size) && 510 } while ((tx_time < mp->segment_size) &&
507 (++mr->retry_count < mp->max_retry)); 511 (++mr->stats.retry_count < mp->max_retry));
508 mr->adjusted_retry_count = mr->retry_count; 512 mr->adjusted_retry_count = mrs->retry_count;
509 if (!(sband->bitrates[i].flags & IEEE80211_RATE_ERP_G)) 513 if (!(sband->bitrates[i].flags & IEEE80211_RATE_ERP_G))
510 mr->retry_count_cts = mr->retry_count; 514 mr->retry_count_cts = mrs->retry_count;
511 } 515 }
512 516
513 for (i = n; i < sband->n_bitrates; i++) { 517 for (i = n; i < sband->n_bitrates; i++) {
@@ -665,7 +669,7 @@ static u32 minstrel_get_expected_throughput(void *priv_sta)
665 /* convert pkt per sec in kbps (1200 is the average pkt size used for 669 /* convert pkt per sec in kbps (1200 is the average pkt size used for
666 * computing cur_tp 670 * computing cur_tp
667 */ 671 */
668 return MINSTREL_TRUNC(mi->r[idx].cur_tp) * 1200 * 8 / 1024; 672 return MINSTREL_TRUNC(mi->r[idx].stats.cur_tp) * 1200 * 8 / 1024;
669} 673}
670 674
671const struct rate_control_ops mac80211_minstrel = { 675const struct rate_control_ops mac80211_minstrel = {
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 046d1bd598a8..97eca86a4af0 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -31,6 +31,27 @@ minstrel_ewma(int old, int new, int weight)
31 return (new * (EWMA_DIV - weight) + old * weight) / EWMA_DIV; 31 return (new * (EWMA_DIV - weight) + old * weight) / EWMA_DIV;
32} 32}
33 33
34struct minstrel_rate_stats {
35 /* current / last sampling period attempts/success counters */
36 unsigned int attempts, last_attempts;
37 unsigned int success, last_success;
38
39 /* total attempts/success counters */
40 u64 att_hist, succ_hist;
41
42 /* current throughput */
43 unsigned int cur_tp;
44
45 /* packet delivery probabilities */
46 unsigned int cur_prob, probability;
47
48 /* maximum retry counts */
49 unsigned int retry_count;
50 unsigned int retry_count_rtscts;
51
52 u8 sample_skipped;
53 bool retry_updated;
54};
34 55
35struct minstrel_rate { 56struct minstrel_rate {
36 int bitrate; 57 int bitrate;
@@ -40,26 +61,10 @@ struct minstrel_rate {
40 unsigned int ack_time; 61 unsigned int ack_time;
41 62
42 int sample_limit; 63 int sample_limit;
43 unsigned int retry_count;
44 unsigned int retry_count_cts; 64 unsigned int retry_count_cts;
45 unsigned int retry_count_rtscts;
46 unsigned int adjusted_retry_count; 65 unsigned int adjusted_retry_count;
47 66
48 u32 success; 67 struct minstrel_rate_stats stats;
49 u32 attempts;
50 u32 last_attempts;
51 u32 last_success;
52 u8 sample_skipped;
53
54 /* parts per thousand */
55 u32 cur_prob;
56 u32 probability;
57
58 /* per-rate throughput */
59 u32 cur_tp;
60
61 u64 succ_hist;
62 u64 att_hist;
63}; 68};
64 69
65struct minstrel_sta_info { 70struct minstrel_sta_info {
@@ -73,8 +78,8 @@ struct minstrel_sta_info {
73 78
74 u8 max_tp_rate[MAX_THR_RATES]; 79 u8 max_tp_rate[MAX_THR_RATES];
75 u8 max_prob_rate; 80 u8 max_prob_rate;
76 unsigned int packet_count; 81 unsigned int total_packets;
77 unsigned int sample_count; 82 unsigned int sample_packets;
78 int sample_deferred; 83 int sample_deferred;
79 84
80 unsigned int sample_row; 85 unsigned int sample_row;
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index fd0b9ca1570e..edde723f9f00 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -72,6 +72,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
72 "this succ/attempt success attempts\n"); 72 "this succ/attempt success attempts\n");
73 for (i = 0; i < mi->n_rates; i++) { 73 for (i = 0; i < mi->n_rates; i++) {
74 struct minstrel_rate *mr = &mi->r[i]; 74 struct minstrel_rate *mr = &mi->r[i];
75 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
75 76
76 *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; 77 *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';
77 *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; 78 *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';
@@ -81,24 +82,24 @@ minstrel_stats_open(struct inode *inode, struct file *file)
81 p += sprintf(p, "%3u%s", mr->bitrate / 2, 82 p += sprintf(p, "%3u%s", mr->bitrate / 2,
82 (mr->bitrate & 1 ? ".5" : " ")); 83 (mr->bitrate & 1 ? ".5" : " "));
83 84
84 tp = MINSTREL_TRUNC(mr->cur_tp / 10); 85 tp = MINSTREL_TRUNC(mrs->cur_tp / 10);
85 prob = MINSTREL_TRUNC(mr->cur_prob * 1000); 86 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
86 eprob = MINSTREL_TRUNC(mr->probability * 1000); 87 eprob = MINSTREL_TRUNC(mrs->probability * 1000);
87 88
88 p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " 89 p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
89 " %3u(%3u) %8llu %8llu\n", 90 " %3u(%3u) %8llu %8llu\n",
90 tp / 10, tp % 10, 91 tp / 10, tp % 10,
91 eprob / 10, eprob % 10, 92 eprob / 10, eprob % 10,
92 prob / 10, prob % 10, 93 prob / 10, prob % 10,
93 mr->last_success, 94 mrs->last_success,
94 mr->last_attempts, 95 mrs->last_attempts,
95 (unsigned long long)mr->succ_hist, 96 (unsigned long long)mrs->succ_hist,
96 (unsigned long long)mr->att_hist); 97 (unsigned long long)mrs->att_hist);
97 } 98 }
98 p += sprintf(p, "\nTotal packet count:: ideal %d " 99 p += sprintf(p, "\nTotal packet count:: ideal %d "
99 "lookaround %d\n\n", 100 "lookaround %d\n\n",
100 mi->packet_count - mi->sample_count, 101 mi->total_packets - mi->sample_packets,
101 mi->sample_count); 102 mi->sample_packets);
102 ms->len = p - ms->buf; 103 ms->len = p - ms->buf;
103 104
104 return 0; 105 return 0;
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 85c1e74b7714..df90ce2db00c 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -135,7 +135,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
135static int 135static int
136minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate) 136minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
137{ 137{
138 return GROUP_IDX((rate->idx / 8) + 1, 138 return GROUP_IDX((rate->idx / MCS_GROUP_RATES) + 1,
139 !!(rate->flags & IEEE80211_TX_RC_SHORT_GI), 139 !!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
140 !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)); 140 !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
141} 141}
@@ -233,12 +233,151 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
233} 233}
234 234
235/* 235/*
236 * Find & sort topmost throughput rates
237 *
238 * If multiple rates provide equal throughput the sorting is based on their
239 * current success probability. Higher success probability is preferred among
240 * MCS groups, CCK rates do not provide aggregation and are therefore at last.
241 */
242static void
243minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u8 index,
244 u8 *tp_list)
245{
246 int cur_group, cur_idx, cur_thr, cur_prob;
247 int tmp_group, tmp_idx, tmp_thr, tmp_prob;
248 int j = MAX_THR_RATES;
249
250 cur_group = index / MCS_GROUP_RATES;
251 cur_idx = index % MCS_GROUP_RATES;
252 cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp;
253 cur_prob = mi->groups[cur_group].rates[cur_idx].probability;
254
255 tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
256 tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
257 tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
258 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
259
260 while (j > 0 && (cur_thr > tmp_thr ||
261 (cur_thr == tmp_thr && cur_prob > tmp_prob))) {
262 j--;
263 tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
264 tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
265 tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
266 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
267 }
268
269 if (j < MAX_THR_RATES - 1) {
270 memmove(&tp_list[j + 1], &tp_list[j], (sizeof(*tp_list) *
271 (MAX_THR_RATES - (j + 1))));
272 }
273 if (j < MAX_THR_RATES)
274 tp_list[j] = index;
275}
276
277/*
278 * Find and set the topmost probability rate per sta and per group
279 */
280static void
281minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u8 index)
282{
283 struct minstrel_mcs_group_data *mg;
284 struct minstrel_rate_stats *mr;
285 int tmp_group, tmp_idx, tmp_tp, tmp_prob, max_tp_group;
286
287 mg = &mi->groups[index / MCS_GROUP_RATES];
288 mr = &mg->rates[index % MCS_GROUP_RATES];
289
290 tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
291 tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
292 tmp_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
293 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
294
295 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
296 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */
297 max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES;
298 if((index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) &&
299 (max_tp_group != MINSTREL_CCK_GROUP))
300 return;
301
302 if (mr->probability > MINSTREL_FRAC(75, 100)) {
303 if (mr->cur_tp > tmp_tp)
304 mi->max_prob_rate = index;
305 if (mr->cur_tp > mg->rates[mg->max_group_prob_rate].cur_tp)
306 mg->max_group_prob_rate = index;
307 } else {
308 if (mr->probability > tmp_prob)
309 mi->max_prob_rate = index;
310 if (mr->probability > mg->rates[mg->max_group_prob_rate].probability)
311 mg->max_group_prob_rate = index;
312 }
313}
314
315
316/*
317 * Assign new rate set per sta and use CCK rates only if the fastest
318 * rate (max_tp_rate[0]) is from CCK group. This prohibits such sorted
319 * rate sets where MCS and CCK rates are mixed, because CCK rates can
320 * not use aggregation.
321 */
322static void
323minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
324 u8 tmp_mcs_tp_rate[MAX_THR_RATES],
325 u8 tmp_cck_tp_rate[MAX_THR_RATES])
326{
327 unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp;
328 int i;
329
330 tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES;
331 tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES;
332 tmp_cck_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
333
334 tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES;
335 tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES;
336 tmp_mcs_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
337
338 if (tmp_cck_tp > tmp_mcs_tp) {
339 for(i = 0; i < MAX_THR_RATES; i++) {
340 minstrel_ht_sort_best_tp_rates(mi, tmp_cck_tp_rate[i],
341 tmp_mcs_tp_rate);
342 }
343 }
344
345}
346
347/*
348 * Try to increase robustness of max_prob rate by decrease number of
349 * streams if possible.
350 */
351static inline void
352minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
353{
354 struct minstrel_mcs_group_data *mg;
355 struct minstrel_rate_stats *mr;
356 int tmp_max_streams, group;
357 int tmp_tp = 0;
358
359 tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
360 MCS_GROUP_RATES].streams;
361 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
362 mg = &mi->groups[group];
363 if (!mg->supported || group == MINSTREL_CCK_GROUP)
364 continue;
365 mr = minstrel_get_ratestats(mi, mg->max_group_prob_rate);
366 if (tmp_tp < mr->cur_tp &&
367 (minstrel_mcs_groups[group].streams < tmp_max_streams)) {
368 mi->max_prob_rate = mg->max_group_prob_rate;
369 tmp_tp = mr->cur_tp;
370 }
371 }
372}
373
374/*
236 * Update rate statistics and select new primary rates 375 * Update rate statistics and select new primary rates
237 * 376 *
238 * Rules for rate selection: 377 * Rules for rate selection:
239 * - max_prob_rate must use only one stream, as a tradeoff between delivery 378 * - max_prob_rate must use only one stream, as a tradeoff between delivery
240 * probability and throughput during strong fluctuations 379 * probability and throughput during strong fluctuations
241 * - as long as the max prob rate has a probability of more than 3/4, pick 380 * - as long as the max prob rate has a probability of more than 75%, pick
242 * higher throughput rates, even if the probablity is a bit lower 381 * higher throughput rates, even if the probablity is a bit lower
243 */ 382 */
244static void 383static void
@@ -246,9 +385,9 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
246{ 385{
247 struct minstrel_mcs_group_data *mg; 386 struct minstrel_mcs_group_data *mg;
248 struct minstrel_rate_stats *mr; 387 struct minstrel_rate_stats *mr;
249 int cur_prob, cur_prob_tp, cur_tp, cur_tp2; 388 int group, i, j;
250 int group, i, index; 389 u8 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
251 bool mi_rates_valid = false; 390 u8 tmp_cck_tp_rate[MAX_THR_RATES], index;
252 391
253 if (mi->ampdu_packets > 0) { 392 if (mi->ampdu_packets > 0) {
254 mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len, 393 mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
@@ -260,13 +399,14 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
260 mi->sample_slow = 0; 399 mi->sample_slow = 0;
261 mi->sample_count = 0; 400 mi->sample_count = 0;
262 401
263 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { 402 /* Initialize global rate indexes */
264 bool mg_rates_valid = false; 403 for(j = 0; j < MAX_THR_RATES; j++){
404 tmp_mcs_tp_rate[j] = 0;
405 tmp_cck_tp_rate[j] = 0;
406 }
265 407
266 cur_prob = 0; 408 /* Find best rate sets within all MCS groups*/
267 cur_prob_tp = 0; 409 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
268 cur_tp = 0;
269 cur_tp2 = 0;
270 410
271 mg = &mi->groups[group]; 411 mg = &mi->groups[group];
272 if (!mg->supported) 412 if (!mg->supported)
@@ -274,24 +414,16 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
274 414
275 mi->sample_count++; 415 mi->sample_count++;
276 416
417 /* (re)Initialize group rate indexes */
418 for(j = 0; j < MAX_THR_RATES; j++)
419 tmp_group_tp_rate[j] = group;
420
277 for (i = 0; i < MCS_GROUP_RATES; i++) { 421 for (i = 0; i < MCS_GROUP_RATES; i++) {
278 if (!(mg->supported & BIT(i))) 422 if (!(mg->supported & BIT(i)))
279 continue; 423 continue;
280 424
281 index = MCS_GROUP_RATES * group + i; 425 index = MCS_GROUP_RATES * group + i;
282 426
283 /* initialize rates selections starting indexes */
284 if (!mg_rates_valid) {
285 mg->max_tp_rate = mg->max_tp_rate2 =
286 mg->max_prob_rate = i;
287 if (!mi_rates_valid) {
288 mi->max_tp_rate = mi->max_tp_rate2 =
289 mi->max_prob_rate = index;
290 mi_rates_valid = true;
291 }
292 mg_rates_valid = true;
293 }
294
295 mr = &mg->rates[i]; 427 mr = &mg->rates[i];
296 mr->retry_updated = false; 428 mr->retry_updated = false;
297 minstrel_calc_rate_ewma(mr); 429 minstrel_calc_rate_ewma(mr);
@@ -300,82 +432,47 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
300 if (!mr->cur_tp) 432 if (!mr->cur_tp)
301 continue; 433 continue;
302 434
303 if ((mr->cur_tp > cur_prob_tp && mr->probability > 435 /* Find max throughput rate set */
304 MINSTREL_FRAC(3, 4)) || mr->probability > cur_prob) { 436 if (group != MINSTREL_CCK_GROUP) {
305 mg->max_prob_rate = index; 437 minstrel_ht_sort_best_tp_rates(mi, index,
306 cur_prob = mr->probability; 438 tmp_mcs_tp_rate);
307 cur_prob_tp = mr->cur_tp; 439 } else if (group == MINSTREL_CCK_GROUP) {
308 } 440 minstrel_ht_sort_best_tp_rates(mi, index,
309 441 tmp_cck_tp_rate);
310 if (mr->cur_tp > cur_tp) {
311 swap(index, mg->max_tp_rate);
312 cur_tp = mr->cur_tp;
313 mr = minstrel_get_ratestats(mi, index);
314 }
315
316 if (index >= mg->max_tp_rate)
317 continue;
318
319 if (mr->cur_tp > cur_tp2) {
320 mg->max_tp_rate2 = index;
321 cur_tp2 = mr->cur_tp;
322 } 442 }
323 }
324 }
325 443
326 /* try to sample all available rates during each interval */ 444 /* Find max throughput rate set within a group */
327 mi->sample_count *= 8; 445 minstrel_ht_sort_best_tp_rates(mi, index,
446 tmp_group_tp_rate);
328 447
329 cur_prob = 0; 448 /* Find max probability rate per group and global */
330 cur_prob_tp = 0; 449 minstrel_ht_set_best_prob_rate(mi, index);
331 cur_tp = 0;
332 cur_tp2 = 0;
333 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
334 mg = &mi->groups[group];
335 if (!mg->supported)
336 continue;
337
338 mr = minstrel_get_ratestats(mi, mg->max_tp_rate);
339 if (cur_tp < mr->cur_tp) {
340 mi->max_tp_rate2 = mi->max_tp_rate;
341 cur_tp2 = cur_tp;
342 mi->max_tp_rate = mg->max_tp_rate;
343 cur_tp = mr->cur_tp;
344 mi->max_prob_streams = minstrel_mcs_groups[group].streams - 1;
345 } 450 }
346 451
347 mr = minstrel_get_ratestats(mi, mg->max_tp_rate2); 452 memcpy(mg->max_group_tp_rate, tmp_group_tp_rate,
348 if (cur_tp2 < mr->cur_tp) { 453 sizeof(mg->max_group_tp_rate));
349 mi->max_tp_rate2 = mg->max_tp_rate2;
350 cur_tp2 = mr->cur_tp;
351 }
352 } 454 }
353 455
354 if (mi->max_prob_streams < 1) 456 /* Assign new rate set per sta */
355 mi->max_prob_streams = 1; 457 minstrel_ht_assign_best_tp_rates(mi, tmp_mcs_tp_rate, tmp_cck_tp_rate);
458 memcpy(mi->max_tp_rate, tmp_mcs_tp_rate, sizeof(mi->max_tp_rate));
356 459
357 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { 460 /* Try to increase robustness of max_prob_rate*/
358 mg = &mi->groups[group]; 461 minstrel_ht_prob_rate_reduce_streams(mi);
359 if (!mg->supported) 462
360 continue; 463 /* try to sample all available rates during each interval */
361 mr = minstrel_get_ratestats(mi, mg->max_prob_rate); 464 mi->sample_count *= 8;
362 if (cur_prob_tp < mr->cur_tp &&
363 minstrel_mcs_groups[group].streams <= mi->max_prob_streams) {
364 mi->max_prob_rate = mg->max_prob_rate;
365 cur_prob = mr->cur_prob;
366 cur_prob_tp = mr->cur_tp;
367 }
368 }
369 465
370#ifdef CONFIG_MAC80211_DEBUGFS 466#ifdef CONFIG_MAC80211_DEBUGFS
371 /* use fixed index if set */ 467 /* use fixed index if set */
372 if (mp->fixed_rate_idx != -1) { 468 if (mp->fixed_rate_idx != -1) {
373 mi->max_tp_rate = mp->fixed_rate_idx; 469 for (i = 0; i < 4; i++)
374 mi->max_tp_rate2 = mp->fixed_rate_idx; 470 mi->max_tp_rate[i] = mp->fixed_rate_idx;
375 mi->max_prob_rate = mp->fixed_rate_idx; 471 mi->max_prob_rate = mp->fixed_rate_idx;
376 } 472 }
377#endif 473#endif
378 474
475 /* Reset update timer */
379 mi->stats_update = jiffies; 476 mi->stats_update = jiffies;
380} 477}
381 478
@@ -420,8 +517,7 @@ minstrel_next_sample_idx(struct minstrel_ht_sta *mi)
420} 517}
421 518
422static void 519static void
423minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx, 520minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u8 *idx, bool primary)
424 bool primary)
425{ 521{
426 int group, orig_group; 522 int group, orig_group;
427 523
@@ -437,9 +533,9 @@ minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
437 continue; 533 continue;
438 534
439 if (primary) 535 if (primary)
440 *idx = mi->groups[group].max_tp_rate; 536 *idx = mi->groups[group].max_group_tp_rate[0];
441 else 537 else
442 *idx = mi->groups[group].max_tp_rate2; 538 *idx = mi->groups[group].max_group_tp_rate[1];
443 break; 539 break;
444 } 540 }
445} 541}
@@ -524,19 +620,19 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
524 * check for sudden death of spatial multiplexing, 620 * check for sudden death of spatial multiplexing,
525 * downgrade to a lower number of streams if necessary. 621 * downgrade to a lower number of streams if necessary.
526 */ 622 */
527 rate = minstrel_get_ratestats(mi, mi->max_tp_rate); 623 rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
528 if (rate->attempts > 30 && 624 if (rate->attempts > 30 &&
529 MINSTREL_FRAC(rate->success, rate->attempts) < 625 MINSTREL_FRAC(rate->success, rate->attempts) <
530 MINSTREL_FRAC(20, 100)) { 626 MINSTREL_FRAC(20, 100)) {
531 minstrel_downgrade_rate(mi, &mi->max_tp_rate, true); 627 minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true);
532 update = true; 628 update = true;
533 } 629 }
534 630
535 rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2); 631 rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]);
536 if (rate2->attempts > 30 && 632 if (rate2->attempts > 30 &&
537 MINSTREL_FRAC(rate2->success, rate2->attempts) < 633 MINSTREL_FRAC(rate2->success, rate2->attempts) <
538 MINSTREL_FRAC(20, 100)) { 634 MINSTREL_FRAC(20, 100)) {
539 minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false); 635 minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false);
540 update = true; 636 update = true;
541 } 637 }
542 638
@@ -661,12 +757,12 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
661 if (!rates) 757 if (!rates)
662 return; 758 return;
663 759
664 /* Start with max_tp_rate */ 760 /* Start with max_tp_rate[0] */
665 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate); 761 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[0]);
666 762
667 if (mp->hw->max_rates >= 3) { 763 if (mp->hw->max_rates >= 3) {
668 /* At least 3 tx rates supported, use max_tp_rate2 next */ 764 /* At least 3 tx rates supported, use max_tp_rate[1] next */
669 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate2); 765 minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate[1]);
670 } 766 }
671 767
672 if (mp->hw->max_rates >= 2) { 768 if (mp->hw->max_rates >= 2) {
@@ -691,7 +787,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
691{ 787{
692 struct minstrel_rate_stats *mr; 788 struct minstrel_rate_stats *mr;
693 struct minstrel_mcs_group_data *mg; 789 struct minstrel_mcs_group_data *mg;
694 unsigned int sample_dur, sample_group; 790 unsigned int sample_dur, sample_group, cur_max_tp_streams;
695 int sample_idx = 0; 791 int sample_idx = 0;
696 792
697 if (mi->sample_wait > 0) { 793 if (mi->sample_wait > 0) {
@@ -718,8 +814,8 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
718 * to the frame. Hence, don't use sampling for the currently 814 * to the frame. Hence, don't use sampling for the currently
719 * used rates. 815 * used rates.
720 */ 816 */
721 if (sample_idx == mi->max_tp_rate || 817 if (sample_idx == mi->max_tp_rate[0] ||
722 sample_idx == mi->max_tp_rate2 || 818 sample_idx == mi->max_tp_rate[1] ||
723 sample_idx == mi->max_prob_rate) 819 sample_idx == mi->max_prob_rate)
724 return -1; 820 return -1;
725 821
@@ -734,9 +830,12 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
734 * Make sure that lower rates get sampled only occasionally, 830 * Make sure that lower rates get sampled only occasionally,
735 * if the link is working perfectly. 831 * if the link is working perfectly.
736 */ 832 */
833
834 cur_max_tp_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
835 MCS_GROUP_RATES].streams;
737 sample_dur = minstrel_get_duration(sample_idx); 836 sample_dur = minstrel_get_duration(sample_idx);
738 if (sample_dur >= minstrel_get_duration(mi->max_tp_rate2) && 837 if (sample_dur >= minstrel_get_duration(mi->max_tp_rate[1]) &&
739 (mi->max_prob_streams < 838 (cur_max_tp_streams - 1 <
740 minstrel_mcs_groups[sample_group].streams || 839 minstrel_mcs_groups[sample_group].streams ||
741 sample_dur >= minstrel_get_duration(mi->max_prob_rate))) { 840 sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {
742 if (mr->sample_skipped < 20) 841 if (mr->sample_skipped < 20)
@@ -1041,8 +1140,8 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
1041 if (!msp->is_ht) 1140 if (!msp->is_ht)
1042 return mac80211_minstrel.get_expected_throughput(priv_sta); 1141 return mac80211_minstrel.get_expected_throughput(priv_sta);
1043 1142
1044 i = mi->max_tp_rate / MCS_GROUP_RATES; 1143 i = mi->max_tp_rate[0] / MCS_GROUP_RATES;
1045 j = mi->max_tp_rate % MCS_GROUP_RATES; 1144 j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
1046 1145
1047 /* convert cur_tp from pkt per second in kbps */ 1146 /* convert cur_tp from pkt per second in kbps */
1048 return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024; 1147 return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024;
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index d655586773ac..01570e0e014b 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -26,28 +26,6 @@ struct mcs_group {
26 26
27extern const struct mcs_group minstrel_mcs_groups[]; 27extern const struct mcs_group minstrel_mcs_groups[];
28 28
29struct minstrel_rate_stats {
30 /* current / last sampling period attempts/success counters */
31 unsigned int attempts, last_attempts;
32 unsigned int success, last_success;
33
34 /* total attempts/success counters */
35 u64 att_hist, succ_hist;
36
37 /* current throughput */
38 unsigned int cur_tp;
39
40 /* packet delivery probabilities */
41 unsigned int cur_prob, probability;
42
43 /* maximum retry counts */
44 unsigned int retry_count;
45 unsigned int retry_count_rtscts;
46
47 bool retry_updated;
48 u8 sample_skipped;
49};
50
51struct minstrel_mcs_group_data { 29struct minstrel_mcs_group_data {
52 u8 index; 30 u8 index;
53 u8 column; 31 u8 column;
@@ -55,10 +33,9 @@ struct minstrel_mcs_group_data {
55 /* bitfield of supported MCS rates of this group */ 33 /* bitfield of supported MCS rates of this group */
56 u8 supported; 34 u8 supported;
57 35
58 /* selected primary rates */ 36 /* sorted rate set within a MCS group*/
59 unsigned int max_tp_rate; 37 u8 max_group_tp_rate[MAX_THR_RATES];
60 unsigned int max_tp_rate2; 38 u8 max_group_prob_rate;
61 unsigned int max_prob_rate;
62 39
63 /* MCS rate statistics */ 40 /* MCS rate statistics */
64 struct minstrel_rate_stats rates[MCS_GROUP_RATES]; 41 struct minstrel_rate_stats rates[MCS_GROUP_RATES];
@@ -74,15 +51,9 @@ struct minstrel_ht_sta {
74 /* ampdu length (EWMA) */ 51 /* ampdu length (EWMA) */
75 unsigned int avg_ampdu_len; 52 unsigned int avg_ampdu_len;
76 53
77 /* best throughput rate */ 54 /* overall sorted rate set */
78 unsigned int max_tp_rate; 55 u8 max_tp_rate[MAX_THR_RATES];
79 56 u8 max_prob_rate;
80 /* second best throughput rate */
81 unsigned int max_tp_rate2;
82
83 /* best probability rate */
84 unsigned int max_prob_rate;
85 unsigned int max_prob_streams;
86 57
87 /* time of last status update */ 58 /* time of last status update */
88 unsigned long stats_update; 59 unsigned long stats_update;
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 3e7d793de0c3..a72ad46f2a04 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -46,8 +46,10 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
46 else 46 else
47 p += sprintf(p, "HT%c0/%cGI ", htmode, gimode); 47 p += sprintf(p, "HT%c0/%cGI ", htmode, gimode);
48 48
49 *(p++) = (idx == mi->max_tp_rate) ? 'T' : ' '; 49 *(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' ';
50 *(p++) = (idx == mi->max_tp_rate2) ? 't' : ' '; 50 *(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' ';
51 *(p++) = (idx == mi->max_tp_rate[2]) ? 'C' : ' ';
52 *(p++) = (idx == mi->max_tp_rate[3]) ? 'D' : ' ';
51 *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' '; 53 *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
52 54
53 if (i == max_mcs) { 55 if (i == max_mcs) {
@@ -100,8 +102,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
100 102
101 file->private_data = ms; 103 file->private_data = ms;
102 p = ms->buf; 104 p = ms->buf;
103 p += sprintf(p, "type rate throughput ewma prob this prob " 105 p += sprintf(p, "type rate throughput ewma prob "
104 "retry this succ/attempt success attempts\n"); 106 "this prob retry this succ/attempt success attempts\n");
105 107
106 p = minstrel_ht_stats_dump(mi, max_mcs, p); 108 p = minstrel_ht_stats_dump(mi, max_mcs, p);
107 for (i = 0; i < max_mcs; i++) 109 for (i = 0; i < max_mcs; i++)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a8d862f9183c..b04ca4049c95 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3,6 +3,7 @@
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -835,6 +836,16 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
835 836
836 spin_lock(&tid_agg_rx->reorder_lock); 837 spin_lock(&tid_agg_rx->reorder_lock);
837 838
839 /*
840 * Offloaded BA sessions have no known starting sequence number so pick
841 * one from first Rxed frame for this tid after BA was started.
842 */
843 if (unlikely(tid_agg_rx->auto_seq)) {
844 tid_agg_rx->auto_seq = false;
845 tid_agg_rx->ssn = mpdu_seq_num;
846 tid_agg_rx->head_seq_num = mpdu_seq_num;
847 }
848
838 buf_size = tid_agg_rx->buf_size; 849 buf_size = tid_agg_rx->buf_size;
839 head_seq_num = tid_agg_rx->head_seq_num; 850 head_seq_num = tid_agg_rx->head_seq_num;
840 851
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index a9bb6eb8c3e0..af0d094b2f2f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -6,6 +6,7 @@
6 * Copyright 2005, Devicescape Software, Inc. 6 * Copyright 2005, Devicescape Software, Inc.
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2013-2014 Intel Mobile Communications GmbH
9 * 10 *
10 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 730030542024..90395c6b9757 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright 2002-2005, Instant802 Networks, Inc. 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 3 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
4 * Copyright 2013-2014 Intel Mobile Communications GmbH
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 89c40d5c0633..42f68cb8957e 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright 2002-2005, Devicescape Software, Inc. 2 * Copyright 2002-2005, Devicescape Software, Inc.
3 * Copyright 2013-2014 Intel Mobile Communications GmbH
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
@@ -167,6 +168,8 @@ struct tid_ampdu_tx {
167 * @dialog_token: dialog token for aggregation session 168 * @dialog_token: dialog token for aggregation session
168 * @rcu_head: RCU head used for freeing this struct 169 * @rcu_head: RCU head used for freeing this struct
169 * @reorder_lock: serializes access to reorder buffer, see below. 170 * @reorder_lock: serializes access to reorder buffer, see below.
171 * @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and
172 * and ssn.
170 * 173 *
171 * This structure's lifetime is managed by RCU, assignments to 174 * This structure's lifetime is managed by RCU, assignments to
172 * the array holding it must hold the aggregation mutex. 175 * the array holding it must hold the aggregation mutex.
@@ -190,6 +193,7 @@ struct tid_ampdu_rx {
190 u16 buf_size; 193 u16 buf_size;
191 u16 timeout; 194 u16 timeout;
192 u8 dialog_token; 195 u8 dialog_token;
196 bool auto_seq;
193}; 197};
194 198
195/** 199/**
@@ -446,6 +450,9 @@ struct sta_info {
446 enum ieee80211_smps_mode known_smps_mode; 450 enum ieee80211_smps_mode known_smps_mode;
447 const struct ieee80211_cipher_scheme *cipher_scheme; 451 const struct ieee80211_cipher_scheme *cipher_scheme;
448 452
453 /* TDLS timeout data */
454 unsigned long last_tdls_pkt_time;
455
449 /* keep last! */ 456 /* keep last! */
450 struct ieee80211_sta sta; 457 struct ieee80211_sta sta;
451}; 458};
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index aa06dcad336e..89290e33dafe 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -3,6 +3,7 @@
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -537,6 +538,8 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
537 * - current throughput (higher value for higher tpt)? 538 * - current throughput (higher value for higher tpt)?
538 */ 539 */
539#define STA_LOST_PKT_THRESHOLD 50 540#define STA_LOST_PKT_THRESHOLD 50
541#define STA_LOST_TDLS_PKT_THRESHOLD 10
542#define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */
540 543
541static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb) 544static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
542{ 545{
@@ -547,7 +550,20 @@ static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
547 !(info->flags & IEEE80211_TX_STAT_AMPDU)) 550 !(info->flags & IEEE80211_TX_STAT_AMPDU))
548 return; 551 return;
549 552
550 if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD) 553 sta->lost_packets++;
554 if (!sta->sta.tdls && sta->lost_packets < STA_LOST_PKT_THRESHOLD)
555 return;
556
557 /*
558 * If we're in TDLS mode, make sure that all STA_LOST_TDLS_PKT_THRESHOLD
559 * of the last packets were lost, and that no ACK was received in the
560 * last STA_LOST_TDLS_PKT_TIME ms, before triggering the CQM packet-loss
561 * mechanism.
562 */
563 if (sta->sta.tdls &&
564 (sta->lost_packets < STA_LOST_TDLS_PKT_THRESHOLD ||
565 time_before(jiffies,
566 sta->last_tdls_pkt_time + STA_LOST_TDLS_PKT_TIME)))
551 return; 567 return;
552 568
553 cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr, 569 cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
@@ -694,6 +710,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
694 if (info->flags & IEEE80211_TX_STAT_ACK) { 710 if (info->flags & IEEE80211_TX_STAT_ACK) {
695 if (sta->lost_packets) 711 if (sta->lost_packets)
696 sta->lost_packets = 0; 712 sta->lost_packets = 0;
713
714 /* Track when last TDLS packet was ACKed */
715 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
716 sta->last_tdls_pkt_time = jiffies;
697 } else { 717 } else {
698 ieee80211_lost_packet(sta, skb); 718 ieee80211_lost_packet(sta, skb);
699 } 719 }
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index f2cb3b6c1871..4ea25dec0698 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2014, Intel Corporation 5 * Copyright 2014, Intel Corporation
6 * Copyright 2014 Intel Mobile Communications GmbH
6 * 7 *
7 * This file is GPLv2 as found in COPYING. 8 * This file is GPLv2 as found in COPYING.
8 */ 9 */
@@ -411,6 +412,9 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
411 tf->ether_type = cpu_to_be16(ETH_P_TDLS); 412 tf->ether_type = cpu_to_be16(ETH_P_TDLS);
412 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; 413 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
413 414
415 /* network header is after the ethernet header */
416 skb_set_network_header(skb, ETH_HLEN);
417
414 switch (action_code) { 418 switch (action_code) {
415 case WLAN_TDLS_SETUP_REQUEST: 419 case WLAN_TDLS_SETUP_REQUEST:
416 tf->category = WLAN_CATEGORY_TDLS; 420 tf->category = WLAN_CATEGORY_TDLS;
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 02ac535d1274..38fae7ebe984 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -672,13 +672,13 @@ DEFINE_EVENT(local_u32_evt, drv_set_rts_threshold,
672); 672);
673 673
674TRACE_EVENT(drv_set_coverage_class, 674TRACE_EVENT(drv_set_coverage_class,
675 TP_PROTO(struct ieee80211_local *local, u8 value), 675 TP_PROTO(struct ieee80211_local *local, s16 value),
676 676
677 TP_ARGS(local, value), 677 TP_ARGS(local, value),
678 678
679 TP_STRUCT__entry( 679 TP_STRUCT__entry(
680 LOCAL_ENTRY 680 LOCAL_ENTRY
681 __field(u8, value) 681 __field(s16, value)
682 ), 682 ),
683 683
684 TP_fast_assign( 684 TP_fast_assign(
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 925c39f4099e..2f7754ca59d2 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3,6 +3,7 @@
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -1788,9 +1789,8 @@ static void ieee80211_tx_latency_start_msrmnt(struct ieee80211_local *local,
1788 * @skb: packet to be sent 1789 * @skb: packet to be sent
1789 * @dev: incoming interface 1790 * @dev: incoming interface
1790 * 1791 *
1791 * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will 1792 * Returns: NETDEV_TX_OK both on success and on failure. On failure skb will
1792 * not be freed, and caller is responsible for either retrying later or freeing 1793 * be freed.
1793 * skb).
1794 * 1794 *
1795 * This function takes in an Ethernet header and encapsulates it with suitable 1795 * This function takes in an Ethernet header and encapsulates it with suitable
1796 * IEEE 802.11 header based on which interface the packet is coming in. The 1796 * IEEE 802.11 header based on which interface the packet is coming in. The
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 725af7a468d2..3c61060a4d2b 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3,6 +3,7 @@
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -1014,6 +1015,31 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1014 } 1015 }
1015 elems->pwr_constr_elem = pos; 1016 elems->pwr_constr_elem = pos;
1016 break; 1017 break;
1018 case WLAN_EID_CISCO_VENDOR_SPECIFIC:
1019 /* Lots of different options exist, but we only care
1020 * about the Dynamic Transmit Power Control element.
1021 * First check for the Cisco OUI, then for the DTPC
1022 * tag (0x00).
1023 */
1024 if (elen < 4) {
1025 elem_parse_failed = true;
1026 break;
1027 }
1028
1029 if (pos[0] != 0x00 || pos[1] != 0x40 ||
1030 pos[2] != 0x96 || pos[3] != 0x00)
1031 break;
1032
1033 if (elen != 6) {
1034 elem_parse_failed = true;
1035 break;
1036 }
1037
1038 if (calc_crc)
1039 crc = crc32_be(crc, pos - 2, elen + 2);
1040
1041 elems->cisco_dtpc_elem = pos;
1042 break;
1017 case WLAN_EID_TIMEOUT_INTERVAL: 1043 case WLAN_EID_TIMEOUT_INTERVAL:
1018 if (elen >= sizeof(struct ieee80211_timeout_interval_ie)) 1044 if (elen >= sizeof(struct ieee80211_timeout_interval_ie))
1019 elems->timeout_int = (void *)pos; 1045 elems->timeout_int = (void *)pos;
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 6459946f0b74..3b873989992c 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright 2004, Instant802 Networks, Inc. 2 * Copyright 2004, Instant802 Networks, Inc.
3 * Copyright 2013-2014 Intel Mobile Communications GmbH
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index f7d4ca4c46e0..983527a4c1ab 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -64,8 +64,11 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
64 if (!info->control.hw_key) 64 if (!info->control.hw_key)
65 tail += IEEE80211_TKIP_ICV_LEN; 65 tail += IEEE80211_TKIP_ICV_LEN;
66 66
67 if (WARN_ON(skb_tailroom(skb) < tail || 67 if (WARN(skb_tailroom(skb) < tail ||
68 skb_headroom(skb) < IEEE80211_TKIP_IV_LEN)) 68 skb_headroom(skb) < IEEE80211_TKIP_IV_LEN,
69 "mmic: not enough head/tail (%d/%d,%d/%d)\n",
70 skb_headroom(skb), IEEE80211_TKIP_IV_LEN,
71 skb_tailroom(skb), tail))
69 return TX_DROP; 72 return TX_DROP;
70 73
71 key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]; 74 key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 992b34070bcb..72d81e2154d5 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -4,6 +4,7 @@
4 * any point in time. 4 * any point in time.
5 * 5 *
6 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> 6 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
7 * Copyright 2013-2014 Intel Mobile Communications GmbH
7 */ 8 */
8 9
9#include <linux/export.h> 10#include <linux/export.h>
diff --git a/net/wireless/core.c b/net/wireless/core.c
index c6620aa679e0..f52a4cd7017c 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -2,6 +2,7 @@
2 * This is the linux wireless configuration interface. 2 * This is the linux wireless configuration interface.
3 * 3 *
4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
5 */ 6 */
6 7
7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -1005,7 +1006,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
1005 rdev->devlist_generation++; 1006 rdev->devlist_generation++;
1006 cfg80211_mlme_purge_registrations(wdev); 1007 cfg80211_mlme_purge_registrations(wdev);
1007#ifdef CONFIG_CFG80211_WEXT 1008#ifdef CONFIG_CFG80211_WEXT
1008 kfree(wdev->wext.keys); 1009 kzfree(wdev->wext.keys);
1009#endif 1010#endif
1010 } 1011 }
1011 /* 1012 /*
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 8f345da3ea5f..e24fc585c883 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -115,7 +115,7 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
115 } 115 }
116 116
117 if (WARN_ON(wdev->connect_keys)) 117 if (WARN_ON(wdev->connect_keys))
118 kfree(wdev->connect_keys); 118 kzfree(wdev->connect_keys);
119 wdev->connect_keys = connkeys; 119 wdev->connect_keys = connkeys;
120 120
121 wdev->ibss_fixed = params->channel_fixed; 121 wdev->ibss_fixed = params->channel_fixed;
@@ -161,7 +161,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
161 161
162 ASSERT_WDEV_LOCK(wdev); 162 ASSERT_WDEV_LOCK(wdev);
163 163
164 kfree(wdev->connect_keys); 164 kzfree(wdev->connect_keys);
165 wdev->connect_keys = NULL; 165 wdev->connect_keys = NULL;
166 166
167 rdev_set_qos_map(rdev, dev, NULL); 167 rdev_set_qos_map(rdev, dev, NULL);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 369fc334fdad..2c52b59e43f3 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -19,7 +19,7 @@
19 19
20 20
21void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, 21void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
22 const u8 *buf, size_t len) 22 const u8 *buf, size_t len, int uapsd_queues)
23{ 23{
24 struct wireless_dev *wdev = dev->ieee80211_ptr; 24 struct wireless_dev *wdev = dev->ieee80211_ptr;
25 struct wiphy *wiphy = wdev->wiphy; 25 struct wiphy *wiphy = wdev->wiphy;
@@ -43,7 +43,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss,
43 return; 43 return;
44 } 44 }
45 45
46 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); 46 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues);
47 /* update current_bss etc., consumes the bss reference */ 47 /* update current_bss etc., consumes the bss reference */
48 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, 48 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
49 status_code, 49 status_code,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3011401f52c0..4cce3e17964d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2,6 +2,7 @@
2 * This is the new netlink-based wireless configuration interface. 2 * This is the new netlink-based wireless configuration interface.
3 * 3 *
4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
5 */ 6 */
6 7
7#include <linux/if.h> 8#include <linux/if.h>
@@ -225,6 +226,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
225 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, 226 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
226 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 }, 227 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
227 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 }, 228 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
229 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
228 230
229 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 231 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
230 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 232 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -388,6 +390,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
388 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, 390 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
389 [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG }, 391 [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
390 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY }, 392 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
393 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
394 [NL80211_ATTR_TSID] = { .type = NLA_U8 },
395 [NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
396 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
397 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
391}; 398};
392 399
393/* policy for the key attributes */ 400/* policy for the key attributes */
@@ -1507,6 +1514,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
1507 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH) 1514 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
1508 CMD(channel_switch, CHANNEL_SWITCH); 1515 CMD(channel_switch, CHANNEL_SWITCH);
1509 CMD(set_qos_map, SET_QOS_MAP); 1516 CMD(set_qos_map, SET_QOS_MAP);
1517 if (rdev->wiphy.flags &
1518 WIPHY_FLAG_SUPPORTS_WMM_ADMISSION)
1519 CMD(add_tx_ts, ADD_TX_TS);
1510 } 1520 }
1511 /* add into the if now */ 1521 /* add into the if now */
1512#undef CMD 1522#undef CMD
@@ -2237,11 +2247,21 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
2237 } 2247 }
2238 2248
2239 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { 2249 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
2250 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK])
2251 return -EINVAL;
2252
2240 coverage_class = nla_get_u8( 2253 coverage_class = nla_get_u8(
2241 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); 2254 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
2242 changed |= WIPHY_PARAM_COVERAGE_CLASS; 2255 changed |= WIPHY_PARAM_COVERAGE_CLASS;
2243 } 2256 }
2244 2257
2258 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
2259 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION))
2260 return -EOPNOTSUPP;
2261
2262 changed |= WIPHY_PARAM_DYN_ACK;
2263 }
2264
2245 if (changed) { 2265 if (changed) {
2246 u8 old_retry_short, old_retry_long; 2266 u8 old_retry_short, old_retry_long;
2247 u32 old_frag_threshold, old_rts_threshold; 2267 u32 old_frag_threshold, old_rts_threshold;
@@ -3326,6 +3346,29 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3326 return PTR_ERR(params.acl); 3346 return PTR_ERR(params.acl);
3327 } 3347 }
3328 3348
3349 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
3350 params.smps_mode =
3351 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
3352 switch (params.smps_mode) {
3353 case NL80211_SMPS_OFF:
3354 break;
3355 case NL80211_SMPS_STATIC:
3356 if (!(rdev->wiphy.features &
3357 NL80211_FEATURE_STATIC_SMPS))
3358 return -EINVAL;
3359 break;
3360 case NL80211_SMPS_DYNAMIC:
3361 if (!(rdev->wiphy.features &
3362 NL80211_FEATURE_DYNAMIC_SMPS))
3363 return -EINVAL;
3364 break;
3365 default:
3366 return -EINVAL;
3367 }
3368 } else {
3369 params.smps_mode = NL80211_SMPS_OFF;
3370 }
3371
3329 wdev_lock(wdev); 3372 wdev_lock(wdev);
3330 err = rdev_start_ap(rdev, dev, &params); 3373 err = rdev_start_ap(rdev, dev, &params);
3331 if (!err) { 3374 if (!err) {
@@ -6583,6 +6626,14 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
6583 sizeof(req.vht_capa)); 6626 sizeof(req.vht_capa));
6584 } 6627 }
6585 6628
6629 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
6630 if (!(rdev->wiphy.features &
6631 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
6632 !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
6633 return -EINVAL;
6634 req.flags |= ASSOC_REQ_USE_RRM;
6635 }
6636
6586 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); 6637 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
6587 if (!err) { 6638 if (!err) {
6588 wdev_lock(dev->ieee80211_ptr); 6639 wdev_lock(dev->ieee80211_ptr);
@@ -6845,7 +6896,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
6845 6896
6846 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); 6897 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
6847 if (err) 6898 if (err)
6848 kfree(connkeys); 6899 kzfree(connkeys);
6849 return err; 6900 return err;
6850} 6901}
6851 6902
@@ -7214,7 +7265,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
7214 7265
7215 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { 7266 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
7216 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) { 7267 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
7217 kfree(connkeys); 7268 kzfree(connkeys);
7218 return -EINVAL; 7269 return -EINVAL;
7219 } 7270 }
7220 memcpy(&connect.ht_capa, 7271 memcpy(&connect.ht_capa,
@@ -7232,7 +7283,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
7232 7283
7233 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) { 7284 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
7234 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) { 7285 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
7235 kfree(connkeys); 7286 kzfree(connkeys);
7236 return -EINVAL; 7287 return -EINVAL;
7237 } 7288 }
7238 memcpy(&connect.vht_capa, 7289 memcpy(&connect.vht_capa,
@@ -7240,11 +7291,19 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
7240 sizeof(connect.vht_capa)); 7291 sizeof(connect.vht_capa));
7241 } 7292 }
7242 7293
7294 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
7295 if (!(rdev->wiphy.features &
7296 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
7297 !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
7298 return -EINVAL;
7299 connect.flags |= ASSOC_REQ_USE_RRM;
7300 }
7301
7243 wdev_lock(dev->ieee80211_ptr); 7302 wdev_lock(dev->ieee80211_ptr);
7244 err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL); 7303 err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
7245 wdev_unlock(dev->ieee80211_ptr); 7304 wdev_unlock(dev->ieee80211_ptr);
7246 if (err) 7305 if (err)
7247 kfree(connkeys); 7306 kzfree(connkeys);
7248 return err; 7307 return err;
7249} 7308}
7250 7309
@@ -8930,13 +8989,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
8930 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN) 8989 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
8931 return -ERANGE; 8990 return -ERANGE;
8932 8991
8933 memcpy(rekey_data.kek, nla_data(tb[NL80211_REKEY_DATA_KEK]), 8992 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
8934 NL80211_KEK_LEN); 8993 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
8935 memcpy(rekey_data.kck, nla_data(tb[NL80211_REKEY_DATA_KCK]), 8994 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
8936 NL80211_KCK_LEN);
8937 memcpy(rekey_data.replay_ctr,
8938 nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]),
8939 NL80211_REPLAY_CTR_LEN);
8940 8995
8941 wdev_lock(wdev); 8996 wdev_lock(wdev);
8942 if (!wdev->current_bss) { 8997 if (!wdev->current_bss) {
@@ -9365,6 +9420,93 @@ static int nl80211_set_qos_map(struct sk_buff *skb,
9365 return ret; 9420 return ret;
9366} 9421}
9367 9422
9423static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
9424{
9425 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9426 struct net_device *dev = info->user_ptr[1];
9427 struct wireless_dev *wdev = dev->ieee80211_ptr;
9428 const u8 *peer;
9429 u8 tsid, up;
9430 u16 admitted_time = 0;
9431 int err;
9432
9433 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
9434 return -EOPNOTSUPP;
9435
9436 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
9437 !info->attrs[NL80211_ATTR_USER_PRIO])
9438 return -EINVAL;
9439
9440 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
9441 if (tsid >= IEEE80211_NUM_TIDS)
9442 return -EINVAL;
9443
9444 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
9445 if (up >= IEEE80211_NUM_UPS)
9446 return -EINVAL;
9447
9448 /* WMM uses TIDs 0-7 even for TSPEC */
9449 if (tsid < IEEE80211_FIRST_TSPEC_TSID) {
9450 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
9451 return -EINVAL;
9452 } else {
9453 /* TODO: handle 802.11 TSPEC/admission control
9454 * need more attributes for that (e.g. BA session requirement)
9455 */
9456 return -EINVAL;
9457 }
9458
9459 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
9460
9461 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
9462 admitted_time =
9463 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
9464 if (!admitted_time)
9465 return -EINVAL;
9466 }
9467
9468 wdev_lock(wdev);
9469 switch (wdev->iftype) {
9470 case NL80211_IFTYPE_STATION:
9471 case NL80211_IFTYPE_P2P_CLIENT:
9472 if (wdev->current_bss)
9473 break;
9474 err = -ENOTCONN;
9475 goto out;
9476 default:
9477 err = -EOPNOTSUPP;
9478 goto out;
9479 }
9480
9481 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
9482
9483 out:
9484 wdev_unlock(wdev);
9485 return err;
9486}
9487
9488static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
9489{
9490 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9491 struct net_device *dev = info->user_ptr[1];
9492 struct wireless_dev *wdev = dev->ieee80211_ptr;
9493 const u8 *peer;
9494 u8 tsid;
9495 int err;
9496
9497 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
9498 return -EINVAL;
9499
9500 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
9501 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
9502
9503 wdev_lock(wdev);
9504 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
9505 wdev_unlock(wdev);
9506
9507 return err;
9508}
9509
9368#define NL80211_FLAG_NEED_WIPHY 0x01 9510#define NL80211_FLAG_NEED_WIPHY 0x01
9369#define NL80211_FLAG_NEED_NETDEV 0x02 9511#define NL80211_FLAG_NEED_NETDEV 0x02
9370#define NL80211_FLAG_NEED_RTNL 0x04 9512#define NL80211_FLAG_NEED_RTNL 0x04
@@ -9375,6 +9517,7 @@ static int nl80211_set_qos_map(struct sk_buff *skb,
9375/* If a netdev is associated, it must be UP, P2P must be started */ 9517/* If a netdev is associated, it must be UP, P2P must be started */
9376#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\ 9518#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
9377 NL80211_FLAG_CHECK_NETDEV_UP) 9519 NL80211_FLAG_CHECK_NETDEV_UP)
9520#define NL80211_FLAG_CLEAR_SKB 0x20
9378 9521
9379static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 9522static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
9380 struct genl_info *info) 9523 struct genl_info *info)
@@ -9458,8 +9601,20 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
9458 dev_put(info->user_ptr[1]); 9601 dev_put(info->user_ptr[1]);
9459 } 9602 }
9460 } 9603 }
9604
9461 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL) 9605 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
9462 rtnl_unlock(); 9606 rtnl_unlock();
9607
9608 /* If needed, clear the netlink message payload from the SKB
9609 * as it might contain key data that shouldn't stick around on
9610 * the heap after the SKB is freed. The netlink message header
9611 * is still needed for further processing, so leave it intact.
9612 */
9613 if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
9614 struct nlmsghdr *nlh = nlmsg_hdr(skb);
9615
9616 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
9617 }
9463} 9618}
9464 9619
9465static const struct genl_ops nl80211_ops[] = { 9620static const struct genl_ops nl80211_ops[] = {
@@ -9527,7 +9682,8 @@ static const struct genl_ops nl80211_ops[] = {
9527 .policy = nl80211_policy, 9682 .policy = nl80211_policy,
9528 .flags = GENL_ADMIN_PERM, 9683 .flags = GENL_ADMIN_PERM,
9529 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 9684 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9530 NL80211_FLAG_NEED_RTNL, 9685 NL80211_FLAG_NEED_RTNL |
9686 NL80211_FLAG_CLEAR_SKB,
9531 }, 9687 },
9532 { 9688 {
9533 .cmd = NL80211_CMD_NEW_KEY, 9689 .cmd = NL80211_CMD_NEW_KEY,
@@ -9535,7 +9691,8 @@ static const struct genl_ops nl80211_ops[] = {
9535 .policy = nl80211_policy, 9691 .policy = nl80211_policy,
9536 .flags = GENL_ADMIN_PERM, 9692 .flags = GENL_ADMIN_PERM,
9537 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 9693 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9538 NL80211_FLAG_NEED_RTNL, 9694 NL80211_FLAG_NEED_RTNL |
9695 NL80211_FLAG_CLEAR_SKB,
9539 }, 9696 },
9540 { 9697 {
9541 .cmd = NL80211_CMD_DEL_KEY, 9698 .cmd = NL80211_CMD_DEL_KEY,
@@ -9713,7 +9870,8 @@ static const struct genl_ops nl80211_ops[] = {
9713 .policy = nl80211_policy, 9870 .policy = nl80211_policy,
9714 .flags = GENL_ADMIN_PERM, 9871 .flags = GENL_ADMIN_PERM,
9715 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 9872 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9716 NL80211_FLAG_NEED_RTNL, 9873 NL80211_FLAG_NEED_RTNL |
9874 NL80211_FLAG_CLEAR_SKB,
9717 }, 9875 },
9718 { 9876 {
9719 .cmd = NL80211_CMD_ASSOCIATE, 9877 .cmd = NL80211_CMD_ASSOCIATE,
@@ -9947,7 +10105,8 @@ static const struct genl_ops nl80211_ops[] = {
9947 .policy = nl80211_policy, 10105 .policy = nl80211_policy,
9948 .flags = GENL_ADMIN_PERM, 10106 .flags = GENL_ADMIN_PERM,
9949 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 10107 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9950 NL80211_FLAG_NEED_RTNL, 10108 NL80211_FLAG_NEED_RTNL |
10109 NL80211_FLAG_CLEAR_SKB,
9951 }, 10110 },
9952 { 10111 {
9953 .cmd = NL80211_CMD_TDLS_MGMT, 10112 .cmd = NL80211_CMD_TDLS_MGMT,
@@ -10105,6 +10264,22 @@ static const struct genl_ops nl80211_ops[] = {
10105 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 10264 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10106 NL80211_FLAG_NEED_RTNL, 10265 NL80211_FLAG_NEED_RTNL,
10107 }, 10266 },
10267 {
10268 .cmd = NL80211_CMD_ADD_TX_TS,
10269 .doit = nl80211_add_tx_ts,
10270 .policy = nl80211_policy,
10271 .flags = GENL_ADMIN_PERM,
10272 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10273 NL80211_FLAG_NEED_RTNL,
10274 },
10275 {
10276 .cmd = NL80211_CMD_DEL_TX_TS,
10277 .doit = nl80211_del_tx_ts,
10278 .policy = nl80211_policy,
10279 .flags = GENL_ADMIN_PERM,
10280 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10281 NL80211_FLAG_NEED_RTNL,
10282 },
10108}; 10283};
10109 10284
10110/* notification functions */ 10285/* notification functions */
@@ -10373,7 +10548,8 @@ nla_put_failure:
10373static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, 10548static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
10374 struct net_device *netdev, 10549 struct net_device *netdev,
10375 const u8 *buf, size_t len, 10550 const u8 *buf, size_t len,
10376 enum nl80211_commands cmd, gfp_t gfp) 10551 enum nl80211_commands cmd, gfp_t gfp,
10552 int uapsd_queues)
10377{ 10553{
10378 struct sk_buff *msg; 10554 struct sk_buff *msg;
10379 void *hdr; 10555 void *hdr;
@@ -10393,6 +10569,19 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
10393 nla_put(msg, NL80211_ATTR_FRAME, len, buf)) 10569 nla_put(msg, NL80211_ATTR_FRAME, len, buf))
10394 goto nla_put_failure; 10570 goto nla_put_failure;
10395 10571
10572 if (uapsd_queues >= 0) {
10573 struct nlattr *nla_wmm =
10574 nla_nest_start(msg, NL80211_ATTR_STA_WME);
10575 if (!nla_wmm)
10576 goto nla_put_failure;
10577
10578 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
10579 uapsd_queues))
10580 goto nla_put_failure;
10581
10582 nla_nest_end(msg, nla_wmm);
10583 }
10584
10396 genlmsg_end(msg, hdr); 10585 genlmsg_end(msg, hdr);
10397 10586
10398 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, 10587 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@@ -10409,15 +10598,15 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
10409 size_t len, gfp_t gfp) 10598 size_t len, gfp_t gfp)
10410{ 10599{
10411 nl80211_send_mlme_event(rdev, netdev, buf, len, 10600 nl80211_send_mlme_event(rdev, netdev, buf, len,
10412 NL80211_CMD_AUTHENTICATE, gfp); 10601 NL80211_CMD_AUTHENTICATE, gfp, -1);
10413} 10602}
10414 10603
10415void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, 10604void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
10416 struct net_device *netdev, const u8 *buf, 10605 struct net_device *netdev, const u8 *buf,
10417 size_t len, gfp_t gfp) 10606 size_t len, gfp_t gfp, int uapsd_queues)
10418{ 10607{
10419 nl80211_send_mlme_event(rdev, netdev, buf, len, 10608 nl80211_send_mlme_event(rdev, netdev, buf, len,
10420 NL80211_CMD_ASSOCIATE, gfp); 10609 NL80211_CMD_ASSOCIATE, gfp, uapsd_queues);
10421} 10610}
10422 10611
10423void nl80211_send_deauth(struct cfg80211_registered_device *rdev, 10612void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
@@ -10425,7 +10614,7 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
10425 size_t len, gfp_t gfp) 10614 size_t len, gfp_t gfp)
10426{ 10615{
10427 nl80211_send_mlme_event(rdev, netdev, buf, len, 10616 nl80211_send_mlme_event(rdev, netdev, buf, len,
10428 NL80211_CMD_DEAUTHENTICATE, gfp); 10617 NL80211_CMD_DEAUTHENTICATE, gfp, -1);
10429} 10618}
10430 10619
10431void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, 10620void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
@@ -10433,7 +10622,7 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
10433 size_t len, gfp_t gfp) 10622 size_t len, gfp_t gfp)
10434{ 10623{
10435 nl80211_send_mlme_event(rdev, netdev, buf, len, 10624 nl80211_send_mlme_event(rdev, netdev, buf, len,
10436 NL80211_CMD_DISASSOCIATE, gfp); 10625 NL80211_CMD_DISASSOCIATE, gfp, -1);
10437} 10626}
10438 10627
10439void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, 10628void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
@@ -10454,7 +10643,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
10454 cmd = NL80211_CMD_UNPROT_DISASSOCIATE; 10643 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
10455 10644
10456 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); 10645 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
10457 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC); 10646 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1);
10458} 10647}
10459EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt); 10648EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
10460 10649
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 49c9a482dd12..7ad70d6f0cc6 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -23,7 +23,8 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
23 const u8 *buf, size_t len, gfp_t gfp); 23 const u8 *buf, size_t len, gfp_t gfp);
24void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, 24void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
25 struct net_device *netdev, 25 struct net_device *netdev,
26 const u8 *buf, size_t len, gfp_t gfp); 26 const u8 *buf, size_t len, gfp_t gfp,
27 int uapsd_queues);
27void nl80211_send_deauth(struct cfg80211_registered_device *rdev, 28void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
28 struct net_device *netdev, 29 struct net_device *netdev,
29 const u8 *buf, size_t len, gfp_t gfp); 30 const u8 *buf, size_t len, gfp_t gfp);
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 56c2240c30ce..f6d457d6a558 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -915,4 +915,35 @@ rdev_set_ap_chanwidth(struct cfg80211_registered_device *rdev,
915 return ret; 915 return ret;
916} 916}
917 917
918static inline int
919rdev_add_tx_ts(struct cfg80211_registered_device *rdev,
920 struct net_device *dev, u8 tsid, const u8 *peer,
921 u8 user_prio, u16 admitted_time)
922{
923 int ret = -EOPNOTSUPP;
924
925 trace_rdev_add_tx_ts(&rdev->wiphy, dev, tsid, peer,
926 user_prio, admitted_time);
927 if (rdev->ops->add_tx_ts)
928 ret = rdev->ops->add_tx_ts(&rdev->wiphy, dev, tsid, peer,
929 user_prio, admitted_time);
930 trace_rdev_return_int(&rdev->wiphy, ret);
931
932 return ret;
933}
934
935static inline int
936rdev_del_tx_ts(struct cfg80211_registered_device *rdev,
937 struct net_device *dev, u8 tsid, const u8 *peer)
938{
939 int ret = -EOPNOTSUPP;
940
941 trace_rdev_del_tx_ts(&rdev->wiphy, dev, tsid, peer);
942 if (rdev->ops->del_tx_ts)
943 ret = rdev->ops->del_tx_ts(&rdev->wiphy, dev, tsid, peer);
944 trace_rdev_return_int(&rdev->wiphy, ret);
945
946 return ret;
947}
948
918#endif /* __CFG80211_RDEV_OPS */ 949#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 1afdf45db38f..b725a31a4751 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -3,6 +3,7 @@
3 * Copyright 2005-2006, Devicescape Software, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com> 5 * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
6 * Copyright 2013-2014 Intel Mobile Communications GmbH
6 * 7 *
7 * Permission to use, copy, modify, and/or distribute this software for any 8 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 9 * purpose with or without fee is hereby granted, provided that the above
@@ -798,6 +799,57 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
798 return 0; 799 return 0;
799} 800}
800 801
802/* check whether old rule contains new rule */
803static bool rule_contains(struct ieee80211_reg_rule *r1,
804 struct ieee80211_reg_rule *r2)
805{
806 /* for simplicity, currently consider only same flags */
807 if (r1->flags != r2->flags)
808 return false;
809
810 /* verify r1 is more restrictive */
811 if ((r1->power_rule.max_antenna_gain >
812 r2->power_rule.max_antenna_gain) ||
813 r1->power_rule.max_eirp > r2->power_rule.max_eirp)
814 return false;
815
816 /* make sure r2's range is contained within r1 */
817 if (r1->freq_range.start_freq_khz > r2->freq_range.start_freq_khz ||
818 r1->freq_range.end_freq_khz < r2->freq_range.end_freq_khz)
819 return false;
820
821 /* and finally verify that r1.max_bw >= r2.max_bw */
822 if (r1->freq_range.max_bandwidth_khz <
823 r2->freq_range.max_bandwidth_khz)
824 return false;
825
826 return true;
827}
828
829/* add or extend current rules. do nothing if rule is already contained */
830static void add_rule(struct ieee80211_reg_rule *rule,
831 struct ieee80211_reg_rule *reg_rules, u32 *n_rules)
832{
833 struct ieee80211_reg_rule *tmp_rule;
834 int i;
835
836 for (i = 0; i < *n_rules; i++) {
837 tmp_rule = &reg_rules[i];
838 /* rule is already contained - do nothing */
839 if (rule_contains(tmp_rule, rule))
840 return;
841
842 /* extend rule if possible */
843 if (rule_contains(rule, tmp_rule)) {
844 memcpy(tmp_rule, rule, sizeof(*rule));
845 return;
846 }
847 }
848
849 memcpy(&reg_rules[*n_rules], rule, sizeof(*rule));
850 (*n_rules)++;
851}
852
801/** 853/**
802 * regdom_intersect - do the intersection between two regulatory domains 854 * regdom_intersect - do the intersection between two regulatory domains
803 * @rd1: first regulatory domain 855 * @rd1: first regulatory domain
@@ -817,12 +869,10 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
817{ 869{
818 int r, size_of_regd; 870 int r, size_of_regd;
819 unsigned int x, y; 871 unsigned int x, y;
820 unsigned int num_rules = 0, rule_idx = 0; 872 unsigned int num_rules = 0;
821 const struct ieee80211_reg_rule *rule1, *rule2; 873 const struct ieee80211_reg_rule *rule1, *rule2;
822 struct ieee80211_reg_rule *intersected_rule; 874 struct ieee80211_reg_rule intersected_rule;
823 struct ieee80211_regdomain *rd; 875 struct ieee80211_regdomain *rd;
824 /* This is just a dummy holder to help us count */
825 struct ieee80211_reg_rule dummy_rule;
826 876
827 if (!rd1 || !rd2) 877 if (!rd1 || !rd2)
828 return NULL; 878 return NULL;
@@ -840,7 +890,7 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
840 for (y = 0; y < rd2->n_reg_rules; y++) { 890 for (y = 0; y < rd2->n_reg_rules; y++) {
841 rule2 = &rd2->reg_rules[y]; 891 rule2 = &rd2->reg_rules[y];
842 if (!reg_rules_intersect(rd1, rd2, rule1, rule2, 892 if (!reg_rules_intersect(rd1, rd2, rule1, rule2,
843 &dummy_rule)) 893 &intersected_rule))
844 num_rules++; 894 num_rules++;
845 } 895 }
846 } 896 }
@@ -855,34 +905,24 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
855 if (!rd) 905 if (!rd)
856 return NULL; 906 return NULL;
857 907
858 for (x = 0; x < rd1->n_reg_rules && rule_idx < num_rules; x++) { 908 for (x = 0; x < rd1->n_reg_rules; x++) {
859 rule1 = &rd1->reg_rules[x]; 909 rule1 = &rd1->reg_rules[x];
860 for (y = 0; y < rd2->n_reg_rules && rule_idx < num_rules; y++) { 910 for (y = 0; y < rd2->n_reg_rules; y++) {
861 rule2 = &rd2->reg_rules[y]; 911 rule2 = &rd2->reg_rules[y];
862 /*
863 * This time around instead of using the stack lets
864 * write to the target rule directly saving ourselves
865 * a memcpy()
866 */
867 intersected_rule = &rd->reg_rules[rule_idx];
868 r = reg_rules_intersect(rd1, rd2, rule1, rule2, 912 r = reg_rules_intersect(rd1, rd2, rule1, rule2,
869 intersected_rule); 913 &intersected_rule);
870 /* 914 /*
871 * No need to memset here the intersected rule here as 915 * No need to memset here the intersected rule here as
872 * we're not using the stack anymore 916 * we're not using the stack anymore
873 */ 917 */
874 if (r) 918 if (r)
875 continue; 919 continue;
876 rule_idx++;
877 }
878 }
879 920
880 if (rule_idx != num_rules) { 921 add_rule(&intersected_rule, rd->reg_rules,
881 kfree(rd); 922 &rd->n_reg_rules);
882 return NULL; 923 }
883 } 924 }
884 925
885 rd->n_reg_rules = num_rules;
886 rd->alpha2[0] = '9'; 926 rd->alpha2[0] = '9';
887 rd->alpha2[1] = '8'; 927 rd->alpha2[1] = '8';
888 rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region, 928 rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 620a4b40d466..bda39f149810 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -2,6 +2,7 @@
2 * cfg80211 scan result handling 2 * cfg80211 scan result handling
3 * 3 *
4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
5 */ 6 */
6#include <linux/kernel.h> 7#include <linux/kernel.h>
7#include <linux/slab.h> 8#include <linux/slab.h>
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8bbeeb302216..dc1668ff543b 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -641,7 +641,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
641 } 641 }
642 642
643 if (status != WLAN_STATUS_SUCCESS) { 643 if (status != WLAN_STATUS_SUCCESS) {
644 kfree(wdev->connect_keys); 644 kzfree(wdev->connect_keys);
645 wdev->connect_keys = NULL; 645 wdev->connect_keys = NULL;
646 wdev->ssid_len = 0; 646 wdev->ssid_len = 0;
647 if (bss) { 647 if (bss) {
@@ -918,7 +918,7 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
918 ASSERT_WDEV_LOCK(wdev); 918 ASSERT_WDEV_LOCK(wdev);
919 919
920 if (WARN_ON(wdev->connect_keys)) { 920 if (WARN_ON(wdev->connect_keys)) {
921 kfree(wdev->connect_keys); 921 kzfree(wdev->connect_keys);
922 wdev->connect_keys = NULL; 922 wdev->connect_keys = NULL;
923 } 923 }
924 924
@@ -978,7 +978,7 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
978 978
979 ASSERT_WDEV_LOCK(wdev); 979 ASSERT_WDEV_LOCK(wdev);
980 980
981 kfree(wdev->connect_keys); 981 kzfree(wdev->connect_keys);
982 wdev->connect_keys = NULL; 982 wdev->connect_keys = NULL;
983 983
984 if (wdev->conn) 984 if (wdev->conn)
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 0c524cd76c83..625a6e6d1168 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1896,6 +1896,51 @@ TRACE_EVENT(rdev_set_ap_chanwidth,
1896 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG) 1896 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
1897); 1897);
1898 1898
1899TRACE_EVENT(rdev_add_tx_ts,
1900 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
1901 u8 tsid, const u8 *peer, u8 user_prio, u16 admitted_time),
1902 TP_ARGS(wiphy, netdev, tsid, peer, user_prio, admitted_time),
1903 TP_STRUCT__entry(
1904 WIPHY_ENTRY
1905 NETDEV_ENTRY
1906 MAC_ENTRY(peer)
1907 __field(u8, tsid)
1908 __field(u8, user_prio)
1909 __field(u16, admitted_time)
1910 ),
1911 TP_fast_assign(
1912 WIPHY_ASSIGN;
1913 NETDEV_ASSIGN;
1914 MAC_ASSIGN(peer, peer);
1915 __entry->tsid = tsid;
1916 __entry->user_prio = user_prio;
1917 __entry->admitted_time = admitted_time;
1918 ),
1919 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", TSID %d, UP %d, time %d",
1920 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
1921 __entry->tsid, __entry->user_prio, __entry->admitted_time)
1922);
1923
1924TRACE_EVENT(rdev_del_tx_ts,
1925 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
1926 u8 tsid, const u8 *peer),
1927 TP_ARGS(wiphy, netdev, tsid, peer),
1928 TP_STRUCT__entry(
1929 WIPHY_ENTRY
1930 NETDEV_ENTRY
1931 MAC_ENTRY(peer)
1932 __field(u8, tsid)
1933 ),
1934 TP_fast_assign(
1935 WIPHY_ASSIGN;
1936 NETDEV_ASSIGN;
1937 MAC_ASSIGN(peer, peer);
1938 __entry->tsid = tsid;
1939 ),
1940 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", TSID %d",
1941 WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tsid)
1942);
1943
1899/************************************************************* 1944/*************************************************************
1900 * cfg80211 exported functions traces * 1945 * cfg80211 exported functions traces *
1901 *************************************************************/ 1946 *************************************************************/
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 728f1c0dc70d..5e233a577d0f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2,6 +2,7 @@
2 * Wireless utility functions 2 * Wireless utility functions
3 * 3 *
4 * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
5 */ 6 */
6#include <linux/export.h> 7#include <linux/export.h>
7#include <linux/bitops.h> 8#include <linux/bitops.h>
@@ -796,7 +797,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
796 netdev_err(dev, "failed to set mgtdef %d\n", i); 797 netdev_err(dev, "failed to set mgtdef %d\n", i);
797 } 798 }
798 799
799 kfree(wdev->connect_keys); 800 kzfree(wdev->connect_keys);
800 wdev->connect_keys = NULL; 801 wdev->connect_keys = NULL;
801} 802}
802 803
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 11120bb14162..0f47948c572f 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -496,6 +496,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
496 err = 0; 496 err = 0;
497 if (!err) { 497 if (!err) {
498 if (!addr) { 498 if (!addr) {
499 memset(wdev->wext.keys->data[idx], 0,
500 sizeof(wdev->wext.keys->data[idx]));
499 wdev->wext.keys->params[idx].key_len = 0; 501 wdev->wext.keys->params[idx].key_len = 0;
500 wdev->wext.keys->params[idx].cipher = 0; 502 wdev->wext.keys->params[idx].cipher = 0;
501 } 503 }
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index c7e5c8eb4f24..368611c05739 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -57,7 +57,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
57 err = cfg80211_connect(rdev, wdev->netdev, 57 err = cfg80211_connect(rdev, wdev->netdev,
58 &wdev->wext.connect, ck, prev_bssid); 58 &wdev->wext.connect, ck, prev_bssid);
59 if (err) 59 if (err)
60 kfree(ck); 60 kzfree(ck);
61 61
62 return err; 62 return err;
63} 63}