diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/Kconfig | 12 | ||||
-rw-r--r-- | net/mac80211/Makefile | 3 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 2 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 2 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 85 | ||||
-rw-r--r-- | net/mac80211/driver-trace.c | 6 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 648 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 9 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 47 | ||||
-rw-r--r-- | net/mac80211/iface.c | 51 | ||||
-rw-r--r-- | net/mac80211/main.c | 120 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 5 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 9 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 26 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 308 | ||||
-rw-r--r-- | net/mac80211/rate.c | 31 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 23 | ||||
-rw-r--r-- | net/mac80211/rc80211_pid_algo.c | 12 | ||||
-rw-r--r-- | net/mac80211/rx.c | 55 | ||||
-rw-r--r-- | net/mac80211/scan.c | 19 | ||||
-rw-r--r-- | net/mac80211/tx.c | 323 | ||||
-rw-r--r-- | net/mac80211/util.c | 68 | ||||
-rw-r--r-- | net/mac80211/wep.c | 6 | ||||
-rw-r--r-- | net/mac80211/wep.h | 3 | ||||
-rw-r--r-- | net/mac80211/wme.c | 6 | ||||
-rw-r--r-- | net/mac80211/wme.h | 3 |
27 files changed, 1330 insertions, 555 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 182c9c5c6818..19a4c66e143e 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -206,3 +206,15 @@ config MAC80211_DEBUG_COUNTERS | |||
206 | and show them in debugfs. | 206 | and show them in debugfs. |
207 | 207 | ||
208 | If unsure, say N. | 208 | If unsure, say N. |
209 | |||
210 | config MAC80211_DRIVER_API_TRACER | ||
211 | bool "Driver API tracer" | ||
212 | depends on MAC80211_DEBUG_MENU | ||
213 | depends on EVENT_TRACING | ||
214 | help | ||
215 | Say Y here to make mac80211 register with the ftrace | ||
216 | framework for the driver API -- you can see which | ||
217 | driver methods it is calling then by looking at the | ||
218 | trace. | ||
219 | |||
220 | If unsure, say N. | ||
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 0e3ab88bb706..91284a74ff91 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -41,6 +41,9 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ | |||
41 | 41 | ||
42 | mac80211-$(CONFIG_PM) += pm.o | 42 | mac80211-$(CONFIG_PM) += pm.o |
43 | 43 | ||
44 | mac80211-$(CONFIG_MAC80211_DRIVER_API_TRACER) += driver-trace.o | ||
45 | CFLAGS_driver-trace.o := -I$(src) | ||
46 | |||
44 | # objects for PID algorithm | 47 | # objects for PID algorithm |
45 | rc80211_pid-y := rc80211_pid_algo.o | 48 | rc80211_pid-y := rc80211_pid_algo.o |
46 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o | 49 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 9e5762ad307d..1958c7c42cd9 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -383,9 +383,6 @@ static void ieee80211_agg_splice_packets(struct ieee80211_local *local, | |||
383 | 383 | ||
384 | if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { | 384 | if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { |
385 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 385 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
386 | /* mark queue as pending, it is stopped already */ | ||
387 | __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING, | ||
388 | &local->queue_stop_reasons[queue]); | ||
389 | /* copy over remaining packets */ | 386 | /* copy over remaining packets */ |
390 | skb_queue_splice_tail_init( | 387 | skb_queue_splice_tail_init( |
391 | &sta->ampdu_mlme.tid_tx[tid]->pending, | 388 | &sta->ampdu_mlme.tid_tx[tid]->pending, |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 36f8f245fa4c..52928ad90570 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1293,7 +1293,7 @@ static void ieee80211_rfkill_poll(struct wiphy *wiphy) | |||
1293 | } | 1293 | } |
1294 | 1294 | ||
1295 | #ifdef CONFIG_NL80211_TESTMODE | 1295 | #ifdef CONFIG_NL80211_TESTMODE |
1296 | int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) | 1296 | static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) |
1297 | { | 1297 | { |
1298 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1298 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1299 | 1299 | ||
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 6c439cd5ccea..96991b68f048 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -175,7 +175,7 @@ static ssize_t queues_read(struct file *file, char __user *user_buf, | |||
175 | for (q = 0; q < local->hw.queues; q++) | 175 | for (q = 0; q < local->hw.queues; q++) |
176 | res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q, | 176 | res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q, |
177 | local->queue_stop_reasons[q], | 177 | local->queue_stop_reasons[q], |
178 | __netif_subqueue_stopped(local->mdev, q)); | 178 | skb_queue_len(&local->pending[q])); |
179 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 179 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
180 | 180 | ||
181 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | 181 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index b13446afd48f..4100c361a99d 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <net/mac80211.h> | 4 | #include <net/mac80211.h> |
5 | #include "ieee80211_i.h" | 5 | #include "ieee80211_i.h" |
6 | #include "driver-trace.h" | ||
6 | 7 | ||
7 | static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | 8 | static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) |
8 | { | 9 | { |
@@ -11,29 +12,37 @@ static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | |||
11 | 12 | ||
12 | static inline int drv_start(struct ieee80211_local *local) | 13 | static inline int drv_start(struct ieee80211_local *local) |
13 | { | 14 | { |
14 | return local->ops->start(&local->hw); | 15 | int ret = local->ops->start(&local->hw); |
16 | trace_drv_start(local, ret); | ||
17 | return ret; | ||
15 | } | 18 | } |
16 | 19 | ||
17 | static inline void drv_stop(struct ieee80211_local *local) | 20 | static inline void drv_stop(struct ieee80211_local *local) |
18 | { | 21 | { |
19 | local->ops->stop(&local->hw); | 22 | local->ops->stop(&local->hw); |
23 | trace_drv_stop(local); | ||
20 | } | 24 | } |
21 | 25 | ||
22 | static inline int drv_add_interface(struct ieee80211_local *local, | 26 | static inline int drv_add_interface(struct ieee80211_local *local, |
23 | struct ieee80211_if_init_conf *conf) | 27 | struct ieee80211_if_init_conf *conf) |
24 | { | 28 | { |
25 | return local->ops->add_interface(&local->hw, conf); | 29 | int ret = local->ops->add_interface(&local->hw, conf); |
30 | trace_drv_add_interface(local, conf->mac_addr, conf->vif, ret); | ||
31 | return ret; | ||
26 | } | 32 | } |
27 | 33 | ||
28 | static inline void drv_remove_interface(struct ieee80211_local *local, | 34 | static inline void drv_remove_interface(struct ieee80211_local *local, |
29 | struct ieee80211_if_init_conf *conf) | 35 | struct ieee80211_if_init_conf *conf) |
30 | { | 36 | { |
31 | local->ops->remove_interface(&local->hw, conf); | 37 | local->ops->remove_interface(&local->hw, conf); |
38 | trace_drv_remove_interface(local, conf->mac_addr, conf->vif); | ||
32 | } | 39 | } |
33 | 40 | ||
34 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | 41 | static inline int drv_config(struct ieee80211_local *local, u32 changed) |
35 | { | 42 | { |
36 | return local->ops->config(&local->hw, changed); | 43 | int ret = local->ops->config(&local->hw, changed); |
44 | trace_drv_config(local, changed, ret); | ||
45 | return ret; | ||
37 | } | 46 | } |
38 | 47 | ||
39 | static inline void drv_bss_info_changed(struct ieee80211_local *local, | 48 | static inline void drv_bss_info_changed(struct ieee80211_local *local, |
@@ -43,6 +52,7 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
43 | { | 52 | { |
44 | if (local->ops->bss_info_changed) | 53 | if (local->ops->bss_info_changed) |
45 | local->ops->bss_info_changed(&local->hw, vif, info, changed); | 54 | local->ops->bss_info_changed(&local->hw, vif, info, changed); |
55 | trace_drv_bss_info_changed(local, vif, info, changed); | ||
46 | } | 56 | } |
47 | 57 | ||
48 | static inline void drv_configure_filter(struct ieee80211_local *local, | 58 | static inline void drv_configure_filter(struct ieee80211_local *local, |
@@ -53,14 +63,18 @@ static inline void drv_configure_filter(struct ieee80211_local *local, | |||
53 | { | 63 | { |
54 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, | 64 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, |
55 | mc_count, mc_list); | 65 | mc_count, mc_list); |
66 | trace_drv_configure_filter(local, changed_flags, total_flags, | ||
67 | mc_count); | ||
56 | } | 68 | } |
57 | 69 | ||
58 | static inline int drv_set_tim(struct ieee80211_local *local, | 70 | static inline int drv_set_tim(struct ieee80211_local *local, |
59 | struct ieee80211_sta *sta, bool set) | 71 | struct ieee80211_sta *sta, bool set) |
60 | { | 72 | { |
73 | int ret = 0; | ||
61 | if (local->ops->set_tim) | 74 | if (local->ops->set_tim) |
62 | return local->ops->set_tim(&local->hw, sta, set); | 75 | ret = local->ops->set_tim(&local->hw, sta, set); |
63 | return 0; | 76 | trace_drv_set_tim(local, sta, set, ret); |
77 | return ret; | ||
64 | } | 78 | } |
65 | 79 | ||
66 | static inline int drv_set_key(struct ieee80211_local *local, | 80 | static inline int drv_set_key(struct ieee80211_local *local, |
@@ -68,7 +82,9 @@ static inline int drv_set_key(struct ieee80211_local *local, | |||
68 | struct ieee80211_sta *sta, | 82 | struct ieee80211_sta *sta, |
69 | struct ieee80211_key_conf *key) | 83 | struct ieee80211_key_conf *key) |
70 | { | 84 | { |
71 | return local->ops->set_key(&local->hw, cmd, vif, sta, key); | 85 | int ret = local->ops->set_key(&local->hw, cmd, vif, sta, key); |
86 | trace_drv_set_key(local, cmd, vif, sta, key, ret); | ||
87 | return ret; | ||
72 | } | 88 | } |
73 | 89 | ||
74 | static inline void drv_update_tkip_key(struct ieee80211_local *local, | 90 | static inline void drv_update_tkip_key(struct ieee80211_local *local, |
@@ -79,32 +95,41 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
79 | if (local->ops->update_tkip_key) | 95 | if (local->ops->update_tkip_key) |
80 | local->ops->update_tkip_key(&local->hw, conf, address, | 96 | local->ops->update_tkip_key(&local->hw, conf, address, |
81 | iv32, phase1key); | 97 | iv32, phase1key); |
98 | trace_drv_update_tkip_key(local, conf, address, iv32); | ||
82 | } | 99 | } |
83 | 100 | ||
84 | static inline int drv_hw_scan(struct ieee80211_local *local, | 101 | static inline int drv_hw_scan(struct ieee80211_local *local, |
85 | struct cfg80211_scan_request *req) | 102 | struct cfg80211_scan_request *req) |
86 | { | 103 | { |
87 | return local->ops->hw_scan(&local->hw, req); | 104 | int ret = local->ops->hw_scan(&local->hw, req); |
105 | trace_drv_hw_scan(local, req, ret); | ||
106 | return ret; | ||
88 | } | 107 | } |
89 | 108 | ||
90 | static inline void drv_sw_scan_start(struct ieee80211_local *local) | 109 | static inline void drv_sw_scan_start(struct ieee80211_local *local) |
91 | { | 110 | { |
92 | if (local->ops->sw_scan_start) | 111 | if (local->ops->sw_scan_start) |
93 | local->ops->sw_scan_start(&local->hw); | 112 | local->ops->sw_scan_start(&local->hw); |
113 | trace_drv_sw_scan_start(local); | ||
94 | } | 114 | } |
95 | 115 | ||
96 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) | 116 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) |
97 | { | 117 | { |
98 | if (local->ops->sw_scan_complete) | 118 | if (local->ops->sw_scan_complete) |
99 | local->ops->sw_scan_complete(&local->hw); | 119 | local->ops->sw_scan_complete(&local->hw); |
120 | trace_drv_sw_scan_complete(local); | ||
100 | } | 121 | } |
101 | 122 | ||
102 | static inline int drv_get_stats(struct ieee80211_local *local, | 123 | static inline int drv_get_stats(struct ieee80211_local *local, |
103 | struct ieee80211_low_level_stats *stats) | 124 | struct ieee80211_low_level_stats *stats) |
104 | { | 125 | { |
105 | if (!local->ops->get_stats) | 126 | int ret = -EOPNOTSUPP; |
106 | return -EOPNOTSUPP; | 127 | |
107 | return local->ops->get_stats(&local->hw, stats); | 128 | if (local->ops->get_stats) |
129 | ret = local->ops->get_stats(&local->hw, stats); | ||
130 | trace_drv_get_stats(local, stats, ret); | ||
131 | |||
132 | return ret; | ||
108 | } | 133 | } |
109 | 134 | ||
110 | static inline void drv_get_tkip_seq(struct ieee80211_local *local, | 135 | static inline void drv_get_tkip_seq(struct ieee80211_local *local, |
@@ -112,14 +137,17 @@ static inline void drv_get_tkip_seq(struct ieee80211_local *local, | |||
112 | { | 137 | { |
113 | if (local->ops->get_tkip_seq) | 138 | if (local->ops->get_tkip_seq) |
114 | local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); | 139 | local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); |
140 | trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16); | ||
115 | } | 141 | } |
116 | 142 | ||
117 | static inline int drv_set_rts_threshold(struct ieee80211_local *local, | 143 | static inline int drv_set_rts_threshold(struct ieee80211_local *local, |
118 | u32 value) | 144 | u32 value) |
119 | { | 145 | { |
146 | int ret = 0; | ||
120 | if (local->ops->set_rts_threshold) | 147 | if (local->ops->set_rts_threshold) |
121 | return local->ops->set_rts_threshold(&local->hw, value); | 148 | ret = local->ops->set_rts_threshold(&local->hw, value); |
122 | return 0; | 149 | trace_drv_set_rts_threshold(local, value, ret); |
150 | return ret; | ||
123 | } | 151 | } |
124 | 152 | ||
125 | static inline void drv_sta_notify(struct ieee80211_local *local, | 153 | static inline void drv_sta_notify(struct ieee80211_local *local, |
@@ -129,46 +157,57 @@ static inline void drv_sta_notify(struct ieee80211_local *local, | |||
129 | { | 157 | { |
130 | if (local->ops->sta_notify) | 158 | if (local->ops->sta_notify) |
131 | local->ops->sta_notify(&local->hw, vif, cmd, sta); | 159 | local->ops->sta_notify(&local->hw, vif, cmd, sta); |
160 | trace_drv_sta_notify(local, vif, cmd, sta); | ||
132 | } | 161 | } |
133 | 162 | ||
134 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 163 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, |
135 | const struct ieee80211_tx_queue_params *params) | 164 | const struct ieee80211_tx_queue_params *params) |
136 | { | 165 | { |
166 | int ret = -EOPNOTSUPP; | ||
137 | if (local->ops->conf_tx) | 167 | if (local->ops->conf_tx) |
138 | return local->ops->conf_tx(&local->hw, queue, params); | 168 | ret = local->ops->conf_tx(&local->hw, queue, params); |
139 | return -EOPNOTSUPP; | 169 | trace_drv_conf_tx(local, queue, params, ret); |
170 | return ret; | ||
140 | } | 171 | } |
141 | 172 | ||
142 | static inline int drv_get_tx_stats(struct ieee80211_local *local, | 173 | static inline int drv_get_tx_stats(struct ieee80211_local *local, |
143 | struct ieee80211_tx_queue_stats *stats) | 174 | struct ieee80211_tx_queue_stats *stats) |
144 | { | 175 | { |
145 | return local->ops->get_tx_stats(&local->hw, stats); | 176 | int ret = local->ops->get_tx_stats(&local->hw, stats); |
177 | trace_drv_get_tx_stats(local, stats, ret); | ||
178 | return ret; | ||
146 | } | 179 | } |
147 | 180 | ||
148 | static inline u64 drv_get_tsf(struct ieee80211_local *local) | 181 | static inline u64 drv_get_tsf(struct ieee80211_local *local) |
149 | { | 182 | { |
183 | u64 ret = -1ULL; | ||
150 | if (local->ops->get_tsf) | 184 | if (local->ops->get_tsf) |
151 | return local->ops->get_tsf(&local->hw); | 185 | ret = local->ops->get_tsf(&local->hw); |
152 | return -1ULL; | 186 | trace_drv_get_tsf(local, ret); |
187 | return ret; | ||
153 | } | 188 | } |
154 | 189 | ||
155 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | 190 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) |
156 | { | 191 | { |
157 | if (local->ops->set_tsf) | 192 | if (local->ops->set_tsf) |
158 | local->ops->set_tsf(&local->hw, tsf); | 193 | local->ops->set_tsf(&local->hw, tsf); |
194 | trace_drv_set_tsf(local, tsf); | ||
159 | } | 195 | } |
160 | 196 | ||
161 | static inline void drv_reset_tsf(struct ieee80211_local *local) | 197 | static inline void drv_reset_tsf(struct ieee80211_local *local) |
162 | { | 198 | { |
163 | if (local->ops->reset_tsf) | 199 | if (local->ops->reset_tsf) |
164 | local->ops->reset_tsf(&local->hw); | 200 | local->ops->reset_tsf(&local->hw); |
201 | trace_drv_reset_tsf(local); | ||
165 | } | 202 | } |
166 | 203 | ||
167 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 204 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
168 | { | 205 | { |
206 | int ret = 1; | ||
169 | if (local->ops->tx_last_beacon) | 207 | if (local->ops->tx_last_beacon) |
170 | return local->ops->tx_last_beacon(&local->hw); | 208 | ret = local->ops->tx_last_beacon(&local->hw); |
171 | return 1; | 209 | trace_drv_tx_last_beacon(local, ret); |
210 | return ret; | ||
172 | } | 211 | } |
173 | 212 | ||
174 | static inline int drv_ampdu_action(struct ieee80211_local *local, | 213 | static inline int drv_ampdu_action(struct ieee80211_local *local, |
@@ -176,10 +215,12 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
176 | struct ieee80211_sta *sta, u16 tid, | 215 | struct ieee80211_sta *sta, u16 tid, |
177 | u16 *ssn) | 216 | u16 *ssn) |
178 | { | 217 | { |
218 | int ret = -EOPNOTSUPP; | ||
179 | if (local->ops->ampdu_action) | 219 | if (local->ops->ampdu_action) |
180 | return local->ops->ampdu_action(&local->hw, action, | 220 | ret = local->ops->ampdu_action(&local->hw, action, |
181 | sta, tid, ssn); | 221 | sta, tid, ssn); |
182 | return -EOPNOTSUPP; | 222 | trace_drv_ampdu_action(local, action, sta, tid, ssn, ret); |
223 | return ret; | ||
183 | } | 224 | } |
184 | 225 | ||
185 | 226 | ||
diff --git a/net/mac80211/driver-trace.c b/net/mac80211/driver-trace.c new file mode 100644 index 000000000000..6da6f79932fc --- /dev/null +++ b/net/mac80211/driver-trace.c | |||
@@ -0,0 +1,6 @@ | |||
1 | /* bug in tracepoint.h, it should include this */ | ||
2 | #include <linux/module.h> | ||
3 | |||
4 | #include "driver-ops.h" | ||
5 | #define CREATE_TRACE_POINTS | ||
6 | #include "driver-trace.h" | ||
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h new file mode 100644 index 000000000000..5a10da2d70fd --- /dev/null +++ b/net/mac80211/driver-trace.h | |||
@@ -0,0 +1,648 @@ | |||
1 | #if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define __MAC80211_DRIVER_TRACE | ||
3 | |||
4 | #include <linux/tracepoint.h> | ||
5 | #include <net/mac80211.h> | ||
6 | #include "ieee80211_i.h" | ||
7 | |||
8 | #if !defined(CONFIG_MAC80211_DRIVER_API_TRACER) || defined(__CHECKER__) | ||
9 | #undef TRACE_EVENT | ||
10 | #define TRACE_EVENT(name, proto, ...) \ | ||
11 | static inline void trace_ ## name(proto) {} | ||
12 | #endif | ||
13 | |||
14 | #undef TRACE_SYSTEM | ||
15 | #define TRACE_SYSTEM mac80211 | ||
16 | |||
17 | #define MAXNAME 32 | ||
18 | #define LOCAL_ENTRY __array(char, wiphy_name, 32) | ||
19 | #define LOCAL_ASSIGN strlcpy(__entry->wiphy_name, wiphy_name(local->hw.wiphy), MAXNAME) | ||
20 | #define LOCAL_PR_FMT "%s" | ||
21 | #define LOCAL_PR_ARG __entry->wiphy_name | ||
22 | |||
23 | #define STA_ENTRY __array(char, sta_addr, ETH_ALEN) | ||
24 | #define STA_ASSIGN (sta ? memcpy(__entry->sta_addr, sta->addr, ETH_ALEN) : memset(__entry->sta_addr, 0, ETH_ALEN)) | ||
25 | #define STA_PR_FMT " sta:%pM" | ||
26 | #define STA_PR_ARG __entry->sta_addr | ||
27 | |||
28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, vif) | ||
29 | #define VIF_ASSIGN __entry->vif_type = vif ? vif->type : 0; __entry->vif = vif | ||
30 | #define VIF_PR_FMT " vif:%p(%d)" | ||
31 | #define VIF_PR_ARG __entry->vif, __entry->vif_type | ||
32 | |||
33 | TRACE_EVENT(drv_start, | ||
34 | TP_PROTO(struct ieee80211_local *local, int ret), | ||
35 | |||
36 | TP_ARGS(local, ret), | ||
37 | |||
38 | TP_STRUCT__entry( | ||
39 | LOCAL_ENTRY | ||
40 | __field(int, ret) | ||
41 | ), | ||
42 | |||
43 | TP_fast_assign( | ||
44 | LOCAL_ASSIGN; | ||
45 | __entry->ret = ret; | ||
46 | ), | ||
47 | |||
48 | TP_printk( | ||
49 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
50 | ) | ||
51 | ); | ||
52 | |||
53 | TRACE_EVENT(drv_stop, | ||
54 | TP_PROTO(struct ieee80211_local *local), | ||
55 | |||
56 | TP_ARGS(local), | ||
57 | |||
58 | TP_STRUCT__entry( | ||
59 | LOCAL_ENTRY | ||
60 | ), | ||
61 | |||
62 | TP_fast_assign( | ||
63 | LOCAL_ASSIGN; | ||
64 | ), | ||
65 | |||
66 | TP_printk( | ||
67 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
68 | ) | ||
69 | ); | ||
70 | |||
71 | TRACE_EVENT(drv_add_interface, | ||
72 | TP_PROTO(struct ieee80211_local *local, | ||
73 | const u8 *addr, | ||
74 | struct ieee80211_vif *vif, | ||
75 | int ret), | ||
76 | |||
77 | TP_ARGS(local, addr, vif, ret), | ||
78 | |||
79 | TP_STRUCT__entry( | ||
80 | LOCAL_ENTRY | ||
81 | VIF_ENTRY | ||
82 | __array(char, addr, 6) | ||
83 | __field(int, ret) | ||
84 | ), | ||
85 | |||
86 | TP_fast_assign( | ||
87 | LOCAL_ASSIGN; | ||
88 | VIF_ASSIGN; | ||
89 | memcpy(__entry->addr, addr, 6); | ||
90 | __entry->ret = ret; | ||
91 | ), | ||
92 | |||
93 | TP_printk( | ||
94 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM ret:%d", | ||
95 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr, __entry->ret | ||
96 | ) | ||
97 | ); | ||
98 | |||
99 | TRACE_EVENT(drv_remove_interface, | ||
100 | TP_PROTO(struct ieee80211_local *local, | ||
101 | const u8 *addr, struct ieee80211_vif *vif), | ||
102 | |||
103 | TP_ARGS(local, addr, vif), | ||
104 | |||
105 | TP_STRUCT__entry( | ||
106 | LOCAL_ENTRY | ||
107 | VIF_ENTRY | ||
108 | __array(char, addr, 6) | ||
109 | ), | ||
110 | |||
111 | TP_fast_assign( | ||
112 | LOCAL_ASSIGN; | ||
113 | VIF_ASSIGN; | ||
114 | memcpy(__entry->addr, addr, 6); | ||
115 | ), | ||
116 | |||
117 | TP_printk( | ||
118 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", | ||
119 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr | ||
120 | ) | ||
121 | ); | ||
122 | |||
123 | TRACE_EVENT(drv_config, | ||
124 | TP_PROTO(struct ieee80211_local *local, | ||
125 | u32 changed, | ||
126 | int ret), | ||
127 | |||
128 | TP_ARGS(local, changed, ret), | ||
129 | |||
130 | TP_STRUCT__entry( | ||
131 | LOCAL_ENTRY | ||
132 | __field(u32, changed) | ||
133 | __field(int, ret) | ||
134 | ), | ||
135 | |||
136 | TP_fast_assign( | ||
137 | LOCAL_ASSIGN; | ||
138 | __entry->changed = changed; | ||
139 | __entry->ret = ret; | ||
140 | ), | ||
141 | |||
142 | TP_printk( | ||
143 | LOCAL_PR_FMT " ch:%#x ret:%d", | ||
144 | LOCAL_PR_ARG, __entry->changed, __entry->ret | ||
145 | ) | ||
146 | ); | ||
147 | |||
148 | TRACE_EVENT(drv_bss_info_changed, | ||
149 | TP_PROTO(struct ieee80211_local *local, | ||
150 | struct ieee80211_vif *vif, | ||
151 | struct ieee80211_bss_conf *info, | ||
152 | u32 changed), | ||
153 | |||
154 | TP_ARGS(local, vif, info, changed), | ||
155 | |||
156 | TP_STRUCT__entry( | ||
157 | LOCAL_ENTRY | ||
158 | VIF_ENTRY | ||
159 | __field(bool, assoc) | ||
160 | __field(u16, aid) | ||
161 | __field(bool, cts) | ||
162 | __field(bool, shortpre) | ||
163 | __field(bool, shortslot) | ||
164 | __field(u8, dtimper) | ||
165 | __field(u16, bcnint) | ||
166 | __field(u16, assoc_cap) | ||
167 | __field(u64, timestamp) | ||
168 | __field(u32, basic_rates) | ||
169 | __field(u32, changed) | ||
170 | ), | ||
171 | |||
172 | TP_fast_assign( | ||
173 | LOCAL_ASSIGN; | ||
174 | VIF_ASSIGN; | ||
175 | __entry->changed = changed; | ||
176 | __entry->aid = info->aid; | ||
177 | __entry->assoc = info->assoc; | ||
178 | __entry->shortpre = info->use_short_preamble; | ||
179 | __entry->cts = info->use_cts_prot; | ||
180 | __entry->shortslot = info->use_short_slot; | ||
181 | __entry->dtimper = info->dtim_period; | ||
182 | __entry->bcnint = info->beacon_int; | ||
183 | __entry->assoc_cap = info->assoc_capability; | ||
184 | __entry->timestamp = info->timestamp; | ||
185 | __entry->basic_rates = info->basic_rates; | ||
186 | ), | ||
187 | |||
188 | TP_printk( | ||
189 | LOCAL_PR_FMT VIF_PR_FMT " changed:%#x", | ||
190 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->changed | ||
191 | ) | ||
192 | ); | ||
193 | |||
194 | TRACE_EVENT(drv_configure_filter, | ||
195 | TP_PROTO(struct ieee80211_local *local, | ||
196 | unsigned int changed_flags, | ||
197 | unsigned int *total_flags, | ||
198 | int mc_count), | ||
199 | |||
200 | TP_ARGS(local, changed_flags, total_flags, mc_count), | ||
201 | |||
202 | TP_STRUCT__entry( | ||
203 | LOCAL_ENTRY | ||
204 | __field(unsigned int, changed) | ||
205 | __field(unsigned int, total) | ||
206 | __field(int, mc) | ||
207 | ), | ||
208 | |||
209 | TP_fast_assign( | ||
210 | LOCAL_ASSIGN; | ||
211 | __entry->changed = changed_flags; | ||
212 | __entry->total = *total_flags; | ||
213 | __entry->mc = mc_count; | ||
214 | ), | ||
215 | |||
216 | TP_printk( | ||
217 | LOCAL_PR_FMT " changed:%#x total:%#x mc:%d", | ||
218 | LOCAL_PR_ARG, __entry->changed, __entry->total, __entry->mc | ||
219 | ) | ||
220 | ); | ||
221 | |||
222 | TRACE_EVENT(drv_set_tim, | ||
223 | TP_PROTO(struct ieee80211_local *local, | ||
224 | struct ieee80211_sta *sta, bool set, int ret), | ||
225 | |||
226 | TP_ARGS(local, sta, set, ret), | ||
227 | |||
228 | TP_STRUCT__entry( | ||
229 | LOCAL_ENTRY | ||
230 | STA_ENTRY | ||
231 | __field(bool, set) | ||
232 | __field(int, ret) | ||
233 | ), | ||
234 | |||
235 | TP_fast_assign( | ||
236 | LOCAL_ASSIGN; | ||
237 | STA_ASSIGN; | ||
238 | __entry->set = set; | ||
239 | __entry->ret = ret; | ||
240 | ), | ||
241 | |||
242 | TP_printk( | ||
243 | LOCAL_PR_FMT STA_PR_FMT " set:%d ret:%d", | ||
244 | LOCAL_PR_ARG, STA_PR_FMT, __entry->set, __entry->ret | ||
245 | ) | ||
246 | ); | ||
247 | |||
248 | TRACE_EVENT(drv_set_key, | ||
249 | TP_PROTO(struct ieee80211_local *local, | ||
250 | enum set_key_cmd cmd, struct ieee80211_vif *vif, | ||
251 | struct ieee80211_sta *sta, | ||
252 | struct ieee80211_key_conf *key, int ret), | ||
253 | |||
254 | TP_ARGS(local, cmd, vif, sta, key, ret), | ||
255 | |||
256 | TP_STRUCT__entry( | ||
257 | LOCAL_ENTRY | ||
258 | VIF_ENTRY | ||
259 | STA_ENTRY | ||
260 | __field(enum ieee80211_key_alg, alg) | ||
261 | __field(u8, hw_key_idx) | ||
262 | __field(u8, flags) | ||
263 | __field(s8, keyidx) | ||
264 | __field(int, ret) | ||
265 | ), | ||
266 | |||
267 | TP_fast_assign( | ||
268 | LOCAL_ASSIGN; | ||
269 | VIF_ASSIGN; | ||
270 | STA_ASSIGN; | ||
271 | __entry->alg = key->alg; | ||
272 | __entry->flags = key->flags; | ||
273 | __entry->keyidx = key->keyidx; | ||
274 | __entry->hw_key_idx = key->hw_key_idx; | ||
275 | __entry->ret = ret; | ||
276 | ), | ||
277 | |||
278 | TP_printk( | ||
279 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", | ||
280 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret | ||
281 | ) | ||
282 | ); | ||
283 | |||
284 | TRACE_EVENT(drv_update_tkip_key, | ||
285 | TP_PROTO(struct ieee80211_local *local, | ||
286 | struct ieee80211_key_conf *conf, | ||
287 | const u8 *address, u32 iv32), | ||
288 | |||
289 | TP_ARGS(local, conf, address, iv32), | ||
290 | |||
291 | TP_STRUCT__entry( | ||
292 | LOCAL_ENTRY | ||
293 | __array(u8, addr, 6) | ||
294 | __field(u32, iv32) | ||
295 | ), | ||
296 | |||
297 | TP_fast_assign( | ||
298 | LOCAL_ASSIGN; | ||
299 | memcpy(__entry->addr, address, 6); | ||
300 | __entry->iv32 = iv32; | ||
301 | ), | ||
302 | |||
303 | TP_printk( | ||
304 | LOCAL_PR_FMT " addr:%pM iv32:%#x", | ||
305 | LOCAL_PR_ARG, __entry->addr, __entry->iv32 | ||
306 | ) | ||
307 | ); | ||
308 | |||
309 | TRACE_EVENT(drv_hw_scan, | ||
310 | TP_PROTO(struct ieee80211_local *local, | ||
311 | struct cfg80211_scan_request *req, int ret), | ||
312 | |||
313 | TP_ARGS(local, req, ret), | ||
314 | |||
315 | TP_STRUCT__entry( | ||
316 | LOCAL_ENTRY | ||
317 | __field(int, ret) | ||
318 | ), | ||
319 | |||
320 | TP_fast_assign( | ||
321 | LOCAL_ASSIGN; | ||
322 | __entry->ret = ret; | ||
323 | ), | ||
324 | |||
325 | TP_printk( | ||
326 | LOCAL_PR_FMT " ret:%d", | ||
327 | LOCAL_PR_ARG, __entry->ret | ||
328 | ) | ||
329 | ); | ||
330 | |||
331 | TRACE_EVENT(drv_sw_scan_start, | ||
332 | TP_PROTO(struct ieee80211_local *local), | ||
333 | |||
334 | TP_ARGS(local), | ||
335 | |||
336 | TP_STRUCT__entry( | ||
337 | LOCAL_ENTRY | ||
338 | ), | ||
339 | |||
340 | TP_fast_assign( | ||
341 | LOCAL_ASSIGN; | ||
342 | ), | ||
343 | |||
344 | TP_printk( | ||
345 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
346 | ) | ||
347 | ); | ||
348 | |||
349 | TRACE_EVENT(drv_sw_scan_complete, | ||
350 | TP_PROTO(struct ieee80211_local *local), | ||
351 | |||
352 | TP_ARGS(local), | ||
353 | |||
354 | TP_STRUCT__entry( | ||
355 | LOCAL_ENTRY | ||
356 | ), | ||
357 | |||
358 | TP_fast_assign( | ||
359 | LOCAL_ASSIGN; | ||
360 | ), | ||
361 | |||
362 | TP_printk( | ||
363 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
364 | ) | ||
365 | ); | ||
366 | |||
367 | TRACE_EVENT(drv_get_stats, | ||
368 | TP_PROTO(struct ieee80211_local *local, | ||
369 | struct ieee80211_low_level_stats *stats, | ||
370 | int ret), | ||
371 | |||
372 | TP_ARGS(local, stats, ret), | ||
373 | |||
374 | TP_STRUCT__entry( | ||
375 | LOCAL_ENTRY | ||
376 | __field(int, ret) | ||
377 | __field(unsigned int, ackfail) | ||
378 | __field(unsigned int, rtsfail) | ||
379 | __field(unsigned int, fcserr) | ||
380 | __field(unsigned int, rtssucc) | ||
381 | ), | ||
382 | |||
383 | TP_fast_assign( | ||
384 | LOCAL_ASSIGN; | ||
385 | __entry->ret = ret; | ||
386 | __entry->ackfail = stats->dot11ACKFailureCount; | ||
387 | __entry->rtsfail = stats->dot11RTSFailureCount; | ||
388 | __entry->fcserr = stats->dot11FCSErrorCount; | ||
389 | __entry->rtssucc = stats->dot11RTSSuccessCount; | ||
390 | ), | ||
391 | |||
392 | TP_printk( | ||
393 | LOCAL_PR_FMT " ret:%d", | ||
394 | LOCAL_PR_ARG, __entry->ret | ||
395 | ) | ||
396 | ); | ||
397 | |||
398 | TRACE_EVENT(drv_get_tkip_seq, | ||
399 | TP_PROTO(struct ieee80211_local *local, | ||
400 | u8 hw_key_idx, u32 *iv32, u16 *iv16), | ||
401 | |||
402 | TP_ARGS(local, hw_key_idx, iv32, iv16), | ||
403 | |||
404 | TP_STRUCT__entry( | ||
405 | LOCAL_ENTRY | ||
406 | __field(u8, hw_key_idx) | ||
407 | __field(u32, iv32) | ||
408 | __field(u16, iv16) | ||
409 | ), | ||
410 | |||
411 | TP_fast_assign( | ||
412 | LOCAL_ASSIGN; | ||
413 | __entry->hw_key_idx = hw_key_idx; | ||
414 | __entry->iv32 = *iv32; | ||
415 | __entry->iv16 = *iv16; | ||
416 | ), | ||
417 | |||
418 | TP_printk( | ||
419 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
420 | ) | ||
421 | ); | ||
422 | |||
423 | TRACE_EVENT(drv_set_rts_threshold, | ||
424 | TP_PROTO(struct ieee80211_local *local, u32 value, int ret), | ||
425 | |||
426 | TP_ARGS(local, value, ret), | ||
427 | |||
428 | TP_STRUCT__entry( | ||
429 | LOCAL_ENTRY | ||
430 | __field(u32, value) | ||
431 | __field(int, ret) | ||
432 | ), | ||
433 | |||
434 | TP_fast_assign( | ||
435 | LOCAL_ASSIGN; | ||
436 | __entry->ret = ret; | ||
437 | __entry->value = value; | ||
438 | ), | ||
439 | |||
440 | TP_printk( | ||
441 | LOCAL_PR_FMT " value:%d ret:%d", | ||
442 | LOCAL_PR_ARG, __entry->value, __entry->ret | ||
443 | ) | ||
444 | ); | ||
445 | |||
446 | TRACE_EVENT(drv_sta_notify, | ||
447 | TP_PROTO(struct ieee80211_local *local, | ||
448 | struct ieee80211_vif *vif, | ||
449 | enum sta_notify_cmd cmd, | ||
450 | struct ieee80211_sta *sta), | ||
451 | |||
452 | TP_ARGS(local, vif, cmd, sta), | ||
453 | |||
454 | TP_STRUCT__entry( | ||
455 | LOCAL_ENTRY | ||
456 | VIF_ENTRY | ||
457 | STA_ENTRY | ||
458 | __field(u32, cmd) | ||
459 | ), | ||
460 | |||
461 | TP_fast_assign( | ||
462 | LOCAL_ASSIGN; | ||
463 | VIF_ASSIGN; | ||
464 | STA_ASSIGN; | ||
465 | __entry->cmd = cmd; | ||
466 | ), | ||
467 | |||
468 | TP_printk( | ||
469 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " cmd:%d", | ||
470 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->cmd | ||
471 | ) | ||
472 | ); | ||
473 | |||
474 | TRACE_EVENT(drv_conf_tx, | ||
475 | TP_PROTO(struct ieee80211_local *local, u16 queue, | ||
476 | const struct ieee80211_tx_queue_params *params, | ||
477 | int ret), | ||
478 | |||
479 | TP_ARGS(local, queue, params, ret), | ||
480 | |||
481 | TP_STRUCT__entry( | ||
482 | LOCAL_ENTRY | ||
483 | __field(u16, queue) | ||
484 | __field(u16, txop) | ||
485 | __field(u16, cw_min) | ||
486 | __field(u16, cw_max) | ||
487 | __field(u8, aifs) | ||
488 | __field(int, ret) | ||
489 | ), | ||
490 | |||
491 | TP_fast_assign( | ||
492 | LOCAL_ASSIGN; | ||
493 | __entry->queue = queue; | ||
494 | __entry->ret = ret; | ||
495 | __entry->txop = params->txop; | ||
496 | __entry->cw_max = params->cw_max; | ||
497 | __entry->cw_min = params->cw_min; | ||
498 | __entry->aifs = params->aifs; | ||
499 | ), | ||
500 | |||
501 | TP_printk( | ||
502 | LOCAL_PR_FMT " queue:%d ret:%d", | ||
503 | LOCAL_PR_ARG, __entry->queue, __entry->ret | ||
504 | ) | ||
505 | ); | ||
506 | |||
507 | TRACE_EVENT(drv_get_tx_stats, | ||
508 | TP_PROTO(struct ieee80211_local *local, | ||
509 | struct ieee80211_tx_queue_stats *stats, | ||
510 | int ret), | ||
511 | |||
512 | TP_ARGS(local, stats, ret), | ||
513 | |||
514 | TP_STRUCT__entry( | ||
515 | LOCAL_ENTRY | ||
516 | __field(int, ret) | ||
517 | ), | ||
518 | |||
519 | TP_fast_assign( | ||
520 | LOCAL_ASSIGN; | ||
521 | __entry->ret = ret; | ||
522 | ), | ||
523 | |||
524 | TP_printk( | ||
525 | LOCAL_PR_FMT " ret:%d", | ||
526 | LOCAL_PR_ARG, __entry->ret | ||
527 | ) | ||
528 | ); | ||
529 | |||
530 | TRACE_EVENT(drv_get_tsf, | ||
531 | TP_PROTO(struct ieee80211_local *local, u64 ret), | ||
532 | |||
533 | TP_ARGS(local, ret), | ||
534 | |||
535 | TP_STRUCT__entry( | ||
536 | LOCAL_ENTRY | ||
537 | __field(u64, ret) | ||
538 | ), | ||
539 | |||
540 | TP_fast_assign( | ||
541 | LOCAL_ASSIGN; | ||
542 | __entry->ret = ret; | ||
543 | ), | ||
544 | |||
545 | TP_printk( | ||
546 | LOCAL_PR_FMT " ret:%llu", | ||
547 | LOCAL_PR_ARG, (unsigned long long)__entry->ret | ||
548 | ) | ||
549 | ); | ||
550 | |||
551 | TRACE_EVENT(drv_set_tsf, | ||
552 | TP_PROTO(struct ieee80211_local *local, u64 tsf), | ||
553 | |||
554 | TP_ARGS(local, tsf), | ||
555 | |||
556 | TP_STRUCT__entry( | ||
557 | LOCAL_ENTRY | ||
558 | __field(u64, tsf) | ||
559 | ), | ||
560 | |||
561 | TP_fast_assign( | ||
562 | LOCAL_ASSIGN; | ||
563 | __entry->tsf = tsf; | ||
564 | ), | ||
565 | |||
566 | TP_printk( | ||
567 | LOCAL_PR_FMT " tsf:%llu", | ||
568 | LOCAL_PR_ARG, (unsigned long long)__entry->tsf | ||
569 | ) | ||
570 | ); | ||
571 | |||
572 | TRACE_EVENT(drv_reset_tsf, | ||
573 | TP_PROTO(struct ieee80211_local *local), | ||
574 | |||
575 | TP_ARGS(local), | ||
576 | |||
577 | TP_STRUCT__entry( | ||
578 | LOCAL_ENTRY | ||
579 | ), | ||
580 | |||
581 | TP_fast_assign( | ||
582 | LOCAL_ASSIGN; | ||
583 | ), | ||
584 | |||
585 | TP_printk( | ||
586 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
587 | ) | ||
588 | ); | ||
589 | |||
590 | TRACE_EVENT(drv_tx_last_beacon, | ||
591 | TP_PROTO(struct ieee80211_local *local, int ret), | ||
592 | |||
593 | TP_ARGS(local, ret), | ||
594 | |||
595 | TP_STRUCT__entry( | ||
596 | LOCAL_ENTRY | ||
597 | __field(int, ret) | ||
598 | ), | ||
599 | |||
600 | TP_fast_assign( | ||
601 | LOCAL_ASSIGN; | ||
602 | __entry->ret = ret; | ||
603 | ), | ||
604 | |||
605 | TP_printk( | ||
606 | LOCAL_PR_FMT " ret:%d", | ||
607 | LOCAL_PR_ARG, __entry->ret | ||
608 | ) | ||
609 | ); | ||
610 | |||
611 | TRACE_EVENT(drv_ampdu_action, | ||
612 | TP_PROTO(struct ieee80211_local *local, | ||
613 | enum ieee80211_ampdu_mlme_action action, | ||
614 | struct ieee80211_sta *sta, u16 tid, | ||
615 | u16 *ssn, int ret), | ||
616 | |||
617 | TP_ARGS(local, action, sta, tid, ssn, ret), | ||
618 | |||
619 | TP_STRUCT__entry( | ||
620 | LOCAL_ENTRY | ||
621 | STA_ENTRY | ||
622 | __field(u32, action) | ||
623 | __field(u16, tid) | ||
624 | __field(u16, ssn) | ||
625 | __field(int, ret) | ||
626 | ), | ||
627 | |||
628 | TP_fast_assign( | ||
629 | LOCAL_ASSIGN; | ||
630 | STA_ASSIGN; | ||
631 | __entry->ret = ret; | ||
632 | __entry->action = action; | ||
633 | __entry->tid = tid; | ||
634 | __entry->ssn = *ssn; | ||
635 | ), | ||
636 | |||
637 | TP_printk( | ||
638 | LOCAL_PR_FMT STA_PR_FMT " action:%d tid:%d ret:%d", | ||
639 | LOCAL_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret | ||
640 | ) | ||
641 | ); | ||
642 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | ||
643 | |||
644 | #undef TRACE_INCLUDE_PATH | ||
645 | #define TRACE_INCLUDE_PATH . | ||
646 | #undef TRACE_INCLUDE_FILE | ||
647 | #define TRACE_INCLUDE_FILE driver-trace | ||
648 | #include <trace/define_trace.h> | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 15d5a53b59a8..8e2220000e5c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -57,7 +57,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
57 | */ | 57 | */ |
58 | if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) | 58 | if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) |
59 | ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0, | 59 | ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0, |
60 | sdata->u.ibss.bssid, 0); | 60 | sdata->u.ibss.bssid, NULL, 0, 0); |
61 | } | 61 | } |
62 | 62 | ||
63 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 63 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
@@ -494,7 +494,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
494 | 494 | ||
495 | capability = WLAN_CAPABILITY_IBSS; | 495 | capability = WLAN_CAPABILITY_IBSS; |
496 | 496 | ||
497 | if (sdata->default_key) | 497 | if (ifibss->privacy) |
498 | capability |= WLAN_CAPABILITY_PRIVACY; | 498 | capability |= WLAN_CAPABILITY_PRIVACY; |
499 | else | 499 | else |
500 | sdata->drop_unencrypted = 0; | 500 | sdata->drop_unencrypted = 0; |
@@ -524,9 +524,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
524 | return; | 524 | return; |
525 | 525 | ||
526 | capability = WLAN_CAPABILITY_IBSS; | 526 | capability = WLAN_CAPABILITY_IBSS; |
527 | if (sdata->default_key) | 527 | if (ifibss->privacy) |
528 | capability |= WLAN_CAPABILITY_PRIVACY; | 528 | capability |= WLAN_CAPABILITY_PRIVACY; |
529 | |||
530 | if (ifibss->fixed_bssid) | 529 | if (ifibss->fixed_bssid) |
531 | bssid = ifibss->bssid; | 530 | bssid = ifibss->bssid; |
532 | if (ifibss->fixed_channel) | 531 | if (ifibss->fixed_channel) |
@@ -872,6 +871,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
872 | } else | 871 | } else |
873 | sdata->u.ibss.fixed_bssid = false; | 872 | sdata->u.ibss.fixed_bssid = false; |
874 | 873 | ||
874 | sdata->u.ibss.privacy = params->privacy; | ||
875 | |||
875 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 876 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
876 | 877 | ||
877 | sdata->u.ibss.channel = params->channel; | 878 | sdata->u.ibss.channel = params->channel; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 327aabc07abe..6a0177137dd5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -247,18 +247,22 @@ struct ieee80211_mgd_work { | |||
247 | 247 | ||
248 | int tries; | 248 | int tries; |
249 | 249 | ||
250 | u8 key[WLAN_KEY_LEN_WEP104]; | ||
251 | u8 key_len, key_idx; | ||
252 | |||
250 | /* must be last */ | 253 | /* must be last */ |
251 | u8 ie[0]; /* for auth or assoc frame, not probe */ | 254 | u8 ie[0]; /* for auth or assoc frame, not probe */ |
252 | }; | 255 | }; |
253 | 256 | ||
254 | /* flags used in struct ieee80211_if_managed.flags */ | 257 | /* flags used in struct ieee80211_if_managed.flags */ |
255 | enum ieee80211_sta_flags { | 258 | enum ieee80211_sta_flags { |
256 | IEEE80211_STA_PROBEREQ_POLL = BIT(3), | 259 | IEEE80211_STA_BEACON_POLL = BIT(0), |
257 | IEEE80211_STA_CONTROL_PORT = BIT(4), | 260 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
258 | IEEE80211_STA_WMM_ENABLED = BIT(5), | 261 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
259 | IEEE80211_STA_DISABLE_11N = BIT(6), | 262 | IEEE80211_STA_WMM_ENABLED = BIT(3), |
260 | IEEE80211_STA_CSA_RECEIVED = BIT(7), | 263 | IEEE80211_STA_DISABLE_11N = BIT(4), |
261 | IEEE80211_STA_MFP_ENABLED = BIT(8), | 264 | IEEE80211_STA_CSA_RECEIVED = BIT(5), |
265 | IEEE80211_STA_MFP_ENABLED = BIT(6), | ||
262 | }; | 266 | }; |
263 | 267 | ||
264 | /* flags for MLME request */ | 268 | /* flags for MLME request */ |
@@ -268,11 +272,16 @@ enum ieee80211_sta_request { | |||
268 | 272 | ||
269 | struct ieee80211_if_managed { | 273 | struct ieee80211_if_managed { |
270 | struct timer_list timer; | 274 | struct timer_list timer; |
275 | struct timer_list conn_mon_timer; | ||
276 | struct timer_list bcn_mon_timer; | ||
271 | struct timer_list chswitch_timer; | 277 | struct timer_list chswitch_timer; |
272 | struct work_struct work; | 278 | struct work_struct work; |
279 | struct work_struct monitor_work; | ||
273 | struct work_struct chswitch_work; | 280 | struct work_struct chswitch_work; |
274 | struct work_struct beacon_loss_work; | 281 | struct work_struct beacon_loss_work; |
275 | 282 | ||
283 | unsigned long probe_timeout; | ||
284 | |||
276 | struct mutex mtx; | 285 | struct mutex mtx; |
277 | struct ieee80211_bss *associated; | 286 | struct ieee80211_bss *associated; |
278 | struct list_head work_list; | 287 | struct list_head work_list; |
@@ -289,8 +298,6 @@ struct ieee80211_if_managed { | |||
289 | 298 | ||
290 | unsigned long request; | 299 | unsigned long request; |
291 | 300 | ||
292 | unsigned long last_beacon; | ||
293 | |||
294 | unsigned int flags; | 301 | unsigned int flags; |
295 | 302 | ||
296 | u32 beacon_crc; | 303 | u32 beacon_crc; |
@@ -321,6 +328,7 @@ struct ieee80211_if_ibss { | |||
321 | 328 | ||
322 | bool fixed_bssid; | 329 | bool fixed_bssid; |
323 | bool fixed_channel; | 330 | bool fixed_channel; |
331 | bool privacy; | ||
324 | 332 | ||
325 | u8 bssid[ETH_ALEN]; | 333 | u8 bssid[ETH_ALEN]; |
326 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 334 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
@@ -559,14 +567,9 @@ enum queue_stop_reason { | |||
559 | IEEE80211_QUEUE_STOP_REASON_CSA, | 567 | IEEE80211_QUEUE_STOP_REASON_CSA, |
560 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, | 568 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
561 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 569 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
562 | IEEE80211_QUEUE_STOP_REASON_PENDING, | ||
563 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 570 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
564 | }; | 571 | }; |
565 | 572 | ||
566 | struct ieee80211_master_priv { | ||
567 | struct ieee80211_local *local; | ||
568 | }; | ||
569 | |||
570 | struct ieee80211_local { | 573 | struct ieee80211_local { |
571 | /* embed the driver visible part. | 574 | /* embed the driver visible part. |
572 | * don't cast (use the static inlines below), but we keep | 575 | * don't cast (use the static inlines below), but we keep |
@@ -579,13 +582,20 @@ struct ieee80211_local { | |||
579 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ | 582 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ |
580 | spinlock_t queue_stop_reason_lock; | 583 | spinlock_t queue_stop_reason_lock; |
581 | 584 | ||
582 | struct net_device *mdev; /* wmaster# - "master" 802.11 device */ | ||
583 | int open_count; | 585 | int open_count; |
584 | int monitors, cooked_mntrs; | 586 | int monitors, cooked_mntrs; |
585 | /* number of interfaces with corresponding FIF_ flags */ | 587 | /* number of interfaces with corresponding FIF_ flags */ |
586 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; | 588 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; |
587 | unsigned int filter_flags; /* FIF_* */ | 589 | unsigned int filter_flags; /* FIF_* */ |
588 | struct iw_statistics wstats; | 590 | struct iw_statistics wstats; |
591 | |||
592 | /* protects the aggregated multicast list and filter calls */ | ||
593 | spinlock_t filter_lock; | ||
594 | |||
595 | /* aggregated multicast list */ | ||
596 | struct dev_addr_list *mc_list; | ||
597 | int mc_count; | ||
598 | |||
589 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 599 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
590 | 600 | ||
591 | /* | 601 | /* |
@@ -805,10 +815,6 @@ struct ieee80211_local { | |||
805 | static inline struct ieee80211_sub_if_data * | 815 | static inline struct ieee80211_sub_if_data * |
806 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | 816 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) |
807 | { | 817 | { |
808 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
809 | |||
810 | BUG_ON(!local || local->mdev == dev); | ||
811 | |||
812 | return netdev_priv(dev); | 818 | return netdev_priv(dev); |
813 | } | 819 | } |
814 | 820 | ||
@@ -988,7 +994,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local); | |||
988 | /* tx handling */ | 994 | /* tx handling */ |
989 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 995 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
990 | void ieee80211_tx_pending(unsigned long data); | 996 | void ieee80211_tx_pending(unsigned long data); |
991 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
992 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | 997 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); |
993 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | 998 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); |
994 | 999 | ||
@@ -1093,8 +1098,8 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
1093 | 1098 | ||
1094 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1099 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1095 | u16 transaction, u16 auth_alg, | 1100 | u16 transaction, u16 auth_alg, |
1096 | u8 *extra, size_t extra_len, | 1101 | u8 *extra, size_t extra_len, const u8 *bssid, |
1097 | const u8 *bssid, int encrypt); | 1102 | const u8 *key, u8 key_len, u8 key_idx); |
1098 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1103 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1099 | const u8 *ie, size_t ie_len); | 1104 | const u8 *ie, size_t ie_len); |
1100 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1105 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 4839a2d97a3b..2f797a86ced5 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -190,10 +190,6 @@ static int ieee80211_open(struct net_device *dev) | |||
190 | ETH_ALEN); | 190 | ETH_ALEN); |
191 | } | 191 | } |
192 | 192 | ||
193 | if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) | ||
194 | memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, | ||
195 | ETH_ALEN); | ||
196 | |||
197 | /* | 193 | /* |
198 | * Validate the MAC address for this device. | 194 | * Validate the MAC address for this device. |
199 | */ | 195 | */ |
@@ -229,9 +225,9 @@ static int ieee80211_open(struct net_device *dev) | |||
229 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | 225 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) |
230 | local->fif_other_bss++; | 226 | local->fif_other_bss++; |
231 | 227 | ||
232 | netif_addr_lock_bh(local->mdev); | 228 | spin_lock_bh(&local->filter_lock); |
233 | ieee80211_configure_filter(local); | 229 | ieee80211_configure_filter(local); |
234 | netif_addr_unlock_bh(local->mdev); | 230 | spin_unlock_bh(&local->filter_lock); |
235 | break; | 231 | break; |
236 | default: | 232 | default: |
237 | conf.vif = &sdata->vif; | 233 | conf.vif = &sdata->vif; |
@@ -243,9 +239,9 @@ static int ieee80211_open(struct net_device *dev) | |||
243 | 239 | ||
244 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 240 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
245 | local->fif_other_bss++; | 241 | local->fif_other_bss++; |
246 | netif_addr_lock_bh(local->mdev); | 242 | spin_lock_bh(&local->filter_lock); |
247 | ieee80211_configure_filter(local); | 243 | ieee80211_configure_filter(local); |
248 | netif_addr_unlock_bh(local->mdev); | 244 | spin_unlock_bh(&local->filter_lock); |
249 | 245 | ||
250 | ieee80211_start_mesh(sdata); | 246 | ieee80211_start_mesh(sdata); |
251 | } | 247 | } |
@@ -279,10 +275,6 @@ static int ieee80211_open(struct net_device *dev) | |||
279 | } | 275 | } |
280 | 276 | ||
281 | if (local->open_count == 0) { | 277 | if (local->open_count == 0) { |
282 | res = dev_open(local->mdev); | ||
283 | WARN_ON(res); | ||
284 | if (res) | ||
285 | goto err_del_interface; | ||
286 | tasklet_enable(&local->tx_pending_tasklet); | 278 | tasklet_enable(&local->tx_pending_tasklet); |
287 | tasklet_enable(&local->tasklet); | 279 | tasklet_enable(&local->tasklet); |
288 | } | 280 | } |
@@ -393,7 +385,14 @@ static int ieee80211_stop(struct net_device *dev) | |||
393 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 385 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
394 | atomic_dec(&local->iff_promiscs); | 386 | atomic_dec(&local->iff_promiscs); |
395 | 387 | ||
396 | dev_mc_unsync(local->mdev, dev); | 388 | netif_addr_lock_bh(dev); |
389 | spin_lock_bh(&local->filter_lock); | ||
390 | __dev_addr_unsync(&local->mc_list, &local->mc_count, | ||
391 | &dev->mc_list, &dev->mc_count); | ||
392 | ieee80211_configure_filter(local); | ||
393 | spin_unlock_bh(&local->filter_lock); | ||
394 | netif_addr_unlock_bh(dev); | ||
395 | |||
397 | del_timer_sync(&local->dynamic_ps_timer); | 396 | del_timer_sync(&local->dynamic_ps_timer); |
398 | cancel_work_sync(&local->dynamic_ps_enable_work); | 397 | cancel_work_sync(&local->dynamic_ps_enable_work); |
399 | 398 | ||
@@ -442,23 +441,25 @@ static int ieee80211_stop(struct net_device *dev) | |||
442 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | 441 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) |
443 | local->fif_other_bss--; | 442 | local->fif_other_bss--; |
444 | 443 | ||
445 | netif_addr_lock_bh(local->mdev); | 444 | spin_lock_bh(&local->filter_lock); |
446 | ieee80211_configure_filter(local); | 445 | ieee80211_configure_filter(local); |
447 | netif_addr_unlock_bh(local->mdev); | 446 | spin_unlock_bh(&local->filter_lock); |
448 | break; | 447 | break; |
449 | case NL80211_IFTYPE_STATION: | 448 | case NL80211_IFTYPE_STATION: |
450 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 449 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
451 | del_timer_sync(&sdata->u.mgd.timer); | 450 | del_timer_sync(&sdata->u.mgd.timer); |
451 | del_timer_sync(&sdata->u.mgd.conn_mon_timer); | ||
452 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); | ||
452 | /* | 453 | /* |
453 | * If the timer fired while we waited for it, it will have | 454 | * If any of the timers fired while we waited for it, it will |
454 | * requeued the work. Now the work will be running again | 455 | * have queued its work. Now the work will be running again |
455 | * but will not rearm the timer again because it checks | 456 | * but will not rearm the timer again because it checks |
456 | * whether the interface is running, which, at this point, | 457 | * whether the interface is running, which, at this point, |
457 | * it no longer is. | 458 | * it no longer is. |
458 | */ | 459 | */ |
459 | cancel_work_sync(&sdata->u.mgd.work); | 460 | cancel_work_sync(&sdata->u.mgd.work); |
460 | cancel_work_sync(&sdata->u.mgd.chswitch_work); | 461 | cancel_work_sync(&sdata->u.mgd.chswitch_work); |
461 | 462 | cancel_work_sync(&sdata->u.mgd.monitor_work); | |
462 | cancel_work_sync(&sdata->u.mgd.beacon_loss_work); | 463 | cancel_work_sync(&sdata->u.mgd.beacon_loss_work); |
463 | 464 | ||
464 | /* | 465 | /* |
@@ -485,9 +486,9 @@ static int ieee80211_stop(struct net_device *dev) | |||
485 | local->fif_other_bss--; | 486 | local->fif_other_bss--; |
486 | atomic_dec(&local->iff_allmultis); | 487 | atomic_dec(&local->iff_allmultis); |
487 | 488 | ||
488 | netif_addr_lock_bh(local->mdev); | 489 | spin_lock_bh(&local->filter_lock); |
489 | ieee80211_configure_filter(local); | 490 | ieee80211_configure_filter(local); |
490 | netif_addr_unlock_bh(local->mdev); | 491 | spin_unlock_bh(&local->filter_lock); |
491 | 492 | ||
492 | ieee80211_stop_mesh(sdata); | 493 | ieee80211_stop_mesh(sdata); |
493 | } | 494 | } |
@@ -533,9 +534,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
533 | ieee80211_recalc_ps(local, -1); | 534 | ieee80211_recalc_ps(local, -1); |
534 | 535 | ||
535 | if (local->open_count == 0) { | 536 | if (local->open_count == 0) { |
536 | if (netif_running(local->mdev)) | ||
537 | dev_close(local->mdev); | ||
538 | |||
539 | drv_stop(local); | 537 | drv_stop(local); |
540 | 538 | ||
541 | ieee80211_led_radio(local, false); | 539 | ieee80211_led_radio(local, false); |
@@ -582,8 +580,11 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
582 | atomic_dec(&local->iff_promiscs); | 580 | atomic_dec(&local->iff_promiscs); |
583 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 581 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
584 | } | 582 | } |
585 | 583 | spin_lock_bh(&local->filter_lock); | |
586 | dev_mc_sync(local->mdev, dev); | 584 | __dev_addr_sync(&local->mc_list, &local->mc_count, |
585 | &dev->mc_list, &dev->mc_count); | ||
586 | ieee80211_configure_filter(local); | ||
587 | spin_unlock_bh(&local->filter_lock); | ||
587 | } | 588 | } |
588 | 589 | ||
589 | /* | 590 | /* |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5b69f5f07299..3234f3751d22 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -83,75 +83,14 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
83 | new_flags |= (1<<31); | 83 | new_flags |= (1<<31); |
84 | 84 | ||
85 | drv_configure_filter(local, changed_flags, &new_flags, | 85 | drv_configure_filter(local, changed_flags, &new_flags, |
86 | local->mdev->mc_count, | 86 | local->mc_count, |
87 | local->mdev->mc_list); | 87 | local->mc_list); |
88 | 88 | ||
89 | WARN_ON(new_flags & (1<<31)); | 89 | WARN_ON(new_flags & (1<<31)); |
90 | 90 | ||
91 | local->filter_flags = new_flags & ~(1<<31); | 91 | local->filter_flags = new_flags & ~(1<<31); |
92 | } | 92 | } |
93 | 93 | ||
94 | /* master interface */ | ||
95 | |||
96 | static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | ||
97 | { | ||
98 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ | ||
99 | return ETH_ALEN; | ||
100 | } | ||
101 | |||
102 | static const struct header_ops ieee80211_header_ops = { | ||
103 | .create = eth_header, | ||
104 | .parse = header_parse_80211, | ||
105 | .rebuild = eth_rebuild_header, | ||
106 | .cache = eth_header_cache, | ||
107 | .cache_update = eth_header_cache_update, | ||
108 | }; | ||
109 | |||
110 | static int ieee80211_master_open(struct net_device *dev) | ||
111 | { | ||
112 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
113 | struct ieee80211_local *local = mpriv->local; | ||
114 | struct ieee80211_sub_if_data *sdata; | ||
115 | int res = -EOPNOTSUPP; | ||
116 | |||
117 | /* we hold the RTNL here so can safely walk the list */ | ||
118 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
119 | if (netif_running(sdata->dev)) { | ||
120 | res = 0; | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (res) | ||
126 | return res; | ||
127 | |||
128 | netif_tx_start_all_queues(local->mdev); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int ieee80211_master_stop(struct net_device *dev) | ||
134 | { | ||
135 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
136 | struct ieee80211_local *local = mpriv->local; | ||
137 | struct ieee80211_sub_if_data *sdata; | ||
138 | |||
139 | /* we hold the RTNL here so can safely walk the list */ | ||
140 | list_for_each_entry(sdata, &local->interfaces, list) | ||
141 | if (netif_running(sdata->dev)) | ||
142 | dev_close(sdata->dev); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | ||
148 | { | ||
149 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
150 | struct ieee80211_local *local = mpriv->local; | ||
151 | |||
152 | ieee80211_configure_filter(local); | ||
153 | } | ||
154 | |||
155 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 94 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
156 | { | 95 | { |
157 | struct ieee80211_channel *chan, *scan_chan; | 96 | struct ieee80211_channel *chan, *scan_chan; |
@@ -310,7 +249,6 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | |||
310 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 249 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
311 | int tmp; | 250 | int tmp; |
312 | 251 | ||
313 | skb->dev = local->mdev; | ||
314 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; | 252 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; |
315 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? | 253 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? |
316 | &local->skb_queue : &local->skb_queue_unreliable, skb); | 254 | &local->skb_queue : &local->skb_queue_unreliable, skb); |
@@ -716,7 +654,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
716 | mutex_init(&local->scan_mtx); | 654 | mutex_init(&local->scan_mtx); |
717 | 655 | ||
718 | spin_lock_init(&local->key_lock); | 656 | spin_lock_init(&local->key_lock); |
719 | 657 | spin_lock_init(&local->filter_lock); | |
720 | spin_lock_init(&local->queue_stop_reason_lock); | 658 | spin_lock_init(&local->queue_stop_reason_lock); |
721 | 659 | ||
722 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 660 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
@@ -752,30 +690,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
752 | } | 690 | } |
753 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 691 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
754 | 692 | ||
755 | static const struct net_device_ops ieee80211_master_ops = { | ||
756 | .ndo_start_xmit = ieee80211_master_start_xmit, | ||
757 | .ndo_open = ieee80211_master_open, | ||
758 | .ndo_stop = ieee80211_master_stop, | ||
759 | .ndo_set_multicast_list = ieee80211_master_set_multicast_list, | ||
760 | .ndo_select_queue = ieee80211_select_queue, | ||
761 | }; | ||
762 | |||
763 | static void ieee80211_master_setup(struct net_device *mdev) | ||
764 | { | ||
765 | mdev->type = ARPHRD_IEEE80211; | ||
766 | mdev->netdev_ops = &ieee80211_master_ops; | ||
767 | mdev->header_ops = &ieee80211_header_ops; | ||
768 | mdev->tx_queue_len = 1000; | ||
769 | mdev->addr_len = ETH_ALEN; | ||
770 | } | ||
771 | |||
772 | int ieee80211_register_hw(struct ieee80211_hw *hw) | 693 | int ieee80211_register_hw(struct ieee80211_hw *hw) |
773 | { | 694 | { |
774 | struct ieee80211_local *local = hw_to_local(hw); | 695 | struct ieee80211_local *local = hw_to_local(hw); |
775 | int result; | 696 | int result; |
776 | enum ieee80211_band band; | 697 | enum ieee80211_band band; |
777 | struct net_device *mdev; | ||
778 | struct ieee80211_master_priv *mpriv; | ||
779 | int channels, i, j, max_bitrates; | 698 | int channels, i, j, max_bitrates; |
780 | bool supp_ht; | 699 | bool supp_ht; |
781 | static const u32 cipher_suites[] = { | 700 | static const u32 cipher_suites[] = { |
@@ -874,16 +793,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
874 | if (hw->queues > IEEE80211_MAX_QUEUES) | 793 | if (hw->queues > IEEE80211_MAX_QUEUES) |
875 | hw->queues = IEEE80211_MAX_QUEUES; | 794 | hw->queues = IEEE80211_MAX_QUEUES; |
876 | 795 | ||
877 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), | ||
878 | "wmaster%d", ieee80211_master_setup, | ||
879 | hw->queues); | ||
880 | if (!mdev) | ||
881 | goto fail_mdev_alloc; | ||
882 | |||
883 | mpriv = netdev_priv(mdev); | ||
884 | mpriv->local = local; | ||
885 | local->mdev = mdev; | ||
886 | |||
887 | local->hw.workqueue = | 796 | local->hw.workqueue = |
888 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); | 797 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); |
889 | if (!local->hw.workqueue) { | 798 | if (!local->hw.workqueue) { |
@@ -918,17 +827,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
918 | } | 827 | } |
919 | 828 | ||
920 | rtnl_lock(); | 829 | rtnl_lock(); |
921 | result = dev_alloc_name(local->mdev, local->mdev->name); | ||
922 | if (result < 0) | ||
923 | goto fail_dev; | ||
924 | |||
925 | memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | ||
926 | SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy)); | ||
927 | local->mdev->features |= NETIF_F_NETNS_LOCAL; | ||
928 | |||
929 | result = register_netdevice(local->mdev); | ||
930 | if (result < 0) | ||
931 | goto fail_dev; | ||
932 | 830 | ||
933 | result = ieee80211_init_rate_ctrl_alg(local, | 831 | result = ieee80211_init_rate_ctrl_alg(local, |
934 | hw->rate_control_algorithm); | 832 | hw->rate_control_algorithm); |
@@ -981,9 +879,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
981 | ieee80211_led_exit(local); | 879 | ieee80211_led_exit(local); |
982 | ieee80211_remove_interfaces(local); | 880 | ieee80211_remove_interfaces(local); |
983 | fail_rate: | 881 | fail_rate: |
984 | unregister_netdevice(local->mdev); | ||
985 | local->mdev = NULL; | ||
986 | fail_dev: | ||
987 | rtnl_unlock(); | 882 | rtnl_unlock(); |
988 | ieee80211_wep_free(local); | 883 | ieee80211_wep_free(local); |
989 | fail_wep: | 884 | fail_wep: |
@@ -992,9 +887,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
992 | debugfs_hw_del(local); | 887 | debugfs_hw_del(local); |
993 | destroy_workqueue(local->hw.workqueue); | 888 | destroy_workqueue(local->hw.workqueue); |
994 | fail_workqueue: | 889 | fail_workqueue: |
995 | if (local->mdev) | ||
996 | free_netdev(local->mdev); | ||
997 | fail_mdev_alloc: | ||
998 | wiphy_unregister(local->hw.wiphy); | 890 | wiphy_unregister(local->hw.wiphy); |
999 | fail_wiphy_register: | 891 | fail_wiphy_register: |
1000 | kfree(local->int_scan_req.channels); | 892 | kfree(local->int_scan_req.channels); |
@@ -1019,13 +911,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1019 | * because the driver cannot be handing us frames any | 911 | * because the driver cannot be handing us frames any |
1020 | * more and the tasklet is killed. | 912 | * more and the tasklet is killed. |
1021 | */ | 913 | */ |
1022 | |||
1023 | /* First, we remove all virtual interfaces. */ | ||
1024 | ieee80211_remove_interfaces(local); | 914 | ieee80211_remove_interfaces(local); |
1025 | 915 | ||
1026 | /* then, finally, remove the master interface */ | ||
1027 | unregister_netdevice(local->mdev); | ||
1028 | |||
1029 | rtnl_unlock(); | 916 | rtnl_unlock(); |
1030 | 917 | ||
1031 | ieee80211_clear_tx_pending(local); | 918 | ieee80211_clear_tx_pending(local); |
@@ -1044,7 +931,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1044 | wiphy_unregister(local->hw.wiphy); | 931 | wiphy_unregister(local->hw.wiphy); |
1045 | ieee80211_wep_free(local); | 932 | ieee80211_wep_free(local); |
1046 | ieee80211_led_exit(local); | 933 | ieee80211_led_exit(local); |
1047 | free_netdev(local->mdev); | ||
1048 | kfree(local->int_scan_req.channels); | 934 | kfree(local->int_scan_req.channels); |
1049 | } | 935 | } |
1050 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 936 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 542ea025494e..8a97b1423088 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -685,9 +685,12 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
685 | fc = le16_to_cpu(mgmt->frame_control); | 685 | fc = le16_to_cpu(mgmt->frame_control); |
686 | 686 | ||
687 | switch (fc & IEEE80211_FCTL_STYPE) { | 687 | switch (fc & IEEE80211_FCTL_STYPE) { |
688 | case IEEE80211_STYPE_ACTION: | ||
689 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
690 | return RX_DROP_MONITOR; | ||
691 | /* fall through */ | ||
688 | case IEEE80211_STYPE_PROBE_RESP: | 692 | case IEEE80211_STYPE_PROBE_RESP: |
689 | case IEEE80211_STYPE_BEACON: | 693 | case IEEE80211_STYPE_BEACON: |
690 | case IEEE80211_STYPE_ACTION: | ||
691 | skb_queue_tail(&ifmsh->skb_queue, skb); | 694 | skb_queue_tail(&ifmsh->skb_queue, skb); |
692 | queue_work(local->hw.workqueue, &ifmsh->work); | 695 | queue_work(local->hw.workqueue, &ifmsh->work); |
693 | return RX_QUEUED; | 696 | return RX_QUEUED; |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index f49ef288e2e2..e93c37ef6a48 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -686,11 +686,11 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
686 | u8 ttl, dst_flags; | 686 | u8 ttl, dst_flags; |
687 | u32 lifetime; | 687 | u32 lifetime; |
688 | 688 | ||
689 | spin_lock(&ifmsh->mesh_preq_queue_lock); | 689 | spin_lock_bh(&ifmsh->mesh_preq_queue_lock); |
690 | if (!ifmsh->preq_queue_len || | 690 | if (!ifmsh->preq_queue_len || |
691 | time_before(jiffies, ifmsh->last_preq + | 691 | time_before(jiffies, ifmsh->last_preq + |
692 | min_preq_int_jiff(sdata))) { | 692 | min_preq_int_jiff(sdata))) { |
693 | spin_unlock(&ifmsh->mesh_preq_queue_lock); | 693 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
694 | return; | 694 | return; |
695 | } | 695 | } |
696 | 696 | ||
@@ -698,7 +698,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
698 | struct mesh_preq_queue, list); | 698 | struct mesh_preq_queue, list); |
699 | list_del(&preq_node->list); | 699 | list_del(&preq_node->list); |
700 | --ifmsh->preq_queue_len; | 700 | --ifmsh->preq_queue_len; |
701 | spin_unlock(&ifmsh->mesh_preq_queue_lock); | 701 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
702 | 702 | ||
703 | rcu_read_lock(); | 703 | rcu_read_lock(); |
704 | mpath = mesh_path_lookup(preq_node->dst, sdata); | 704 | mpath = mesh_path_lookup(preq_node->dst, sdata); |
@@ -784,7 +784,6 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
784 | mesh_path_add(dst_addr, sdata); | 784 | mesh_path_add(dst_addr, sdata); |
785 | mpath = mesh_path_lookup(dst_addr, sdata); | 785 | mpath = mesh_path_lookup(dst_addr, sdata); |
786 | if (!mpath) { | 786 | if (!mpath) { |
787 | dev_kfree_skb(skb); | ||
788 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 787 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
789 | err = -ENOSPC; | 788 | err = -ENOSPC; |
790 | goto endlookup; | 789 | goto endlookup; |
@@ -804,6 +803,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
804 | memcpy(hdr->addr1, mpath->next_hop->sta.addr, | 803 | memcpy(hdr->addr1, mpath->next_hop->sta.addr, |
805 | ETH_ALEN); | 804 | ETH_ALEN); |
806 | } else { | 805 | } else { |
806 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
807 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | 807 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { |
808 | /* Start discovery only if it is not running yet */ | 808 | /* Start discovery only if it is not running yet */ |
809 | mesh_queue_preq(mpath, PREQ_Q_F_START); | 809 | mesh_queue_preq(mpath, PREQ_Q_F_START); |
@@ -815,6 +815,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
815 | skb_unlink(skb_to_free, &mpath->frame_queue); | 815 | skb_unlink(skb_to_free, &mpath->frame_queue); |
816 | } | 816 | } |
817 | 817 | ||
818 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
818 | skb_queue_tail(&mpath->frame_queue, skb); | 819 | skb_queue_tail(&mpath->frame_queue, skb); |
819 | if (skb_to_free) | 820 | if (skb_to_free) |
820 | mesh_path_discard_frame(skb_to_free, sdata); | 821 | mesh_path_discard_frame(skb_to_free, sdata); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 479597e88583..04b9e4d61b8e 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -55,7 +55,25 @@ static DEFINE_RWLOCK(pathtbl_resize_lock); | |||
55 | */ | 55 | */ |
56 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | 56 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) |
57 | { | 57 | { |
58 | struct sk_buff *skb; | ||
59 | struct ieee80211_hdr *hdr; | ||
60 | struct sk_buff_head tmpq; | ||
61 | unsigned long flags; | ||
62 | |||
58 | rcu_assign_pointer(mpath->next_hop, sta); | 63 | rcu_assign_pointer(mpath->next_hop, sta); |
64 | |||
65 | __skb_queue_head_init(&tmpq); | ||
66 | |||
67 | spin_lock_irqsave(&mpath->frame_queue.lock, flags); | ||
68 | |||
69 | while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { | ||
70 | hdr = (struct ieee80211_hdr *) skb->data; | ||
71 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); | ||
72 | __skb_queue_tail(&tmpq, skb); | ||
73 | } | ||
74 | |||
75 | skb_queue_splice(&tmpq, &mpath->frame_queue); | ||
76 | spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); | ||
59 | } | 77 | } |
60 | 78 | ||
61 | 79 | ||
@@ -481,11 +499,9 @@ enddel: | |||
481 | */ | 499 | */ |
482 | void mesh_path_tx_pending(struct mesh_path *mpath) | 500 | void mesh_path_tx_pending(struct mesh_path *mpath) |
483 | { | 501 | { |
484 | struct sk_buff *skb; | 502 | if (mpath->flags & MESH_PATH_ACTIVE) |
485 | 503 | ieee80211_add_pending_skbs(mpath->sdata->local, | |
486 | while ((skb = skb_dequeue(&mpath->frame_queue)) && | 504 | &mpath->frame_queue); |
487 | (mpath->flags & MESH_PATH_ACTIVE)) | ||
488 | dev_queue_xmit(skb); | ||
489 | } | 505 | } |
490 | 506 | ||
491 | /** | 507 | /** |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c9db9646025b..523c0d994d15 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -31,8 +31,23 @@ | |||
31 | #define IEEE80211_AUTH_MAX_TRIES 3 | 31 | #define IEEE80211_AUTH_MAX_TRIES 3 |
32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
33 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 33 | #define IEEE80211_ASSOC_MAX_TRIES 3 |
34 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) | 34 | |
35 | #define IEEE80211_PROBE_WAIT (HZ / 5) | 35 | /* |
36 | * beacon loss detection timeout | ||
37 | * XXX: should depend on beacon interval | ||
38 | */ | ||
39 | #define IEEE80211_BEACON_LOSS_TIME (2 * HZ) | ||
40 | /* | ||
41 | * Time the connection can be idle before we probe | ||
42 | * it to see if we can still talk to the AP. | ||
43 | */ | ||
44 | #define IEEE80211_CONNECTION_IDLE_TIME (2 * HZ) | ||
45 | /* | ||
46 | * Time we wait for a probe response after sending | ||
47 | * a probe request because of beacon loss or for | ||
48 | * checking the connection still works. | ||
49 | */ | ||
50 | #define IEEE80211_PROBE_WAIT (HZ / 5) | ||
36 | 51 | ||
37 | #define TMR_RUNNING_TIMER 0 | 52 | #define TMR_RUNNING_TIMER 0 |
38 | #define TMR_RUNNING_CHANSW 1 | 53 | #define TMR_RUNNING_CHANSW 1 |
@@ -72,6 +87,35 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) | |||
72 | WARN_ON(!mutex_is_locked(&ifmgd->mtx)); | 87 | WARN_ON(!mutex_is_locked(&ifmgd->mtx)); |
73 | } | 88 | } |
74 | 89 | ||
90 | /* | ||
91 | * We can have multiple work items (and connection probing) | ||
92 | * scheduling this timer, but we need to take care to only | ||
93 | * reschedule it when it should fire _earlier_ than it was | ||
94 | * asked for before, or if it's not pending right now. This | ||
95 | * function ensures that. Note that it then is required to | ||
96 | * run this function for all timeouts after the first one | ||
97 | * has happened -- the work that runs from this timer will | ||
98 | * do that. | ||
99 | */ | ||
100 | static void run_again(struct ieee80211_if_managed *ifmgd, | ||
101 | unsigned long timeout) | ||
102 | { | ||
103 | ASSERT_MGD_MTX(ifmgd); | ||
104 | |||
105 | if (!timer_pending(&ifmgd->timer) || | ||
106 | time_before(timeout, ifmgd->timer.expires)) | ||
107 | mod_timer(&ifmgd->timer, timeout); | ||
108 | } | ||
109 | |||
110 | static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) | ||
111 | { | ||
112 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) | ||
113 | return; | ||
114 | |||
115 | mod_timer(&sdata->u.mgd.bcn_mon_timer, | ||
116 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); | ||
117 | } | ||
118 | |||
75 | static int ecw2cw(int ecw) | 119 | static int ecw2cw(int ecw) |
76 | { | 120 | { |
77 | return (1 << ecw) - 1; | 121 | return (1 << ecw) - 1; |
@@ -646,7 +690,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
646 | 690 | ||
647 | if (count == 1 && found->u.mgd.powersave && | 691 | if (count == 1 && found->u.mgd.powersave && |
648 | found->u.mgd.associated && list_empty(&found->u.mgd.work_list) && | 692 | found->u.mgd.associated && list_empty(&found->u.mgd.work_list) && |
649 | !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) { | 693 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | |
694 | IEEE80211_STA_CONNECTION_POLL))) { | ||
650 | s32 beaconint_us; | 695 | s32 beaconint_us; |
651 | 696 | ||
652 | if (latency < 0) | 697 | if (latency < 0) |
@@ -852,6 +897,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
852 | sdata->u.mgd.associated = bss; | 897 | sdata->u.mgd.associated = bss; |
853 | memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); | 898 | memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); |
854 | 899 | ||
900 | /* just to be sure */ | ||
901 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
902 | IEEE80211_STA_BEACON_POLL); | ||
903 | |||
855 | ieee80211_led_assoc(local, 1); | 904 | ieee80211_led_assoc(local, 1); |
856 | 905 | ||
857 | sdata->vif.bss_conf.assoc = 1; | 906 | sdata->vif.bss_conf.assoc = 1; |
@@ -916,7 +965,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
916 | ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); | 965 | ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); |
917 | 966 | ||
918 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 967 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
919 | mod_timer(&ifmgd->timer, wk->timeout); | 968 | run_again(ifmgd, wk->timeout); |
920 | 969 | ||
921 | return RX_MGMT_NONE; | 970 | return RX_MGMT_NONE; |
922 | } | 971 | } |
@@ -954,25 +1003,30 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
954 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); | 1003 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); |
955 | 1004 | ||
956 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, | 1005 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, |
957 | wk->bss->cbss.bssid, 0); | 1006 | wk->bss->cbss.bssid, NULL, 0, 0); |
958 | wk->auth_transaction = 2; | 1007 | wk->auth_transaction = 2; |
959 | 1008 | ||
960 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 1009 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
961 | mod_timer(&ifmgd->timer, wk->timeout); | 1010 | run_again(ifmgd, wk->timeout); |
962 | 1011 | ||
963 | return RX_MGMT_NONE; | 1012 | return RX_MGMT_NONE; |
964 | } | 1013 | } |
965 | 1014 | ||
966 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | 1015 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) |
967 | const u8 *bssid, bool deauth) | ||
968 | { | 1016 | { |
969 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1017 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
970 | struct ieee80211_local *local = sdata->local; | 1018 | struct ieee80211_local *local = sdata->local; |
971 | struct sta_info *sta; | 1019 | struct sta_info *sta; |
972 | u32 changed = 0, config_changed = 0; | 1020 | u32 changed = 0, config_changed = 0; |
1021 | u8 bssid[ETH_ALEN]; | ||
973 | 1022 | ||
974 | ASSERT_MGD_MTX(ifmgd); | 1023 | ASSERT_MGD_MTX(ifmgd); |
975 | 1024 | ||
1025 | if (WARN_ON(!ifmgd->associated)) | ||
1026 | return; | ||
1027 | |||
1028 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | ||
1029 | |||
976 | ifmgd->associated = NULL; | 1030 | ifmgd->associated = NULL; |
977 | memset(ifmgd->bssid, 0, ETH_ALEN); | 1031 | memset(ifmgd->bssid, 0, ETH_ALEN); |
978 | 1032 | ||
@@ -1079,7 +1133,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
1079 | ieee80211_send_assoc(sdata, wk); | 1133 | ieee80211_send_assoc(sdata, wk); |
1080 | 1134 | ||
1081 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 1135 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
1082 | mod_timer(&ifmgd->timer, wk->timeout); | 1136 | run_again(ifmgd, wk->timeout); |
1083 | 1137 | ||
1084 | return RX_MGMT_NONE; | 1138 | return RX_MGMT_NONE; |
1085 | } | 1139 | } |
@@ -1092,31 +1146,24 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
1092 | * from AP because we know that the connection is working both ways | 1146 | * from AP because we know that the connection is working both ways |
1093 | * at that time. But multicast frames (and hence also beacons) must | 1147 | * at that time. But multicast frames (and hence also beacons) must |
1094 | * be ignored here, because we need to trigger the timer during | 1148 | * be ignored here, because we need to trigger the timer during |
1095 | * data idle periods for sending the periodical probe request to | 1149 | * data idle periods for sending the periodic probe request to the |
1096 | * the AP. | 1150 | * AP we're connected to. |
1097 | */ | 1151 | */ |
1098 | if (!is_multicast_ether_addr(hdr->addr1)) | 1152 | if (is_multicast_ether_addr(hdr->addr1)) |
1099 | mod_timer(&sdata->u.mgd.timer, | 1153 | return; |
1100 | jiffies + IEEE80211_MONITORING_INTERVAL); | 1154 | |
1155 | mod_timer(&sdata->u.mgd.conn_mon_timer, | ||
1156 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | ||
1101 | } | 1157 | } |
1102 | 1158 | ||
1103 | void ieee80211_beacon_loss_work(struct work_struct *work) | 1159 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, |
1160 | bool beacon) | ||
1104 | { | 1161 | { |
1105 | struct ieee80211_sub_if_data *sdata = | ||
1106 | container_of(work, struct ieee80211_sub_if_data, | ||
1107 | u.mgd.beacon_loss_work); | ||
1108 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1162 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1109 | const u8 *ssid; | 1163 | const u8 *ssid; |
1164 | bool already = false; | ||
1110 | 1165 | ||
1111 | /* | 1166 | if (!netif_running(sdata->dev)) |
1112 | * The driver has already reported this event and we have | ||
1113 | * already sent a probe request. Maybe the AP died and the | ||
1114 | * driver keeps reporting until we disassociate... We have | ||
1115 | * to ignore that because otherwise we would continually | ||
1116 | * reset the timer and never check whether we received a | ||
1117 | * probe response! | ||
1118 | */ | ||
1119 | if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) | ||
1120 | return; | 1167 | return; |
1121 | 1168 | ||
1122 | mutex_lock(&ifmgd->mtx); | 1169 | mutex_lock(&ifmgd->mtx); |
@@ -1125,12 +1172,35 @@ void ieee80211_beacon_loss_work(struct work_struct *work) | |||
1125 | goto out; | 1172 | goto out; |
1126 | 1173 | ||
1127 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1174 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1128 | if (net_ratelimit()) | 1175 | if (beacon && net_ratelimit()) |
1129 | printk(KERN_DEBUG "%s: driver reports beacon loss from AP " | 1176 | printk(KERN_DEBUG "%s: detected beacon loss from AP " |
1130 | "- sending probe request\n", sdata->dev->name); | 1177 | "- sending probe request\n", sdata->dev->name); |
1131 | #endif | 1178 | #endif |
1132 | 1179 | ||
1133 | ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; | 1180 | /* |
1181 | * The driver/our work has already reported this event or the | ||
1182 | * connection monitoring has kicked in and we have already sent | ||
1183 | * a probe request. Or maybe the AP died and the driver keeps | ||
1184 | * reporting until we disassociate... | ||
1185 | * | ||
1186 | * In either case we have to ignore the current call to this | ||
1187 | * function (except for setting the correct probe reason bit) | ||
1188 | * because otherwise we would reset the timer every time and | ||
1189 | * never check whether we received a probe response! | ||
1190 | */ | ||
1191 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | ||
1192 | IEEE80211_STA_CONNECTION_POLL)) | ||
1193 | already = true; | ||
1194 | |||
1195 | if (beacon) | ||
1196 | ifmgd->flags |= IEEE80211_STA_BEACON_POLL; | ||
1197 | else | ||
1198 | ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL; | ||
1199 | |||
1200 | if (already) | ||
1201 | goto out; | ||
1202 | |||
1203 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | ||
1134 | 1204 | ||
1135 | mutex_lock(&sdata->local->iflist_mtx); | 1205 | mutex_lock(&sdata->local->iflist_mtx); |
1136 | ieee80211_recalc_ps(sdata->local, -1); | 1206 | ieee80211_recalc_ps(sdata->local, -1); |
@@ -1140,11 +1210,21 @@ void ieee80211_beacon_loss_work(struct work_struct *work) | |||
1140 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, | 1210 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, |
1141 | ssid + 2, ssid[1], NULL, 0); | 1211 | ssid + 2, ssid[1], NULL, 0); |
1142 | 1212 | ||
1143 | mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT); | 1213 | run_again(ifmgd, ifmgd->probe_timeout); |
1214 | |||
1144 | out: | 1215 | out: |
1145 | mutex_unlock(&ifmgd->mtx); | 1216 | mutex_unlock(&ifmgd->mtx); |
1146 | } | 1217 | } |
1147 | 1218 | ||
1219 | void ieee80211_beacon_loss_work(struct work_struct *work) | ||
1220 | { | ||
1221 | struct ieee80211_sub_if_data *sdata = | ||
1222 | container_of(work, struct ieee80211_sub_if_data, | ||
1223 | u.mgd.beacon_loss_work); | ||
1224 | |||
1225 | ieee80211_mgd_probe_ap(sdata, true); | ||
1226 | } | ||
1227 | |||
1148 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) | 1228 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) |
1149 | { | 1229 | { |
1150 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1230 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
@@ -1176,7 +1256,8 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | |||
1176 | return; | 1256 | return; |
1177 | ieee80211_send_auth(sdata, 3, wk->auth_alg, | 1257 | ieee80211_send_auth(sdata, 3, wk->auth_alg, |
1178 | elems.challenge - 2, elems.challenge_len + 2, | 1258 | elems.challenge - 2, elems.challenge_len + 2, |
1179 | wk->bss->cbss.bssid, 1); | 1259 | wk->bss->cbss.bssid, |
1260 | wk->key, wk->key_len, wk->key_idx); | ||
1180 | wk->auth_transaction = 4; | 1261 | wk->auth_transaction = 4; |
1181 | } | 1262 | } |
1182 | 1263 | ||
@@ -1257,7 +1338,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1257 | sdata->dev->name, bssid, reason_code); | 1338 | sdata->dev->name, bssid, reason_code); |
1258 | 1339 | ||
1259 | if (!wk) { | 1340 | if (!wk) { |
1260 | ieee80211_set_disassoc(sdata, bssid, true); | 1341 | ieee80211_set_disassoc(sdata); |
1261 | } else { | 1342 | } else { |
1262 | list_del(&wk->list); | 1343 | list_del(&wk->list); |
1263 | kfree(wk); | 1344 | kfree(wk); |
@@ -1290,7 +1371,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1290 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", | 1371 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", |
1291 | sdata->dev->name, reason_code); | 1372 | sdata->dev->name, reason_code); |
1292 | 1373 | ||
1293 | ieee80211_set_disassoc(sdata, ifmgd->associated->cbss.bssid, false); | 1374 | ieee80211_set_disassoc(sdata); |
1294 | return RX_MGMT_CFG80211_DISASSOC; | 1375 | return RX_MGMT_CFG80211_DISASSOC; |
1295 | } | 1376 | } |
1296 | 1377 | ||
@@ -1349,8 +1430,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1349 | sdata->dev->name, tu, ms); | 1430 | sdata->dev->name, tu, ms); |
1350 | wk->timeout = jiffies + msecs_to_jiffies(ms); | 1431 | wk->timeout = jiffies + msecs_to_jiffies(ms); |
1351 | if (ms > IEEE80211_ASSOC_TIMEOUT) | 1432 | if (ms > IEEE80211_ASSOC_TIMEOUT) |
1352 | mod_timer(&ifmgd->timer, | 1433 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); |
1353 | jiffies + msecs_to_jiffies(ms)); | ||
1354 | return RX_MGMT_NONE; | 1434 | return RX_MGMT_NONE; |
1355 | } | 1435 | } |
1356 | 1436 | ||
@@ -1392,9 +1472,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1392 | return RX_MGMT_NONE; | 1472 | return RX_MGMT_NONE; |
1393 | } | 1473 | } |
1394 | 1474 | ||
1395 | /* update new sta with its last rx activity */ | ||
1396 | sta->last_rx = jiffies; | ||
1397 | |||
1398 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | 1475 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | |
1399 | WLAN_STA_ASSOC_AP); | 1476 | WLAN_STA_ASSOC_AP); |
1400 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 1477 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
@@ -1497,10 +1574,11 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1497 | ieee80211_set_associated(sdata, wk->bss, changed); | 1574 | ieee80211_set_associated(sdata, wk->bss, changed); |
1498 | 1575 | ||
1499 | /* | 1576 | /* |
1500 | * initialise the time of last beacon to be the association time, | 1577 | * Start timer to probe the connection to the AP now. |
1501 | * otherwise beacon loss check will trigger immediately | 1578 | * Also start the timer that will detect beacon loss. |
1502 | */ | 1579 | */ |
1503 | ifmgd->last_beacon = jiffies; | 1580 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
1581 | mod_beacon_timer(sdata); | ||
1504 | 1582 | ||
1505 | list_del(&wk->list); | 1583 | list_del(&wk->list); |
1506 | kfree(wk); | 1584 | kfree(wk); |
@@ -1584,11 +1662,22 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1584 | 1662 | ||
1585 | if (ifmgd->associated && | 1663 | if (ifmgd->associated && |
1586 | memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && | 1664 | memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && |
1587 | ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { | 1665 | ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
1588 | ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | 1666 | IEEE80211_STA_CONNECTION_POLL)) { |
1667 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1668 | IEEE80211_STA_BEACON_POLL); | ||
1589 | mutex_lock(&sdata->local->iflist_mtx); | 1669 | mutex_lock(&sdata->local->iflist_mtx); |
1590 | ieee80211_recalc_ps(sdata->local, -1); | 1670 | ieee80211_recalc_ps(sdata->local, -1); |
1591 | mutex_unlock(&sdata->local->iflist_mtx); | 1671 | mutex_unlock(&sdata->local->iflist_mtx); |
1672 | /* | ||
1673 | * We've received a probe response, but are not sure whether | ||
1674 | * we have or will be receiving any beacons or data, so let's | ||
1675 | * schedule the timers again, just in case. | ||
1676 | */ | ||
1677 | mod_beacon_timer(sdata); | ||
1678 | mod_timer(&ifmgd->conn_mon_timer, | ||
1679 | round_jiffies_up(jiffies + | ||
1680 | IEEE80211_CONNECTION_IDLE_TIME)); | ||
1592 | } | 1681 | } |
1593 | } | 1682 | } |
1594 | 1683 | ||
@@ -1638,27 +1727,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1638 | if (rx_status->freq != local->hw.conf.channel->center_freq) | 1727 | if (rx_status->freq != local->hw.conf.channel->center_freq) |
1639 | return; | 1728 | return; |
1640 | 1729 | ||
1641 | if (WARN_ON(!ifmgd->associated)) | 1730 | /* |
1731 | * We might have received a number of frames, among them a | ||
1732 | * disassoc frame and a beacon... | ||
1733 | */ | ||
1734 | if (!ifmgd->associated) | ||
1642 | return; | 1735 | return; |
1643 | 1736 | ||
1644 | bssid = ifmgd->associated->cbss.bssid; | 1737 | bssid = ifmgd->associated->cbss.bssid; |
1645 | 1738 | ||
1646 | if (WARN_ON(memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)) | 1739 | /* |
1740 | * And in theory even frames from a different AP we were just | ||
1741 | * associated to a split-second ago! | ||
1742 | */ | ||
1743 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) | ||
1647 | return; | 1744 | return; |
1648 | 1745 | ||
1649 | if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { | 1746 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { |
1650 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1747 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1651 | if (net_ratelimit()) { | 1748 | if (net_ratelimit()) { |
1652 | printk(KERN_DEBUG "%s: cancelling probereq poll due " | 1749 | printk(KERN_DEBUG "%s: cancelling probereq poll due " |
1653 | "to a received beacon\n", sdata->dev->name); | 1750 | "to a received beacon\n", sdata->dev->name); |
1654 | } | 1751 | } |
1655 | #endif | 1752 | #endif |
1656 | ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | 1753 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; |
1657 | mutex_lock(&local->iflist_mtx); | 1754 | mutex_lock(&local->iflist_mtx); |
1658 | ieee80211_recalc_ps(local, -1); | 1755 | ieee80211_recalc_ps(local, -1); |
1659 | mutex_unlock(&local->iflist_mtx); | 1756 | mutex_unlock(&local->iflist_mtx); |
1660 | } | 1757 | } |
1661 | 1758 | ||
1759 | /* | ||
1760 | * Push the beacon loss detection into the future since | ||
1761 | * we are processing a beacon from the AP just now. | ||
1762 | */ | ||
1763 | mod_beacon_timer(sdata); | ||
1764 | |||
1662 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); | 1765 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); |
1663 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, | 1766 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, |
1664 | len - baselen, &elems, | 1767 | len - baselen, &elems, |
@@ -1960,6 +2063,37 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1960 | /* then process the rest of the work */ | 2063 | /* then process the rest of the work */ |
1961 | mutex_lock(&ifmgd->mtx); | 2064 | mutex_lock(&ifmgd->mtx); |
1962 | 2065 | ||
2066 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | ||
2067 | IEEE80211_STA_CONNECTION_POLL) && | ||
2068 | ifmgd->associated) { | ||
2069 | if (time_is_after_jiffies(ifmgd->probe_timeout)) | ||
2070 | run_again(ifmgd, ifmgd->probe_timeout); | ||
2071 | else { | ||
2072 | u8 bssid[ETH_ALEN]; | ||
2073 | /* | ||
2074 | * We actually lost the connection ... or did we? | ||
2075 | * Let's make sure! | ||
2076 | */ | ||
2077 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
2078 | IEEE80211_STA_BEACON_POLL); | ||
2079 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | ||
2080 | printk(KERN_DEBUG "No probe response from AP %pM" | ||
2081 | " after %dms, disconnecting.\n", | ||
2082 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | ||
2083 | ieee80211_set_disassoc(sdata); | ||
2084 | mutex_unlock(&ifmgd->mtx); | ||
2085 | /* | ||
2086 | * must be outside lock due to cfg80211, | ||
2087 | * but that's not a problem. | ||
2088 | */ | ||
2089 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
2090 | IEEE80211_STYPE_DEAUTH, | ||
2091 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
2092 | NULL); | ||
2093 | mutex_lock(&ifmgd->mtx); | ||
2094 | } | ||
2095 | } | ||
2096 | |||
1963 | list_for_each_entry(wk, &ifmgd->work_list, list) { | 2097 | list_for_each_entry(wk, &ifmgd->work_list, list) { |
1964 | if (wk->state != IEEE80211_MGD_STATE_IDLE) { | 2098 | if (wk->state != IEEE80211_MGD_STATE_IDLE) { |
1965 | anybusy = true; | 2099 | anybusy = true; |
@@ -1980,8 +2114,15 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1980 | } | 2114 | } |
1981 | 2115 | ||
1982 | list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { | 2116 | list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { |
1983 | if (time_before(jiffies, wk->timeout)) | 2117 | if (time_is_after_jiffies(wk->timeout)) { |
2118 | /* | ||
2119 | * This work item isn't supposed to be worked on | ||
2120 | * right now, but take care to adjust the timer | ||
2121 | * properly. | ||
2122 | */ | ||
2123 | run_again(ifmgd, wk->timeout); | ||
1984 | continue; | 2124 | continue; |
2125 | } | ||
1985 | 2126 | ||
1986 | switch (wk->state) { | 2127 | switch (wk->state) { |
1987 | default: | 2128 | default: |
@@ -2040,15 +2181,54 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2040 | ieee80211_recalc_idle(local); | 2181 | ieee80211_recalc_idle(local); |
2041 | } | 2182 | } |
2042 | 2183 | ||
2184 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) | ||
2185 | { | ||
2186 | struct ieee80211_sub_if_data *sdata = | ||
2187 | (struct ieee80211_sub_if_data *) data; | ||
2188 | struct ieee80211_local *local = sdata->local; | ||
2189 | |||
2190 | if (local->quiescing) | ||
2191 | return; | ||
2192 | |||
2193 | queue_work(sdata->local->hw.workqueue, | ||
2194 | &sdata->u.mgd.beacon_loss_work); | ||
2195 | } | ||
2196 | |||
2197 | static void ieee80211_sta_conn_mon_timer(unsigned long data) | ||
2198 | { | ||
2199 | struct ieee80211_sub_if_data *sdata = | ||
2200 | (struct ieee80211_sub_if_data *) data; | ||
2201 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2202 | struct ieee80211_local *local = sdata->local; | ||
2203 | |||
2204 | if (local->quiescing) | ||
2205 | return; | ||
2206 | |||
2207 | queue_work(local->hw.workqueue, &ifmgd->monitor_work); | ||
2208 | } | ||
2209 | |||
2210 | static void ieee80211_sta_monitor_work(struct work_struct *work) | ||
2211 | { | ||
2212 | struct ieee80211_sub_if_data *sdata = | ||
2213 | container_of(work, struct ieee80211_sub_if_data, | ||
2214 | u.mgd.monitor_work); | ||
2215 | |||
2216 | if (sdata->local->sw_scanning || sdata->local->hw_scanning) | ||
2217 | return; | ||
2218 | |||
2219 | ieee80211_mgd_probe_ap(sdata, false); | ||
2220 | } | ||
2221 | |||
2043 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | 2222 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) |
2044 | { | 2223 | { |
2045 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 2224 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
2046 | /* | 2225 | sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | |
2047 | * Need to update last_beacon to avoid beacon loss | 2226 | IEEE80211_STA_CONNECTION_POLL); |
2048 | * test to trigger. | ||
2049 | */ | ||
2050 | sdata->u.mgd.last_beacon = jiffies; | ||
2051 | 2227 | ||
2228 | /* let's probe the connection once */ | ||
2229 | queue_work(sdata->local->hw.workqueue, | ||
2230 | &sdata->u.mgd.monitor_work); | ||
2231 | /* and do all the other regular work too */ | ||
2052 | queue_work(sdata->local->hw.workqueue, | 2232 | queue_work(sdata->local->hw.workqueue, |
2053 | &sdata->u.mgd.work); | 2233 | &sdata->u.mgd.work); |
2054 | } | 2234 | } |
@@ -2073,6 +2253,11 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
2073 | cancel_work_sync(&ifmgd->chswitch_work); | 2253 | cancel_work_sync(&ifmgd->chswitch_work); |
2074 | if (del_timer_sync(&ifmgd->chswitch_timer)) | 2254 | if (del_timer_sync(&ifmgd->chswitch_timer)) |
2075 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); | 2255 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); |
2256 | |||
2257 | cancel_work_sync(&ifmgd->monitor_work); | ||
2258 | /* these will just be re-established on connection */ | ||
2259 | del_timer_sync(&ifmgd->conn_mon_timer); | ||
2260 | del_timer_sync(&ifmgd->bcn_mon_timer); | ||
2076 | } | 2261 | } |
2077 | 2262 | ||
2078 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | 2263 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) |
@@ -2093,10 +2278,15 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2093 | 2278 | ||
2094 | ifmgd = &sdata->u.mgd; | 2279 | ifmgd = &sdata->u.mgd; |
2095 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); | 2280 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); |
2281 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); | ||
2096 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 2282 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
2097 | INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); | 2283 | INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); |
2098 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 2284 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
2099 | (unsigned long) sdata); | 2285 | (unsigned long) sdata); |
2286 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | ||
2287 | (unsigned long) sdata); | ||
2288 | setup_timer(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, | ||
2289 | (unsigned long) sdata); | ||
2100 | setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, | 2290 | setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, |
2101 | (unsigned long) sdata); | 2291 | (unsigned long) sdata); |
2102 | skb_queue_head_init(&ifmgd->skb_queue); | 2292 | skb_queue_head_init(&ifmgd->skb_queue); |
@@ -2175,6 +2365,12 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2175 | wk->ie_len = req->ie_len; | 2365 | wk->ie_len = req->ie_len; |
2176 | } | 2366 | } |
2177 | 2367 | ||
2368 | if (req->key && req->key_len) { | ||
2369 | wk->key_len = req->key_len; | ||
2370 | wk->key_idx = req->key_idx; | ||
2371 | memcpy(wk->key, req->key, req->key_len); | ||
2372 | } | ||
2373 | |||
2178 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 2374 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); |
2179 | memcpy(wk->ssid, ssid + 2, ssid[1]); | 2375 | memcpy(wk->ssid, ssid + 2, ssid[1]); |
2180 | wk->ssid_len = ssid[1]; | 2376 | wk->ssid_len = ssid[1]; |
@@ -2290,7 +2486,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2290 | 2486 | ||
2291 | if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { | 2487 | if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { |
2292 | bssid = req->bss->bssid; | 2488 | bssid = req->bss->bssid; |
2293 | ieee80211_set_disassoc(sdata, bssid, true); | 2489 | ieee80211_set_disassoc(sdata); |
2294 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { | 2490 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { |
2295 | if (&wk->bss->cbss == req->bss) { | 2491 | if (&wk->bss->cbss == req->bss) { |
2296 | bssid = req->bss->bssid; | 2492 | bssid = req->bss->bssid; |
@@ -2332,7 +2528,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2332 | return -ENOLINK; | 2528 | return -ENOLINK; |
2333 | } | 2529 | } |
2334 | 2530 | ||
2335 | ieee80211_set_disassoc(sdata, req->bss->bssid, false); | 2531 | ieee80211_set_disassoc(sdata); |
2336 | 2532 | ||
2337 | mutex_unlock(&ifmgd->mtx); | 2533 | mutex_unlock(&ifmgd->mtx); |
2338 | 2534 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 4641f00a1e5c..b33efc4fc267 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -198,6 +198,35 @@ static void rate_control_release(struct kref *kref) | |||
198 | kfree(ctrl_ref); | 198 | kfree(ctrl_ref); |
199 | } | 199 | } |
200 | 200 | ||
201 | static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) | ||
202 | { | ||
203 | struct sk_buff *skb = txrc->skb; | ||
204 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
205 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
206 | __le16 fc; | ||
207 | |||
208 | fc = hdr->frame_control; | ||
209 | |||
210 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); | ||
211 | } | ||
212 | |||
213 | bool rate_control_send_low(struct ieee80211_sta *sta, | ||
214 | void *priv_sta, | ||
215 | struct ieee80211_tx_rate_control *txrc) | ||
216 | { | ||
217 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | ||
218 | |||
219 | if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { | ||
220 | info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); | ||
221 | info->control.rates[0].count = | ||
222 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | ||
223 | 1 : txrc->hw->max_rate_tries; | ||
224 | return true; | ||
225 | } | ||
226 | return false; | ||
227 | } | ||
228 | EXPORT_SYMBOL(rate_control_send_low); | ||
229 | |||
201 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 230 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
202 | struct sta_info *sta, | 231 | struct sta_info *sta, |
203 | struct ieee80211_tx_rate_control *txrc) | 232 | struct ieee80211_tx_rate_control *txrc) |
@@ -258,7 +287,7 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
258 | struct rate_control_ref *ref, *old; | 287 | struct rate_control_ref *ref, *old; |
259 | 288 | ||
260 | ASSERT_RTNL(); | 289 | ASSERT_RTNL(); |
261 | if (local->open_count || netif_running(local->mdev)) | 290 | if (local->open_count) |
262 | return -EBUSY; | 291 | return -EBUSY; |
263 | 292 | ||
264 | ref = rate_control_alloc(name, local); | 293 | ref = rate_control_alloc(name, local); |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 37771abd8f5a..7c5142988bbb 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -70,20 +70,6 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) | |||
70 | return i; | 70 | return i; |
71 | } | 71 | } |
72 | 72 | ||
73 | static inline bool | ||
74 | use_low_rate(struct sk_buff *skb) | ||
75 | { | ||
76 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
77 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
78 | u16 fc; | ||
79 | |||
80 | fc = le16_to_cpu(hdr->frame_control); | ||
81 | |||
82 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || | ||
83 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA); | ||
84 | } | ||
85 | |||
86 | |||
87 | static void | 73 | static void |
88 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | 74 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) |
89 | { | 75 | { |
@@ -232,7 +218,6 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
232 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) | 218 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) |
233 | { | 219 | { |
234 | struct sk_buff *skb = txrc->skb; | 220 | struct sk_buff *skb = txrc->skb; |
235 | struct ieee80211_supported_band *sband = txrc->sband; | ||
236 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 221 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
237 | struct minstrel_sta_info *mi = priv_sta; | 222 | struct minstrel_sta_info *mi = priv_sta; |
238 | struct minstrel_priv *mp = priv; | 223 | struct minstrel_priv *mp = priv; |
@@ -245,14 +230,8 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
245 | int mrr_ndx[3]; | 230 | int mrr_ndx[3]; |
246 | int sample_rate; | 231 | int sample_rate; |
247 | 232 | ||
248 | if (!sta || !mi || use_low_rate(skb)) { | 233 | if (rate_control_send_low(sta, priv_sta, txrc)) |
249 | ar[0].idx = rate_lowest_index(sband, sta); | ||
250 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
251 | ar[0].count = 1; | ||
252 | else | ||
253 | ar[0].count = mp->max_retry; | ||
254 | return; | 234 | return; |
255 | } | ||
256 | 235 | ||
257 | mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; | 236 | mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; |
258 | 237 | ||
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index a0bef767ceb5..8c053be9dc24 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -276,11 +276,9 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, | |||
276 | { | 276 | { |
277 | struct sk_buff *skb = txrc->skb; | 277 | struct sk_buff *skb = txrc->skb; |
278 | struct ieee80211_supported_band *sband = txrc->sband; | 278 | struct ieee80211_supported_band *sband = txrc->sband; |
279 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
280 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 279 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
281 | struct rc_pid_sta_info *spinfo = priv_sta; | 280 | struct rc_pid_sta_info *spinfo = priv_sta; |
282 | int rateidx; | 281 | int rateidx; |
283 | u16 fc; | ||
284 | 282 | ||
285 | if (txrc->rts) | 283 | if (txrc->rts) |
286 | info->control.rates[0].count = | 284 | info->control.rates[0].count = |
@@ -290,16 +288,8 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, | |||
290 | txrc->hw->conf.short_frame_max_tx_count; | 288 | txrc->hw->conf.short_frame_max_tx_count; |
291 | 289 | ||
292 | /* Send management frames and NO_ACK data using lowest rate. */ | 290 | /* Send management frames and NO_ACK data using lowest rate. */ |
293 | fc = le16_to_cpu(hdr->frame_control); | 291 | if (rate_control_send_low(sta, priv_sta, txrc)) |
294 | if (!sta || !spinfo || | ||
295 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | ||
296 | info->flags & IEEE80211_TX_CTL_NO_ACK) { | ||
297 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | ||
298 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
299 | info->control.rates[0].count = 1; | ||
300 | |||
301 | return; | 292 | return; |
302 | } | ||
303 | 293 | ||
304 | rateidx = spinfo->txrate_idx; | 294 | rateidx = spinfo->txrate_idx; |
305 | 295 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fe6b99059531..66c797cc85ce 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -833,28 +833,22 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
833 | if (!sta) | 833 | if (!sta) |
834 | return RX_CONTINUE; | 834 | return RX_CONTINUE; |
835 | 835 | ||
836 | /* Update last_rx only for IBSS packets which are for the current | 836 | /* |
837 | * BSSID to avoid keeping the current IBSS network alive in cases where | 837 | * Update last_rx only for IBSS packets which are for the current |
838 | * other STAs are using different BSSID. */ | 838 | * BSSID to avoid keeping the current IBSS network alive in cases |
839 | * where other STAs start using different BSSID. | ||
840 | */ | ||
839 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 841 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
840 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, | 842 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, |
841 | NL80211_IFTYPE_ADHOC); | 843 | NL80211_IFTYPE_ADHOC); |
842 | if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) | 844 | if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) |
843 | sta->last_rx = jiffies; | 845 | sta->last_rx = jiffies; |
844 | } else | 846 | } else if (!is_multicast_ether_addr(hdr->addr1)) { |
845 | if (!is_multicast_ether_addr(hdr->addr1) || | 847 | /* |
846 | rx->sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
847 | /* Update last_rx only for unicast frames in order to prevent | ||
848 | * the Probe Request frames (the only broadcast frames from a | ||
849 | * STA in infrastructure mode) from keeping a connection alive. | ||
850 | * Mesh beacons will update last_rx when if they are found to | 848 | * Mesh beacons will update last_rx when if they are found to |
851 | * match the current local configuration when processed. | 849 | * match the current local configuration when processed. |
852 | */ | 850 | */ |
853 | if (rx->sdata->vif.type == NL80211_IFTYPE_STATION && | 851 | sta->last_rx = jiffies; |
854 | ieee80211_is_beacon(hdr->frame_control)) { | ||
855 | rx->sdata->u.mgd.last_beacon = jiffies; | ||
856 | } else | ||
857 | sta->last_rx = jiffies; | ||
858 | } | 852 | } |
859 | 853 | ||
860 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 854 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
@@ -1484,10 +1478,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1484 | struct ieee80211s_hdr *mesh_hdr; | 1478 | struct ieee80211s_hdr *mesh_hdr; |
1485 | unsigned int hdrlen; | 1479 | unsigned int hdrlen; |
1486 | struct sk_buff *skb = rx->skb, *fwd_skb; | 1480 | struct sk_buff *skb = rx->skb, *fwd_skb; |
1481 | struct ieee80211_local *local = rx->local; | ||
1482 | struct ieee80211_sub_if_data *sdata; | ||
1487 | 1483 | ||
1488 | hdr = (struct ieee80211_hdr *) skb->data; | 1484 | hdr = (struct ieee80211_hdr *) skb->data; |
1489 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1485 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1490 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1486 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1487 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1491 | 1488 | ||
1492 | if (!ieee80211_is_data(hdr->frame_control)) | 1489 | if (!ieee80211_is_data(hdr->frame_control)) |
1493 | return RX_CONTINUE; | 1490 | return RX_CONTINUE; |
@@ -1497,10 +1494,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1497 | return RX_DROP_MONITOR; | 1494 | return RX_DROP_MONITOR; |
1498 | 1495 | ||
1499 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | 1496 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ |
1500 | struct ieee80211_sub_if_data *sdata; | ||
1501 | struct mesh_path *mppath; | 1497 | struct mesh_path *mppath; |
1502 | 1498 | ||
1503 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1504 | rcu_read_lock(); | 1499 | rcu_read_lock(); |
1505 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | 1500 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); |
1506 | if (!mppath) { | 1501 | if (!mppath) { |
@@ -1526,6 +1521,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1526 | dropped_frames_ttl); | 1521 | dropped_frames_ttl); |
1527 | else { | 1522 | else { |
1528 | struct ieee80211_hdr *fwd_hdr; | 1523 | struct ieee80211_hdr *fwd_hdr; |
1524 | struct ieee80211_tx_info *info; | ||
1525 | |||
1529 | fwd_skb = skb_copy(skb, GFP_ATOMIC); | 1526 | fwd_skb = skb_copy(skb, GFP_ATOMIC); |
1530 | 1527 | ||
1531 | if (!fwd_skb && net_ratelimit()) | 1528 | if (!fwd_skb && net_ratelimit()) |
@@ -1539,9 +1536,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1539 | */ | 1536 | */ |
1540 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); | 1537 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); |
1541 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); | 1538 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); |
1542 | fwd_skb->dev = rx->local->mdev; | 1539 | info = IEEE80211_SKB_CB(fwd_skb); |
1540 | memset(info, 0, sizeof(*info)); | ||
1541 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
1543 | fwd_skb->iif = rx->dev->ifindex; | 1542 | fwd_skb->iif = rx->dev->ifindex; |
1544 | dev_queue_xmit(fwd_skb); | 1543 | ieee80211_select_queue(local, fwd_skb); |
1544 | if (is_multicast_ether_addr(fwd_hdr->addr3)) | ||
1545 | memcpy(fwd_hdr->addr1, fwd_hdr->addr3, | ||
1546 | ETH_ALEN); | ||
1547 | else { | ||
1548 | int err = mesh_nexthop_lookup(fwd_skb, sdata); | ||
1549 | /* Failed to immediately resolve next hop: | ||
1550 | * fwded frame was dropped or will be added | ||
1551 | * later to the pending skb queue. */ | ||
1552 | if (err) | ||
1553 | return RX_DROP_MONITOR; | ||
1554 | } | ||
1555 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1556 | fwded_frames); | ||
1557 | ieee80211_add_pending_skb(local, fwd_skb); | ||
1545 | } | 1558 | } |
1546 | } | 1559 | } |
1547 | 1560 | ||
@@ -1809,8 +1822,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
1809 | return RX_DROP_MONITOR; | 1822 | return RX_DROP_MONITOR; |
1810 | } | 1823 | } |
1811 | 1824 | ||
1812 | static void ieee80211_rx_michael_mic_report(struct net_device *dev, | 1825 | static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, |
1813 | struct ieee80211_hdr *hdr, | ||
1814 | struct ieee80211_rx_data *rx) | 1826 | struct ieee80211_rx_data *rx) |
1815 | { | 1827 | { |
1816 | int keyidx; | 1828 | int keyidx; |
@@ -2120,7 +2132,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2120 | } | 2132 | } |
2121 | 2133 | ||
2122 | if ((status->flag & RX_FLAG_MMIC_ERROR)) { | 2134 | if ((status->flag & RX_FLAG_MMIC_ERROR)) { |
2123 | ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx); | 2135 | ieee80211_rx_michael_mic_report(hdr, &rx); |
2124 | return; | 2136 | return; |
2125 | } | 2137 | } |
2126 | 2138 | ||
@@ -2489,7 +2501,6 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2489 | 2501 | ||
2490 | BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); | 2502 | BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); |
2491 | 2503 | ||
2492 | skb->dev = local->mdev; | ||
2493 | skb->pkt_type = IEEE80211_RX_MSG; | 2504 | skb->pkt_type = IEEE80211_RX_MSG; |
2494 | skb_queue_tail(&local->skb_queue, skb); | 2505 | skb_queue_tail(&local->skb_queue, skb); |
2495 | tasklet_schedule(&local->tasklet); | 2506 | tasklet_schedule(&local->tasklet); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 5f4f7869d050..74820656dc89 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -294,16 +294,13 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
294 | if (was_hw_scan) | 294 | if (was_hw_scan) |
295 | goto done; | 295 | goto done; |
296 | 296 | ||
297 | netif_tx_lock_bh(local->mdev); | 297 | spin_lock_bh(&local->filter_lock); |
298 | netif_addr_lock(local->mdev); | ||
299 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | 298 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; |
300 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | 299 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, |
301 | &local->filter_flags, | 300 | &local->filter_flags, |
302 | local->mdev->mc_count, | 301 | local->mc_count, |
303 | local->mdev->mc_list); | 302 | local->mc_list); |
304 | 303 | spin_unlock_bh(&local->filter_lock); | |
305 | netif_addr_unlock(local->mdev); | ||
306 | netif_tx_unlock_bh(local->mdev); | ||
307 | 304 | ||
308 | drv_sw_scan_complete(local); | 305 | drv_sw_scan_complete(local); |
309 | 306 | ||
@@ -382,13 +379,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
382 | local->scan_state = SCAN_SET_CHANNEL; | 379 | local->scan_state = SCAN_SET_CHANNEL; |
383 | local->scan_channel_idx = 0; | 380 | local->scan_channel_idx = 0; |
384 | 381 | ||
385 | netif_addr_lock_bh(local->mdev); | 382 | spin_lock_bh(&local->filter_lock); |
386 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | 383 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; |
387 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | 384 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, |
388 | &local->filter_flags, | 385 | &local->filter_flags, |
389 | local->mdev->mc_count, | 386 | local->mc_count, |
390 | local->mdev->mc_list); | 387 | local->mc_list); |
391 | netif_addr_unlock_bh(local->mdev); | 388 | spin_unlock_bh(&local->filter_lock); |
392 | 389 | ||
393 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | 390 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ |
394 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | 391 | queue_delayed_work(local->hw.workqueue, &local->scan_work, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 60ae086995b1..2572509d5568 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -451,7 +451,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
451 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 451 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
452 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 452 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
453 | 453 | ||
454 | if (unlikely(tx->skb->do_not_encrypt)) | 454 | if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) |
455 | tx->key = NULL; | 455 | tx->key = NULL; |
456 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 456 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
457 | tx->key = key; | 457 | tx->key = key; |
@@ -497,7 +497,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
497 | } | 497 | } |
498 | 498 | ||
499 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 499 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
500 | tx->skb->do_not_encrypt = 1; | 500 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
501 | 501 | ||
502 | return TX_CONTINUE; | 502 | return TX_CONTINUE; |
503 | } | 503 | } |
@@ -512,6 +512,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
512 | int i, len; | 512 | int i, len; |
513 | bool inval = false, rts = false, short_preamble = false; | 513 | bool inval = false, rts = false, short_preamble = false; |
514 | struct ieee80211_tx_rate_control txrc; | 514 | struct ieee80211_tx_rate_control txrc; |
515 | u32 sta_flags; | ||
515 | 516 | ||
516 | memset(&txrc, 0, sizeof(txrc)); | 517 | memset(&txrc, 0, sizeof(txrc)); |
517 | 518 | ||
@@ -544,7 +545,26 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
544 | (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) | 545 | (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) |
545 | txrc.short_preamble = short_preamble = true; | 546 | txrc.short_preamble = short_preamble = true; |
546 | 547 | ||
548 | sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; | ||
549 | |||
550 | /* | ||
551 | * Lets not bother rate control if we're associated and cannot | ||
552 | * talk to the sta. This should not happen. | ||
553 | */ | ||
554 | if (WARN((tx->local->sw_scanning) && | ||
555 | (sta_flags & WLAN_STA_ASSOC) && | ||
556 | !rate_usable_index_exists(sband, &tx->sta->sta), | ||
557 | "%s: Dropped data frame as no usable bitrate found while " | ||
558 | "scanning and associated. Target station: " | ||
559 | "%pM on %d GHz band\n", | ||
560 | tx->dev->name, hdr->addr1, | ||
561 | tx->channel->band ? 5 : 2)) | ||
562 | return TX_DROP; | ||
547 | 563 | ||
564 | /* | ||
565 | * If we're associated with the sta at this point we know we can at | ||
566 | * least send the frame at the lowest bit rate. | ||
567 | */ | ||
548 | rate_control_get_rate(tx->sdata, tx->sta, &txrc); | 568 | rate_control_get_rate(tx->sdata, tx->sta, &txrc); |
549 | 569 | ||
550 | if (unlikely(info->control.rates[0].idx < 0)) | 570 | if (unlikely(info->control.rates[0].idx < 0)) |
@@ -754,9 +774,7 @@ static int ieee80211_fragment(struct ieee80211_local *local, | |||
754 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); | 774 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); |
755 | skb_copy_queue_mapping(tmp, skb); | 775 | skb_copy_queue_mapping(tmp, skb); |
756 | tmp->priority = skb->priority; | 776 | tmp->priority = skb->priority; |
757 | tmp->do_not_encrypt = skb->do_not_encrypt; | ||
758 | tmp->dev = skb->dev; | 777 | tmp->dev = skb->dev; |
759 | tmp->iif = skb->iif; | ||
760 | 778 | ||
761 | /* copy header and data */ | 779 | /* copy header and data */ |
762 | memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen); | 780 | memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen); |
@@ -784,7 +802,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
784 | 802 | ||
785 | /* | 803 | /* |
786 | * Warn when submitting a fragmented A-MPDU frame and drop it. | 804 | * Warn when submitting a fragmented A-MPDU frame and drop it. |
787 | * This scenario is handled in __ieee80211_tx_prepare but extra | 805 | * This scenario is handled in ieee80211_tx_prepare but extra |
788 | * caution taken here as fragmented ampdu may cause Tx stop. | 806 | * caution taken here as fragmented ampdu may cause Tx stop. |
789 | */ | 807 | */ |
790 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) | 808 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
@@ -923,11 +941,12 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
923 | struct ieee80211_radiotap_header *rthdr = | 941 | struct ieee80211_radiotap_header *rthdr = |
924 | (struct ieee80211_radiotap_header *) skb->data; | 942 | (struct ieee80211_radiotap_header *) skb->data; |
925 | struct ieee80211_supported_band *sband; | 943 | struct ieee80211_supported_band *sband; |
944 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
926 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | 945 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); |
927 | 946 | ||
928 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 947 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
929 | 948 | ||
930 | skb->do_not_encrypt = 1; | 949 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
931 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 950 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
932 | 951 | ||
933 | /* | 952 | /* |
@@ -965,7 +984,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
965 | skb_trim(skb, skb->len - FCS_LEN); | 984 | skb_trim(skb, skb->len - FCS_LEN); |
966 | } | 985 | } |
967 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | 986 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) |
968 | tx->skb->do_not_encrypt = 0; | 987 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; |
969 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | 988 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) |
970 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 989 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
971 | break; | 990 | break; |
@@ -998,13 +1017,12 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
998 | * initialises @tx | 1017 | * initialises @tx |
999 | */ | 1018 | */ |
1000 | static ieee80211_tx_result | 1019 | static ieee80211_tx_result |
1001 | __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 1020 | ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, |
1002 | struct sk_buff *skb, | 1021 | struct ieee80211_tx_data *tx, |
1003 | struct net_device *dev) | 1022 | struct sk_buff *skb) |
1004 | { | 1023 | { |
1005 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1024 | struct ieee80211_local *local = sdata->local; |
1006 | struct ieee80211_hdr *hdr; | 1025 | struct ieee80211_hdr *hdr; |
1007 | struct ieee80211_sub_if_data *sdata; | ||
1008 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1026 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1009 | int hdrlen, tid; | 1027 | int hdrlen, tid; |
1010 | u8 *qc, *state; | 1028 | u8 *qc, *state; |
@@ -1012,9 +1030,9 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1012 | 1030 | ||
1013 | memset(tx, 0, sizeof(*tx)); | 1031 | memset(tx, 0, sizeof(*tx)); |
1014 | tx->skb = skb; | 1032 | tx->skb = skb; |
1015 | tx->dev = dev; /* use original interface */ | 1033 | tx->dev = sdata->dev; /* use original interface */ |
1016 | tx->local = local; | 1034 | tx->local = local; |
1017 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1035 | tx->sdata = sdata; |
1018 | tx->channel = local->hw.conf.channel; | 1036 | tx->channel = local->hw.conf.channel; |
1019 | /* | 1037 | /* |
1020 | * Set this flag (used below to indicate "automatic fragmentation"), | 1038 | * Set this flag (used below to indicate "automatic fragmentation"), |
@@ -1023,7 +1041,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1023 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 1041 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
1024 | 1042 | ||
1025 | /* process and remove the injection radiotap header */ | 1043 | /* process and remove the injection radiotap header */ |
1026 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1027 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { | 1044 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { |
1028 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) | 1045 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) |
1029 | return TX_DROP; | 1046 | return TX_DROP; |
@@ -1119,50 +1136,28 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1119 | return TX_CONTINUE; | 1136 | return TX_CONTINUE; |
1120 | } | 1137 | } |
1121 | 1138 | ||
1122 | /* | ||
1123 | * NB: @tx is uninitialised when passed in here | ||
1124 | */ | ||
1125 | static int ieee80211_tx_prepare(struct ieee80211_local *local, | ||
1126 | struct ieee80211_tx_data *tx, | ||
1127 | struct sk_buff *skb) | ||
1128 | { | ||
1129 | struct net_device *dev; | ||
1130 | |||
1131 | dev = dev_get_by_index(&init_net, skb->iif); | ||
1132 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { | ||
1133 | dev_put(dev); | ||
1134 | dev = NULL; | ||
1135 | } | ||
1136 | if (unlikely(!dev)) | ||
1137 | return -ENODEV; | ||
1138 | /* | ||
1139 | * initialises tx with control | ||
1140 | * | ||
1141 | * return value is safe to ignore here because this function | ||
1142 | * can only be invoked for multicast frames | ||
1143 | * | ||
1144 | * XXX: clean up | ||
1145 | */ | ||
1146 | __ieee80211_tx_prepare(tx, skb, dev); | ||
1147 | dev_put(dev); | ||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static int __ieee80211_tx(struct ieee80211_local *local, | 1139 | static int __ieee80211_tx(struct ieee80211_local *local, |
1152 | struct sk_buff **skbp, | 1140 | struct sk_buff **skbp, |
1153 | struct sta_info *sta) | 1141 | struct sta_info *sta, |
1142 | bool txpending) | ||
1154 | { | 1143 | { |
1155 | struct sk_buff *skb = *skbp, *next; | 1144 | struct sk_buff *skb = *skbp, *next; |
1156 | struct ieee80211_tx_info *info; | 1145 | struct ieee80211_tx_info *info; |
1146 | unsigned long flags; | ||
1157 | int ret, len; | 1147 | int ret, len; |
1158 | bool fragm = false; | 1148 | bool fragm = false; |
1159 | 1149 | ||
1160 | local->mdev->trans_start = jiffies; | ||
1161 | |||
1162 | while (skb) { | 1150 | while (skb) { |
1163 | if (ieee80211_queue_stopped(&local->hw, | 1151 | int q = skb_get_queue_mapping(skb); |
1164 | skb_get_queue_mapping(skb))) | 1152 | |
1165 | return IEEE80211_TX_PENDING; | 1153 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1154 | ret = IEEE80211_TX_OK; | ||
1155 | if (local->queue_stop_reasons[q] || | ||
1156 | (!txpending && !skb_queue_empty(&local->pending[q]))) | ||
1157 | ret = IEEE80211_TX_PENDING; | ||
1158 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
1159 | if (ret != IEEE80211_TX_OK) | ||
1160 | return ret; | ||
1166 | 1161 | ||
1167 | info = IEEE80211_SKB_CB(skb); | 1162 | info = IEEE80211_SKB_CB(skb); |
1168 | 1163 | ||
@@ -1234,10 +1229,10 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1234 | return 0; | 1229 | return 0; |
1235 | } | 1230 | } |
1236 | 1231 | ||
1237 | static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | 1232 | static void ieee80211_tx(struct ieee80211_sub_if_data *sdata, |
1238 | bool txpending) | 1233 | struct sk_buff *skb, bool txpending) |
1239 | { | 1234 | { |
1240 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1235 | struct ieee80211_local *local = sdata->local; |
1241 | struct ieee80211_tx_data tx; | 1236 | struct ieee80211_tx_data tx; |
1242 | ieee80211_tx_result res_prepare; | 1237 | ieee80211_tx_result res_prepare; |
1243 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1238 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -1248,8 +1243,6 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1248 | 1243 | ||
1249 | queue = skb_get_queue_mapping(skb); | 1244 | queue = skb_get_queue_mapping(skb); |
1250 | 1245 | ||
1251 | WARN_ON(!txpending && !skb_queue_empty(&local->pending[queue])); | ||
1252 | |||
1253 | if (unlikely(skb->len < 10)) { | 1246 | if (unlikely(skb->len < 10)) { |
1254 | dev_kfree_skb(skb); | 1247 | dev_kfree_skb(skb); |
1255 | return; | 1248 | return; |
@@ -1258,7 +1251,7 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1258 | rcu_read_lock(); | 1251 | rcu_read_lock(); |
1259 | 1252 | ||
1260 | /* initialises tx */ | 1253 | /* initialises tx */ |
1261 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev); | 1254 | res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); |
1262 | 1255 | ||
1263 | if (unlikely(res_prepare == TX_DROP)) { | 1256 | if (unlikely(res_prepare == TX_DROP)) { |
1264 | dev_kfree_skb(skb); | 1257 | dev_kfree_skb(skb); |
@@ -1277,7 +1270,7 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1277 | 1270 | ||
1278 | retries = 0; | 1271 | retries = 0; |
1279 | retry: | 1272 | retry: |
1280 | ret = __ieee80211_tx(local, &tx.skb, tx.sta); | 1273 | ret = __ieee80211_tx(local, &tx.skb, tx.sta, txpending); |
1281 | switch (ret) { | 1274 | switch (ret) { |
1282 | case IEEE80211_TX_OK: | 1275 | case IEEE80211_TX_OK: |
1283 | break; | 1276 | break; |
@@ -1295,34 +1288,35 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1295 | 1288 | ||
1296 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1289 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1297 | 1290 | ||
1298 | if (__netif_subqueue_stopped(local->mdev, queue)) { | 1291 | if (local->queue_stop_reasons[queue] || |
1292 | !skb_queue_empty(&local->pending[queue])) { | ||
1293 | /* | ||
1294 | * if queue is stopped, queue up frames for later | ||
1295 | * transmission from the tasklet | ||
1296 | */ | ||
1299 | do { | 1297 | do { |
1300 | next = skb->next; | 1298 | next = skb->next; |
1301 | skb->next = NULL; | 1299 | skb->next = NULL; |
1302 | if (unlikely(txpending)) | 1300 | if (unlikely(txpending)) |
1303 | skb_queue_head(&local->pending[queue], | 1301 | __skb_queue_head(&local->pending[queue], |
1304 | skb); | 1302 | skb); |
1305 | else | 1303 | else |
1306 | skb_queue_tail(&local->pending[queue], | 1304 | __skb_queue_tail(&local->pending[queue], |
1307 | skb); | 1305 | skb); |
1308 | } while ((skb = next)); | 1306 | } while ((skb = next)); |
1309 | 1307 | ||
1310 | /* | ||
1311 | * Make sure nobody will enable the queue on us | ||
1312 | * (without going through the tasklet) nor disable the | ||
1313 | * netdev queue underneath the pending handling code. | ||
1314 | */ | ||
1315 | __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING, | ||
1316 | &local->queue_stop_reasons[queue]); | ||
1317 | |||
1318 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 1308 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
1319 | flags); | 1309 | flags); |
1320 | } else { | 1310 | } else { |
1311 | /* | ||
1312 | * otherwise retry, but this is a race condition or | ||
1313 | * a driver bug (which we warn about if it persists) | ||
1314 | */ | ||
1321 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 1315 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
1322 | flags); | 1316 | flags); |
1323 | 1317 | ||
1324 | retries++; | 1318 | retries++; |
1325 | if (WARN(retries > 10, "tx refused but queue active")) | 1319 | if (WARN(retries > 10, "tx refused but queue active\n")) |
1326 | goto drop; | 1320 | goto drop; |
1327 | goto retry; | 1321 | goto retry; |
1328 | } | 1322 | } |
@@ -1383,14 +1377,13 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1383 | return 0; | 1377 | return 0; |
1384 | } | 1378 | } |
1385 | 1379 | ||
1386 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | 1380 | static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, |
1381 | struct sk_buff *skb) | ||
1387 | { | 1382 | { |
1388 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | 1383 | struct ieee80211_local *local = sdata->local; |
1389 | struct ieee80211_local *local = mpriv->local; | ||
1390 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1384 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1391 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1385 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1392 | struct net_device *odev = NULL; | 1386 | struct ieee80211_sub_if_data *tmp_sdata; |
1393 | struct ieee80211_sub_if_data *osdata; | ||
1394 | int headroom; | 1387 | int headroom; |
1395 | bool may_encrypt; | 1388 | bool may_encrypt; |
1396 | enum { | 1389 | enum { |
@@ -1399,20 +1392,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1399 | UNKNOWN_ADDRESS, | 1392 | UNKNOWN_ADDRESS, |
1400 | } monitor_iface = NOT_MONITOR; | 1393 | } monitor_iface = NOT_MONITOR; |
1401 | 1394 | ||
1402 | if (skb->iif) | 1395 | dev_hold(sdata->dev); |
1403 | odev = dev_get_by_index(&init_net, skb->iif); | ||
1404 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { | ||
1405 | dev_put(odev); | ||
1406 | odev = NULL; | ||
1407 | } | ||
1408 | if (unlikely(!odev)) { | ||
1409 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1410 | printk(KERN_DEBUG "%s: Discarded packet with nonexistent " | ||
1411 | "originating device\n", dev->name); | ||
1412 | #endif | ||
1413 | dev_kfree_skb(skb); | ||
1414 | return NETDEV_TX_OK; | ||
1415 | } | ||
1416 | 1396 | ||
1417 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 1397 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
1418 | local->hw.conf.dynamic_ps_timeout > 0 && | 1398 | local->hw.conf.dynamic_ps_timeout > 0 && |
@@ -1428,26 +1408,18 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1428 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1408 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1429 | } | 1409 | } |
1430 | 1410 | ||
1431 | memset(info, 0, sizeof(*info)); | ||
1432 | |||
1433 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1411 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
1434 | 1412 | ||
1435 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); | 1413 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
1436 | |||
1437 | if (ieee80211_vif_is_mesh(&osdata->vif) && | ||
1438 | ieee80211_is_data(hdr->frame_control)) { | 1414 | ieee80211_is_data(hdr->frame_control)) { |
1439 | if (is_multicast_ether_addr(hdr->addr3)) | 1415 | if (is_multicast_ether_addr(hdr->addr3)) |
1440 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); | 1416 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); |
1441 | else | 1417 | else |
1442 | if (mesh_nexthop_lookup(skb, osdata)) { | 1418 | if (mesh_nexthop_lookup(skb, sdata)) { |
1443 | dev_put(odev); | 1419 | dev_put(sdata->dev); |
1444 | return NETDEV_TX_OK; | 1420 | return; |
1445 | } | 1421 | } |
1446 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) | 1422 | } else if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { |
1447 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, | ||
1448 | fwded_frames); | ||
1449 | } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { | ||
1450 | struct ieee80211_sub_if_data *sdata; | ||
1451 | int hdrlen; | 1423 | int hdrlen; |
1452 | u16 len_rthdr; | 1424 | u16 len_rthdr; |
1453 | 1425 | ||
@@ -1471,19 +1443,17 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1471 | */ | 1443 | */ |
1472 | 1444 | ||
1473 | rcu_read_lock(); | 1445 | rcu_read_lock(); |
1474 | list_for_each_entry_rcu(sdata, &local->interfaces, | 1446 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, |
1475 | list) { | 1447 | list) { |
1476 | if (!netif_running(sdata->dev)) | 1448 | if (!netif_running(tmp_sdata->dev)) |
1477 | continue; | 1449 | continue; |
1478 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 1450 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) |
1479 | continue; | 1451 | continue; |
1480 | if (compare_ether_addr(sdata->dev->dev_addr, | 1452 | if (compare_ether_addr(tmp_sdata->dev->dev_addr, |
1481 | hdr->addr2)) { | 1453 | hdr->addr2)) { |
1482 | dev_hold(sdata->dev); | 1454 | dev_hold(tmp_sdata->dev); |
1483 | dev_put(odev); | 1455 | dev_put(sdata->dev); |
1484 | osdata = sdata; | 1456 | sdata = tmp_sdata; |
1485 | odev = osdata->dev; | ||
1486 | skb->iif = sdata->dev->ifindex; | ||
1487 | monitor_iface = FOUND_SDATA; | 1457 | monitor_iface = FOUND_SDATA; |
1488 | break; | 1458 | break; |
1489 | } | 1459 | } |
@@ -1492,31 +1462,31 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1492 | } | 1462 | } |
1493 | } | 1463 | } |
1494 | 1464 | ||
1495 | may_encrypt = !skb->do_not_encrypt; | 1465 | may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); |
1496 | 1466 | ||
1497 | headroom = osdata->local->tx_headroom; | 1467 | headroom = local->tx_headroom; |
1498 | if (may_encrypt) | 1468 | if (may_encrypt) |
1499 | headroom += IEEE80211_ENCRYPT_HEADROOM; | 1469 | headroom += IEEE80211_ENCRYPT_HEADROOM; |
1500 | headroom -= skb_headroom(skb); | 1470 | headroom -= skb_headroom(skb); |
1501 | headroom = max_t(int, 0, headroom); | 1471 | headroom = max_t(int, 0, headroom); |
1502 | 1472 | ||
1503 | if (ieee80211_skb_resize(osdata->local, skb, headroom, may_encrypt)) { | 1473 | if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) { |
1504 | dev_kfree_skb(skb); | 1474 | dev_kfree_skb(skb); |
1505 | dev_put(odev); | 1475 | dev_put(sdata->dev); |
1506 | return NETDEV_TX_OK; | 1476 | return; |
1507 | } | 1477 | } |
1508 | 1478 | ||
1509 | if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1479 | tmp_sdata = sdata; |
1510 | osdata = container_of(osdata->bss, | 1480 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1511 | struct ieee80211_sub_if_data, | 1481 | tmp_sdata = container_of(sdata->bss, |
1512 | u.ap); | 1482 | struct ieee80211_sub_if_data, |
1483 | u.ap); | ||
1513 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) | 1484 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) |
1514 | info->control.vif = &osdata->vif; | 1485 | info->control.vif = &tmp_sdata->vif; |
1515 | |||
1516 | ieee80211_tx(odev, skb, false); | ||
1517 | dev_put(odev); | ||
1518 | 1486 | ||
1519 | return NETDEV_TX_OK; | 1487 | ieee80211_select_queue(local, skb); |
1488 | ieee80211_tx(sdata, skb, false); | ||
1489 | dev_put(sdata->dev); | ||
1520 | } | 1490 | } |
1521 | 1491 | ||
1522 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, | 1492 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, |
@@ -1526,6 +1496,7 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1526 | struct ieee80211_channel *chan = local->hw.conf.channel; | 1496 | struct ieee80211_channel *chan = local->hw.conf.channel; |
1527 | struct ieee80211_radiotap_header *prthdr = | 1497 | struct ieee80211_radiotap_header *prthdr = |
1528 | (struct ieee80211_radiotap_header *)skb->data; | 1498 | (struct ieee80211_radiotap_header *)skb->data; |
1499 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1529 | u16 len_rthdr; | 1500 | u16 len_rthdr; |
1530 | 1501 | ||
1531 | /* | 1502 | /* |
@@ -1563,15 +1534,9 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1563 | if (unlikely(skb->len < len_rthdr)) | 1534 | if (unlikely(skb->len < len_rthdr)) |
1564 | goto fail; /* skb too short for claimed rt header extent */ | 1535 | goto fail; /* skb too short for claimed rt header extent */ |
1565 | 1536 | ||
1566 | skb->dev = local->mdev; | ||
1567 | |||
1568 | /* needed because we set skb device to master */ | 1537 | /* needed because we set skb device to master */ |
1569 | skb->iif = dev->ifindex; | 1538 | skb->iif = dev->ifindex; |
1570 | 1539 | ||
1571 | /* sometimes we do encrypt injected frames, will be fixed | ||
1572 | * up in radiotap parser if not wanted */ | ||
1573 | skb->do_not_encrypt = 0; | ||
1574 | |||
1575 | /* | 1540 | /* |
1576 | * fix up the pointers accounting for the radiotap | 1541 | * fix up the pointers accounting for the radiotap |
1577 | * header still being in there. We are being given | 1542 | * header still being in there. We are being given |
@@ -1586,8 +1551,10 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1586 | skb_set_network_header(skb, len_rthdr); | 1551 | skb_set_network_header(skb, len_rthdr); |
1587 | skb_set_transport_header(skb, len_rthdr); | 1552 | skb_set_transport_header(skb, len_rthdr); |
1588 | 1553 | ||
1589 | /* pass the radiotap header up to the next stage intact */ | 1554 | memset(info, 0, sizeof(*info)); |
1590 | dev_queue_xmit(skb); | 1555 | |
1556 | /* pass the radiotap header up to xmit */ | ||
1557 | ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); | ||
1591 | return NETDEV_TX_OK; | 1558 | return NETDEV_TX_OK; |
1592 | 1559 | ||
1593 | fail: | 1560 | fail: |
@@ -1615,6 +1582,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1615 | { | 1582 | { |
1616 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1583 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1617 | struct ieee80211_local *local = sdata->local; | 1584 | struct ieee80211_local *local = sdata->local; |
1585 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1618 | int ret = NETDEV_TX_BUSY, head_need; | 1586 | int ret = NETDEV_TX_BUSY, head_need; |
1619 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1587 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1620 | __le16 fc; | 1588 | __le16 fc; |
@@ -1844,7 +1812,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1844 | 1812 | ||
1845 | skb->iif = dev->ifindex; | 1813 | skb->iif = dev->ifindex; |
1846 | 1814 | ||
1847 | skb->dev = local->mdev; | ||
1848 | dev->stats.tx_packets++; | 1815 | dev->stats.tx_packets++; |
1849 | dev->stats.tx_bytes += skb->len; | 1816 | dev->stats.tx_bytes += skb->len; |
1850 | 1817 | ||
@@ -1855,8 +1822,10 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1855 | skb_set_network_header(skb, nh_pos); | 1822 | skb_set_network_header(skb, nh_pos); |
1856 | skb_set_transport_header(skb, h_pos); | 1823 | skb_set_transport_header(skb, h_pos); |
1857 | 1824 | ||
1825 | memset(info, 0, sizeof(*info)); | ||
1826 | |||
1858 | dev->trans_start = jiffies; | 1827 | dev->trans_start = jiffies; |
1859 | dev_queue_xmit(skb); | 1828 | ieee80211_xmit(sdata, skb); |
1860 | 1829 | ||
1861 | return NETDEV_TX_OK; | 1830 | return NETDEV_TX_OK; |
1862 | 1831 | ||
@@ -1898,7 +1867,6 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1898 | return true; | 1867 | return true; |
1899 | } | 1868 | } |
1900 | 1869 | ||
1901 | /* validate info->control.vif against skb->iif */ | ||
1902 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1870 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1903 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1871 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1904 | sdata = container_of(sdata->bss, | 1872 | sdata = container_of(sdata->bss, |
@@ -1912,12 +1880,13 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1912 | } | 1880 | } |
1913 | 1881 | ||
1914 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { | 1882 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { |
1915 | ieee80211_tx(dev, skb, true); | 1883 | /* do not use sdata, it may have been changed above */ |
1884 | ieee80211_tx(IEEE80211_DEV_TO_SUB_IF(dev), skb, true); | ||
1916 | } else { | 1885 | } else { |
1917 | hdr = (struct ieee80211_hdr *)skb->data; | 1886 | hdr = (struct ieee80211_hdr *)skb->data; |
1918 | sta = sta_info_get(local, hdr->addr1); | 1887 | sta = sta_info_get(local, hdr->addr1); |
1919 | 1888 | ||
1920 | ret = __ieee80211_tx(local, &skb, sta); | 1889 | ret = __ieee80211_tx(local, &skb, sta, true); |
1921 | if (ret != IEEE80211_TX_OK) | 1890 | if (ret != IEEE80211_TX_OK) |
1922 | result = false; | 1891 | result = false; |
1923 | } | 1892 | } |
@@ -1929,59 +1898,43 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1929 | } | 1898 | } |
1930 | 1899 | ||
1931 | /* | 1900 | /* |
1932 | * Transmit all pending packets. Called from tasklet, locks master device | 1901 | * Transmit all pending packets. Called from tasklet. |
1933 | * TX lock so that no new packets can come in. | ||
1934 | */ | 1902 | */ |
1935 | void ieee80211_tx_pending(unsigned long data) | 1903 | void ieee80211_tx_pending(unsigned long data) |
1936 | { | 1904 | { |
1937 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1905 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1938 | struct net_device *dev = local->mdev; | ||
1939 | unsigned long flags; | 1906 | unsigned long flags; |
1940 | int i; | 1907 | int i; |
1941 | bool next; | 1908 | bool txok; |
1942 | 1909 | ||
1943 | rcu_read_lock(); | 1910 | rcu_read_lock(); |
1944 | netif_tx_lock_bh(dev); | ||
1945 | 1911 | ||
1912 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
1946 | for (i = 0; i < local->hw.queues; i++) { | 1913 | for (i = 0; i < local->hw.queues; i++) { |
1947 | /* | 1914 | /* |
1948 | * If queue is stopped by something other than due to pending | 1915 | * If queue is stopped by something other than due to pending |
1949 | * frames, or we have no pending frames, proceed to next queue. | 1916 | * frames, or we have no pending frames, proceed to next queue. |
1950 | */ | 1917 | */ |
1951 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1918 | if (local->queue_stop_reasons[i] || |
1952 | next = false; | ||
1953 | if (local->queue_stop_reasons[i] != | ||
1954 | BIT(IEEE80211_QUEUE_STOP_REASON_PENDING) || | ||
1955 | skb_queue_empty(&local->pending[i])) | 1919 | skb_queue_empty(&local->pending[i])) |
1956 | next = true; | ||
1957 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
1958 | |||
1959 | if (next) | ||
1960 | continue; | 1920 | continue; |
1961 | 1921 | ||
1962 | /* | ||
1963 | * start the queue now to allow processing our packets, | ||
1964 | * we're under the tx lock here anyway so nothing will | ||
1965 | * happen as a result of this | ||
1966 | */ | ||
1967 | netif_start_subqueue(local->mdev, i); | ||
1968 | |||
1969 | while (!skb_queue_empty(&local->pending[i])) { | 1922 | while (!skb_queue_empty(&local->pending[i])) { |
1970 | struct sk_buff *skb = skb_dequeue(&local->pending[i]); | 1923 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); |
1971 | 1924 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | |
1972 | if (!ieee80211_tx_pending_skb(local, skb)) { | 1925 | flags); |
1973 | skb_queue_head(&local->pending[i], skb); | 1926 | |
1927 | txok = ieee80211_tx_pending_skb(local, skb); | ||
1928 | if (!txok) | ||
1929 | __skb_queue_head(&local->pending[i], skb); | ||
1930 | spin_lock_irqsave(&local->queue_stop_reason_lock, | ||
1931 | flags); | ||
1932 | if (!txok) | ||
1974 | break; | 1933 | break; |
1975 | } | ||
1976 | } | 1934 | } |
1977 | |||
1978 | /* Start regular packet processing again. */ | ||
1979 | if (skb_queue_empty(&local->pending[i])) | ||
1980 | ieee80211_wake_queue_by_reason(&local->hw, i, | ||
1981 | IEEE80211_QUEUE_STOP_REASON_PENDING); | ||
1982 | } | 1935 | } |
1936 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
1983 | 1937 | ||
1984 | netif_tx_unlock_bh(dev); | ||
1985 | rcu_read_unlock(); | 1938 | rcu_read_unlock(); |
1986 | } | 1939 | } |
1987 | 1940 | ||
@@ -2156,8 +2109,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
2156 | 2109 | ||
2157 | info = IEEE80211_SKB_CB(skb); | 2110 | info = IEEE80211_SKB_CB(skb); |
2158 | 2111 | ||
2159 | skb->do_not_encrypt = 1; | 2112 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
2160 | |||
2161 | info->band = band; | 2113 | info->band = band; |
2162 | /* | 2114 | /* |
2163 | * XXX: For now, always use the lowest rate | 2115 | * XXX: For now, always use the lowest rate |
@@ -2228,9 +2180,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2228 | sdata = vif_to_sdata(vif); | 2180 | sdata = vif_to_sdata(vif); |
2229 | bss = &sdata->u.ap; | 2181 | bss = &sdata->u.ap; |
2230 | 2182 | ||
2231 | if (!bss) | ||
2232 | return NULL; | ||
2233 | |||
2234 | rcu_read_lock(); | 2183 | rcu_read_lock(); |
2235 | beacon = rcu_dereference(bss->beacon); | 2184 | beacon = rcu_dereference(bss->beacon); |
2236 | 2185 | ||
@@ -2256,7 +2205,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2256 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2205 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2257 | } | 2206 | } |
2258 | 2207 | ||
2259 | if (!ieee80211_tx_prepare(local, &tx, skb)) | 2208 | if (!ieee80211_tx_prepare(sdata, &tx, skb)) |
2260 | break; | 2209 | break; |
2261 | dev_kfree_skb_any(skb); | 2210 | dev_kfree_skb_any(skb); |
2262 | } | 2211 | } |
@@ -2276,3 +2225,25 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2276 | return skb; | 2225 | return skb; |
2277 | } | 2226 | } |
2278 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); | 2227 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); |
2228 | |||
2229 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
2230 | int encrypt) | ||
2231 | { | ||
2232 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2233 | skb_set_mac_header(skb, 0); | ||
2234 | skb_set_network_header(skb, 0); | ||
2235 | skb_set_transport_header(skb, 0); | ||
2236 | |||
2237 | skb->iif = sdata->dev->ifindex; | ||
2238 | if (!encrypt) | ||
2239 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
2240 | |||
2241 | /* | ||
2242 | * The other path calling ieee80211_xmit is from the tasklet, | ||
2243 | * and while we can handle concurrent transmissions locking | ||
2244 | * requirements are that we do not come into tx with bhs on. | ||
2245 | */ | ||
2246 | local_bh_disable(); | ||
2247 | ieee80211_xmit(sdata, skb); | ||
2248 | local_bh_enable(); | ||
2249 | } | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 915e77769312..7fc55846d601 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "mesh.h" | 31 | #include "mesh.h" |
32 | #include "wme.h" | 32 | #include "wme.h" |
33 | #include "led.h" | 33 | #include "led.h" |
34 | #include "wep.h" | ||
34 | 35 | ||
35 | /* privid for wiphys to determine whether they belong to us or not */ | 36 | /* privid for wiphys to determine whether they belong to us or not */ |
36 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; | 37 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; |
@@ -274,16 +275,12 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
274 | 275 | ||
275 | __clear_bit(reason, &local->queue_stop_reasons[queue]); | 276 | __clear_bit(reason, &local->queue_stop_reasons[queue]); |
276 | 277 | ||
277 | if (!skb_queue_empty(&local->pending[queue]) && | ||
278 | local->queue_stop_reasons[queue] == | ||
279 | BIT(IEEE80211_QUEUE_STOP_REASON_PENDING)) | ||
280 | tasklet_schedule(&local->tx_pending_tasklet); | ||
281 | |||
282 | if (local->queue_stop_reasons[queue] != 0) | 278 | if (local->queue_stop_reasons[queue] != 0) |
283 | /* someone still has this queue stopped */ | 279 | /* someone still has this queue stopped */ |
284 | return; | 280 | return; |
285 | 281 | ||
286 | netif_wake_subqueue(local->mdev, queue); | 282 | if (!skb_queue_empty(&local->pending[queue])) |
283 | tasklet_schedule(&local->tx_pending_tasklet); | ||
287 | } | 284 | } |
288 | 285 | ||
289 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 286 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
@@ -312,14 +309,6 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
312 | if (WARN_ON(queue >= hw->queues)) | 309 | if (WARN_ON(queue >= hw->queues)) |
313 | return; | 310 | return; |
314 | 311 | ||
315 | /* | ||
316 | * Only stop if it was previously running, this is necessary | ||
317 | * for correct pending packets handling because there we may | ||
318 | * start (but not wake) the queue and rely on that. | ||
319 | */ | ||
320 | if (!local->queue_stop_reasons[queue]) | ||
321 | netif_stop_subqueue(local->mdev, queue); | ||
322 | |||
323 | __set_bit(reason, &local->queue_stop_reasons[queue]); | 312 | __set_bit(reason, &local->queue_stop_reasons[queue]); |
324 | } | 313 | } |
325 | 314 | ||
@@ -350,8 +339,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
350 | 339 | ||
351 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 340 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
352 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 341 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
353 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING); | 342 | __skb_queue_tail(&local->pending[queue], skb); |
354 | skb_queue_tail(&local->pending[queue], skb); | ||
355 | __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 343 | __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
356 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 344 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
357 | } | 345 | } |
@@ -372,16 +360,12 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
372 | while ((skb = skb_dequeue(skbs))) { | 360 | while ((skb = skb_dequeue(skbs))) { |
373 | ret++; | 361 | ret++; |
374 | queue = skb_get_queue_mapping(skb); | 362 | queue = skb_get_queue_mapping(skb); |
375 | skb_queue_tail(&local->pending[queue], skb); | 363 | __skb_queue_tail(&local->pending[queue], skb); |
376 | } | 364 | } |
377 | 365 | ||
378 | for (i = 0; i < hw->queues; i++) { | 366 | for (i = 0; i < hw->queues; i++) |
379 | if (ret) | ||
380 | __ieee80211_stop_queue(hw, i, | ||
381 | IEEE80211_QUEUE_STOP_REASON_PENDING); | ||
382 | __ieee80211_wake_queue(hw, i, | 367 | __ieee80211_wake_queue(hw, i, |
383 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 368 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
384 | } | ||
385 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 369 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
386 | 370 | ||
387 | return ret; | 371 | return ret; |
@@ -412,11 +396,16 @@ EXPORT_SYMBOL(ieee80211_stop_queues); | |||
412 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | 396 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) |
413 | { | 397 | { |
414 | struct ieee80211_local *local = hw_to_local(hw); | 398 | struct ieee80211_local *local = hw_to_local(hw); |
399 | unsigned long flags; | ||
400 | int ret; | ||
415 | 401 | ||
416 | if (WARN_ON(queue >= hw->queues)) | 402 | if (WARN_ON(queue >= hw->queues)) |
417 | return true; | 403 | return true; |
418 | 404 | ||
419 | return __netif_subqueue_stopped(local->mdev, queue); | 405 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
406 | ret = !!local->queue_stop_reasons[queue]; | ||
407 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
408 | return ret; | ||
420 | } | 409 | } |
421 | EXPORT_SYMBOL(ieee80211_queue_stopped); | 410 | EXPORT_SYMBOL(ieee80211_queue_stopped); |
422 | 411 | ||
@@ -760,20 +749,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
760 | ieee80211_set_wmm_default(sdata); | 749 | ieee80211_set_wmm_default(sdata); |
761 | } | 750 | } |
762 | 751 | ||
763 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
764 | int encrypt) | ||
765 | { | ||
766 | skb->dev = sdata->local->mdev; | ||
767 | skb_set_mac_header(skb, 0); | ||
768 | skb_set_network_header(skb, 0); | ||
769 | skb_set_transport_header(skb, 0); | ||
770 | |||
771 | skb->iif = sdata->dev->ifindex; | ||
772 | skb->do_not_encrypt = !encrypt; | ||
773 | |||
774 | dev_queue_xmit(skb); | ||
775 | } | ||
776 | |||
777 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 752 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
778 | enum ieee80211_band band) | 753 | enum ieee80211_band band) |
779 | { | 754 | { |
@@ -804,12 +779,13 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | |||
804 | 779 | ||
805 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 780 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
806 | u16 transaction, u16 auth_alg, | 781 | u16 transaction, u16 auth_alg, |
807 | u8 *extra, size_t extra_len, | 782 | u8 *extra, size_t extra_len, const u8 *bssid, |
808 | const u8 *bssid, int encrypt) | 783 | const u8 *key, u8 key_len, u8 key_idx) |
809 | { | 784 | { |
810 | struct ieee80211_local *local = sdata->local; | 785 | struct ieee80211_local *local = sdata->local; |
811 | struct sk_buff *skb; | 786 | struct sk_buff *skb; |
812 | struct ieee80211_mgmt *mgmt; | 787 | struct ieee80211_mgmt *mgmt; |
788 | int err; | ||
813 | 789 | ||
814 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 790 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
815 | sizeof(*mgmt) + 6 + extra_len); | 791 | sizeof(*mgmt) + 6 + extra_len); |
@@ -824,8 +800,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
824 | memset(mgmt, 0, 24 + 6); | 800 | memset(mgmt, 0, 24 + 6); |
825 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 801 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
826 | IEEE80211_STYPE_AUTH); | 802 | IEEE80211_STYPE_AUTH); |
827 | if (encrypt) | ||
828 | mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
829 | memcpy(mgmt->da, bssid, ETH_ALEN); | 803 | memcpy(mgmt->da, bssid, ETH_ALEN); |
830 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 804 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
831 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | 805 | memcpy(mgmt->bssid, bssid, ETH_ALEN); |
@@ -835,7 +809,13 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
835 | if (extra) | 809 | if (extra) |
836 | memcpy(skb_put(skb, extra_len), extra, extra_len); | 810 | memcpy(skb_put(skb, extra_len), extra, extra_len); |
837 | 811 | ||
838 | ieee80211_tx_skb(sdata, skb, encrypt); | 812 | if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) { |
813 | mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
814 | err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx); | ||
815 | WARN_ON(err); | ||
816 | } | ||
817 | |||
818 | ieee80211_tx_skb(sdata, skb, 0); | ||
839 | } | 819 | } |
840 | 820 | ||
841 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 821 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
@@ -1043,9 +1023,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1043 | /* reconfigure hardware */ | 1023 | /* reconfigure hardware */ |
1044 | ieee80211_hw_config(local, ~0); | 1024 | ieee80211_hw_config(local, ~0); |
1045 | 1025 | ||
1046 | netif_addr_lock_bh(local->mdev); | 1026 | spin_lock_bh(&local->filter_lock); |
1047 | ieee80211_configure_filter(local); | 1027 | ieee80211_configure_filter(local); |
1048 | netif_addr_unlock_bh(local->mdev); | 1028 | spin_unlock_bh(&local->filter_lock); |
1049 | 1029 | ||
1050 | /* Finally also reconfigure all the BSS information */ | 1030 | /* Finally also reconfigure all the BSS information */ |
1051 | list_for_each_entry(sdata, &local->interfaces, list) { | 1031 | list_for_each_entry(sdata, &local->interfaces, list) { |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 4fafb2d27c84..8a980f136941 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -144,9 +144,9 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | |||
144 | * | 144 | * |
145 | * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) | 145 | * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) |
146 | */ | 146 | */ |
147 | static int ieee80211_wep_encrypt(struct ieee80211_local *local, | 147 | int ieee80211_wep_encrypt(struct ieee80211_local *local, |
148 | struct sk_buff *skb, | 148 | struct sk_buff *skb, |
149 | const u8 *key, int keylen, int keyidx) | 149 | const u8 *key, int keylen, int keyidx) |
150 | { | 150 | { |
151 | u8 *iv; | 151 | u8 *iv; |
152 | size_t len; | 152 | size_t len; |
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h index 85219ded8703..fe29d7e5759f 100644 --- a/net/mac80211/wep.h +++ b/net/mac80211/wep.h | |||
@@ -20,6 +20,9 @@ int ieee80211_wep_init(struct ieee80211_local *local); | |||
20 | void ieee80211_wep_free(struct ieee80211_local *local); | 20 | void ieee80211_wep_free(struct ieee80211_local *local); |
21 | void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | 21 | void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, |
22 | size_t klen, u8 *data, size_t data_len); | 22 | size_t klen, u8 *data, size_t data_len); |
23 | int ieee80211_wep_encrypt(struct ieee80211_local *local, | ||
24 | struct sk_buff *skb, | ||
25 | const u8 *key, int keylen, int keyidx); | ||
23 | int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | 26 | int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, |
24 | size_t klen, u8 *data, size_t data_len); | 27 | size_t klen, u8 *data, size_t data_len); |
25 | bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); | 28 | bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 116a923b14d6..b19b7696f3a2 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -85,10 +85,8 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) | |||
85 | return ieee802_1d_to_ac[skb->priority]; | 85 | return ieee802_1d_to_ac[skb->priority]; |
86 | } | 86 | } |
87 | 87 | ||
88 | u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | 88 | void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb) |
89 | { | 89 | { |
90 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
91 | struct ieee80211_local *local = mpriv->local; | ||
92 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 90 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
93 | u16 queue; | 91 | u16 queue; |
94 | u8 tid; | 92 | u8 tid; |
@@ -113,5 +111,5 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | |||
113 | *p = 0; | 111 | *p = 0; |
114 | } | 112 | } |
115 | 113 | ||
116 | return queue; | 114 | skb_set_queue_mapping(skb, queue); |
117 | } | 115 | } |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 7520d2e014dc..d4fd87ca5118 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | extern const int ieee802_1d_to_ac[8]; | 21 | extern const int ieee802_1d_to_ac[8]; |
22 | 22 | ||
23 | u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb); | 23 | void ieee80211_select_queue(struct ieee80211_local *local, |
24 | struct sk_buff *skb); | ||
24 | 25 | ||
25 | #endif /* _WME_H */ | 26 | #endif /* _WME_H */ |