aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-04-12 20:43:46 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-12 20:43:46 -0400
commit4e78eb0dbf867ccf206706ff2af34084f71a99bf (patch)
treef3193699ad846ec45abcf5bc95105cb5a460de8f /net
parent716723c2d2f0d5af9911966fb3cd8ccd33480d63 (diff)
parent6d00ec0514bd909e89ede59501342732dbef49fd (diff)
Merge tag 'mac80211-next-for-davem-2015-04-10' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says: ==================== There isn't much left, but we have * new mac80211 internal software queue to allow drivers to have shorter hardware queues and pull on-demand * use rhashtable for mac80211 station table * minstrel rate control debug improvements and some refactoring * fix noisy message about TX power reduction * fix continuous message printing and activity if CRDA doesn't respond * fix VHT-related capabilities with "iw connect" or "iwconfig ..." * fix Kconfig for cfg80211 wireless extensions compatibility ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-tx.c44
-rw-r--r--net/mac80211/driver-ops.h12
-rw-r--r--net/mac80211/ieee80211_i.h28
-rw-r--r--net/mac80211/iface.c23
-rw-r--r--net/mac80211/main.c12
-rw-r--r--net/mac80211/mlme.c14
-rw-r--r--net/mac80211/rc80211_minstrel.c125
-rw-r--r--net/mac80211/rc80211_minstrel.h49
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c125
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c217
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h5
-rw-r--r--net/mac80211/rc80211_minstrel_ht_debugfs.c216
-rw-r--r--net/mac80211/rx.c22
-rw-r--r--net/mac80211/sta_info.c186
-rw-r--r--net/mac80211/sta_info.h40
-rw-r--r--net/mac80211/status.c8
-rw-r--r--net/mac80211/trace.h31
-rw-r--r--net/mac80211/tx.c115
-rw-r--r--net/mac80211/util.c62
-rw-r--r--net/wireless/Kconfig2
-rw-r--r--net/wireless/nl80211.c2
-rw-r--r--net/wireless/reg.c34
-rw-r--r--net/wireless/reg.h9
-rw-r--r--net/wireless/sme.c74
-rw-r--r--net/wireless/util.c41
25 files changed, 1113 insertions, 383 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 20522492d8cc..cce9d425c718 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -188,6 +188,43 @@ ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid)
188 __release(agg_queue); 188 __release(agg_queue);
189} 189}
190 190
191static void
192ieee80211_agg_stop_txq(struct sta_info *sta, int tid)
193{
194 struct ieee80211_txq *txq = sta->sta.txq[tid];
195 struct txq_info *txqi;
196
197 if (!txq)
198 return;
199
200 txqi = to_txq_info(txq);
201
202 /* Lock here to protect against further seqno updates on dequeue */
203 spin_lock_bh(&txqi->queue.lock);
204 set_bit(IEEE80211_TXQ_STOP, &txqi->flags);
205 spin_unlock_bh(&txqi->queue.lock);
206}
207
208static void
209ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
210{
211 struct ieee80211_txq *txq = sta->sta.txq[tid];
212 struct txq_info *txqi;
213
214 if (!txq)
215 return;
216
217 txqi = to_txq_info(txq);
218
219 if (enable)
220 set_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
221 else
222 clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
223
224 clear_bit(IEEE80211_TXQ_STOP, &txqi->flags);
225 drv_wake_tx_queue(sta->sdata->local, txqi);
226}
227
191/* 228/*
192 * splice packets from the STA's pending to the local pending, 229 * splice packets from the STA's pending to the local pending,
193 * requires a call to ieee80211_agg_splice_finish later 230 * requires a call to ieee80211_agg_splice_finish later
@@ -247,6 +284,7 @@ static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid)
247 ieee80211_assign_tid_tx(sta, tid, NULL); 284 ieee80211_assign_tid_tx(sta, tid, NULL);
248 285
249 ieee80211_agg_splice_finish(sta->sdata, tid); 286 ieee80211_agg_splice_finish(sta->sdata, tid);
287 ieee80211_agg_start_txq(sta, tid, false);
250 288
251 kfree_rcu(tid_tx, rcu_head); 289 kfree_rcu(tid_tx, rcu_head);
252} 290}
@@ -418,6 +456,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
418 */ 456 */
419 clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); 457 clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
420 458
459 ieee80211_agg_stop_txq(sta, tid);
460
421 /* 461 /*
422 * Make sure no packets are being processed. This ensures that 462 * Make sure no packets are being processed. This ensures that
423 * we have a valid starting sequence number and that in-flight 463 * we have a valid starting sequence number and that in-flight
@@ -440,6 +480,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
440 ieee80211_agg_splice_finish(sdata, tid); 480 ieee80211_agg_splice_finish(sdata, tid);
441 spin_unlock_bh(&sta->lock); 481 spin_unlock_bh(&sta->lock);
442 482
483 ieee80211_agg_start_txq(sta, tid, false);
484
443 kfree_rcu(tid_tx, rcu_head); 485 kfree_rcu(tid_tx, rcu_head);
444 return; 486 return;
445 } 487 }
@@ -669,6 +711,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
669 ieee80211_agg_splice_finish(sta->sdata, tid); 711 ieee80211_agg_splice_finish(sta->sdata, tid);
670 712
671 spin_unlock_bh(&sta->lock); 713 spin_unlock_bh(&sta->lock);
714
715 ieee80211_agg_start_txq(sta, tid, true);
672} 716}
673 717
674void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) 718void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 0a39d3db951a..26e1ca8a474a 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1367,4 +1367,16 @@ drv_tdls_recv_channel_switch(struct ieee80211_local *local,
1367 trace_drv_return_void(local); 1367 trace_drv_return_void(local);
1368} 1368}
1369 1369
1370static inline void drv_wake_tx_queue(struct ieee80211_local *local,
1371 struct txq_info *txq)
1372{
1373 struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif);
1374
1375 if (!check_sdata_in_driver(sdata))
1376 return;
1377
1378 trace_drv_wake_tx_queue(local, sdata, txq);
1379 local->ops->wake_tx_queue(&local->hw, &txq->txq);
1380}
1381
1370#endif /* __MAC80211_DRIVER_OPS */ 1382#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 487f5e2a9283..ab46ab4a7249 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -26,6 +26,7 @@
26#include <linux/etherdevice.h> 26#include <linux/etherdevice.h>
27#include <linux/leds.h> 27#include <linux/leds.h>
28#include <linux/idr.h> 28#include <linux/idr.h>
29#include <linux/rhashtable.h>
29#include <net/ieee80211_radiotap.h> 30#include <net/ieee80211_radiotap.h>
30#include <net/cfg80211.h> 31#include <net/cfg80211.h>
31#include <net/mac80211.h> 32#include <net/mac80211.h>
@@ -810,6 +811,19 @@ struct mac80211_qos_map {
810 struct rcu_head rcu_head; 811 struct rcu_head rcu_head;
811}; 812};
812 813
814enum txq_info_flags {
815 IEEE80211_TXQ_STOP,
816 IEEE80211_TXQ_AMPDU,
817};
818
819struct txq_info {
820 struct sk_buff_head queue;
821 unsigned long flags;
822
823 /* keep last! */
824 struct ieee80211_txq txq;
825};
826
813struct ieee80211_sub_if_data { 827struct ieee80211_sub_if_data {
814 struct list_head list; 828 struct list_head list;
815 829
@@ -852,6 +866,7 @@ struct ieee80211_sub_if_data {
852 bool control_port_no_encrypt; 866 bool control_port_no_encrypt;
853 int encrypt_headroom; 867 int encrypt_headroom;
854 868
869 atomic_t txqs_len[IEEE80211_NUM_ACS];
855 struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; 870 struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
856 struct mac80211_qos_map __rcu *qos_map; 871 struct mac80211_qos_map __rcu *qos_map;
857 872
@@ -1187,7 +1202,7 @@ struct ieee80211_local {
1187 spinlock_t tim_lock; 1202 spinlock_t tim_lock;
1188 unsigned long num_sta; 1203 unsigned long num_sta;
1189 struct list_head sta_list; 1204 struct list_head sta_list;
1190 struct sta_info __rcu *sta_hash[STA_HASH_SIZE]; 1205 struct rhashtable sta_hash;
1191 struct timer_list sta_cleanup; 1206 struct timer_list sta_cleanup;
1192 int sta_generation; 1207 int sta_generation;
1193 1208
@@ -1449,6 +1464,10 @@ static inline struct ieee80211_local *hw_to_local(
1449 return container_of(hw, struct ieee80211_local, hw); 1464 return container_of(hw, struct ieee80211_local, hw);
1450} 1465}
1451 1466
1467static inline struct txq_info *to_txq_info(struct ieee80211_txq *txq)
1468{
1469 return container_of(txq, struct txq_info, txq);
1470}
1452 1471
1453static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) 1472static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
1454{ 1473{
@@ -1905,6 +1924,9 @@ static inline bool ieee80211_can_run_worker(struct ieee80211_local *local)
1905 return true; 1924 return true;
1906} 1925}
1907 1926
1927void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
1928 struct sta_info *sta,
1929 struct txq_info *txq, int tid);
1908void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, 1930void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
1909 u16 transaction, u16 auth_alg, u16 status, 1931 u16 transaction, u16 auth_alg, u16 status,
1910 const u8 *extra, size_t extra_len, const u8 *bssid, 1932 const u8 *extra, size_t extra_len, const u8 *bssid,
@@ -1943,10 +1965,6 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
1943void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata); 1965void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
1944void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata); 1966void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
1945 1967
1946size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
1947 const u8 *ids, int n_ids,
1948 const u8 *after_ric, int n_after_ric,
1949 size_t offset);
1950size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); 1968size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
1951u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 1969u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1952 u16 cap); 1970 u16 cap);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index a0cd97fd0c49..b4ac596a7cb7 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -969,6 +969,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
969 } 969 }
970 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 970 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
971 971
972 if (sdata->vif.txq) {
973 struct txq_info *txqi = to_txq_info(sdata->vif.txq);
974
975 ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
976 atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
977 }
978
972 if (local->open_count == 0) 979 if (local->open_count == 0)
973 ieee80211_clear_tx_pending(local); 980 ieee80211_clear_tx_pending(local);
974 981
@@ -1654,6 +1661,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1654{ 1661{
1655 struct net_device *ndev = NULL; 1662 struct net_device *ndev = NULL;
1656 struct ieee80211_sub_if_data *sdata = NULL; 1663 struct ieee80211_sub_if_data *sdata = NULL;
1664 struct txq_info *txqi;
1657 int ret, i; 1665 int ret, i;
1658 int txqs = 1; 1666 int txqs = 1;
1659 1667
@@ -1673,10 +1681,18 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1673 ieee80211_assign_perm_addr(local, wdev->address, type); 1681 ieee80211_assign_perm_addr(local, wdev->address, type);
1674 memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); 1682 memcpy(sdata->vif.addr, wdev->address, ETH_ALEN);
1675 } else { 1683 } else {
1684 int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size,
1685 sizeof(void *));
1686 int txq_size = 0;
1687
1688 if (local->ops->wake_tx_queue)
1689 txq_size += sizeof(struct txq_info) +
1690 local->hw.txq_data_size;
1691
1676 if (local->hw.queues >= IEEE80211_NUM_ACS) 1692 if (local->hw.queues >= IEEE80211_NUM_ACS)
1677 txqs = IEEE80211_NUM_ACS; 1693 txqs = IEEE80211_NUM_ACS;
1678 1694
1679 ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, 1695 ndev = alloc_netdev_mqs(size + txq_size,
1680 name, name_assign_type, 1696 name, name_assign_type,
1681 ieee80211_if_setup, txqs, 1); 1697 ieee80211_if_setup, txqs, 1);
1682 if (!ndev) 1698 if (!ndev)
@@ -1711,6 +1727,11 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1711 memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); 1727 memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN);
1712 memcpy(sdata->name, ndev->name, IFNAMSIZ); 1728 memcpy(sdata->name, ndev->name, IFNAMSIZ);
1713 1729
1730 if (txq_size) {
1731 txqi = netdev_priv(ndev) + size;
1732 ieee80211_init_tx_queue(sdata, NULL, txqi, 0);
1733 }
1734
1714 sdata->dev = ndev; 1735 sdata->dev = ndev;
1715 } 1736 }
1716 1737
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 4977967c8b00..df3051d96aff 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -557,6 +557,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
557 557
558 local = wiphy_priv(wiphy); 558 local = wiphy_priv(wiphy);
559 559
560 if (sta_info_init(local))
561 goto err_free;
562
560 local->hw.wiphy = wiphy; 563 local->hw.wiphy = wiphy;
561 564
562 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); 565 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
@@ -629,8 +632,6 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
629 spin_lock_init(&local->ack_status_lock); 632 spin_lock_init(&local->ack_status_lock);
630 idr_init(&local->ack_status_frames); 633 idr_init(&local->ack_status_frames);
631 634
632 sta_info_init(local);
633
634 for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { 635 for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
635 skb_queue_head_init(&local->pending[i]); 636 skb_queue_head_init(&local->pending[i]);
636 atomic_set(&local->agg_queue_stop[i], 0); 637 atomic_set(&local->agg_queue_stop[i], 0);
@@ -650,6 +651,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
650 ieee80211_roc_setup(local); 651 ieee80211_roc_setup(local);
651 652
652 return &local->hw; 653 return &local->hw;
654 err_free:
655 wiphy_free(wiphy);
656 return NULL;
653} 657}
654EXPORT_SYMBOL(ieee80211_alloc_hw_nm); 658EXPORT_SYMBOL(ieee80211_alloc_hw_nm);
655 659
@@ -1035,6 +1039,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
1035 1039
1036 local->dynamic_ps_forced_timeout = -1; 1040 local->dynamic_ps_forced_timeout = -1;
1037 1041
1042 if (!local->hw.txq_ac_max_pending)
1043 local->hw.txq_ac_max_pending = 64;
1044
1038 result = ieee80211_wep_init(local); 1045 result = ieee80211_wep_init(local);
1039 if (result < 0) 1046 if (result < 0)
1040 wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", 1047 wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
@@ -1173,7 +1180,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
1173 1180
1174 destroy_workqueue(local->workqueue); 1181 destroy_workqueue(local->workqueue);
1175 wiphy_unregister(local->hw.wiphy); 1182 wiphy_unregister(local->hw.wiphy);
1176 sta_info_stop(local);
1177 ieee80211_wep_free(local); 1183 ieee80211_wep_free(local);
1178 ieee80211_led_exit(local); 1184 ieee80211_led_exit(local);
1179 kfree(local->int_scan_req); 1185 kfree(local->int_scan_req);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 00103f36dcbf..26053bf2faa8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1348,15 +1348,15 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
1348 */ 1348 */
1349 if (has_80211h_pwr && 1349 if (has_80211h_pwr &&
1350 (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) { 1350 (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) {
1351 sdata_info(sdata, 1351 sdata_dbg(sdata,
1352 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", 1352 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
1353 pwr_level_80211h, chan_pwr, pwr_reduction_80211h, 1353 pwr_level_80211h, chan_pwr, pwr_reduction_80211h,
1354 sdata->u.mgd.bssid); 1354 sdata->u.mgd.bssid);
1355 new_ap_level = pwr_level_80211h; 1355 new_ap_level = pwr_level_80211h;
1356 } else { /* has_cisco_pwr is always true here. */ 1356 } else { /* has_cisco_pwr is always true here. */
1357 sdata_info(sdata, 1357 sdata_dbg(sdata,
1358 "Limiting TX power to %d dBm as advertised by %pM\n", 1358 "Limiting TX power to %d dBm as advertised by %pM\n",
1359 pwr_level_cisco, sdata->u.mgd.bssid); 1359 pwr_level_cisco, sdata->u.mgd.bssid);
1360 new_ap_level = pwr_level_cisco; 1360 new_ap_level = pwr_level_cisco;
1361 } 1361 }
1362 1362
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index ef6e8a6c4253..247552a7f6c2 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -69,14 +69,39 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
69 return i; 69 return i;
70} 70}
71 71
72/* return current EMWA throughput */
73int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma)
74{
75 int usecs;
76
77 usecs = mr->perfect_tx_time;
78 if (!usecs)
79 usecs = 1000000;
80
81 /* reset thr. below 10% success */
82 if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100))
83 return 0;
84
85 if (prob_ewma > MINSTREL_FRAC(90, 100))
86 return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs));
87 else
88 return MINSTREL_TRUNC(100000 * (prob_ewma / usecs));
89}
90
72/* find & sort topmost throughput rates */ 91/* find & sort topmost throughput rates */
73static inline void 92static inline void
74minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) 93minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
75{ 94{
76 int j = MAX_THR_RATES; 95 int j = MAX_THR_RATES;
96 struct minstrel_rate_stats *tmp_mrs = &mi->r[j - 1].stats;
97 struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats;
77 98
78 while (j > 0 && mi->r[i].stats.cur_tp > mi->r[tp_list[j - 1]].stats.cur_tp) 99 while (j > 0 && (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) >
100 minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))) {
79 j--; 101 j--;
102 tmp_mrs = &mi->r[tp_list[j - 1]].stats;
103 }
104
80 if (j < MAX_THR_RATES - 1) 105 if (j < MAX_THR_RATES - 1)
81 memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); 106 memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1));
82 if (j < MAX_THR_RATES) 107 if (j < MAX_THR_RATES)
@@ -127,13 +152,47 @@ minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
127 rate_control_set_rates(mp->hw, mi->sta, ratetbl); 152 rate_control_set_rates(mp->hw, mi->sta, ratetbl);
128} 153}
129 154
155/*
156* Recalculate statistics and counters of a given rate
157*/
158void
159minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
160{
161 if (unlikely(mrs->attempts > 0)) {
162 mrs->sample_skipped = 0;
163 mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
164 if (unlikely(!mrs->att_hist)) {
165 mrs->prob_ewma = mrs->cur_prob;
166 } else {
167 /* update exponential weighted moving variance */
168 mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd,
169 mrs->cur_prob,
170 mrs->prob_ewma,
171 EWMA_LEVEL);
172
173 /*update exponential weighted moving avarage */
174 mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
175 mrs->cur_prob,
176 EWMA_LEVEL);
177 }
178 mrs->att_hist += mrs->attempts;
179 mrs->succ_hist += mrs->success;
180 } else {
181 mrs->sample_skipped++;
182 }
183
184 mrs->last_success = mrs->success;
185 mrs->last_attempts = mrs->attempts;
186 mrs->success = 0;
187 mrs->attempts = 0;
188}
189
130static void 190static void
131minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) 191minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
132{ 192{
133 u8 tmp_tp_rate[MAX_THR_RATES]; 193 u8 tmp_tp_rate[MAX_THR_RATES];
134 u8 tmp_prob_rate = 0; 194 u8 tmp_prob_rate = 0;
135 u32 usecs; 195 int i, tmp_cur_tp, tmp_prob_tp;
136 int i;
137 196
138 for (i = 0; i < MAX_THR_RATES; i++) 197 for (i = 0; i < MAX_THR_RATES; i++)
139 tmp_tp_rate[i] = 0; 198 tmp_tp_rate[i] = 0;
@@ -141,38 +200,15 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
141 for (i = 0; i < mi->n_rates; i++) { 200 for (i = 0; i < mi->n_rates; i++) {
142 struct minstrel_rate *mr = &mi->r[i]; 201 struct minstrel_rate *mr = &mi->r[i];
143 struct minstrel_rate_stats *mrs = &mi->r[i].stats; 202 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
203 struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats;
144 204
145 usecs = mr->perfect_tx_time; 205 /* Update statistics of success probability per rate */
146 if (!usecs) 206 minstrel_calc_rate_stats(mrs);
147 usecs = 1000000;
148
149 if (unlikely(mrs->attempts > 0)) {
150 mrs->sample_skipped = 0;
151 mrs->cur_prob = MINSTREL_FRAC(mrs->success,
152 mrs->attempts);
153 mrs->succ_hist += mrs->success;
154 mrs->att_hist += mrs->attempts;
155 mrs->probability = minstrel_ewma(mrs->probability,
156 mrs->cur_prob,
157 EWMA_LEVEL);
158 } else
159 mrs->sample_skipped++;
160
161 mrs->last_success = mrs->success;
162 mrs->last_attempts = mrs->attempts;
163 mrs->success = 0;
164 mrs->attempts = 0;
165
166 /* Update throughput per rate, reset thr. below 10% success */
167 if (mrs->probability < MINSTREL_FRAC(10, 100))
168 mrs->cur_tp = 0;
169 else
170 mrs->cur_tp = mrs->probability * (1000000 / usecs);
171 207
172 /* Sample less often below the 10% chance of success. 208 /* Sample less often below the 10% chance of success.
173 * Sample less often above the 95% chance of success. */ 209 * Sample less often above the 95% chance of success. */
174 if (mrs->probability > MINSTREL_FRAC(95, 100) || 210 if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
175 mrs->probability < MINSTREL_FRAC(10, 100)) { 211 mrs->prob_ewma < MINSTREL_FRAC(10, 100)) {
176 mr->adjusted_retry_count = mrs->retry_count >> 1; 212 mr->adjusted_retry_count = mrs->retry_count >> 1;
177 if (mr->adjusted_retry_count > 2) 213 if (mr->adjusted_retry_count > 2)
178 mr->adjusted_retry_count = 2; 214 mr->adjusted_retry_count = 2;
@@ -192,11 +228,14 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
192 * choose the maximum throughput rate as max_prob_rate 228 * choose the maximum throughput rate as max_prob_rate
193 * (2) if all success probabilities < 95%, the rate with 229 * (2) if all success probabilities < 95%, the rate with
194 * highest success probability is chosen as max_prob_rate */ 230 * highest success probability is chosen as max_prob_rate */
195 if (mrs->probability >= MINSTREL_FRAC(95, 100)) { 231 if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) {
196 if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp) 232 tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_ewma);
233 tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate],
234 tmp_mrs->prob_ewma);
235 if (tmp_cur_tp >= tmp_prob_tp)
197 tmp_prob_rate = i; 236 tmp_prob_rate = i;
198 } else { 237 } else {
199 if (mrs->probability >= mi->r[tmp_prob_rate].stats.probability) 238 if (mrs->prob_ewma >= tmp_mrs->prob_ewma)
200 tmp_prob_rate = i; 239 tmp_prob_rate = i;
201 } 240 }
202 } 241 }
@@ -215,7 +254,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
215#endif 254#endif
216 255
217 /* Reset update timer */ 256 /* Reset update timer */
218 mi->stats_update = jiffies; 257 mi->last_stats_update = jiffies;
219 258
220 minstrel_update_rates(mp, mi); 259 minstrel_update_rates(mp, mi);
221} 260}
@@ -253,7 +292,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
253 if (mi->sample_deferred > 0) 292 if (mi->sample_deferred > 0)
254 mi->sample_deferred--; 293 mi->sample_deferred--;
255 294
256 if (time_after(jiffies, mi->stats_update + 295 if (time_after(jiffies, mi->last_stats_update +
257 (mp->update_interval * HZ) / 1000)) 296 (mp->update_interval * HZ) / 1000))
258 minstrel_update_stats(mp, mi); 297 minstrel_update_stats(mp, mi);
259} 298}
@@ -385,7 +424,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
385 * has a probability of >95%, we shouldn't be attempting 424 * has a probability of >95%, we shouldn't be attempting
386 * to use it, as this only wastes precious airtime */ 425 * to use it, as this only wastes precious airtime */
387 if (!mrr_capable && 426 if (!mrr_capable &&
388 (mi->r[ndx].stats.probability > MINSTREL_FRAC(95, 100))) 427 (mi->r[ndx].stats.prob_ewma > MINSTREL_FRAC(95, 100)))
389 return; 428 return;
390 429
391 mi->prev_sample = true; 430 mi->prev_sample = true;
@@ -519,7 +558,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
519 } 558 }
520 559
521 mi->n_rates = n; 560 mi->n_rates = n;
522 mi->stats_update = jiffies; 561 mi->last_stats_update = jiffies;
523 562
524 init_sample_table(mi); 563 init_sample_table(mi);
525 minstrel_update_rates(mp, mi); 564 minstrel_update_rates(mp, mi);
@@ -553,7 +592,7 @@ minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
553 if (!mi->sample_table) 592 if (!mi->sample_table)
554 goto error1; 593 goto error1;
555 594
556 mi->stats_update = jiffies; 595 mi->last_stats_update = jiffies;
557 return mi; 596 return mi;
558 597
559error1: 598error1:
@@ -663,12 +702,18 @@ minstrel_free(void *priv)
663static u32 minstrel_get_expected_throughput(void *priv_sta) 702static u32 minstrel_get_expected_throughput(void *priv_sta)
664{ 703{
665 struct minstrel_sta_info *mi = priv_sta; 704 struct minstrel_sta_info *mi = priv_sta;
705 struct minstrel_rate_stats *tmp_mrs;
666 int idx = mi->max_tp_rate[0]; 706 int idx = mi->max_tp_rate[0];
707 int tmp_cur_tp;
667 708
668 /* convert pkt per sec in kbps (1200 is the average pkt size used for 709 /* convert pkt per sec in kbps (1200 is the average pkt size used for
669 * computing cur_tp 710 * computing cur_tp
670 */ 711 */
671 return MINSTREL_TRUNC(mi->r[idx].stats.cur_tp) * 1200 * 8 / 1024; 712 tmp_mrs = &mi->r[idx].stats;
713 tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma);
714 tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
715
716 return tmp_cur_tp;
672} 717}
673 718
674const struct rate_control_ops mac80211_minstrel = { 719const struct rate_control_ops mac80211_minstrel = {
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 410efe620c57..c230bbe93262 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -13,7 +13,6 @@
13#define EWMA_DIV 128 13#define EWMA_DIV 128
14#define SAMPLE_COLUMNS 10 /* number of columns in sample table */ 14#define SAMPLE_COLUMNS 10 /* number of columns in sample table */
15 15
16
17/* scaled fraction values */ 16/* scaled fraction values */
18#define MINSTREL_SCALE 16 17#define MINSTREL_SCALE 16
19#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) 18#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
@@ -24,11 +23,34 @@
24 23
25/* 24/*
26 * Perform EWMA (Exponentially Weighted Moving Average) calculation 25 * Perform EWMA (Exponentially Weighted Moving Average) calculation
27 */ 26 */
28static inline int 27static inline int
29minstrel_ewma(int old, int new, int weight) 28minstrel_ewma(int old, int new, int weight)
30{ 29{
31 return (new * (EWMA_DIV - weight) + old * weight) / EWMA_DIV; 30 int diff, incr;
31
32 diff = new - old;
33 incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
34
35 return old + incr;
36}
37
38/*
39 * Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation
40 */
41static inline int
42minstrel_ewmsd(int old_ewmsd, int cur_prob, int prob_ewma, int weight)
43{
44 int diff, incr, tmp_var;
45
46 /* calculate exponential weighted moving variance */
47 diff = MINSTREL_TRUNC((cur_prob - prob_ewma) * 1000000);
48 incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
49 tmp_var = old_ewmsd * old_ewmsd;
50 tmp_var = weight * (tmp_var + diff * incr / 1000000) / EWMA_DIV;
51
52 /* return standard deviation */
53 return (u16) int_sqrt(tmp_var);
32} 54}
33 55
34struct minstrel_rate_stats { 56struct minstrel_rate_stats {
@@ -39,11 +61,13 @@ struct minstrel_rate_stats {
39 /* total attempts/success counters */ 61 /* total attempts/success counters */
40 u64 att_hist, succ_hist; 62 u64 att_hist, succ_hist;
41 63
42 /* current throughput */ 64 /* statistis of packet delivery probability
43 unsigned int cur_tp; 65 * cur_prob - current prob within last update intervall
44 66 * prob_ewma - exponential weighted moving average of prob
45 /* packet delivery probabilities */ 67 * prob_ewmsd - exp. weighted moving standard deviation of prob */
46 unsigned int cur_prob, probability; 68 unsigned int cur_prob;
69 unsigned int prob_ewma;
70 u16 prob_ewmsd;
47 71
48 /* maximum retry counts */ 72 /* maximum retry counts */
49 u8 retry_count; 73 u8 retry_count;
@@ -71,7 +95,7 @@ struct minstrel_rate {
71struct minstrel_sta_info { 95struct minstrel_sta_info {
72 struct ieee80211_sta *sta; 96 struct ieee80211_sta *sta;
73 97
74 unsigned long stats_update; 98 unsigned long last_stats_update;
75 unsigned int sp_ack_dur; 99 unsigned int sp_ack_dur;
76 unsigned int rate_avg; 100 unsigned int rate_avg;
77 101
@@ -95,6 +119,7 @@ struct minstrel_sta_info {
95 119
96#ifdef CONFIG_MAC80211_DEBUGFS 120#ifdef CONFIG_MAC80211_DEBUGFS
97 struct dentry *dbg_stats; 121 struct dentry *dbg_stats;
122 struct dentry *dbg_stats_csv;
98#endif 123#endif
99}; 124};
100 125
@@ -121,7 +146,6 @@ struct minstrel_priv {
121 u32 fixed_rate_idx; 146 u32 fixed_rate_idx;
122 struct dentry *dbg_fixed_rate; 147 struct dentry *dbg_fixed_rate;
123#endif 148#endif
124
125}; 149};
126 150
127struct minstrel_debugfs_info { 151struct minstrel_debugfs_info {
@@ -133,8 +157,13 @@ extern const struct rate_control_ops mac80211_minstrel;
133void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); 157void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
134void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); 158void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
135 159
160/* Recalculate success probabilities and counters for a given rate using EWMA */
161void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
162int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma);
163
136/* debugfs */ 164/* debugfs */
137int minstrel_stats_open(struct inode *inode, struct file *file); 165int minstrel_stats_open(struct inode *inode, struct file *file);
166int minstrel_stats_csv_open(struct inode *inode, struct file *file);
138ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); 167ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
139int minstrel_stats_release(struct inode *inode, struct file *file); 168int minstrel_stats_release(struct inode *inode, struct file *file);
140 169
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 2acab1bcaa4b..1db5f7c3318a 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -54,12 +54,28 @@
54#include <net/mac80211.h> 54#include <net/mac80211.h>
55#include "rc80211_minstrel.h" 55#include "rc80211_minstrel.h"
56 56
57ssize_t
58minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
59{
60 struct minstrel_debugfs_info *ms;
61
62 ms = file->private_data;
63 return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
64}
65
66int
67minstrel_stats_release(struct inode *inode, struct file *file)
68{
69 kfree(file->private_data);
70 return 0;
71}
72
57int 73int
58minstrel_stats_open(struct inode *inode, struct file *file) 74minstrel_stats_open(struct inode *inode, struct file *file)
59{ 75{
60 struct minstrel_sta_info *mi = inode->i_private; 76 struct minstrel_sta_info *mi = inode->i_private;
61 struct minstrel_debugfs_info *ms; 77 struct minstrel_debugfs_info *ms;
62 unsigned int i, tp, prob, eprob; 78 unsigned int i, tp_max, tp_avg, prob, eprob;
63 char *p; 79 char *p;
64 80
65 ms = kmalloc(2048, GFP_KERNEL); 81 ms = kmalloc(2048, GFP_KERNEL);
@@ -68,8 +84,14 @@ minstrel_stats_open(struct inode *inode, struct file *file)
68 84
69 file->private_data = ms; 85 file->private_data = ms;
70 p = ms->buf; 86 p = ms->buf;
71 p += sprintf(p, "rate tpt eprob *prob" 87 p += sprintf(p, "\n");
72 " *ok(*cum) ok( cum)\n"); 88 p += sprintf(p, "best __________rate_________ ______"
89 "statistics______ ________last_______ "
90 "______sum-of________\n");
91 p += sprintf(p, "rate [name idx airtime max_tp] [ ø(tp) ø(prob) "
92 "sd(prob)] [prob.|retry|suc|att] "
93 "[#success | #attempts]\n");
94
73 for (i = 0; i < mi->n_rates; i++) { 95 for (i = 0; i < mi->n_rates; i++) {
74 struct minstrel_rate *mr = &mi->r[i]; 96 struct minstrel_rate *mr = &mi->r[i];
75 struct minstrel_rate_stats *mrs = &mi->r[i].stats; 97 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
@@ -79,18 +101,26 @@ minstrel_stats_open(struct inode *inode, struct file *file)
79 *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; 101 *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' ';
80 *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; 102 *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' ';
81 *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; 103 *(p++) = (i == mi->max_prob_rate) ? 'P' : ' ';
82 p += sprintf(p, "%3u%s", mr->bitrate / 2, 104
105 p += sprintf(p, " %3u%s ", mr->bitrate / 2,
83 (mr->bitrate & 1 ? ".5" : " ")); 106 (mr->bitrate & 1 ? ".5" : " "));
107 p += sprintf(p, "%3u ", i);
108 p += sprintf(p, "%6u ", mr->perfect_tx_time);
84 109
85 tp = MINSTREL_TRUNC(mrs->cur_tp / 10); 110 tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
111 tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
86 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 112 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
87 eprob = MINSTREL_TRUNC(mrs->probability * 1000); 113 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
88 114
89 p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u" 115 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
90 " %4u(%4u) %9llu(%9llu)\n", 116 " %3u.%1u %3u %3u %-3u "
91 tp / 10, tp % 10, 117 "%9llu %-9llu\n",
118 tp_max / 10, tp_max % 10,
119 tp_avg / 10, tp_avg % 10,
92 eprob / 10, eprob % 10, 120 eprob / 10, eprob % 10,
121 mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
93 prob / 10, prob % 10, 122 prob / 10, prob % 10,
123 mrs->retry_count,
94 mrs->last_success, 124 mrs->last_success,
95 mrs->last_attempts, 125 mrs->last_attempts,
96 (unsigned long long)mrs->succ_hist, 126 (unsigned long long)mrs->succ_hist,
@@ -107,25 +137,75 @@ minstrel_stats_open(struct inode *inode, struct file *file)
107 return 0; 137 return 0;
108} 138}
109 139
110ssize_t 140static const struct file_operations minstrel_stat_fops = {
111minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) 141 .owner = THIS_MODULE,
142 .open = minstrel_stats_open,
143 .read = minstrel_stats_read,
144 .release = minstrel_stats_release,
145 .llseek = default_llseek,
146};
147
148int
149minstrel_stats_csv_open(struct inode *inode, struct file *file)
112{ 150{
151 struct minstrel_sta_info *mi = inode->i_private;
113 struct minstrel_debugfs_info *ms; 152 struct minstrel_debugfs_info *ms;
153 unsigned int i, tp_max, tp_avg, prob, eprob;
154 char *p;
114 155
115 ms = file->private_data; 156 ms = kmalloc(2048, GFP_KERNEL);
116 return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); 157 if (!ms)
117} 158 return -ENOMEM;
159
160 file->private_data = ms;
161 p = ms->buf;
162
163 for (i = 0; i < mi->n_rates; i++) {
164 struct minstrel_rate *mr = &mi->r[i];
165 struct minstrel_rate_stats *mrs = &mi->r[i].stats;
166
167 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : ""));
168 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : ""));
169 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[2]) ? "C" : ""));
170 p += sprintf(p, "%s" ,((i == mi->max_tp_rate[3]) ? "D" : ""));
171 p += sprintf(p, "%s" ,((i == mi->max_prob_rate) ? "P" : ""));
172
173 p += sprintf(p, ",%u%s", mr->bitrate / 2,
174 (mr->bitrate & 1 ? ".5," : ","));
175 p += sprintf(p, "%u,", i);
176 p += sprintf(p, "%u,",mr->perfect_tx_time);
177
178 tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
179 tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
180 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
181 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
182
183 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
184 "%llu,%llu,%d,%d\n",
185 tp_max / 10, tp_max % 10,
186 tp_avg / 10, tp_avg % 10,
187 eprob / 10, eprob % 10,
188 mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
189 prob / 10, prob % 10,
190 mrs->retry_count,
191 mrs->last_success,
192 mrs->last_attempts,
193 (unsigned long long)mrs->succ_hist,
194 (unsigned long long)mrs->att_hist,
195 mi->total_packets - mi->sample_packets,
196 mi->sample_packets);
197
198 }
199 ms->len = p - ms->buf;
200
201 WARN_ON(ms->len + sizeof(*ms) > 2048);
118 202
119int
120minstrel_stats_release(struct inode *inode, struct file *file)
121{
122 kfree(file->private_data);
123 return 0; 203 return 0;
124} 204}
125 205
126static const struct file_operations minstrel_stat_fops = { 206static const struct file_operations minstrel_stat_csv_fops = {
127 .owner = THIS_MODULE, 207 .owner = THIS_MODULE,
128 .open = minstrel_stats_open, 208 .open = minstrel_stats_csv_open,
129 .read = minstrel_stats_read, 209 .read = minstrel_stats_read,
130 .release = minstrel_stats_release, 210 .release = minstrel_stats_release,
131 .llseek = default_llseek, 211 .llseek = default_llseek,
@@ -138,6 +218,9 @@ minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
138 218
139 mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi, 219 mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi,
140 &minstrel_stat_fops); 220 &minstrel_stat_fops);
221
222 mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO, dir,
223 mi, &minstrel_stat_csv_fops);
141} 224}
142 225
143void 226void
@@ -146,4 +229,6 @@ minstrel_remove_sta_debugfs(void *priv, void *priv_sta)
146 struct minstrel_sta_info *mi = priv_sta; 229 struct minstrel_sta_info *mi = priv_sta;
147 230
148 debugfs_remove(mi->dbg_stats); 231 debugfs_remove(mi->dbg_stats);
232
233 debugfs_remove(mi->dbg_stats_csv);
149} 234}
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 60698fc7042e..7430a1df2ab1 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -313,67 +313,35 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index)
313 return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES]; 313 return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES];
314} 314}
315 315
316
317/* 316/*
318 * Recalculate success probabilities and counters for a rate using EWMA 317 * Return current throughput based on the average A-MPDU length, taking into
318 * account the expected number of retransmissions and their expected length
319 */ 319 */
320static void 320int
321minstrel_calc_rate_ewma(struct minstrel_rate_stats *mr) 321minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
322 int prob_ewma)
322{ 323{
323 if (unlikely(mr->attempts > 0)) {
324 mr->sample_skipped = 0;
325 mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts);
326 if (!mr->att_hist)
327 mr->probability = mr->cur_prob;
328 else
329 mr->probability = minstrel_ewma(mr->probability,
330 mr->cur_prob, EWMA_LEVEL);
331 mr->att_hist += mr->attempts;
332 mr->succ_hist += mr->success;
333 } else {
334 mr->sample_skipped++;
335 }
336 mr->last_success = mr->success;
337 mr->last_attempts = mr->attempts;
338 mr->success = 0;
339 mr->attempts = 0;
340}
341
342/*
343 * Calculate throughput based on the average A-MPDU length, taking into account
344 * the expected number of retransmissions and their expected length
345 */
346static void
347minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
348{
349 struct minstrel_rate_stats *mr;
350 unsigned int nsecs = 0; 324 unsigned int nsecs = 0;
351 unsigned int tp;
352 unsigned int prob;
353 325
354 mr = &mi->groups[group].rates[rate]; 326 /* do not account throughput if sucess prob is below 10% */
355 prob = mr->probability; 327 if (prob_ewma < MINSTREL_FRAC(10, 100))
356 328 return 0;
357 if (prob < MINSTREL_FRAC(1, 10)) {
358 mr->cur_tp = 0;
359 return;
360 }
361
362 /*
363 * For the throughput calculation, limit the probability value to 90% to
364 * account for collision related packet error rate fluctuation
365 */
366 if (prob > MINSTREL_FRAC(9, 10))
367 prob = MINSTREL_FRAC(9, 10);
368 329
369 if (group != MINSTREL_CCK_GROUP) 330 if (group != MINSTREL_CCK_GROUP)
370 nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); 331 nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
371 332
372 nsecs += minstrel_mcs_groups[group].duration[rate]; 333 nsecs += minstrel_mcs_groups[group].duration[rate];
373 334
374 /* prob is scaled - see MINSTREL_FRAC above */ 335 /*
375 tp = 1000000 * ((prob * 1000) / nsecs); 336 * For the throughput calculation, limit the probability value to 90% to
376 mr->cur_tp = MINSTREL_TRUNC(tp); 337 * account for collision related packet error rate fluctuation
338 * (prob is scaled - see MINSTREL_FRAC above)
339 */
340 if (prob_ewma > MINSTREL_FRAC(90, 100))
341 return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000)
342 / nsecs));
343 else
344 return MINSTREL_TRUNC(100000 * ((prob_ewma * 1000) / nsecs));
377} 345}
378 346
379/* 347/*
@@ -387,22 +355,23 @@ static void
387minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index, 355minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index,
388 u16 *tp_list) 356 u16 *tp_list)
389{ 357{
390 int cur_group, cur_idx, cur_thr, cur_prob; 358 int cur_group, cur_idx, cur_tp_avg, cur_prob;
391 int tmp_group, tmp_idx, tmp_thr, tmp_prob; 359 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob;
392 int j = MAX_THR_RATES; 360 int j = MAX_THR_RATES;
393 361
394 cur_group = index / MCS_GROUP_RATES; 362 cur_group = index / MCS_GROUP_RATES;
395 cur_idx = index % MCS_GROUP_RATES; 363 cur_idx = index % MCS_GROUP_RATES;
396 cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp; 364 cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma;
397 cur_prob = mi->groups[cur_group].rates[cur_idx].probability; 365 cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob);
398 366
399 do { 367 do {
400 tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; 368 tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
401 tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; 369 tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
402 tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp; 370 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
403 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability; 371 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx,
404 if (cur_thr < tmp_thr || 372 tmp_prob);
405 (cur_thr == tmp_thr && cur_prob <= tmp_prob)) 373 if (cur_tp_avg < tmp_tp_avg ||
374 (cur_tp_avg == tmp_tp_avg && cur_prob <= tmp_prob))
406 break; 375 break;
407 j--; 376 j--;
408 } while (j > 0); 377 } while (j > 0);
@@ -422,16 +391,21 @@ static void
422minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index) 391minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
423{ 392{
424 struct minstrel_mcs_group_data *mg; 393 struct minstrel_mcs_group_data *mg;
425 struct minstrel_rate_stats *mr; 394 struct minstrel_rate_stats *mrs;
426 int tmp_group, tmp_idx, tmp_tp, tmp_prob, max_tp_group; 395 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob;
396 int max_tp_group, cur_tp_avg, cur_group, cur_idx;
397 int max_gpr_group, max_gpr_idx;
398 int max_gpr_tp_avg, max_gpr_prob;
427 399
400 cur_group = index / MCS_GROUP_RATES;
401 cur_idx = index % MCS_GROUP_RATES;
428 mg = &mi->groups[index / MCS_GROUP_RATES]; 402 mg = &mi->groups[index / MCS_GROUP_RATES];
429 mr = &mg->rates[index % MCS_GROUP_RATES]; 403 mrs = &mg->rates[index % MCS_GROUP_RATES];
430 404
431 tmp_group = mi->max_prob_rate / MCS_GROUP_RATES; 405 tmp_group = mi->max_prob_rate / MCS_GROUP_RATES;
432 tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES; 406 tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES;
433 tmp_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp; 407 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
434 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability; 408 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
435 409
436 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from 410 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from
437 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */ 411 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */
@@ -440,15 +414,24 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
440 (max_tp_group != MINSTREL_CCK_GROUP)) 414 (max_tp_group != MINSTREL_CCK_GROUP))
441 return; 415 return;
442 416
443 if (mr->probability > MINSTREL_FRAC(75, 100)) { 417 if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) {
444 if (mr->cur_tp > tmp_tp) 418 cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx,
419 mrs->prob_ewma);
420 if (cur_tp_avg > tmp_tp_avg)
445 mi->max_prob_rate = index; 421 mi->max_prob_rate = index;
446 if (mr->cur_tp > mg->rates[mg->max_group_prob_rate].cur_tp) 422
423 max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
424 max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
425 max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma;
426 max_gpr_tp_avg = minstrel_ht_get_tp_avg(mi, max_gpr_group,
427 max_gpr_idx,
428 max_gpr_prob);
429 if (cur_tp_avg > max_gpr_tp_avg)
447 mg->max_group_prob_rate = index; 430 mg->max_group_prob_rate = index;
448 } else { 431 } else {
449 if (mr->probability > tmp_prob) 432 if (mrs->prob_ewma > tmp_prob)
450 mi->max_prob_rate = index; 433 mi->max_prob_rate = index;
451 if (mr->probability > mg->rates[mg->max_group_prob_rate].probability) 434 if (mrs->prob_ewma > mg->rates[mg->max_group_prob_rate].prob_ewma)
452 mg->max_group_prob_rate = index; 435 mg->max_group_prob_rate = index;
453 } 436 }
454} 437}
@@ -465,16 +448,18 @@ minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
465 u16 tmp_mcs_tp_rate[MAX_THR_RATES], 448 u16 tmp_mcs_tp_rate[MAX_THR_RATES],
466 u16 tmp_cck_tp_rate[MAX_THR_RATES]) 449 u16 tmp_cck_tp_rate[MAX_THR_RATES])
467{ 450{
468 unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp; 451 unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp, tmp_prob;
469 int i; 452 int i;
470 453
471 tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES; 454 tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES;
472 tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES; 455 tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES;
473 tmp_cck_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp; 456 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
457 tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
474 458
475 tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES; 459 tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES;
476 tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES; 460 tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES;
477 tmp_mcs_tp = mi->groups[tmp_group].rates[tmp_idx].cur_tp; 461 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma;
462 tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob);
478 463
479 if (tmp_cck_tp > tmp_mcs_tp) { 464 if (tmp_cck_tp > tmp_mcs_tp) {
480 for(i = 0; i < MAX_THR_RATES; i++) { 465 for(i = 0; i < MAX_THR_RATES; i++) {
@@ -493,8 +478,7 @@ static inline void
493minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) 478minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
494{ 479{
495 struct minstrel_mcs_group_data *mg; 480 struct minstrel_mcs_group_data *mg;
496 struct minstrel_rate_stats *mr; 481 int tmp_max_streams, group, tmp_idx, tmp_prob;
497 int tmp_max_streams, group;
498 int tmp_tp = 0; 482 int tmp_tp = 0;
499 483
500 tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] / 484 tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] /
@@ -503,11 +487,16 @@ minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
503 mg = &mi->groups[group]; 487 mg = &mi->groups[group];
504 if (!mg->supported || group == MINSTREL_CCK_GROUP) 488 if (!mg->supported || group == MINSTREL_CCK_GROUP)
505 continue; 489 continue;
506 mr = minstrel_get_ratestats(mi, mg->max_group_prob_rate); 490
507 if (tmp_tp < mr->cur_tp && 491 tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
492 tmp_prob = mi->groups[group].rates[tmp_idx].prob_ewma;
493
494 if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) &&
508 (minstrel_mcs_groups[group].streams < tmp_max_streams)) { 495 (minstrel_mcs_groups[group].streams < tmp_max_streams)) {
509 mi->max_prob_rate = mg->max_group_prob_rate; 496 mi->max_prob_rate = mg->max_group_prob_rate;
510 tmp_tp = mr->cur_tp; 497 tmp_tp = minstrel_ht_get_tp_avg(mi, group,
498 tmp_idx,
499 tmp_prob);
511 } 500 }
512 } 501 }
513} 502}
@@ -525,8 +514,8 @@ static void
525minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) 514minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
526{ 515{
527 struct minstrel_mcs_group_data *mg; 516 struct minstrel_mcs_group_data *mg;
528 struct minstrel_rate_stats *mr; 517 struct minstrel_rate_stats *mrs;
529 int group, i, j; 518 int group, i, j, cur_prob;
530 u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES]; 519 u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
531 u16 tmp_cck_tp_rate[MAX_THR_RATES], index; 520 u16 tmp_cck_tp_rate[MAX_THR_RATES], index;
532 521
@@ -565,12 +554,12 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
565 554
566 index = MCS_GROUP_RATES * group + i; 555 index = MCS_GROUP_RATES * group + i;
567 556
568 mr = &mg->rates[i]; 557 mrs = &mg->rates[i];
569 mr->retry_updated = false; 558 mrs->retry_updated = false;
570 minstrel_calc_rate_ewma(mr); 559 minstrel_calc_rate_stats(mrs);
571 minstrel_ht_calc_tp(mi, group, i); 560 cur_prob = mrs->prob_ewma;
572 561
573 if (!mr->cur_tp) 562 if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0)
574 continue; 563 continue;
575 564
576 /* Find max throughput rate set */ 565 /* Find max throughput rate set */
@@ -614,7 +603,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
614#endif 603#endif
615 604
616 /* Reset update timer */ 605 /* Reset update timer */
617 mi->stats_update = jiffies; 606 mi->last_stats_update = jiffies;
618} 607}
619 608
620static bool 609static bool
@@ -637,7 +626,7 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct ieee80211_tx_rate *rat
637} 626}
638 627
639static void 628static void
640minstrel_next_sample_idx(struct minstrel_ht_sta *mi) 629minstrel_set_next_sample_idx(struct minstrel_ht_sta *mi)
641{ 630{
642 struct minstrel_mcs_group_data *mg; 631 struct minstrel_mcs_group_data *mg;
643 632
@@ -778,7 +767,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
778 update = true; 767 update = true;
779 } 768 }
780 769
781 if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { 770 if (time_after(jiffies, mi->last_stats_update +
771 (mp->update_interval / 2 * HZ) / 1000)) {
782 update = true; 772 update = true;
783 minstrel_ht_update_stats(mp, mi); 773 minstrel_ht_update_stats(mp, mi);
784 } 774 }
@@ -791,7 +781,7 @@ static void
791minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, 781minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
792 int index) 782 int index)
793{ 783{
794 struct minstrel_rate_stats *mr; 784 struct minstrel_rate_stats *mrs;
795 const struct mcs_group *group; 785 const struct mcs_group *group;
796 unsigned int tx_time, tx_time_rtscts, tx_time_data; 786 unsigned int tx_time, tx_time_rtscts, tx_time_data;
797 unsigned int cw = mp->cw_min; 787 unsigned int cw = mp->cw_min;
@@ -800,16 +790,16 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
800 unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len); 790 unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len);
801 unsigned int overhead = 0, overhead_rtscts = 0; 791 unsigned int overhead = 0, overhead_rtscts = 0;
802 792
803 mr = minstrel_get_ratestats(mi, index); 793 mrs = minstrel_get_ratestats(mi, index);
804 if (mr->probability < MINSTREL_FRAC(1, 10)) { 794 if (mrs->prob_ewma < MINSTREL_FRAC(1, 10)) {
805 mr->retry_count = 1; 795 mrs->retry_count = 1;
806 mr->retry_count_rtscts = 1; 796 mrs->retry_count_rtscts = 1;
807 return; 797 return;
808 } 798 }
809 799
810 mr->retry_count = 2; 800 mrs->retry_count = 2;
811 mr->retry_count_rtscts = 2; 801 mrs->retry_count_rtscts = 2;
812 mr->retry_updated = true; 802 mrs->retry_updated = true;
813 803
814 group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; 804 group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
815 tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000; 805 tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;
@@ -840,9 +830,9 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
840 tx_time_rtscts += ctime + overhead_rtscts + tx_time_data; 830 tx_time_rtscts += ctime + overhead_rtscts + tx_time_data;
841 831
842 if (tx_time_rtscts < mp->segment_size) 832 if (tx_time_rtscts < mp->segment_size)
843 mr->retry_count_rtscts++; 833 mrs->retry_count_rtscts++;
844 } while ((tx_time < mp->segment_size) && 834 } while ((tx_time < mp->segment_size) &&
845 (++mr->retry_count < mp->max_retry)); 835 (++mrs->retry_count < mp->max_retry));
846} 836}
847 837
848 838
@@ -851,22 +841,22 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
851 struct ieee80211_sta_rates *ratetbl, int offset, int index) 841 struct ieee80211_sta_rates *ratetbl, int offset, int index)
852{ 842{
853 const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; 843 const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
854 struct minstrel_rate_stats *mr; 844 struct minstrel_rate_stats *mrs;
855 u8 idx; 845 u8 idx;
856 u16 flags = group->flags; 846 u16 flags = group->flags;
857 847
858 mr = minstrel_get_ratestats(mi, index); 848 mrs = minstrel_get_ratestats(mi, index);
859 if (!mr->retry_updated) 849 if (!mrs->retry_updated)
860 minstrel_calc_retransmit(mp, mi, index); 850 minstrel_calc_retransmit(mp, mi, index);
861 851
862 if (mr->probability < MINSTREL_FRAC(20, 100) || !mr->retry_count) { 852 if (mrs->prob_ewma < MINSTREL_FRAC(20, 100) || !mrs->retry_count) {
863 ratetbl->rate[offset].count = 2; 853 ratetbl->rate[offset].count = 2;
864 ratetbl->rate[offset].count_rts = 2; 854 ratetbl->rate[offset].count_rts = 2;
865 ratetbl->rate[offset].count_cts = 2; 855 ratetbl->rate[offset].count_cts = 2;
866 } else { 856 } else {
867 ratetbl->rate[offset].count = mr->retry_count; 857 ratetbl->rate[offset].count = mrs->retry_count;
868 ratetbl->rate[offset].count_cts = mr->retry_count; 858 ratetbl->rate[offset].count_cts = mrs->retry_count;
869 ratetbl->rate[offset].count_rts = mr->retry_count_rtscts; 859 ratetbl->rate[offset].count_rts = mrs->retry_count_rtscts;
870 } 860 }
871 861
872 if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) 862 if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP)
@@ -924,7 +914,7 @@ minstrel_get_duration(int index)
924static int 914static int
925minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) 915minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
926{ 916{
927 struct minstrel_rate_stats *mr; 917 struct minstrel_rate_stats *mrs;
928 struct minstrel_mcs_group_data *mg; 918 struct minstrel_mcs_group_data *mg;
929 unsigned int sample_dur, sample_group, cur_max_tp_streams; 919 unsigned int sample_dur, sample_group, cur_max_tp_streams;
930 int sample_idx = 0; 920 int sample_idx = 0;
@@ -940,12 +930,12 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
940 sample_group = mi->sample_group; 930 sample_group = mi->sample_group;
941 mg = &mi->groups[sample_group]; 931 mg = &mi->groups[sample_group];
942 sample_idx = sample_table[mg->column][mg->index]; 932 sample_idx = sample_table[mg->column][mg->index];
943 minstrel_next_sample_idx(mi); 933 minstrel_set_next_sample_idx(mi);
944 934
945 if (!(mg->supported & BIT(sample_idx))) 935 if (!(mg->supported & BIT(sample_idx)))
946 return -1; 936 return -1;
947 937
948 mr = &mg->rates[sample_idx]; 938 mrs = &mg->rates[sample_idx];
949 sample_idx += sample_group * MCS_GROUP_RATES; 939 sample_idx += sample_group * MCS_GROUP_RATES;
950 940
951 /* 941 /*
@@ -962,7 +952,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
962 * Do not sample if the probability is already higher than 95% 952 * Do not sample if the probability is already higher than 95%
963 * to avoid wasting airtime. 953 * to avoid wasting airtime.
964 */ 954 */
965 if (mr->probability > MINSTREL_FRAC(95, 100)) 955 if (mrs->prob_ewma > MINSTREL_FRAC(95, 100))
966 return -1; 956 return -1;
967 957
968 /* 958 /*
@@ -977,7 +967,7 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
977 (cur_max_tp_streams - 1 < 967 (cur_max_tp_streams - 1 <
978 minstrel_mcs_groups[sample_group].streams || 968 minstrel_mcs_groups[sample_group].streams ||
979 sample_dur >= minstrel_get_duration(mi->max_prob_rate))) { 969 sample_dur >= minstrel_get_duration(mi->max_prob_rate))) {
980 if (mr->sample_skipped < 20) 970 if (mrs->sample_skipped < 20)
981 return -1; 971 return -1;
982 972
983 if (mi->sample_slow++ > 2) 973 if (mi->sample_slow++ > 2)
@@ -1131,7 +1121,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
1131 memset(mi, 0, sizeof(*mi)); 1121 memset(mi, 0, sizeof(*mi));
1132 1122
1133 mi->sta = sta; 1123 mi->sta = sta;
1134 mi->stats_update = jiffies; 1124 mi->last_stats_update = jiffies;
1135 1125
1136 ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0); 1126 ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0);
1137 mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1, 0); 1127 mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1, 0);
@@ -1328,16 +1318,19 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
1328{ 1318{
1329 struct minstrel_ht_sta_priv *msp = priv_sta; 1319 struct minstrel_ht_sta_priv *msp = priv_sta;
1330 struct minstrel_ht_sta *mi = &msp->ht; 1320 struct minstrel_ht_sta *mi = &msp->ht;
1331 int i, j; 1321 int i, j, prob, tp_avg;
1332 1322
1333 if (!msp->is_ht) 1323 if (!msp->is_ht)
1334 return mac80211_minstrel.get_expected_throughput(priv_sta); 1324 return mac80211_minstrel.get_expected_throughput(priv_sta);
1335 1325
1336 i = mi->max_tp_rate[0] / MCS_GROUP_RATES; 1326 i = mi->max_tp_rate[0] / MCS_GROUP_RATES;
1337 j = mi->max_tp_rate[0] % MCS_GROUP_RATES; 1327 j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
1328 prob = mi->groups[i].rates[j].prob_ewma;
1329
1330 /* convert tp_avg from pkt per second in kbps */
1331 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * AVG_PKT_SIZE * 8 / 1024;
1338 1332
1339 /* convert cur_tp from pkt per second in kbps */ 1333 return tp_avg;
1340 return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024;
1341} 1334}
1342 1335
1343static const struct rate_control_ops mac80211_minstrel_ht = { 1336static const struct rate_control_ops mac80211_minstrel_ht = {
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index f2217d6aa0c2..e8b52a94d24b 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -78,7 +78,7 @@ struct minstrel_ht_sta {
78 u16 max_prob_rate; 78 u16 max_prob_rate;
79 79
80 /* time of last status update */ 80 /* time of last status update */
81 unsigned long stats_update; 81 unsigned long last_stats_update;
82 82
83 /* overhead time in usec for each frame */ 83 /* overhead time in usec for each frame */
84 unsigned int overhead; 84 unsigned int overhead;
@@ -112,6 +112,7 @@ struct minstrel_ht_sta_priv {
112 }; 112 };
113#ifdef CONFIG_MAC80211_DEBUGFS 113#ifdef CONFIG_MAC80211_DEBUGFS
114 struct dentry *dbg_stats; 114 struct dentry *dbg_stats;
115 struct dentry *dbg_stats_csv;
115#endif 116#endif
116 void *ratelist; 117 void *ratelist;
117 void *sample_table; 118 void *sample_table;
@@ -120,5 +121,7 @@ struct minstrel_ht_sta_priv {
120 121
121void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); 122void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
122void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta); 123void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
124int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
125 int prob_ewma);
123 126
124#endif 127#endif
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 20c676b8e5b6..6822ce0f95e5 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -19,7 +19,7 @@ static char *
19minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) 19minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
20{ 20{
21 const struct mcs_group *mg; 21 const struct mcs_group *mg;
22 unsigned int j, tp, prob, eprob; 22 unsigned int j, tp_max, tp_avg, prob, eprob, tx_time;
23 char htmode = '2'; 23 char htmode = '2';
24 char gimode = 'L'; 24 char gimode = 'L';
25 u32 gflags; 25 u32 gflags;
@@ -38,19 +38,26 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
38 gimode = 'S'; 38 gimode = 'S';
39 39
40 for (j = 0; j < MCS_GROUP_RATES; j++) { 40 for (j = 0; j < MCS_GROUP_RATES; j++) {
41 struct minstrel_rate_stats *mr = &mi->groups[i].rates[j]; 41 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
42 static const int bitrates[4] = { 10, 20, 55, 110 }; 42 static const int bitrates[4] = { 10, 20, 55, 110 };
43 int idx = i * MCS_GROUP_RATES + j; 43 int idx = i * MCS_GROUP_RATES + j;
44 44
45 if (!(mi->groups[i].supported & BIT(j))) 45 if (!(mi->groups[i].supported & BIT(j)))
46 continue; 46 continue;
47 47
48 if (gflags & IEEE80211_TX_RC_MCS) 48 if (gflags & IEEE80211_TX_RC_MCS) {
49 p += sprintf(p, " HT%c0/%cGI ", htmode, gimode); 49 p += sprintf(p, "HT%c0 ", htmode);
50 else if (gflags & IEEE80211_TX_RC_VHT_MCS) 50 p += sprintf(p, "%cGI ", gimode);
51 p += sprintf(p, "VHT%c0/%cGI ", htmode, gimode); 51 p += sprintf(p, "%d ", mg->streams);
52 else 52 } else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
53 p += sprintf(p, " CCK/%cP ", j < 4 ? 'L' : 'S'); 53 p += sprintf(p, "VHT%c0 ", htmode);
54 p += sprintf(p, "%cGI ", gimode);
55 p += sprintf(p, "%d ", mg->streams);
56 } else {
57 p += sprintf(p, "CCK ");
58 p += sprintf(p, "%cP ", j < 4 ? 'L' : 'S');
59 p += sprintf(p, "1 ");
60 }
54 61
55 *(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' '; 62 *(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' ';
56 *(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' '; 63 *(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' ';
@@ -59,29 +66,39 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
59 *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' '; 66 *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
60 67
61 if (gflags & IEEE80211_TX_RC_MCS) { 68 if (gflags & IEEE80211_TX_RC_MCS) {
62 p += sprintf(p, " MCS%-2u ", (mg->streams - 1) * 8 + j); 69 p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j);
63 } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { 70 } else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
64 p += sprintf(p, " MCS%-1u/%1u", j, mg->streams); 71 p += sprintf(p, " MCS%-1u/%1u", j, mg->streams);
65 } else { 72 } else {
66 int r = bitrates[j % 4]; 73 int r = bitrates[j % 4];
67 74
68 p += sprintf(p, " %2u.%1uM ", r / 10, r % 10); 75 p += sprintf(p, " %2u.%1uM", r / 10, r % 10);
69 } 76 }
70 77
71 tp = mr->cur_tp / 10; 78 p += sprintf(p, " %3u ", idx);
72 prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
73 eprob = MINSTREL_TRUNC(mr->probability * 1000);
74 79
75 p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u " 80 /* tx_time[rate(i)] in usec */
76 "%3u %4u(%4u) %9llu(%9llu)\n", 81 tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
77 tp / 10, tp % 10, 82 p += sprintf(p, "%6u ", tx_time);
83
84 tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
85 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
86 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
87 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
88
89 p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
90 " %3u.%1u %3u %3u %-3u "
91 "%9llu %-9llu\n",
92 tp_max / 10, tp_max % 10,
93 tp_avg / 10, tp_avg % 10,
78 eprob / 10, eprob % 10, 94 eprob / 10, eprob % 10,
95 mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
79 prob / 10, prob % 10, 96 prob / 10, prob % 10,
80 mr->retry_count, 97 mrs->retry_count,
81 mr->last_success, 98 mrs->last_success,
82 mr->last_attempts, 99 mrs->last_attempts,
83 (unsigned long long)mr->succ_hist, 100 (unsigned long long)mrs->succ_hist,
84 (unsigned long long)mr->att_hist); 101 (unsigned long long)mrs->att_hist);
85 } 102 }
86 103
87 return p; 104 return p;
@@ -94,8 +111,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
94 struct minstrel_ht_sta *mi = &msp->ht; 111 struct minstrel_ht_sta *mi = &msp->ht;
95 struct minstrel_debugfs_info *ms; 112 struct minstrel_debugfs_info *ms;
96 unsigned int i; 113 unsigned int i;
97 char *p;
98 int ret; 114 int ret;
115 char *p;
99 116
100 if (!msp->is_ht) { 117 if (!msp->is_ht) {
101 inode->i_private = &msp->legacy; 118 inode->i_private = &msp->legacy;
@@ -110,8 +127,14 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
110 127
111 file->private_data = ms; 128 file->private_data = ms;
112 p = ms->buf; 129 p = ms->buf;
113 p += sprintf(p, " type rate tpt eprob *prob " 130
114 "ret *ok(*cum) ok( cum)\n"); 131 p += sprintf(p, "\n");
132 p += sprintf(p, " best ____________rate__________ "
133 "______statistics______ ________last_______ "
134 "______sum-of________\n");
135 p += sprintf(p, "mode guard # rate [name idx airtime max_tp] "
136 "[ ø(tp) ø(prob) sd(prob)] [prob.|retry|suc|att] [#success | "
137 "#attempts]\n");
115 138
116 p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p); 139 p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
117 for (i = 0; i < MINSTREL_CCK_GROUP; i++) 140 for (i = 0; i < MINSTREL_CCK_GROUP; i++)
@@ -123,11 +146,10 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
123 "lookaround %d\n", 146 "lookaround %d\n",
124 max(0, (int) mi->total_packets - (int) mi->sample_packets), 147 max(0, (int) mi->total_packets - (int) mi->sample_packets),
125 mi->sample_packets); 148 mi->sample_packets);
126 p += sprintf(p, "Average A-MPDU length: %d.%d\n", 149 p += sprintf(p, "Average # of aggregated frames per A-MPDU: %d.%d\n",
127 MINSTREL_TRUNC(mi->avg_ampdu_len), 150 MINSTREL_TRUNC(mi->avg_ampdu_len),
128 MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10); 151 MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
129 ms->len = p - ms->buf; 152 ms->len = p - ms->buf;
130
131 WARN_ON(ms->len + sizeof(*ms) > 32768); 153 WARN_ON(ms->len + sizeof(*ms) > 32768);
132 154
133 return nonseekable_open(inode, file); 155 return nonseekable_open(inode, file);
@@ -141,6 +163,143 @@ static const struct file_operations minstrel_ht_stat_fops = {
141 .llseek = no_llseek, 163 .llseek = no_llseek,
142}; 164};
143 165
166static char *
167minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
168{
169 const struct mcs_group *mg;
170 unsigned int j, tp_max, tp_avg, prob, eprob, tx_time;
171 char htmode = '2';
172 char gimode = 'L';
173 u32 gflags;
174
175 if (!mi->groups[i].supported)
176 return p;
177
178 mg = &minstrel_mcs_groups[i];
179 gflags = mg->flags;
180
181 if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
182 htmode = '4';
183 else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
184 htmode = '8';
185 if (gflags & IEEE80211_TX_RC_SHORT_GI)
186 gimode = 'S';
187
188 for (j = 0; j < MCS_GROUP_RATES; j++) {
189 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
190 static const int bitrates[4] = { 10, 20, 55, 110 };
191 int idx = i * MCS_GROUP_RATES + j;
192
193 if (!(mi->groups[i].supported & BIT(j)))
194 continue;
195
196 if (gflags & IEEE80211_TX_RC_MCS) {
197 p += sprintf(p, "HT%c0,", htmode);
198 p += sprintf(p, "%cGI,", gimode);
199 p += sprintf(p, "%d,", mg->streams);
200 } else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
201 p += sprintf(p, "VHT%c0,", htmode);
202 p += sprintf(p, "%cGI,", gimode);
203 p += sprintf(p, "%d,", mg->streams);
204 } else {
205 p += sprintf(p, "CCK,");
206 p += sprintf(p, "%cP,", j < 4 ? 'L' : 'S');
207 p += sprintf(p, "1,");
208 }
209
210 p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[0]) ? "A" : ""));
211 p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[1]) ? "B" : ""));
212 p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[2]) ? "C" : ""));
213 p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[3]) ? "D" : ""));
214 p += sprintf(p, "%s" ,((idx == mi->max_prob_rate) ? "P" : ""));
215
216 if (gflags & IEEE80211_TX_RC_MCS) {
217 p += sprintf(p, ",MCS%-2u,", (mg->streams - 1) * 8 + j);
218 } else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
219 p += sprintf(p, ",MCS%-1u/%1u,", j, mg->streams);
220 } else {
221 int r = bitrates[j % 4];
222 p += sprintf(p, ",%2u.%1uM,", r / 10, r % 10);
223 }
224
225 p += sprintf(p, "%u,", idx);
226 tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
227 p += sprintf(p, "%u,", tx_time);
228
229 tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
230 tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
231 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
232 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
233
234 p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
235 "%u,%llu,%llu,",
236 tp_max / 10, tp_max % 10,
237 tp_avg / 10, tp_avg % 10,
238 eprob / 10, eprob % 10,
239 mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
240 prob / 10, prob % 10,
241 mrs->retry_count,
242 mrs->last_success,
243 mrs->last_attempts,
244 (unsigned long long)mrs->succ_hist,
245 (unsigned long long)mrs->att_hist);
246 p += sprintf(p, "%d,%d,%d.%d\n",
247 max(0, (int) mi->total_packets -
248 (int) mi->sample_packets),
249 mi->sample_packets,
250 MINSTREL_TRUNC(mi->avg_ampdu_len),
251 MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
252 }
253
254 return p;
255}
256
257static int
258minstrel_ht_stats_csv_open(struct inode *inode, struct file *file)
259{
260 struct minstrel_ht_sta_priv *msp = inode->i_private;
261 struct minstrel_ht_sta *mi = &msp->ht;
262 struct minstrel_debugfs_info *ms;
263 unsigned int i;
264 int ret;
265 char *p;
266
267 if (!msp->is_ht) {
268 inode->i_private = &msp->legacy;
269 ret = minstrel_stats_csv_open(inode, file);
270 inode->i_private = msp;
271 return ret;
272 }
273
274 ms = kmalloc(32768, GFP_KERNEL);
275
276 if (!ms)
277 return -ENOMEM;
278
279 file->private_data = ms;
280
281 p = ms->buf;
282
283 p = minstrel_ht_stats_csv_dump(mi, MINSTREL_CCK_GROUP, p);
284 for (i = 0; i < MINSTREL_CCK_GROUP; i++)
285 p = minstrel_ht_stats_csv_dump(mi, i, p);
286 for (i++; i < ARRAY_SIZE(mi->groups); i++)
287 p = minstrel_ht_stats_csv_dump(mi, i, p);
288
289 ms->len = p - ms->buf;
290 WARN_ON(ms->len + sizeof(*ms) > 32768);
291
292 return nonseekable_open(inode, file);
293}
294
295static const struct file_operations minstrel_ht_stat_csv_fops = {
296 .owner = THIS_MODULE,
297 .open = minstrel_ht_stats_csv_open,
298 .read = minstrel_stats_read,
299 .release = minstrel_stats_release,
300 .llseek = no_llseek,
301};
302
144void 303void
145minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) 304minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
146{ 305{
@@ -148,6 +307,8 @@ minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
148 307
149 msp->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, msp, 308 msp->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, msp,
150 &minstrel_ht_stat_fops); 309 &minstrel_ht_stat_fops);
310 msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO,
311 dir, msp, &minstrel_ht_stat_csv_fops);
151} 312}
152 313
153void 314void
@@ -156,4 +317,5 @@ minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta)
156 struct minstrel_ht_sta_priv *msp = priv_sta; 317 struct minstrel_ht_sta_priv *msp = priv_sta;
157 318
158 debugfs_remove(msp->dbg_stats); 319 debugfs_remove(msp->dbg_stats);
320 debugfs_remove(msp->dbg_stats_csv);
159} 321}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2cd02278d4d4..260eed45b6d2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1185,6 +1185,7 @@ static void sta_ps_start(struct sta_info *sta)
1185 struct ieee80211_sub_if_data *sdata = sta->sdata; 1185 struct ieee80211_sub_if_data *sdata = sta->sdata;
1186 struct ieee80211_local *local = sdata->local; 1186 struct ieee80211_local *local = sdata->local;
1187 struct ps_data *ps; 1187 struct ps_data *ps;
1188 int tid;
1188 1189
1189 if (sta->sdata->vif.type == NL80211_IFTYPE_AP || 1190 if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
1190 sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1191 sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -1198,6 +1199,18 @@ static void sta_ps_start(struct sta_info *sta)
1198 drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); 1199 drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
1199 ps_dbg(sdata, "STA %pM aid %d enters power save mode\n", 1200 ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
1200 sta->sta.addr, sta->sta.aid); 1201 sta->sta.addr, sta->sta.aid);
1202
1203 if (!sta->sta.txq[0])
1204 return;
1205
1206 for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
1207 struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
1208
1209 if (!skb_queue_len(&txqi->queue))
1210 set_bit(tid, &sta->txq_buffered_tids);
1211 else
1212 clear_bit(tid, &sta->txq_buffered_tids);
1213 }
1201} 1214}
1202 1215
1203static void sta_ps_end(struct sta_info *sta) 1216static void sta_ps_end(struct sta_info *sta)
@@ -3424,7 +3437,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
3424 __le16 fc; 3437 __le16 fc;
3425 struct ieee80211_rx_data rx; 3438 struct ieee80211_rx_data rx;
3426 struct ieee80211_sub_if_data *prev; 3439 struct ieee80211_sub_if_data *prev;
3427 struct sta_info *sta, *tmp, *prev_sta; 3440 struct sta_info *sta, *prev_sta;
3441 struct rhash_head *tmp;
3428 int err = 0; 3442 int err = 0;
3429 3443
3430 fc = ((struct ieee80211_hdr *)skb->data)->frame_control; 3444 fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
@@ -3459,9 +3473,13 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
3459 ieee80211_scan_rx(local, skb); 3473 ieee80211_scan_rx(local, skb);
3460 3474
3461 if (ieee80211_is_data(fc)) { 3475 if (ieee80211_is_data(fc)) {
3476 const struct bucket_table *tbl;
3477
3462 prev_sta = NULL; 3478 prev_sta = NULL;
3463 3479
3464 for_each_sta_info(local, hdr->addr2, sta, tmp) { 3480 tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
3481
3482 for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
3465 if (!prev_sta) { 3483 if (!prev_sta) {
3466 prev_sta = sta; 3484 prev_sta = sta;
3467 continue; 3485 continue;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index aacaa1a85e63..12971b71d0fa 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -64,32 +64,20 @@
64 * freed before they are done using it. 64 * freed before they are done using it.
65 */ 65 */
66 66
67static const struct rhashtable_params sta_rht_params = {
68 .nelem_hint = 3, /* start small */
69 .head_offset = offsetof(struct sta_info, hash_node),
70 .key_offset = offsetof(struct sta_info, sta.addr),
71 .key_len = ETH_ALEN,
72 .hashfn = sta_addr_hash,
73};
74
67/* Caller must hold local->sta_mtx */ 75/* Caller must hold local->sta_mtx */
68static int sta_info_hash_del(struct ieee80211_local *local, 76static int sta_info_hash_del(struct ieee80211_local *local,
69 struct sta_info *sta) 77 struct sta_info *sta)
70{ 78{
71 struct sta_info *s; 79 return rhashtable_remove_fast(&local->sta_hash, &sta->hash_node,
72 80 sta_rht_params);
73 s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)],
74 lockdep_is_held(&local->sta_mtx));
75 if (!s)
76 return -ENOENT;
77 if (s == sta) {
78 rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)],
79 s->hnext);
80 return 0;
81 }
82
83 while (rcu_access_pointer(s->hnext) &&
84 rcu_access_pointer(s->hnext) != sta)
85 s = rcu_dereference_protected(s->hnext,
86 lockdep_is_held(&local->sta_mtx));
87 if (rcu_access_pointer(s->hnext)) {
88 rcu_assign_pointer(s->hnext, sta->hnext);
89 return 0;
90 }
91
92 return -ENOENT;
93} 81}
94 82
95static void __cleanup_single_sta(struct sta_info *sta) 83static void __cleanup_single_sta(struct sta_info *sta)
@@ -118,6 +106,16 @@ static void __cleanup_single_sta(struct sta_info *sta)
118 atomic_dec(&ps->num_sta_ps); 106 atomic_dec(&ps->num_sta_ps);
119 } 107 }
120 108
109 if (sta->sta.txq[0]) {
110 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
111 struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
112 int n = skb_queue_len(&txqi->queue);
113
114 ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
115 atomic_sub(n, &sdata->txqs_len[txqi->txq.ac]);
116 }
117 }
118
121 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 119 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
122 local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); 120 local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
123 ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); 121 ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]);
@@ -159,18 +157,8 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
159 const u8 *addr) 157 const u8 *addr)
160{ 158{
161 struct ieee80211_local *local = sdata->local; 159 struct ieee80211_local *local = sdata->local;
162 struct sta_info *sta;
163 160
164 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], 161 return rhashtable_lookup_fast(&local->sta_hash, addr, sta_rht_params);
165 lockdep_is_held(&local->sta_mtx));
166 while (sta) {
167 if (sta->sdata == sdata &&
168 ether_addr_equal(sta->sta.addr, addr))
169 break;
170 sta = rcu_dereference_check(sta->hnext,
171 lockdep_is_held(&local->sta_mtx));
172 }
173 return sta;
174} 162}
175 163
176/* 164/*
@@ -182,18 +170,24 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
182{ 170{
183 struct ieee80211_local *local = sdata->local; 171 struct ieee80211_local *local = sdata->local;
184 struct sta_info *sta; 172 struct sta_info *sta;
173 struct rhash_head *tmp;
174 const struct bucket_table *tbl;
185 175
186 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], 176 rcu_read_lock();
187 lockdep_is_held(&local->sta_mtx)); 177 tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
188 while (sta) { 178
189 if ((sta->sdata == sdata || 179 for_each_sta_info(local, tbl, addr, sta, tmp) {
190 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && 180 if (sta->sdata == sdata ||
191 ether_addr_equal(sta->sta.addr, addr)) 181 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) {
192 break; 182 rcu_read_unlock();
193 sta = rcu_dereference_check(sta->hnext, 183 /* this is safe as the caller must already hold
194 lockdep_is_held(&local->sta_mtx)); 184 * another rcu read section or the mutex
185 */
186 return sta;
187 }
195 } 188 }
196 return sta; 189 rcu_read_unlock();
190 return NULL;
197} 191}
198 192
199struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, 193struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
@@ -234,6 +228,8 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
234 228
235 sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); 229 sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
236 230
231 if (sta->sta.txq[0])
232 kfree(to_txq_info(sta->sta.txq[0]));
237 kfree(rcu_dereference_raw(sta->sta.rates)); 233 kfree(rcu_dereference_raw(sta->sta.rates));
238 kfree(sta); 234 kfree(sta);
239} 235}
@@ -242,9 +238,8 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
242static void sta_info_hash_add(struct ieee80211_local *local, 238static void sta_info_hash_add(struct ieee80211_local *local,
243 struct sta_info *sta) 239 struct sta_info *sta)
244{ 240{
245 lockdep_assert_held(&local->sta_mtx); 241 rhashtable_insert_fast(&local->sta_hash, &sta->hash_node,
246 sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; 242 sta_rht_params);
247 rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
248} 243}
249 244
250static void sta_deliver_ps_frames(struct work_struct *wk) 245static void sta_deliver_ps_frames(struct work_struct *wk)
@@ -285,11 +280,12 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
285 const u8 *addr, gfp_t gfp) 280 const u8 *addr, gfp_t gfp)
286{ 281{
287 struct ieee80211_local *local = sdata->local; 282 struct ieee80211_local *local = sdata->local;
283 struct ieee80211_hw *hw = &local->hw;
288 struct sta_info *sta; 284 struct sta_info *sta;
289 struct timespec uptime; 285 struct timespec uptime;
290 int i; 286 int i;
291 287
292 sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); 288 sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
293 if (!sta) 289 if (!sta)
294 return NULL; 290 return NULL;
295 291
@@ -321,11 +317,25 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
321 for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) 317 for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
322 ewma_init(&sta->chain_signal_avg[i], 1024, 8); 318 ewma_init(&sta->chain_signal_avg[i], 1024, 8);
323 319
324 if (sta_prepare_rate_control(local, sta, gfp)) { 320 if (local->ops->wake_tx_queue) {
325 kfree(sta); 321 void *txq_data;
326 return NULL; 322 int size = sizeof(struct txq_info) +
323 ALIGN(hw->txq_data_size, sizeof(void *));
324
325 txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
326 if (!txq_data)
327 goto free;
328
329 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
330 struct txq_info *txq = txq_data + i * size;
331
332 ieee80211_init_tx_queue(sdata, sta, txq, i);
333 }
327 } 334 }
328 335
336 if (sta_prepare_rate_control(local, sta, gfp))
337 goto free_txq;
338
329 for (i = 0; i < IEEE80211_NUM_TIDS; i++) { 339 for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
330 /* 340 /*
331 * timer_to_tid must be initialized with identity mapping 341 * timer_to_tid must be initialized with identity mapping
@@ -346,7 +356,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
346 if (sdata->vif.type == NL80211_IFTYPE_AP || 356 if (sdata->vif.type == NL80211_IFTYPE_AP ||
347 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { 357 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
348 struct ieee80211_supported_band *sband = 358 struct ieee80211_supported_band *sband =
349 local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; 359 hw->wiphy->bands[ieee80211_get_sdata_band(sdata)];
350 u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 360 u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >>
351 IEEE80211_HT_CAP_SM_PS_SHIFT; 361 IEEE80211_HT_CAP_SM_PS_SHIFT;
352 /* 362 /*
@@ -371,6 +381,13 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
371 sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); 381 sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
372 382
373 return sta; 383 return sta;
384
385free_txq:
386 if (sta->sta.txq[0])
387 kfree(to_txq_info(sta->sta.txq[0]));
388free:
389 kfree(sta);
390 return NULL;
374} 391}
375 392
376static int sta_info_insert_check(struct sta_info *sta) 393static int sta_info_insert_check(struct sta_info *sta)
@@ -640,6 +657,8 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
640 657
641 indicate_tim |= 658 indicate_tim |=
642 sta->driver_buffered_tids & tids; 659 sta->driver_buffered_tids & tids;
660 indicate_tim |=
661 sta->txq_buffered_tids & tids;
643 } 662 }
644 663
645 done: 664 done:
@@ -948,19 +967,32 @@ static void sta_info_cleanup(unsigned long data)
948 round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL)); 967 round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL));
949} 968}
950 969
951void sta_info_init(struct ieee80211_local *local) 970u32 sta_addr_hash(const void *key, u32 length, u32 seed)
971{
972 return jhash(key, ETH_ALEN, seed);
973}
974
975int sta_info_init(struct ieee80211_local *local)
952{ 976{
977 int err;
978
979 err = rhashtable_init(&local->sta_hash, &sta_rht_params);
980 if (err)
981 return err;
982
953 spin_lock_init(&local->tim_lock); 983 spin_lock_init(&local->tim_lock);
954 mutex_init(&local->sta_mtx); 984 mutex_init(&local->sta_mtx);
955 INIT_LIST_HEAD(&local->sta_list); 985 INIT_LIST_HEAD(&local->sta_list);
956 986
957 setup_timer(&local->sta_cleanup, sta_info_cleanup, 987 setup_timer(&local->sta_cleanup, sta_info_cleanup,
958 (unsigned long)local); 988 (unsigned long)local);
989 return 0;
959} 990}
960 991
961void sta_info_stop(struct ieee80211_local *local) 992void sta_info_stop(struct ieee80211_local *local)
962{ 993{
963 del_timer_sync(&local->sta_cleanup); 994 del_timer_sync(&local->sta_cleanup);
995 rhashtable_destroy(&local->sta_hash);
964} 996}
965 997
966 998
@@ -1024,16 +1056,21 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
1024} 1056}
1025 1057
1026struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw, 1058struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
1027 const u8 *addr, 1059 const u8 *addr,
1028 const u8 *localaddr) 1060 const u8 *localaddr)
1029{ 1061{
1030 struct sta_info *sta, *nxt; 1062 struct ieee80211_local *local = hw_to_local(hw);
1063 struct sta_info *sta;
1064 struct rhash_head *tmp;
1065 const struct bucket_table *tbl;
1066
1067 tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
1031 1068
1032 /* 1069 /*
1033 * Just return a random station if localaddr is NULL 1070 * Just return a random station if localaddr is NULL
1034 * ... first in list. 1071 * ... first in list.
1035 */ 1072 */
1036 for_each_sta_info(hw_to_local(hw), addr, sta, nxt) { 1073 for_each_sta_info(local, tbl, addr, sta, tmp) {
1037 if (localaddr && 1074 if (localaddr &&
1038 !ether_addr_equal(sta->sdata->vif.addr, localaddr)) 1075 !ether_addr_equal(sta->sdata->vif.addr, localaddr))
1039 continue; 1076 continue;
@@ -1071,7 +1108,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
1071 struct ieee80211_sub_if_data *sdata = sta->sdata; 1108 struct ieee80211_sub_if_data *sdata = sta->sdata;
1072 struct ieee80211_local *local = sdata->local; 1109 struct ieee80211_local *local = sdata->local;
1073 struct sk_buff_head pending; 1110 struct sk_buff_head pending;
1074 int filtered = 0, buffered = 0, ac; 1111 int filtered = 0, buffered = 0, ac, i;
1075 unsigned long flags; 1112 unsigned long flags;
1076 struct ps_data *ps; 1113 struct ps_data *ps;
1077 1114
@@ -1090,10 +1127,22 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
1090 1127
1091 BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); 1128 BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
1092 sta->driver_buffered_tids = 0; 1129 sta->driver_buffered_tids = 0;
1130 sta->txq_buffered_tids = 0;
1093 1131
1094 if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) 1132 if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
1095 drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); 1133 drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
1096 1134
1135 if (sta->sta.txq[0]) {
1136 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
1137 struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
1138
1139 if (!skb_queue_len(&txqi->queue))
1140 continue;
1141
1142 drv_wake_tx_queue(local, txqi);
1143 }
1144 }
1145
1097 skb_queue_head_init(&pending); 1146 skb_queue_head_init(&pending);
1098 1147
1099 /* sync with ieee80211_tx_h_unicast_ps_buf */ 1148 /* sync with ieee80211_tx_h_unicast_ps_buf */
@@ -1275,8 +1324,10 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
1275 /* if we already have frames from software, then we can't also 1324 /* if we already have frames from software, then we can't also
1276 * release from hardware queues 1325 * release from hardware queues
1277 */ 1326 */
1278 if (skb_queue_empty(&frames)) 1327 if (skb_queue_empty(&frames)) {
1279 driver_release_tids |= sta->driver_buffered_tids & tids; 1328 driver_release_tids |= sta->driver_buffered_tids & tids;
1329 driver_release_tids |= sta->txq_buffered_tids & tids;
1330 }
1280 1331
1281 if (driver_release_tids) { 1332 if (driver_release_tids) {
1282 /* If the driver has data on more than one TID then 1333 /* If the driver has data on more than one TID then
@@ -1447,6 +1498,9 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
1447 1498
1448 sta_info_recalc_tim(sta); 1499 sta_info_recalc_tim(sta);
1449 } else { 1500 } else {
1501 unsigned long tids = sta->txq_buffered_tids & driver_release_tids;
1502 int tid;
1503
1450 /* 1504 /*
1451 * We need to release a frame that is buffered somewhere in the 1505 * We need to release a frame that is buffered somewhere in the
1452 * driver ... it'll have to handle that. 1506 * driver ... it'll have to handle that.
@@ -1466,8 +1520,22 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
1466 * that the TID(s) became empty before returning here from the 1520 * that the TID(s) became empty before returning here from the
1467 * release function. 1521 * release function.
1468 * Either way, however, when the driver tells us that the TID(s) 1522 * Either way, however, when the driver tells us that the TID(s)
1469 * became empty we'll do the TIM recalculation. 1523 * became empty or we find that a txq became empty, we'll do the
1524 * TIM recalculation.
1470 */ 1525 */
1526
1527 if (!sta->sta.txq[0])
1528 return;
1529
1530 for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
1531 struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
1532
1533 if (!(tids & BIT(tid)) || skb_queue_len(&txqi->queue))
1534 continue;
1535
1536 sta_info_recalc_tim(sta);
1537 break;
1538 }
1471 } 1539 }
1472} 1540}
1473 1541
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 7e2fa4018d41..5c164fb3f6c5 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -16,6 +16,7 @@
16#include <linux/workqueue.h> 16#include <linux/workqueue.h>
17#include <linux/average.h> 17#include <linux/average.h>
18#include <linux/etherdevice.h> 18#include <linux/etherdevice.h>
19#include <linux/rhashtable.h>
19#include "key.h" 20#include "key.h"
20 21
21/** 22/**
@@ -248,7 +249,7 @@ struct sta_ampdu_mlme {
248 * 249 *
249 * @list: global linked list entry 250 * @list: global linked list entry
250 * @free_list: list entry for keeping track of stations to free 251 * @free_list: list entry for keeping track of stations to free
251 * @hnext: hash table linked list pointer 252 * @hash_node: hash node for rhashtable
252 * @local: pointer to the global information 253 * @local: pointer to the global information
253 * @sdata: virtual interface this station belongs to 254 * @sdata: virtual interface this station belongs to
254 * @ptk: peer keys negotiated with this station, if any 255 * @ptk: peer keys negotiated with this station, if any
@@ -276,6 +277,7 @@ struct sta_ampdu_mlme {
276 * entered power saving state, these are also delivered to 277 * entered power saving state, these are also delivered to
277 * the station when it leaves powersave or polls for frames 278 * the station when it leaves powersave or polls for frames
278 * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on 279 * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on
280 * @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on
279 * @rx_packets: Number of MSDUs received from this STA 281 * @rx_packets: Number of MSDUs received from this STA
280 * @rx_bytes: Number of bytes received from this STA 282 * @rx_bytes: Number of bytes received from this STA
281 * @last_rx: time (in jiffies) when last frame was received from this STA 283 * @last_rx: time (in jiffies) when last frame was received from this STA
@@ -341,7 +343,7 @@ struct sta_info {
341 /* General information, mostly static */ 343 /* General information, mostly static */
342 struct list_head list, free_list; 344 struct list_head list, free_list;
343 struct rcu_head rcu_head; 345 struct rcu_head rcu_head;
344 struct sta_info __rcu *hnext; 346 struct rhash_head hash_node;
345 struct ieee80211_local *local; 347 struct ieee80211_local *local;
346 struct ieee80211_sub_if_data *sdata; 348 struct ieee80211_sub_if_data *sdata;
347 struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; 349 struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
@@ -370,6 +372,7 @@ struct sta_info {
370 struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; 372 struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
371 struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; 373 struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
372 unsigned long driver_buffered_tids; 374 unsigned long driver_buffered_tids;
375 unsigned long txq_buffered_tids;
373 376
374 /* Updated from RX path only, no locking requirements */ 377 /* Updated from RX path only, no locking requirements */
375 unsigned long rx_packets; 378 unsigned long rx_packets;
@@ -537,10 +540,6 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
537 lockdep_is_held(&sta->ampdu_mlme.mtx)); 540 lockdep_is_held(&sta->ampdu_mlme.mtx));
538} 541}
539 542
540#define STA_HASH_SIZE 256
541#define STA_HASH(sta) (sta[5])
542
543
544/* Maximum number of frames to buffer per power saving station per AC */ 543/* Maximum number of frames to buffer per power saving station per AC */
545#define STA_MAX_TX_BUFFER 64 544#define STA_MAX_TX_BUFFER 64
546 545
@@ -561,26 +560,15 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
561struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, 560struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
562 const u8 *addr); 561 const u8 *addr);
563 562
564static inline 563u32 sta_addr_hash(const void *key, u32 length, u32 seed);
565void for_each_sta_info_type_check(struct ieee80211_local *local, 564
566 const u8 *addr, 565#define _sta_bucket_idx(_tbl, _a) \
567 struct sta_info *sta, 566 rht_bucket_index(_tbl, sta_addr_hash(_a, ETH_ALEN, (_tbl)->hash_rnd))
568 struct sta_info *nxt)
569{
570}
571 567
572#define for_each_sta_info(local, _addr, _sta, nxt) \ 568#define for_each_sta_info(local, tbl, _addr, _sta, _tmp) \
573 for ( /* initialise loop */ \ 569 rht_for_each_entry_rcu(_sta, _tmp, tbl, \
574 _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ 570 _sta_bucket_idx(tbl, _addr), \
575 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ 571 hash_node) \
576 /* typecheck */ \
577 for_each_sta_info_type_check(local, (_addr), _sta, nxt),\
578 /* continue condition */ \
579 _sta; \
580 /* advance loop */ \
581 _sta = nxt, \
582 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
583 ) \
584 /* compare address and run code only if it matches */ \ 572 /* compare address and run code only if it matches */ \
585 if (ether_addr_equal(_sta->sta.addr, (_addr))) 573 if (ether_addr_equal(_sta->sta.addr, (_addr)))
586 574
@@ -617,7 +605,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
617 605
618void sta_info_recalc_tim(struct sta_info *sta); 606void sta_info_recalc_tim(struct sta_info *sta);
619 607
620void sta_info_init(struct ieee80211_local *local); 608int sta_info_init(struct ieee80211_local *local);
621void sta_info_stop(struct ieee80211_local *local); 609void sta_info_stop(struct ieee80211_local *local);
622 610
623/** 611/**
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 2c51742428d5..005fdbe39a8b 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -654,7 +654,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
654 struct ieee80211_supported_band *sband; 654 struct ieee80211_supported_band *sband;
655 struct ieee80211_sub_if_data *sdata; 655 struct ieee80211_sub_if_data *sdata;
656 struct net_device *prev_dev = NULL; 656 struct net_device *prev_dev = NULL;
657 struct sta_info *sta, *tmp; 657 struct sta_info *sta;
658 struct rhash_head *tmp;
658 int retry_count; 659 int retry_count;
659 int rates_idx; 660 int rates_idx;
660 bool send_to_cooked; 661 bool send_to_cooked;
@@ -663,6 +664,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
663 int rtap_len; 664 int rtap_len;
664 int shift = 0; 665 int shift = 0;
665 int tid = IEEE80211_NUM_TIDS; 666 int tid = IEEE80211_NUM_TIDS;
667 const struct bucket_table *tbl;
666 668
667 rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); 669 rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
668 670
@@ -671,7 +673,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
671 sband = local->hw.wiphy->bands[info->band]; 673 sband = local->hw.wiphy->bands[info->band];
672 fc = hdr->frame_control; 674 fc = hdr->frame_control;
673 675
674 for_each_sta_info(local, hdr->addr1, sta, tmp) { 676 tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
677
678 for_each_sta_info(local, tbl, hdr->addr1, sta, tmp) {
675 /* skip wrong virtual interface */ 679 /* skip wrong virtual interface */
676 if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr)) 680 if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr))
677 continue; 681 continue;
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index e9e462b349e5..790bd45081c4 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2312,6 +2312,37 @@ TRACE_EVENT(drv_tdls_recv_channel_switch,
2312 ) 2312 )
2313); 2313);
2314 2314
2315TRACE_EVENT(drv_wake_tx_queue,
2316 TP_PROTO(struct ieee80211_local *local,
2317 struct ieee80211_sub_if_data *sdata,
2318 struct txq_info *txq),
2319
2320 TP_ARGS(local, sdata, txq),
2321
2322 TP_STRUCT__entry(
2323 LOCAL_ENTRY
2324 VIF_ENTRY
2325 STA_ENTRY
2326 __field(u8, ac)
2327 __field(u8, tid)
2328 ),
2329
2330 TP_fast_assign(
2331 struct ieee80211_sta *sta = txq->txq.sta;
2332
2333 LOCAL_ASSIGN;
2334 VIF_ASSIGN;
2335 STA_ASSIGN;
2336 __entry->ac = txq->txq.ac;
2337 __entry->tid = txq->txq.tid;
2338 ),
2339
2340 TP_printk(
2341 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ac:%d tid:%d",
2342 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ac, __entry->tid
2343 )
2344);
2345
2315#ifdef CONFIG_MAC80211_MESSAGE_TRACING 2346#ifdef CONFIG_MAC80211_MESSAGE_TRACING
2316#undef TRACE_SYSTEM 2347#undef TRACE_SYSTEM
2317#define TRACE_SYSTEM mac80211_msg 2348#define TRACE_SYSTEM mac80211_msg
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9f7fb4eec37b..667111ee6a20 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -767,12 +767,22 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
767 return TX_CONTINUE; 767 return TX_CONTINUE;
768} 768}
769 769
770static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid)
771{
772 u16 *seq = &sta->tid_seq[tid];
773 __le16 ret = cpu_to_le16(*seq);
774
775 /* Increase the sequence number. */
776 *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
777
778 return ret;
779}
780
770static ieee80211_tx_result debug_noinline 781static ieee80211_tx_result debug_noinline
771ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) 782ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
772{ 783{
773 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); 784 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
774 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; 785 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
775 u16 *seq;
776 u8 *qc; 786 u8 *qc;
777 int tid; 787 int tid;
778 788
@@ -823,13 +833,10 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
823 833
824 qc = ieee80211_get_qos_ctl(hdr); 834 qc = ieee80211_get_qos_ctl(hdr);
825 tid = *qc & IEEE80211_QOS_CTL_TID_MASK; 835 tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
826 seq = &tx->sta->tid_seq[tid];
827 tx->sta->tx_msdu[tid]++; 836 tx->sta->tx_msdu[tid]++;
828 837
829 hdr->seq_ctrl = cpu_to_le16(*seq); 838 if (!tx->sta->sta.txq[0])
830 839 hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid);
831 /* Increase the sequence number. */
832 *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
833 840
834 return TX_CONTINUE; 841 return TX_CONTINUE;
835} 842}
@@ -1070,7 +1077,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
1070 * nothing -- this aggregation session is being started 1077 * nothing -- this aggregation session is being started
1071 * but that might still fail with the driver 1078 * but that might still fail with the driver
1072 */ 1079 */
1073 } else { 1080 } else if (!tx->sta->sta.txq[tid]) {
1074 spin_lock(&tx->sta->lock); 1081 spin_lock(&tx->sta->lock);
1075 /* 1082 /*
1076 * Need to re-check now, because we may get here 1083 * Need to re-check now, because we may get here
@@ -1211,13 +1218,102 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1211 return TX_CONTINUE; 1218 return TX_CONTINUE;
1212} 1219}
1213 1220
1221static void ieee80211_drv_tx(struct ieee80211_local *local,
1222 struct ieee80211_vif *vif,
1223 struct ieee80211_sta *pubsta,
1224 struct sk_buff *skb)
1225{
1226 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1227 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1228 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1229 struct ieee80211_tx_control control = {
1230 .sta = pubsta,
1231 };
1232 struct ieee80211_txq *txq = NULL;
1233 struct txq_info *txqi;
1234 u8 ac;
1235
1236 if (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)
1237 goto tx_normal;
1238
1239 if (!ieee80211_is_data(hdr->frame_control))
1240 goto tx_normal;
1241
1242 if (pubsta) {
1243 u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
1244
1245 txq = pubsta->txq[tid];
1246 } else if (vif) {
1247 txq = vif->txq;
1248 }
1249
1250 if (!txq)
1251 goto tx_normal;
1252
1253 ac = txq->ac;
1254 txqi = to_txq_info(txq);
1255 atomic_inc(&sdata->txqs_len[ac]);
1256 if (atomic_read(&sdata->txqs_len[ac]) >= local->hw.txq_ac_max_pending)
1257 netif_stop_subqueue(sdata->dev, ac);
1258
1259 skb_queue_tail(&txqi->queue, skb);
1260 drv_wake_tx_queue(local, txqi);
1261
1262 return;
1263
1264tx_normal:
1265 drv_tx(local, &control, skb);
1266}
1267
1268struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
1269 struct ieee80211_txq *txq)
1270{
1271 struct ieee80211_local *local = hw_to_local(hw);
1272 struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
1273 struct txq_info *txqi = container_of(txq, struct txq_info, txq);
1274 struct ieee80211_hdr *hdr;
1275 struct sk_buff *skb = NULL;
1276 u8 ac = txq->ac;
1277
1278 spin_lock_bh(&txqi->queue.lock);
1279
1280 if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags))
1281 goto out;
1282
1283 skb = __skb_dequeue(&txqi->queue);
1284 if (!skb)
1285 goto out;
1286
1287 atomic_dec(&sdata->txqs_len[ac]);
1288 if (__netif_subqueue_stopped(sdata->dev, ac))
1289 ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]);
1290
1291 hdr = (struct ieee80211_hdr *)skb->data;
1292 if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) {
1293 struct sta_info *sta = container_of(txq->sta, struct sta_info,
1294 sta);
1295 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1296
1297 hdr->seq_ctrl = ieee80211_tx_next_seq(sta, txq->tid);
1298 if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
1299 info->flags |= IEEE80211_TX_CTL_AMPDU;
1300 else
1301 info->flags &= ~IEEE80211_TX_CTL_AMPDU;
1302 }
1303
1304out:
1305 spin_unlock_bh(&txqi->queue.lock);
1306
1307 return skb;
1308}
1309EXPORT_SYMBOL(ieee80211_tx_dequeue);
1310
1214static bool ieee80211_tx_frags(struct ieee80211_local *local, 1311static bool ieee80211_tx_frags(struct ieee80211_local *local,
1215 struct ieee80211_vif *vif, 1312 struct ieee80211_vif *vif,
1216 struct ieee80211_sta *sta, 1313 struct ieee80211_sta *sta,
1217 struct sk_buff_head *skbs, 1314 struct sk_buff_head *skbs,
1218 bool txpending) 1315 bool txpending)
1219{ 1316{
1220 struct ieee80211_tx_control control;
1221 struct sk_buff *skb, *tmp; 1317 struct sk_buff *skb, *tmp;
1222 unsigned long flags; 1318 unsigned long flags;
1223 1319
@@ -1275,10 +1371,9 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1275 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 1371 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1276 1372
1277 info->control.vif = vif; 1373 info->control.vif = vif;
1278 control.sta = sta;
1279 1374
1280 __skb_unlink(skb, skbs); 1375 __skb_unlink(skb, skbs);
1281 drv_tx(local, &control, skb); 1376 ieee80211_drv_tx(local, vif, sta, skb);
1282 } 1377 }
1283 1378
1284 return true; 1379 return true;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d1742a7d9ea4..79412f16b61d 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -308,6 +308,11 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
308 for (ac = 0; ac < n_acs; ac++) { 308 for (ac = 0; ac < n_acs; ac++) {
309 int ac_queue = sdata->vif.hw_queue[ac]; 309 int ac_queue = sdata->vif.hw_queue[ac];
310 310
311 if (local->ops->wake_tx_queue &&
312 (atomic_read(&sdata->txqs_len[ac]) >
313 local->hw.txq_ac_max_pending))
314 continue;
315
311 if (ac_queue == queue || 316 if (ac_queue == queue ||
312 (sdata->vif.cab_queue == queue && 317 (sdata->vif.cab_queue == queue &&
313 local->queue_stop_reasons[ac_queue] == 0 && 318 local->queue_stop_reasons[ac_queue] == 0 &&
@@ -2189,46 +2194,6 @@ void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata)
2189 mutex_unlock(&local->chanctx_mtx); 2194 mutex_unlock(&local->chanctx_mtx);
2190} 2195}
2191 2196
2192static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
2193{
2194 int i;
2195
2196 for (i = 0; i < n_ids; i++)
2197 if (ids[i] == id)
2198 return true;
2199 return false;
2200}
2201
2202size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
2203 const u8 *ids, int n_ids,
2204 const u8 *after_ric, int n_after_ric,
2205 size_t offset)
2206{
2207 size_t pos = offset;
2208
2209 while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
2210 if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
2211 pos += 2 + ies[pos + 1];
2212
2213 while (pos < ielen &&
2214 !ieee80211_id_in_list(after_ric, n_after_ric,
2215 ies[pos]))
2216 pos += 2 + ies[pos + 1];
2217 } else {
2218 pos += 2 + ies[pos + 1];
2219 }
2220 }
2221
2222 return pos;
2223}
2224
2225size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
2226 const u8 *ids, int n_ids, size_t offset)
2227{
2228 return ieee80211_ie_split_ric(ies, ielen, ids, n_ids, NULL, 0, offset);
2229}
2230EXPORT_SYMBOL(ieee80211_ie_split);
2231
2232size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) 2197size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
2233{ 2198{
2234 size_t pos = offset; 2199 size_t pos = offset;
@@ -3352,3 +3317,20 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo)
3352 3317
3353 return buf; 3318 return buf;
3354} 3319}
3320
3321void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
3322 struct sta_info *sta,
3323 struct txq_info *txqi, int tid)
3324{
3325 skb_queue_head_init(&txqi->queue);
3326 txqi->txq.vif = &sdata->vif;
3327
3328 if (sta) {
3329 txqi->txq.sta = &sta->sta;
3330 sta->sta.txq[tid] = &txqi->txq;
3331 txqi->txq.ac = ieee802_1d_to_ac[tid & 7];
3332 } else {
3333 sdata->vif.txq = &txqi->txq;
3334 txqi->txq.ac = IEEE80211_AC_BE;
3335 }
3336}
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index b13dfb4ff001..4f5543dd2524 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -175,7 +175,7 @@ config CFG80211_INTERNAL_REGDB
175 Most distributions have a CRDA package. So if unsure, say N. 175 Most distributions have a CRDA package. So if unsure, say N.
176 176
177config CFG80211_WEXT 177config CFG80211_WEXT
178 bool "cfg80211 wireless extensions compatibility" 178 bool "cfg80211 wireless extensions compatibility" if !CFG80211_WEXT_EXPORT
179 depends on CFG80211 179 depends on CFG80211
180 select WEXT_CORE 180 select WEXT_CORE
181 default y if CFG80211_WEXT_EXPORT 181 default y if CFG80211_WEXT_EXPORT
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6dd1ab3b10ea..dd78445c7d50 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5664,7 +5664,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
5664 } 5664 }
5665 } 5665 }
5666 5666
5667 r = set_regdom(rd); 5667 r = set_regdom(rd, REGD_SOURCE_CRDA);
5668 /* set_regdom took ownership */ 5668 /* set_regdom took ownership */
5669 rd = NULL; 5669 rd = NULL;
5670 5670
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index be5f81caa488..0e347f888fe9 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -135,6 +135,11 @@ static spinlock_t reg_indoor_lock;
135/* Used to track the userspace process controlling the indoor setting */ 135/* Used to track the userspace process controlling the indoor setting */
136static u32 reg_is_indoor_portid; 136static u32 reg_is_indoor_portid;
137 137
138/* Max number of consecutive attempts to communicate with CRDA */
139#define REG_MAX_CRDA_TIMEOUTS 10
140
141static u32 reg_crda_timeouts;
142
138static const struct ieee80211_regdomain *get_cfg80211_regdom(void) 143static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
139{ 144{
140 return rtnl_dereference(cfg80211_regdomain); 145 return rtnl_dereference(cfg80211_regdomain);
@@ -485,7 +490,7 @@ static void reg_regdb_search(struct work_struct *work)
485 mutex_unlock(&reg_regdb_search_mutex); 490 mutex_unlock(&reg_regdb_search_mutex);
486 491
487 if (!IS_ERR_OR_NULL(regdom)) 492 if (!IS_ERR_OR_NULL(regdom))
488 set_regdom(regdom); 493 set_regdom(regdom, REGD_SOURCE_INTERNAL_DB);
489 494
490 rtnl_unlock(); 495 rtnl_unlock();
491} 496}
@@ -535,15 +540,20 @@ static int call_crda(const char *alpha2)
535 snprintf(country, sizeof(country), "COUNTRY=%c%c", 540 snprintf(country, sizeof(country), "COUNTRY=%c%c",
536 alpha2[0], alpha2[1]); 541 alpha2[0], alpha2[1]);
537 542
543 /* query internal regulatory database (if it exists) */
544 reg_regdb_query(alpha2);
545
546 if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) {
547 pr_info("Exceeded CRDA call max attempts. Not calling CRDA\n");
548 return -EINVAL;
549 }
550
538 if (!is_world_regdom((char *) alpha2)) 551 if (!is_world_regdom((char *) alpha2))
539 pr_info("Calling CRDA for country: %c%c\n", 552 pr_info("Calling CRDA for country: %c%c\n",
540 alpha2[0], alpha2[1]); 553 alpha2[0], alpha2[1]);
541 else 554 else
542 pr_info("Calling CRDA to update world regulatory domain\n"); 555 pr_info("Calling CRDA to update world regulatory domain\n");
543 556
544 /* query internal regulatory database (if it exists) */
545 reg_regdb_query(alpha2);
546
547 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env); 557 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env);
548} 558}
549 559
@@ -2293,6 +2303,9 @@ int regulatory_hint_user(const char *alpha2,
2293 request->initiator = NL80211_REGDOM_SET_BY_USER; 2303 request->initiator = NL80211_REGDOM_SET_BY_USER;
2294 request->user_reg_hint_type = user_reg_hint_type; 2304 request->user_reg_hint_type = user_reg_hint_type;
2295 2305
2306 /* Allow calling CRDA again */
2307 reg_crda_timeouts = 0;
2308
2296 queue_regulatory_request(request); 2309 queue_regulatory_request(request);
2297 2310
2298 return 0; 2311 return 0;
@@ -2362,6 +2375,9 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
2362 request->alpha2[1] = alpha2[1]; 2375 request->alpha2[1] = alpha2[1];
2363 request->initiator = NL80211_REGDOM_SET_BY_DRIVER; 2376 request->initiator = NL80211_REGDOM_SET_BY_DRIVER;
2364 2377
2378 /* Allow calling CRDA again */
2379 reg_crda_timeouts = 0;
2380
2365 queue_regulatory_request(request); 2381 queue_regulatory_request(request);
2366 2382
2367 return 0; 2383 return 0;
@@ -2415,6 +2431,9 @@ void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band,
2415 request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; 2431 request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
2416 request->country_ie_env = env; 2432 request->country_ie_env = env;
2417 2433
2434 /* Allow calling CRDA again */
2435 reg_crda_timeouts = 0;
2436
2418 queue_regulatory_request(request); 2437 queue_regulatory_request(request);
2419 request = NULL; 2438 request = NULL;
2420out: 2439out:
@@ -2893,7 +2912,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
2893 * multiple drivers can be ironed out later. Caller must've already 2912 * multiple drivers can be ironed out later. Caller must've already
2894 * kmalloc'd the rd structure. 2913 * kmalloc'd the rd structure.
2895 */ 2914 */
2896int set_regdom(const struct ieee80211_regdomain *rd) 2915int set_regdom(const struct ieee80211_regdomain *rd,
2916 enum ieee80211_regd_source regd_src)
2897{ 2917{
2898 struct regulatory_request *lr; 2918 struct regulatory_request *lr;
2899 bool user_reset = false; 2919 bool user_reset = false;
@@ -2904,6 +2924,9 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2904 return -EINVAL; 2924 return -EINVAL;
2905 } 2925 }
2906 2926
2927 if (regd_src == REGD_SOURCE_CRDA)
2928 reg_crda_timeouts = 0;
2929
2907 lr = get_last_request(); 2930 lr = get_last_request();
2908 2931
2909 /* Note that this doesn't update the wiphys, this is done below */ 2932 /* Note that this doesn't update the wiphys, this is done below */
@@ -3063,6 +3086,7 @@ static void reg_timeout_work(struct work_struct *work)
3063{ 3086{
3064 REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); 3087 REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
3065 rtnl_lock(); 3088 rtnl_lock();
3089 reg_crda_timeouts++;
3066 restore_regulatory_settings(true); 3090 restore_regulatory_settings(true);
3067 rtnl_unlock(); 3091 rtnl_unlock();
3068} 3092}
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index a2c4e16459da..9f495d76eca0 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -16,6 +16,11 @@
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19enum ieee80211_regd_source {
20 REGD_SOURCE_INTERNAL_DB,
21 REGD_SOURCE_CRDA,
22};
23
19extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain; 24extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
20 25
21bool reg_is_valid_request(const char *alpha2); 26bool reg_is_valid_request(const char *alpha2);
@@ -46,7 +51,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy);
46int __init regulatory_init(void); 51int __init regulatory_init(void);
47void regulatory_exit(void); 52void regulatory_exit(void);
48 53
49int set_regdom(const struct ieee80211_regdomain *rd); 54int set_regdom(const struct ieee80211_regdomain *rd,
55 enum ieee80211_regd_source regd_src);
56
50unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, 57unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
51 const struct ieee80211_reg_rule *rule); 58 const struct ieee80211_reg_rule *rule);
52 59
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index ea1da6621ff0..d11454f87bac 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -42,7 +42,7 @@ struct cfg80211_conn {
42 CFG80211_CONN_CONNECTED, 42 CFG80211_CONN_CONNECTED,
43 } state; 43 } state;
44 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; 44 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
45 u8 *ie; 45 const u8 *ie;
46 size_t ie_len; 46 size_t ie_len;
47 bool auto_auth, prev_bssid_valid; 47 bool auto_auth, prev_bssid_valid;
48}; 48};
@@ -423,6 +423,62 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
423 schedule_work(&rdev->conn_work); 423 schedule_work(&rdev->conn_work);
424} 424}
425 425
426static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
427 const u8 *ies, size_t ies_len,
428 const u8 **out_ies, size_t *out_ies_len)
429{
430 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
431 u8 *buf;
432 size_t offs;
433
434 if (!rdev->wiphy.extended_capabilities_len ||
435 (ies && cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ies_len))) {
436 *out_ies = kmemdup(ies, ies_len, GFP_KERNEL);
437 if (!*out_ies)
438 return -ENOMEM;
439 *out_ies_len = ies_len;
440 return 0;
441 }
442
443 buf = kmalloc(ies_len + rdev->wiphy.extended_capabilities_len + 2,
444 GFP_KERNEL);
445 if (!buf)
446 return -ENOMEM;
447
448 if (ies_len) {
449 static const u8 before_extcapa[] = {
450 /* not listing IEs expected to be created by driver */
451 WLAN_EID_RSN,
452 WLAN_EID_QOS_CAPA,
453 WLAN_EID_RRM_ENABLED_CAPABILITIES,
454 WLAN_EID_MOBILITY_DOMAIN,
455 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
456 WLAN_EID_BSS_COEX_2040,
457 };
458
459 offs = ieee80211_ie_split(ies, ies_len, before_extcapa,
460 ARRAY_SIZE(before_extcapa), 0);
461 memcpy(buf, ies, offs);
462 /* leave a whole for extended capabilities IE */
463 memcpy(buf + offs + rdev->wiphy.extended_capabilities_len + 2,
464 ies + offs, ies_len - offs);
465 } else {
466 offs = 0;
467 }
468
469 /* place extended capabilities IE (with only driver capabilities) */
470 buf[offs] = WLAN_EID_EXT_CAPABILITY;
471 buf[offs + 1] = rdev->wiphy.extended_capabilities_len;
472 memcpy(buf + offs + 2,
473 rdev->wiphy.extended_capabilities,
474 rdev->wiphy.extended_capabilities_len);
475
476 *out_ies = buf;
477 *out_ies_len = ies_len + rdev->wiphy.extended_capabilities_len + 2;
478
479 return 0;
480}
481
426static int cfg80211_sme_connect(struct wireless_dev *wdev, 482static int cfg80211_sme_connect(struct wireless_dev *wdev,
427 struct cfg80211_connect_params *connect, 483 struct cfg80211_connect_params *connect,
428 const u8 *prev_bssid) 484 const u8 *prev_bssid)
@@ -453,16 +509,14 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
453 memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN); 509 memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN);
454 } 510 }
455 511
456 if (connect->ie) { 512 if (cfg80211_sme_get_conn_ies(wdev, connect->ie, connect->ie_len,
457 wdev->conn->ie = kmemdup(connect->ie, connect->ie_len, 513 &wdev->conn->ie,
458 GFP_KERNEL); 514 &wdev->conn->params.ie_len)) {
459 wdev->conn->params.ie = wdev->conn->ie; 515 kfree(wdev->conn);
460 if (!wdev->conn->ie) { 516 wdev->conn = NULL;
461 kfree(wdev->conn); 517 return -ENOMEM;
462 wdev->conn = NULL;
463 return -ENOMEM;
464 }
465 } 518 }
519 wdev->conn->params.ie = wdev->conn->ie;
466 520
467 if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { 521 if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
468 wdev->conn->auto_auth = true; 522 wdev->conn->auto_auth = true;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index f218b151530a..70051ab52f4f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1290,6 +1290,47 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
1290} 1290}
1291EXPORT_SYMBOL(cfg80211_get_p2p_attr); 1291EXPORT_SYMBOL(cfg80211_get_p2p_attr);
1292 1292
1293static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
1294{
1295 int i;
1296
1297 for (i = 0; i < n_ids; i++)
1298 if (ids[i] == id)
1299 return true;
1300 return false;
1301}
1302
1303size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
1304 const u8 *ids, int n_ids,
1305 const u8 *after_ric, int n_after_ric,
1306 size_t offset)
1307{
1308 size_t pos = offset;
1309
1310 while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
1311 if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
1312 pos += 2 + ies[pos + 1];
1313
1314 while (pos < ielen &&
1315 !ieee80211_id_in_list(after_ric, n_after_ric,
1316 ies[pos]))
1317 pos += 2 + ies[pos + 1];
1318 } else {
1319 pos += 2 + ies[pos + 1];
1320 }
1321 }
1322
1323 return pos;
1324}
1325EXPORT_SYMBOL(ieee80211_ie_split_ric);
1326
1327size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
1328 const u8 *ids, int n_ids, size_t offset)
1329{
1330 return ieee80211_ie_split_ric(ies, ielen, ids, n_ids, NULL, 0, offset);
1331}
1332EXPORT_SYMBOL(ieee80211_ie_split);
1333
1293bool ieee80211_operating_class_to_band(u8 operating_class, 1334bool ieee80211_operating_class_to_band(u8 operating_class,
1294 enum ieee80211_band *band) 1335 enum ieee80211_band *band)
1295{ 1336{