diff options
author | David S. Miller <davem@davemloft.net> | 2010-03-22 21:15:15 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-22 21:15:15 -0400 |
commit | 33e2bf6aa16061bae1253514e7c32af27d2b4b31 (patch) | |
tree | 652d13b4feea9a8f562186e7badae72d2e22fe1f /net/mac80211 | |
parent | e880eb6c5c9d98e389ffc0d8947f75d70785361a (diff) | |
parent | 819bfecc4fc6b6e5a793f719a45b7146ce423b79 (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/Kconfig | 9 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 2 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 16 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/iface.c | 116 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 2 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.h | 11 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_debugfs.c | 41 | ||||
-rw-r--r-- | net/mac80211/rx.c | 9 | ||||
-rw-r--r-- | net/mac80211/scan.c | 71 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/status.c | 14 |
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 | ||
16 | if MAC80211 != n | 16 | if MAC80211 != n |
17 | 17 | ||
18 | config MAC80211_HAS_RC | ||
19 | def_bool n | ||
20 | |||
18 | config MAC80211_RC_PID | 21 | config 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 | ||
25 | config MAC80211_RC_MINSTREL | 29 | config 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 | ||
31 | choice | 36 | choice |
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 | ||
63 | endif | 69 | endif |
64 | 70 | ||
71 | comment "Some wireless drivers require a rate control algorithm" | ||
72 | depends on MAC80211_HAS_RC=n | ||
73 | |||
65 | config MAC80211_MESH | 74 | config 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); | |||
57 | STA_FILE(tx_retry_failed, tx_retry_failed, LU); | 57 | STA_FILE(tx_retry_failed, tx_retry_failed, LU); |
58 | STA_FILE(tx_retry_count, tx_retry_count, LU); | 58 | STA_FILE(tx_retry_count, tx_retry_count, LU); |
59 | STA_FILE(last_signal, last_signal, D); | 59 | STA_FILE(last_signal, last_signal, D); |
60 | STA_FILE(last_noise, last_noise, D); | ||
61 | STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); | 60 | STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU); |
62 | 61 | ||
63 | static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | 62 | static 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 | ||
818 | static 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 | |||
818 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 930 | int 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 | ||
544 | static struct rate_control_ops mac80211_minstrel = { | 544 | struct 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 | ||
83 | struct minstrel_debugfs_info { | ||
84 | size_t len; | ||
85 | char buf[]; | ||
86 | }; | ||
87 | |||
88 | extern struct rate_control_ops mac80211_minstrel; | ||
83 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 89 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
84 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | 90 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); |
85 | 91 | ||
92 | /* debugfs */ | ||
93 | int minstrel_stats_open(struct inode *inode, struct file *file); | ||
94 | ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); | ||
95 | int 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 | ||
55 | struct minstrel_stats_info { | 55 | int |
56 | struct minstrel_sta_info *mi; | ||
57 | char buf[4096]; | ||
58 | size_t len; | ||
59 | }; | ||
60 | |||
61 | static int | ||
62 | minstrel_stats_open(struct inode *inode, struct file *file) | 56 | minstrel_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 | ||
109 | static ssize_t | 103 | ssize_t |
110 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o) | 104 | minstrel_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 | ||
132 | static int | 112 | int |
133 | minstrel_stats_release(struct inode *inode, struct file *file) | 113 | minstrel_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 | ||
431 | static unsigned long | ||
432 | ieee80211_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 | |||
428 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, | 443 | static 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) { |