aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-03-22 21:15:15 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-22 21:15:15 -0400
commit33e2bf6aa16061bae1253514e7c32af27d2b4b31 (patch)
tree652d13b4feea9a8f562186e7badae72d2e22fe1f /net/mac80211
parente880eb6c5c9d98e389ffc0d8947f75d70785361a (diff)
parent819bfecc4fc6b6e5a793f719a45b7146ce423b79 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: Documentation/feature-removal-schedule.txt drivers/net/wireless/ath/ath5k/phy.c
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/Kconfig9
-rw-r--r--net/mac80211/debugfs_sta.c2
-rw-r--r--net/mac80211/ibss.c16
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/iface.c116
-rw-r--r--net/mac80211/rc80211_minstrel.c2
-rw-r--r--net/mac80211/rc80211_minstrel.h11
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c41
-rw-r--r--net/mac80211/rx.c9
-rw-r--r--net/mac80211/scan.c71
-rw-r--r--net/mac80211/sta_info.h2
-rw-r--r--net/mac80211/status.c14
12 files changed, 225 insertions, 69 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index a952b7f8c648..334c359da5e8 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -15,8 +15,12 @@ comment "CFG80211 needs to be enabled for MAC80211"
15 15
16if MAC80211 != n 16if MAC80211 != n
17 17
18config MAC80211_HAS_RC
19 def_bool n
20
18config MAC80211_RC_PID 21config MAC80211_RC_PID
19 bool "PID controller based rate control algorithm" if EMBEDDED 22 bool "PID controller based rate control algorithm" if EMBEDDED
23 select MAC80211_HAS_RC
20 ---help--- 24 ---help---
21 This option enables a TX rate control algorithm for 25 This option enables a TX rate control algorithm for
22 mac80211 that uses a PID controller to select the TX 26 mac80211 that uses a PID controller to select the TX
@@ -24,12 +28,14 @@ config MAC80211_RC_PID
24 28
25config MAC80211_RC_MINSTREL 29config MAC80211_RC_MINSTREL
26 bool "Minstrel" if EMBEDDED 30 bool "Minstrel" if EMBEDDED
31 select MAC80211_HAS_RC
27 default y 32 default y
28 ---help--- 33 ---help---
29 This option enables the 'minstrel' TX rate control algorithm 34 This option enables the 'minstrel' TX rate control algorithm
30 35
31choice 36choice
32 prompt "Default rate control algorithm" 37 prompt "Default rate control algorithm"
38 depends on MAC80211_HAS_RC
33 default MAC80211_RC_DEFAULT_MINSTREL 39 default MAC80211_RC_DEFAULT_MINSTREL
34 ---help--- 40 ---help---
35 This option selects the default rate control algorithm 41 This option selects the default rate control algorithm
@@ -62,6 +68,9 @@ config MAC80211_RC_DEFAULT
62 68
63endif 69endif
64 70
71comment "Some wireless drivers require a rate control algorithm"
72 depends on MAC80211_HAS_RC=n
73
65config MAC80211_MESH 74config MAC80211_MESH
66 bool "Enable mac80211 mesh networking (pre-802.11s) support" 75 bool "Enable mac80211 mesh networking (pre-802.11s) support"
67 depends on MAC80211 && EXPERIMENTAL 76 depends on MAC80211 && EXPERIMENTAL
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index d92800bb2d2f..23e720034577 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -57,7 +57,6 @@ STA_FILE(tx_filtered, tx_filtered_count, LU);
57STA_FILE(tx_retry_failed, tx_retry_failed, LU); 57STA_FILE(tx_retry_failed, tx_retry_failed, LU);
58STA_FILE(tx_retry_count, tx_retry_count, LU); 58STA_FILE(tx_retry_count, tx_retry_count, LU);
59STA_FILE(last_signal, last_signal, D); 59STA_FILE(last_signal, last_signal, D);
60STA_FILE(last_noise, last_noise, D);
61STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); 60STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
62 61
63static ssize_t sta_flags_read(struct file *file, char __user *userbuf, 62static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
@@ -289,7 +288,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
289 DEBUGFS_ADD(tx_retry_failed); 288 DEBUGFS_ADD(tx_retry_failed);
290 DEBUGFS_ADD(tx_retry_count); 289 DEBUGFS_ADD(tx_retry_count);
291 DEBUGFS_ADD(last_signal); 290 DEBUGFS_ADD(last_signal);
292 DEBUGFS_ADD(last_noise);
293 DEBUGFS_ADD(wep_weak_iv_count); 291 DEBUGFS_ADD(wep_weak_iv_count);
294 DEBUGFS_ADD(ht_capa); 292 DEBUGFS_ADD(ht_capa);
295} 293}
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index f3e942486749..01974c2510a8 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -264,17 +264,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
264 sta->sta.supp_rates[band] = supp_rates | 264 sta->sta.supp_rates[band] = supp_rates |
265 ieee80211_mandatory_rates(local, band); 265 ieee80211_mandatory_rates(local, band);
266 266
267 if (sta->sta.supp_rates[band] != prev_rates) {
267#ifdef CONFIG_MAC80211_IBSS_DEBUG 268#ifdef CONFIG_MAC80211_IBSS_DEBUG
268 if (sta->sta.supp_rates[band] != prev_rates)
269 printk(KERN_DEBUG "%s: updated supp_rates set " 269 printk(KERN_DEBUG "%s: updated supp_rates set "
270 "for %pM based on beacon info (0x%llx | " 270 "for %pM based on beacon/probe_response "
271 "0x%llx -> 0x%llx)\n", 271 "(0x%x -> 0x%x)\n",
272 sdata->name, 272 sdata->name, sta->sta.addr,
273 sta->sta.addr, 273 prev_rates, sta->sta.supp_rates[band]);
274 (unsigned long long) prev_rates,
275 (unsigned long long) supp_rates,
276 (unsigned long long) sta->sta.supp_rates[band]);
277#endif 274#endif
275 rate_control_rate_init(sta);
276 }
278 rcu_read_unlock(); 277 rcu_read_unlock();
279 } else { 278 } else {
280 rcu_read_unlock(); 279 rcu_read_unlock();
@@ -370,6 +369,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
370 sdata->name, mgmt->bssid); 369 sdata->name, mgmt->bssid);
371#endif 370#endif
372 ieee80211_sta_join_ibss(sdata, bss); 371 ieee80211_sta_join_ibss(sdata, bss);
372 supp_rates = ieee80211_sta_get_rates(local, elems, band);
373 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 373 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
374 supp_rates, GFP_KERNEL); 374 supp_rates, GFP_KERNEL);
375 } 375 }
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 241533e1bc03..b84126491ab1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -745,6 +745,7 @@ struct ieee80211_local {
745 int scan_channel_idx; 745 int scan_channel_idx;
746 int scan_ies_len; 746 int scan_ies_len;
747 747
748 unsigned long leave_oper_channel_time;
748 enum mac80211_scan_state next_scan_state; 749 enum mac80211_scan_state next_scan_state;
749 struct delayed_work scan_work; 750 struct delayed_work scan_work;
750 struct ieee80211_sub_if_data *scan_sdata; 751 struct ieee80211_sub_if_data *scan_sdata;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 0793d7a8d743..d5571b9420cd 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -815,6 +815,118 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
815 return 0; 815 return 0;
816} 816}
817 817
818static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
819 struct net_device *dev,
820 enum nl80211_iftype type)
821{
822 struct ieee80211_sub_if_data *sdata;
823 u64 mask, start, addr, val, inc;
824 u8 *m;
825 u8 tmp_addr[ETH_ALEN];
826 int i;
827
828 /* default ... something at least */
829 memcpy(dev->perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
830
831 if (is_zero_ether_addr(local->hw.wiphy->addr_mask) &&
832 local->hw.wiphy->n_addresses <= 1)
833 return;
834
835
836 mutex_lock(&local->iflist_mtx);
837
838 switch (type) {
839 case NL80211_IFTYPE_MONITOR:
840 /* doesn't matter */
841 break;
842 case NL80211_IFTYPE_WDS:
843 case NL80211_IFTYPE_AP_VLAN:
844 /* match up with an AP interface */
845 list_for_each_entry(sdata, &local->interfaces, list) {
846 if (sdata->vif.type != NL80211_IFTYPE_AP)
847 continue;
848 memcpy(dev->perm_addr, sdata->vif.addr, ETH_ALEN);
849 break;
850 }
851 /* keep default if no AP interface present */
852 break;
853 default:
854 /* assign a new address if possible -- try n_addresses first */
855 for (i = 0; i < local->hw.wiphy->n_addresses; i++) {
856 bool used = false;
857
858 list_for_each_entry(sdata, &local->interfaces, list) {
859 if (memcmp(local->hw.wiphy->addresses[i].addr,
860 sdata->vif.addr, ETH_ALEN) == 0) {
861 used = true;
862 break;
863 }
864 }
865
866 if (!used) {
867 memcpy(dev->perm_addr,
868 local->hw.wiphy->addresses[i].addr,
869 ETH_ALEN);
870 break;
871 }
872 }
873
874 /* try mask if available */
875 if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
876 break;
877
878 m = local->hw.wiphy->addr_mask;
879 mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
880 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
881 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
882
883 if (__ffs64(mask) + hweight64(mask) != fls64(mask)) {
884 /* not a contiguous mask ... not handled now! */
885 printk(KERN_DEBUG "not contiguous\n");
886 break;
887 }
888
889 m = local->hw.wiphy->perm_addr;
890 start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
891 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
892 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
893
894 inc = 1ULL<<__ffs64(mask);
895 val = (start & mask);
896 addr = (start & ~mask) | (val & mask);
897 do {
898 bool used = false;
899
900 tmp_addr[5] = addr >> 0*8;
901 tmp_addr[4] = addr >> 1*8;
902 tmp_addr[3] = addr >> 2*8;
903 tmp_addr[2] = addr >> 3*8;
904 tmp_addr[1] = addr >> 4*8;
905 tmp_addr[0] = addr >> 5*8;
906
907 val += inc;
908
909 list_for_each_entry(sdata, &local->interfaces, list) {
910 if (memcmp(tmp_addr, sdata->vif.addr,
911 ETH_ALEN) == 0) {
912 used = true;
913 break;
914 }
915 }
916
917 if (!used) {
918 memcpy(dev->perm_addr, tmp_addr, ETH_ALEN);
919 break;
920 }
921 addr = (start & ~mask) | (val & mask);
922 } while (addr != start);
923
924 break;
925 }
926
927 mutex_unlock(&local->iflist_mtx);
928}
929
818int ieee80211_if_add(struct ieee80211_local *local, const char *name, 930int ieee80211_if_add(struct ieee80211_local *local, const char *name,
819 struct net_device **new_dev, enum nl80211_iftype type, 931 struct net_device **new_dev, enum nl80211_iftype type,
820 struct vif_params *params) 932 struct vif_params *params)
@@ -844,8 +956,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
844 if (ret < 0) 956 if (ret < 0)
845 goto fail; 957 goto fail;
846 958
847 memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); 959 ieee80211_assign_perm_addr(local, ndev, type);
848 memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN); 960 memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
849 SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); 961 SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
850 962
851 /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ 963 /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 6e5d68b4e427..4926d929fd9f 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -541,7 +541,7 @@ minstrel_free(void *priv)
541 kfree(priv); 541 kfree(priv);
542} 542}
543 543
544static struct rate_control_ops mac80211_minstrel = { 544struct rate_control_ops mac80211_minstrel = {
545 .name = "minstrel", 545 .name = "minstrel",
546 .tx_status = minstrel_tx_status, 546 .tx_status = minstrel_tx_status,
547 .get_rate = minstrel_get_rate, 547 .get_rate = minstrel_get_rate,
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 38bf4168fc3a..0f5a83370aa6 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -80,7 +80,18 @@ struct minstrel_priv {
80 unsigned int lookaround_rate_mrr; 80 unsigned int lookaround_rate_mrr;
81}; 81};
82 82
83struct minstrel_debugfs_info {
84 size_t len;
85 char buf[];
86};
87
88extern struct rate_control_ops mac80211_minstrel;
83void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); 89void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
84void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); 90void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
85 91
92/* debugfs */
93int minstrel_stats_open(struct inode *inode, struct file *file);
94ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
95int minstrel_stats_release(struct inode *inode, struct file *file);
96
86#endif 97#endif
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index a715d9454f64..56d0f24957d9 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -52,21 +52,15 @@
52#include <net/mac80211.h> 52#include <net/mac80211.h>
53#include "rc80211_minstrel.h" 53#include "rc80211_minstrel.h"
54 54
55struct minstrel_stats_info { 55int
56 struct minstrel_sta_info *mi;
57 char buf[4096];
58 size_t len;
59};
60
61static int
62minstrel_stats_open(struct inode *inode, struct file *file) 56minstrel_stats_open(struct inode *inode, struct file *file)
63{ 57{
64 struct minstrel_sta_info *mi = inode->i_private; 58 struct minstrel_sta_info *mi = inode->i_private;
65 struct minstrel_stats_info *ms; 59 struct minstrel_debugfs_info *ms;
66 unsigned int i, tp, prob, eprob; 60 unsigned int i, tp, prob, eprob;
67 char *p; 61 char *p;
68 62
69 ms = kmalloc(sizeof(*ms), GFP_KERNEL); 63 ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL);
70 if (!ms) 64 if (!ms)
71 return -ENOMEM; 65 return -ENOMEM;
72 66
@@ -106,36 +100,19 @@ minstrel_stats_open(struct inode *inode, struct file *file)
106 return 0; 100 return 0;
107} 101}
108 102
109static ssize_t 103ssize_t
110minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o) 104minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
111{ 105{
112 struct minstrel_stats_info *ms; 106 struct minstrel_debugfs_info *ms;
113 char *src;
114 107
115 ms = file->private_data; 108 ms = file->private_data;
116 src = ms->buf; 109 return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
117
118 len = min(len, ms->len);
119 if (len <= *o)
120 return 0;
121
122 src += *o;
123 len -= *o;
124 *o += len;
125
126 if (copy_to_user(buf, src, len))
127 return -EFAULT;
128
129 return len;
130} 110}
131 111
132static int 112int
133minstrel_stats_release(struct inode *inode, struct file *file) 113minstrel_stats_release(struct inode *inode, struct file *file)
134{ 114{
135 struct minstrel_stats_info *ms = file->private_data; 115 kfree(file->private_data);
136
137 kfree(ms);
138
139 return 0; 116 return 0;
140} 117}
141 118
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b5c48de81d8b..1da57c8e849a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -178,14 +178,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
178 pos++; 178 pos++;
179 } 179 }
180 180
181 /* IEEE80211_RADIOTAP_DBM_ANTNOISE */
182 if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
183 *pos = status->noise;
184 rthdr->it_present |=
185 cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);
186 pos++;
187 }
188
189 /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ 181 /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */
190 182
191 /* IEEE80211_RADIOTAP_ANTENNA */ 183 /* IEEE80211_RADIOTAP_ANTENNA */
@@ -1077,7 +1069,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1077 sta->rx_fragments++; 1069 sta->rx_fragments++;
1078 sta->rx_bytes += rx->skb->len; 1070 sta->rx_bytes += rx->skb->len;
1079 sta->last_signal = status->signal; 1071 sta->last_signal = status->signal;
1080 sta->last_noise = status->noise;
1081 1072
1082 /* 1073 /*
1083 * Change STA power saving mode only at the end of a frame 1074 * Change STA power saving mode only at the end of a frame
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index b822dce97867..75a85978c3b3 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -14,6 +14,8 @@
14 14
15#include <linux/if_arp.h> 15#include <linux/if_arp.h>
16#include <linux/rtnetlink.h> 16#include <linux/rtnetlink.h>
17#include <linux/pm_qos_params.h>
18#include <net/sch_generic.h>
17#include <net/mac80211.h> 19#include <net/mac80211.h>
18 20
19#include "ieee80211_i.h" 21#include "ieee80211_i.h"
@@ -321,6 +323,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
321 323
322 ieee80211_offchannel_stop_beaconing(local); 324 ieee80211_offchannel_stop_beaconing(local);
323 325
326 local->leave_oper_channel_time = 0;
324 local->next_scan_state = SCAN_DECISION; 327 local->next_scan_state = SCAN_DECISION;
325 local->scan_channel_idx = 0; 328 local->scan_channel_idx = 0;
326 329
@@ -425,11 +428,28 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
425 return rc; 428 return rc;
426} 429}
427 430
431static unsigned long
432ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
433{
434 /*
435 * TODO: channel switching also consumes quite some time,
436 * add that delay as well to get a better estimation
437 */
438 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
439 return IEEE80211_PASSIVE_CHANNEL_TIME;
440 return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
441}
442
428static int ieee80211_scan_state_decision(struct ieee80211_local *local, 443static int ieee80211_scan_state_decision(struct ieee80211_local *local,
429 unsigned long *next_delay) 444 unsigned long *next_delay)
430{ 445{
431 bool associated = false; 446 bool associated = false;
447 bool tx_empty = true;
448 bool bad_latency;
449 bool listen_int_exceeded;
450 unsigned long min_beacon_int = 0;
432 struct ieee80211_sub_if_data *sdata; 451 struct ieee80211_sub_if_data *sdata;
452 struct ieee80211_channel *next_chan;
433 453
434 /* if no more bands/channels left, complete scan and advance to the idle state */ 454 /* if no more bands/channels left, complete scan and advance to the idle state */
435 if (local->scan_channel_idx >= local->scan_req->n_channels) { 455 if (local->scan_channel_idx >= local->scan_req->n_channels) {
@@ -437,7 +457,11 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
437 return 1; 457 return 1;
438 } 458 }
439 459
440 /* check if at least one STA interface is associated */ 460 /*
461 * check if at least one STA interface is associated,
462 * check if at least one STA interface has pending tx frames
463 * and grab the lowest used beacon interval
464 */
441 mutex_lock(&local->iflist_mtx); 465 mutex_lock(&local->iflist_mtx);
442 list_for_each_entry(sdata, &local->interfaces, list) { 466 list_for_each_entry(sdata, &local->interfaces, list) {
443 if (!ieee80211_sdata_running(sdata)) 467 if (!ieee80211_sdata_running(sdata))
@@ -446,7 +470,16 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
446 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 470 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
447 if (sdata->u.mgd.associated) { 471 if (sdata->u.mgd.associated) {
448 associated = true; 472 associated = true;
449 break; 473
474 if (sdata->vif.bss_conf.beacon_int <
475 min_beacon_int || min_beacon_int == 0)
476 min_beacon_int =
477 sdata->vif.bss_conf.beacon_int;
478
479 if (!qdisc_all_tx_empty(sdata->dev)) {
480 tx_empty = false;
481 break;
482 }
450 } 483 }
451 } 484 }
452 } 485 }
@@ -455,11 +488,34 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
455 if (local->scan_channel) { 488 if (local->scan_channel) {
456 /* 489 /*
457 * we're currently scanning a different channel, let's 490 * we're currently scanning a different channel, let's
458 * switch back to the operating channel now if at least 491 * see if we can scan another channel without interfering
459 * one interface is associated. Otherwise just scan the 492 * with the current traffic situation.
460 * next channel 493 *
494 * Since we don't know if the AP has pending frames for us
495 * we can only check for our tx queues and use the current
496 * pm_qos requirements for rx. Hence, if no tx traffic occurs
497 * at all we will scan as many channels in a row as the pm_qos
498 * latency allows us to. Additionally we also check for the
499 * currently negotiated listen interval to prevent losing
500 * frames unnecessarily.
501 *
502 * Otherwise switch back to the operating channel.
461 */ 503 */
462 if (associated) 504 next_chan = local->scan_req->channels[local->scan_channel_idx];
505
506 bad_latency = time_after(jiffies +
507 ieee80211_scan_get_channel_time(next_chan),
508 local->leave_oper_channel_time +
509 usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY)));
510
511 listen_int_exceeded = time_after(jiffies +
512 ieee80211_scan_get_channel_time(next_chan),
513 local->leave_oper_channel_time +
514 usecs_to_jiffies(min_beacon_int * 1024) *
515 local->hw.conf.listen_interval);
516
517 if (associated && ( !tx_empty || bad_latency ||
518 listen_int_exceeded))
463 local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; 519 local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
464 else 520 else
465 local->next_scan_state = SCAN_SET_CHANNEL; 521 local->next_scan_state = SCAN_SET_CHANNEL;
@@ -491,6 +547,9 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca
491 else 547 else
492 *next_delay = HZ / 10; 548 *next_delay = HZ / 10;
493 549
550 /* remember when we left the operating channel */
551 local->leave_oper_channel_time = jiffies;
552
494 /* advance to the next channel to be scanned */ 553 /* advance to the next channel to be scanned */
495 local->next_scan_state = SCAN_SET_CHANNEL; 554 local->next_scan_state = SCAN_SET_CHANNEL;
496} 555}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 822d84522937..2b635909de5c 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -200,7 +200,6 @@ struct sta_ampdu_mlme {
200 * @rx_fragments: number of received MPDUs 200 * @rx_fragments: number of received MPDUs
201 * @rx_dropped: number of dropped MPDUs from this STA 201 * @rx_dropped: number of dropped MPDUs from this STA
202 * @last_signal: signal of last received frame from this STA 202 * @last_signal: signal of last received frame from this STA
203 * @last_noise: noise of last received frame from this STA
204 * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) 203 * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue)
205 * @tx_filtered_count: number of frames the hardware filtered for this STA 204 * @tx_filtered_count: number of frames the hardware filtered for this STA
206 * @tx_retry_failed: number of frames that failed retry 205 * @tx_retry_failed: number of frames that failed retry
@@ -267,7 +266,6 @@ struct sta_info {
267 unsigned long rx_fragments; 266 unsigned long rx_fragments;
268 unsigned long rx_dropped; 267 unsigned long rx_dropped;
269 int last_signal; 268 int last_signal;
270 int last_noise;
271 __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; 269 __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
272 270
273 /* Updated from TX status path only, no locking requirements */ 271 /* Updated from TX status path only, no locking requirements */
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 56d5b9a6ec5b..11805a3a626f 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -171,7 +171,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
171 struct net_device *prev_dev = NULL; 171 struct net_device *prev_dev = NULL;
172 struct sta_info *sta, *tmp; 172 struct sta_info *sta, *tmp;
173 int retry_count = -1, i; 173 int retry_count = -1, i;
174 bool injected; 174 bool send_to_cooked;
175 175
176 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 176 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
177 /* the HW cannot have attempted that rate */ 177 /* the HW cannot have attempted that rate */
@@ -296,11 +296,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
296 /* this was a transmitted frame, but now we want to reuse it */ 296 /* this was a transmitted frame, but now we want to reuse it */
297 skb_orphan(skb); 297 skb_orphan(skb);
298 298
299 /* Need to make a copy before skb->cb gets cleared */
300 send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) ||
301 (type != IEEE80211_FTYPE_DATA);
302
299 /* 303 /*
300 * This is a bit racy but we can avoid a lot of work 304 * This is a bit racy but we can avoid a lot of work
301 * with this test... 305 * with this test...
302 */ 306 */
303 if (!local->monitors && !local->cooked_mntrs) { 307 if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
304 dev_kfree_skb(skb); 308 dev_kfree_skb(skb);
305 return; 309 return;
306 } 310 }
@@ -345,9 +349,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
345 /* for now report the total retry_count */ 349 /* for now report the total retry_count */
346 rthdr->data_retries = retry_count; 350 rthdr->data_retries = retry_count;
347 351
348 /* Need to make a copy before skb->cb gets cleared */
349 injected = !!(info->flags & IEEE80211_TX_CTL_INJECTED);
350
351 /* XXX: is this sufficient for BPF? */ 352 /* XXX: is this sufficient for BPF? */
352 skb_set_mac_header(skb, 0); 353 skb_set_mac_header(skb, 0);
353 skb->ip_summed = CHECKSUM_UNNECESSARY; 354 skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -362,8 +363,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
362 continue; 363 continue;
363 364
364 if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && 365 if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
365 !injected && 366 !send_to_cooked)
366 (type == IEEE80211_FTYPE_DATA))
367 continue; 367 continue;
368 368
369 if (prev_dev) { 369 if (prev_dev) {