diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/Kconfig | 2 | ||||
-rw-r--r-- | net/mac80211/agg-rx.c | 7 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 23 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 27 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 6 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 122 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 6 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 213 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 14 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 16 | ||||
-rw-r--r-- | net/mac80211/iface.c | 9 | ||||
-rw-r--r-- | net/mac80211/main.c | 85 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 4 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 84 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 68 | ||||
-rw-r--r-- | net/mac80211/rx.c | 115 | ||||
-rw-r--r-- | net/mac80211/scan.c | 96 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 3 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/status.c | 4 | ||||
-rw-r--r-- | net/mac80211/tx.c | 30 | ||||
-rw-r--r-- | net/mac80211/util.c | 6 | ||||
-rw-r--r-- | net/mac80211/work.c | 121 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 39 |
24 files changed, 714 insertions, 388 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index c766056d0488..dbf5e4006bc1 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -17,7 +17,7 @@ comment "CFG80211 needs to be enabled for MAC80211" | |||
17 | if MAC80211 != n | 17 | if MAC80211 != n |
18 | 18 | ||
19 | config MAC80211_HAS_RC | 19 | config MAC80211_HAS_RC |
20 | def_bool n | 20 | bool |
21 | 21 | ||
22 | config MAC80211_RC_PID | 22 | config MAC80211_RC_PID |
23 | bool "PID controller based rate control algorithm" if EXPERT | 23 | bool "PID controller based rate control algorithm" if EXPERT |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 227ca82eef72..0c9d0c07eae6 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -76,7 +76,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
76 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 76 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
77 | 77 | ||
78 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, | 78 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
79 | &sta->sta, tid, NULL)) | 79 | &sta->sta, tid, NULL, 0)) |
80 | printk(KERN_DEBUG "HW problem - can not stop rx " | 80 | printk(KERN_DEBUG "HW problem - can not stop rx " |
81 | "aggregation for tid %d\n", tid); | 81 | "aggregation for tid %d\n", tid); |
82 | 82 | ||
@@ -232,6 +232,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
232 | if (buf_size == 0) | 232 | if (buf_size == 0) |
233 | buf_size = IEEE80211_MAX_AMPDU_BUF; | 233 | buf_size = IEEE80211_MAX_AMPDU_BUF; |
234 | 234 | ||
235 | /* make sure the size doesn't exceed the maximum supported by the hw */ | ||
236 | if (buf_size > local->hw.max_rx_aggregation_subframes) | ||
237 | buf_size = local->hw.max_rx_aggregation_subframes; | ||
235 | 238 | ||
236 | /* examine state machine */ | 239 | /* examine state machine */ |
237 | mutex_lock(&sta->ampdu_mlme.mtx); | 240 | mutex_lock(&sta->ampdu_mlme.mtx); |
@@ -287,7 +290,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
287 | } | 290 | } |
288 | 291 | ||
289 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, | 292 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
290 | &sta->sta, tid, &start_seq_num); | 293 | &sta->sta, tid, &start_seq_num, 0); |
291 | #ifdef CONFIG_MAC80211_HT_DEBUG | 294 | #ifdef CONFIG_MAC80211_HT_DEBUG |
292 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | 295 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); |
293 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 296 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 9cc472c6a6a5..63d852cb4ca2 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -190,7 +190,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
190 | 190 | ||
191 | ret = drv_ampdu_action(local, sta->sdata, | 191 | ret = drv_ampdu_action(local, sta->sdata, |
192 | IEEE80211_AMPDU_TX_STOP, | 192 | IEEE80211_AMPDU_TX_STOP, |
193 | &sta->sta, tid, NULL); | 193 | &sta->sta, tid, NULL, 0); |
194 | 194 | ||
195 | /* HW shall not deny going back to legacy */ | 195 | /* HW shall not deny going back to legacy */ |
196 | if (WARN_ON(ret)) { | 196 | if (WARN_ON(ret)) { |
@@ -311,7 +311,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
311 | start_seq_num = sta->tid_seq[tid] >> 4; | 311 | start_seq_num = sta->tid_seq[tid] >> 4; |
312 | 312 | ||
313 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, | 313 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, |
314 | &sta->sta, tid, &start_seq_num); | 314 | &sta->sta, tid, &start_seq_num, 0); |
315 | if (ret) { | 315 | if (ret) { |
316 | #ifdef CONFIG_MAC80211_HT_DEBUG | 316 | #ifdef CONFIG_MAC80211_HT_DEBUG |
317 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | 317 | printk(KERN_DEBUG "BA request denied - HW unavailable for" |
@@ -342,7 +342,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
342 | /* send AddBA request */ | 342 | /* send AddBA request */ |
343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | 343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
344 | tid_tx->dialog_token, start_seq_num, | 344 | tid_tx->dialog_token, start_seq_num, |
345 | 0x40, tid_tx->timeout); | 345 | local->hw.max_tx_aggregation_subframes, |
346 | tid_tx->timeout); | ||
346 | } | 347 | } |
347 | 348 | ||
348 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | 349 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, |
@@ -487,7 +488,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
487 | 488 | ||
488 | drv_ampdu_action(local, sta->sdata, | 489 | drv_ampdu_action(local, sta->sdata, |
489 | IEEE80211_AMPDU_TX_OPERATIONAL, | 490 | IEEE80211_AMPDU_TX_OPERATIONAL, |
490 | &sta->sta, tid, NULL); | 491 | &sta->sta, tid, NULL, |
492 | sta->ampdu_mlme.tid_tx[tid]->buf_size); | ||
491 | 493 | ||
492 | /* | 494 | /* |
493 | * synchronize with TX path, while splicing the TX path | 495 | * synchronize with TX path, while splicing the TX path |
@@ -742,9 +744,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
742 | { | 744 | { |
743 | struct tid_ampdu_tx *tid_tx; | 745 | struct tid_ampdu_tx *tid_tx; |
744 | u16 capab, tid; | 746 | u16 capab, tid; |
747 | u8 buf_size; | ||
745 | 748 | ||
746 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 749 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
747 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 750 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
751 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
748 | 752 | ||
749 | mutex_lock(&sta->ampdu_mlme.mtx); | 753 | mutex_lock(&sta->ampdu_mlme.mtx); |
750 | 754 | ||
@@ -767,12 +771,23 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
767 | 771 | ||
768 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 772 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
769 | == WLAN_STATUS_SUCCESS) { | 773 | == WLAN_STATUS_SUCCESS) { |
774 | /* | ||
775 | * IEEE 802.11-2007 7.3.1.14: | ||
776 | * In an ADDBA Response frame, when the Status Code field | ||
777 | * is set to 0, the Buffer Size subfield is set to a value | ||
778 | * of at least 1. | ||
779 | */ | ||
780 | if (!buf_size) | ||
781 | goto out; | ||
782 | |||
770 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, | 783 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, |
771 | &tid_tx->state)) { | 784 | &tid_tx->state)) { |
772 | /* ignore duplicate response */ | 785 | /* ignore duplicate response */ |
773 | goto out; | 786 | goto out; |
774 | } | 787 | } |
775 | 788 | ||
789 | tid_tx->buf_size = buf_size; | ||
790 | |||
776 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) | 791 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) |
777 | ieee80211_agg_tx_operational(local, sta, tid); | 792 | ieee80211_agg_tx_operational(local, sta, tid); |
778 | 793 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9cd73b11506e..140503d4c97a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1215,6 +1215,9 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1215 | { | 1215 | { |
1216 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1216 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1217 | struct ieee80211_sub_if_data *sdata = NULL; | 1217 | struct ieee80211_sub_if_data *sdata = NULL; |
1218 | struct ieee80211_channel *old_oper; | ||
1219 | enum nl80211_channel_type old_oper_type; | ||
1220 | enum nl80211_channel_type old_vif_oper_type= NL80211_CHAN_NO_HT; | ||
1218 | 1221 | ||
1219 | if (netdev) | 1222 | if (netdev) |
1220 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | 1223 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); |
@@ -1232,13 +1235,23 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1232 | break; | 1235 | break; |
1233 | } | 1236 | } |
1234 | 1237 | ||
1235 | local->oper_channel = chan; | 1238 | if (sdata) |
1239 | old_vif_oper_type = sdata->vif.bss_conf.channel_type; | ||
1240 | old_oper_type = local->_oper_channel_type; | ||
1236 | 1241 | ||
1237 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) | 1242 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) |
1238 | return -EBUSY; | 1243 | return -EBUSY; |
1239 | 1244 | ||
1240 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1245 | old_oper = local->oper_channel; |
1241 | if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) | 1246 | local->oper_channel = chan; |
1247 | |||
1248 | /* Update driver if changes were actually made. */ | ||
1249 | if ((old_oper != local->oper_channel) || | ||
1250 | (old_oper_type != local->_oper_channel_type)) | ||
1251 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
1252 | |||
1253 | if ((sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) && | ||
1254 | old_vif_oper_type != sdata->vif.bss_conf.channel_type) | ||
1242 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); | 1255 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); |
1243 | 1256 | ||
1244 | return 0; | 1257 | return 0; |
@@ -1274,8 +1287,11 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1274 | case NL80211_IFTYPE_P2P_GO: | 1287 | case NL80211_IFTYPE_P2P_GO: |
1275 | if (sdata->local->ops->hw_scan) | 1288 | if (sdata->local->ops->hw_scan) |
1276 | break; | 1289 | break; |
1277 | /* FIXME: implement NoA while scanning in software */ | 1290 | /* |
1278 | return -EOPNOTSUPP; | 1291 | * FIXME: implement NoA while scanning in software, |
1292 | * for now fall through to allow scanning only when | ||
1293 | * beaconing hasn't been configured yet | ||
1294 | */ | ||
1279 | case NL80211_IFTYPE_AP: | 1295 | case NL80211_IFTYPE_AP: |
1280 | if (sdata->u.ap.beacon) | 1296 | if (sdata->u.ap.beacon) |
1281 | return -EOPNOTSUPP; | 1297 | return -EOPNOTSUPP; |
@@ -1847,6 +1863,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1847 | 1863 | ||
1848 | wk->type = IEEE80211_WORK_OFFCHANNEL_TX; | 1864 | wk->type = IEEE80211_WORK_OFFCHANNEL_TX; |
1849 | wk->chan = chan; | 1865 | wk->chan = chan; |
1866 | wk->chan_type = channel_type; | ||
1850 | wk->sdata = sdata; | 1867 | wk->sdata = sdata; |
1851 | wk->done = ieee80211_offchan_tx_done; | 1868 | wk->done = ieee80211_offchan_tx_done; |
1852 | wk->offchan_tx.frame = skb; | 1869 | wk->offchan_tx.frame = skb; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 1f02e599a318..51f0d780dafa 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -60,6 +60,10 @@ static const struct file_operations name## _ops = { \ | |||
60 | debugfs_create_file(#name, mode, phyd, local, &name## _ops); | 60 | debugfs_create_file(#name, mode, phyd, local, &name## _ops); |
61 | 61 | ||
62 | 62 | ||
63 | DEBUGFS_READONLY_FILE(user_power, "%d", | ||
64 | local->user_power_level); | ||
65 | DEBUGFS_READONLY_FILE(power, "%d", | ||
66 | local->hw.conf.power_level); | ||
63 | DEBUGFS_READONLY_FILE(frequency, "%d", | 67 | DEBUGFS_READONLY_FILE(frequency, "%d", |
64 | local->hw.conf.channel->center_freq); | 68 | local->hw.conf.channel->center_freq); |
65 | DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", | 69 | DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", |
@@ -391,6 +395,8 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
391 | DEBUGFS_ADD(uapsd_queues); | 395 | DEBUGFS_ADD(uapsd_queues); |
392 | DEBUGFS_ADD(uapsd_max_sp_len); | 396 | DEBUGFS_ADD(uapsd_max_sp_len); |
393 | DEBUGFS_ADD(channel_type); | 397 | DEBUGFS_ADD(channel_type); |
398 | DEBUGFS_ADD(user_power); | ||
399 | DEBUGFS_ADD(power); | ||
394 | 400 | ||
395 | statsd = debugfs_create_dir("statistics", phyd); | 401 | statsd = debugfs_create_dir("statistics", phyd); |
396 | 402 | ||
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 2dabdf7680d0..dacace6b1393 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -36,7 +36,7 @@ static ssize_t ieee80211_if_read( | |||
36 | ret = (*format)(sdata, buf, sizeof(buf)); | 36 | ret = (*format)(sdata, buf, sizeof(buf)); |
37 | read_unlock(&dev_base_lock); | 37 | read_unlock(&dev_base_lock); |
38 | 38 | ||
39 | if (ret != -EINVAL) | 39 | if (ret >= 0) |
40 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); | 40 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); |
41 | 41 | ||
42 | return ret; | 42 | return ret; |
@@ -81,6 +81,8 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
81 | IEEE80211_IF_FMT(name, field, "%d\n") | 81 | IEEE80211_IF_FMT(name, field, "%d\n") |
82 | #define IEEE80211_IF_FMT_HEX(name, field) \ | 82 | #define IEEE80211_IF_FMT_HEX(name, field) \ |
83 | IEEE80211_IF_FMT(name, field, "%#x\n") | 83 | IEEE80211_IF_FMT(name, field, "%#x\n") |
84 | #define IEEE80211_IF_FMT_LHEX(name, field) \ | ||
85 | IEEE80211_IF_FMT(name, field, "%#lx\n") | ||
84 | #define IEEE80211_IF_FMT_SIZE(name, field) \ | 86 | #define IEEE80211_IF_FMT_SIZE(name, field) \ |
85 | IEEE80211_IF_FMT(name, field, "%zd\n") | 87 | IEEE80211_IF_FMT(name, field, "%zd\n") |
86 | 88 | ||
@@ -145,6 +147,9 @@ IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], | |||
145 | HEX); | 147 | HEX); |
146 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | 148 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], |
147 | HEX); | 149 | HEX); |
150 | IEEE80211_IF_FILE(flags, flags, HEX); | ||
151 | IEEE80211_IF_FILE(state, state, LHEX); | ||
152 | IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); | ||
148 | 153 | ||
149 | /* STA attributes */ | 154 | /* STA attributes */ |
150 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 155 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
@@ -216,6 +221,104 @@ static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, | |||
216 | 221 | ||
217 | __IEEE80211_IF_FILE_W(smps); | 222 | __IEEE80211_IF_FILE_W(smps); |
218 | 223 | ||
224 | static ssize_t ieee80211_if_fmt_tkip_mic_test( | ||
225 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
226 | { | ||
227 | return -EOPNOTSUPP; | ||
228 | } | ||
229 | |||
230 | static int hwaddr_aton(const char *txt, u8 *addr) | ||
231 | { | ||
232 | int i; | ||
233 | |||
234 | for (i = 0; i < ETH_ALEN; i++) { | ||
235 | int a, b; | ||
236 | |||
237 | a = hex_to_bin(*txt++); | ||
238 | if (a < 0) | ||
239 | return -1; | ||
240 | b = hex_to_bin(*txt++); | ||
241 | if (b < 0) | ||
242 | return -1; | ||
243 | *addr++ = (a << 4) | b; | ||
244 | if (i < 5 && *txt++ != ':') | ||
245 | return -1; | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static ssize_t ieee80211_if_parse_tkip_mic_test( | ||
252 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | ||
253 | { | ||
254 | struct ieee80211_local *local = sdata->local; | ||
255 | u8 addr[ETH_ALEN]; | ||
256 | struct sk_buff *skb; | ||
257 | struct ieee80211_hdr *hdr; | ||
258 | __le16 fc; | ||
259 | |||
260 | /* | ||
261 | * Assume colon-delimited MAC address with possible white space | ||
262 | * following. | ||
263 | */ | ||
264 | if (buflen < 3 * ETH_ALEN - 1) | ||
265 | return -EINVAL; | ||
266 | if (hwaddr_aton(buf, addr) < 0) | ||
267 | return -EINVAL; | ||
268 | |||
269 | if (!ieee80211_sdata_running(sdata)) | ||
270 | return -ENOTCONN; | ||
271 | |||
272 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 100); | ||
273 | if (!skb) | ||
274 | return -ENOMEM; | ||
275 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
276 | |||
277 | hdr = (struct ieee80211_hdr *) skb_put(skb, 24); | ||
278 | memset(hdr, 0, 24); | ||
279 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | ||
280 | |||
281 | switch (sdata->vif.type) { | ||
282 | case NL80211_IFTYPE_AP: | ||
283 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | ||
284 | /* DA BSSID SA */ | ||
285 | memcpy(hdr->addr1, addr, ETH_ALEN); | ||
286 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
287 | memcpy(hdr->addr3, sdata->vif.addr, ETH_ALEN); | ||
288 | break; | ||
289 | case NL80211_IFTYPE_STATION: | ||
290 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | ||
291 | /* BSSID SA DA */ | ||
292 | if (sdata->vif.bss_conf.bssid == NULL) { | ||
293 | dev_kfree_skb(skb); | ||
294 | return -ENOTCONN; | ||
295 | } | ||
296 | memcpy(hdr->addr1, sdata->vif.bss_conf.bssid, ETH_ALEN); | ||
297 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
298 | memcpy(hdr->addr3, addr, ETH_ALEN); | ||
299 | break; | ||
300 | default: | ||
301 | dev_kfree_skb(skb); | ||
302 | return -EOPNOTSUPP; | ||
303 | } | ||
304 | hdr->frame_control = fc; | ||
305 | |||
306 | /* | ||
307 | * Add some length to the test frame to make it look bit more valid. | ||
308 | * The exact contents does not matter since the recipient is required | ||
309 | * to drop this because of the Michael MIC failure. | ||
310 | */ | ||
311 | memset(skb_put(skb, 50), 0, 50); | ||
312 | |||
313 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_TKIP_MIC_FAILURE; | ||
314 | |||
315 | ieee80211_tx_skb(sdata, skb); | ||
316 | |||
317 | return buflen; | ||
318 | } | ||
319 | |||
320 | __IEEE80211_IF_FILE_W(tkip_mic_test); | ||
321 | |||
219 | /* AP attributes */ | 322 | /* AP attributes */ |
220 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 323 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
221 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 324 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
@@ -283,6 +386,9 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, | |||
283 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 386 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
284 | { | 387 | { |
285 | DEBUGFS_ADD(drop_unencrypted); | 388 | DEBUGFS_ADD(drop_unencrypted); |
389 | DEBUGFS_ADD(flags); | ||
390 | DEBUGFS_ADD(state); | ||
391 | DEBUGFS_ADD(channel_type); | ||
286 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 392 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
287 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 393 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
288 | 394 | ||
@@ -291,22 +397,30 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
291 | DEBUGFS_ADD(last_beacon); | 397 | DEBUGFS_ADD(last_beacon); |
292 | DEBUGFS_ADD(ave_beacon); | 398 | DEBUGFS_ADD(ave_beacon); |
293 | DEBUGFS_ADD_MODE(smps, 0600); | 399 | DEBUGFS_ADD_MODE(smps, 0600); |
400 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | ||
294 | } | 401 | } |
295 | 402 | ||
296 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 403 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
297 | { | 404 | { |
298 | DEBUGFS_ADD(drop_unencrypted); | 405 | DEBUGFS_ADD(drop_unencrypted); |
406 | DEBUGFS_ADD(flags); | ||
407 | DEBUGFS_ADD(state); | ||
408 | DEBUGFS_ADD(channel_type); | ||
299 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 409 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
300 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 410 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
301 | 411 | ||
302 | DEBUGFS_ADD(num_sta_ps); | 412 | DEBUGFS_ADD(num_sta_ps); |
303 | DEBUGFS_ADD(dtim_count); | 413 | DEBUGFS_ADD(dtim_count); |
304 | DEBUGFS_ADD(num_buffered_multicast); | 414 | DEBUGFS_ADD(num_buffered_multicast); |
415 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | ||
305 | } | 416 | } |
306 | 417 | ||
307 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 418 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
308 | { | 419 | { |
309 | DEBUGFS_ADD(drop_unencrypted); | 420 | DEBUGFS_ADD(drop_unencrypted); |
421 | DEBUGFS_ADD(flags); | ||
422 | DEBUGFS_ADD(state); | ||
423 | DEBUGFS_ADD(channel_type); | ||
310 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 424 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
311 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 425 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
312 | 426 | ||
@@ -316,12 +430,18 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) | |||
316 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 430 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
317 | { | 431 | { |
318 | DEBUGFS_ADD(drop_unencrypted); | 432 | DEBUGFS_ADD(drop_unencrypted); |
433 | DEBUGFS_ADD(flags); | ||
434 | DEBUGFS_ADD(state); | ||
435 | DEBUGFS_ADD(channel_type); | ||
319 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 436 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
320 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 437 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
321 | } | 438 | } |
322 | 439 | ||
323 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 440 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
324 | { | 441 | { |
442 | DEBUGFS_ADD(flags); | ||
443 | DEBUGFS_ADD(state); | ||
444 | DEBUGFS_ADD(channel_type); | ||
325 | } | 445 | } |
326 | 446 | ||
327 | #ifdef CONFIG_MAC80211_MESH | 447 | #ifdef CONFIG_MAC80211_MESH |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 98d589960a49..78af32d4bc58 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -382,17 +382,17 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
382 | struct ieee80211_sub_if_data *sdata, | 382 | struct ieee80211_sub_if_data *sdata, |
383 | enum ieee80211_ampdu_mlme_action action, | 383 | enum ieee80211_ampdu_mlme_action action, |
384 | struct ieee80211_sta *sta, u16 tid, | 384 | struct ieee80211_sta *sta, u16 tid, |
385 | u16 *ssn) | 385 | u16 *ssn, u8 buf_size) |
386 | { | 386 | { |
387 | int ret = -EOPNOTSUPP; | 387 | int ret = -EOPNOTSUPP; |
388 | 388 | ||
389 | might_sleep(); | 389 | might_sleep(); |
390 | 390 | ||
391 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn); | 391 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); |
392 | 392 | ||
393 | if (local->ops->ampdu_action) | 393 | if (local->ops->ampdu_action) |
394 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, | 394 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, |
395 | sta, tid, ssn); | 395 | sta, tid, ssn, buf_size); |
396 | 396 | ||
397 | trace_drv_return_int(local, ret); | 397 | trace_drv_return_int(local, ret); |
398 | 398 | ||
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 49c84218b2f4..e5cce19a7d65 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -9,6 +9,11 @@ | |||
9 | #undef TRACE_EVENT | 9 | #undef TRACE_EVENT |
10 | #define TRACE_EVENT(name, proto, ...) \ | 10 | #define TRACE_EVENT(name, proto, ...) \ |
11 | static inline void trace_ ## name(proto) {} | 11 | static inline void trace_ ## name(proto) {} |
12 | #undef DECLARE_EVENT_CLASS | ||
13 | #define DECLARE_EVENT_CLASS(...) | ||
14 | #undef DEFINE_EVENT | ||
15 | #define DEFINE_EVENT(evt_class, name, proto, ...) \ | ||
16 | static inline void trace_ ## name(proto) {} | ||
12 | #endif | 17 | #endif |
13 | 18 | ||
14 | #undef TRACE_SYSTEM | 19 | #undef TRACE_SYSTEM |
@@ -38,7 +43,7 @@ static inline void trace_ ## name(proto) {} | |||
38 | * Tracing for driver callbacks. | 43 | * Tracing for driver callbacks. |
39 | */ | 44 | */ |
40 | 45 | ||
41 | TRACE_EVENT(drv_return_void, | 46 | DECLARE_EVENT_CLASS(local_only_evt, |
42 | TP_PROTO(struct ieee80211_local *local), | 47 | TP_PROTO(struct ieee80211_local *local), |
43 | TP_ARGS(local), | 48 | TP_ARGS(local), |
44 | TP_STRUCT__entry( | 49 | TP_STRUCT__entry( |
@@ -50,6 +55,11 @@ TRACE_EVENT(drv_return_void, | |||
50 | TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) | 55 | TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) |
51 | ); | 56 | ); |
52 | 57 | ||
58 | DEFINE_EVENT(local_only_evt, drv_return_void, | ||
59 | TP_PROTO(struct ieee80211_local *local), | ||
60 | TP_ARGS(local) | ||
61 | ); | ||
62 | |||
53 | TRACE_EVENT(drv_return_int, | 63 | TRACE_EVENT(drv_return_int, |
54 | TP_PROTO(struct ieee80211_local *local, int ret), | 64 | TP_PROTO(struct ieee80211_local *local, int ret), |
55 | TP_ARGS(local, ret), | 65 | TP_ARGS(local, ret), |
@@ -78,40 +88,14 @@ TRACE_EVENT(drv_return_u64, | |||
78 | TP_printk(LOCAL_PR_FMT " - %llu", LOCAL_PR_ARG, __entry->ret) | 88 | TP_printk(LOCAL_PR_FMT " - %llu", LOCAL_PR_ARG, __entry->ret) |
79 | ); | 89 | ); |
80 | 90 | ||
81 | TRACE_EVENT(drv_start, | 91 | DEFINE_EVENT(local_only_evt, drv_start, |
82 | TP_PROTO(struct ieee80211_local *local), | 92 | TP_PROTO(struct ieee80211_local *local), |
83 | 93 | TP_ARGS(local) | |
84 | TP_ARGS(local), | ||
85 | |||
86 | TP_STRUCT__entry( | ||
87 | LOCAL_ENTRY | ||
88 | ), | ||
89 | |||
90 | TP_fast_assign( | ||
91 | LOCAL_ASSIGN; | ||
92 | ), | ||
93 | |||
94 | TP_printk( | ||
95 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
96 | ) | ||
97 | ); | 94 | ); |
98 | 95 | ||
99 | TRACE_EVENT(drv_stop, | 96 | DEFINE_EVENT(local_only_evt, drv_stop, |
100 | TP_PROTO(struct ieee80211_local *local), | 97 | TP_PROTO(struct ieee80211_local *local), |
101 | 98 | TP_ARGS(local) | |
102 | TP_ARGS(local), | ||
103 | |||
104 | TP_STRUCT__entry( | ||
105 | LOCAL_ENTRY | ||
106 | ), | ||
107 | |||
108 | TP_fast_assign( | ||
109 | LOCAL_ASSIGN; | ||
110 | ), | ||
111 | |||
112 | TP_printk( | ||
113 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
114 | ) | ||
115 | ); | 99 | ); |
116 | 100 | ||
117 | TRACE_EVENT(drv_add_interface, | 101 | TRACE_EVENT(drv_add_interface, |
@@ -439,40 +423,14 @@ TRACE_EVENT(drv_hw_scan, | |||
439 | ) | 423 | ) |
440 | ); | 424 | ); |
441 | 425 | ||
442 | TRACE_EVENT(drv_sw_scan_start, | 426 | DEFINE_EVENT(local_only_evt, drv_sw_scan_start, |
443 | TP_PROTO(struct ieee80211_local *local), | 427 | TP_PROTO(struct ieee80211_local *local), |
444 | 428 | TP_ARGS(local) | |
445 | TP_ARGS(local), | ||
446 | |||
447 | TP_STRUCT__entry( | ||
448 | LOCAL_ENTRY | ||
449 | ), | ||
450 | |||
451 | TP_fast_assign( | ||
452 | LOCAL_ASSIGN; | ||
453 | ), | ||
454 | |||
455 | TP_printk( | ||
456 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
457 | ) | ||
458 | ); | 429 | ); |
459 | 430 | ||
460 | TRACE_EVENT(drv_sw_scan_complete, | 431 | DEFINE_EVENT(local_only_evt, drv_sw_scan_complete, |
461 | TP_PROTO(struct ieee80211_local *local), | 432 | TP_PROTO(struct ieee80211_local *local), |
462 | 433 | TP_ARGS(local) | |
463 | TP_ARGS(local), | ||
464 | |||
465 | TP_STRUCT__entry( | ||
466 | LOCAL_ENTRY | ||
467 | ), | ||
468 | |||
469 | TP_fast_assign( | ||
470 | LOCAL_ASSIGN; | ||
471 | ), | ||
472 | |||
473 | TP_printk( | ||
474 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
475 | ) | ||
476 | ); | 434 | ); |
477 | 435 | ||
478 | TRACE_EVENT(drv_get_stats, | 436 | TRACE_EVENT(drv_get_stats, |
@@ -702,23 +660,9 @@ TRACE_EVENT(drv_conf_tx, | |||
702 | ) | 660 | ) |
703 | ); | 661 | ); |
704 | 662 | ||
705 | TRACE_EVENT(drv_get_tsf, | 663 | DEFINE_EVENT(local_only_evt, drv_get_tsf, |
706 | TP_PROTO(struct ieee80211_local *local), | 664 | TP_PROTO(struct ieee80211_local *local), |
707 | 665 | TP_ARGS(local) | |
708 | TP_ARGS(local), | ||
709 | |||
710 | TP_STRUCT__entry( | ||
711 | LOCAL_ENTRY | ||
712 | ), | ||
713 | |||
714 | TP_fast_assign( | ||
715 | LOCAL_ASSIGN; | ||
716 | ), | ||
717 | |||
718 | TP_printk( | ||
719 | LOCAL_PR_FMT, | ||
720 | LOCAL_PR_ARG | ||
721 | ) | ||
722 | ); | 666 | ); |
723 | 667 | ||
724 | TRACE_EVENT(drv_set_tsf, | 668 | TRACE_EVENT(drv_set_tsf, |
@@ -742,41 +686,14 @@ TRACE_EVENT(drv_set_tsf, | |||
742 | ) | 686 | ) |
743 | ); | 687 | ); |
744 | 688 | ||
745 | TRACE_EVENT(drv_reset_tsf, | 689 | DEFINE_EVENT(local_only_evt, drv_reset_tsf, |
746 | TP_PROTO(struct ieee80211_local *local), | 690 | TP_PROTO(struct ieee80211_local *local), |
747 | 691 | TP_ARGS(local) | |
748 | TP_ARGS(local), | ||
749 | |||
750 | TP_STRUCT__entry( | ||
751 | LOCAL_ENTRY | ||
752 | ), | ||
753 | |||
754 | TP_fast_assign( | ||
755 | LOCAL_ASSIGN; | ||
756 | ), | ||
757 | |||
758 | TP_printk( | ||
759 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
760 | ) | ||
761 | ); | 692 | ); |
762 | 693 | ||
763 | TRACE_EVENT(drv_tx_last_beacon, | 694 | DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, |
764 | TP_PROTO(struct ieee80211_local *local), | 695 | TP_PROTO(struct ieee80211_local *local), |
765 | 696 | TP_ARGS(local) | |
766 | TP_ARGS(local), | ||
767 | |||
768 | TP_STRUCT__entry( | ||
769 | LOCAL_ENTRY | ||
770 | ), | ||
771 | |||
772 | TP_fast_assign( | ||
773 | LOCAL_ASSIGN; | ||
774 | ), | ||
775 | |||
776 | TP_printk( | ||
777 | LOCAL_PR_FMT, | ||
778 | LOCAL_PR_ARG | ||
779 | ) | ||
780 | ); | 697 | ); |
781 | 698 | ||
782 | TRACE_EVENT(drv_ampdu_action, | 699 | TRACE_EVENT(drv_ampdu_action, |
@@ -784,9 +701,9 @@ TRACE_EVENT(drv_ampdu_action, | |||
784 | struct ieee80211_sub_if_data *sdata, | 701 | struct ieee80211_sub_if_data *sdata, |
785 | enum ieee80211_ampdu_mlme_action action, | 702 | enum ieee80211_ampdu_mlme_action action, |
786 | struct ieee80211_sta *sta, u16 tid, | 703 | struct ieee80211_sta *sta, u16 tid, |
787 | u16 *ssn), | 704 | u16 *ssn, u8 buf_size), |
788 | 705 | ||
789 | TP_ARGS(local, sdata, action, sta, tid, ssn), | 706 | TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size), |
790 | 707 | ||
791 | TP_STRUCT__entry( | 708 | TP_STRUCT__entry( |
792 | LOCAL_ENTRY | 709 | LOCAL_ENTRY |
@@ -794,6 +711,7 @@ TRACE_EVENT(drv_ampdu_action, | |||
794 | __field(u32, action) | 711 | __field(u32, action) |
795 | __field(u16, tid) | 712 | __field(u16, tid) |
796 | __field(u16, ssn) | 713 | __field(u16, ssn) |
714 | __field(u8, buf_size) | ||
797 | VIF_ENTRY | 715 | VIF_ENTRY |
798 | ), | 716 | ), |
799 | 717 | ||
@@ -804,11 +722,13 @@ TRACE_EVENT(drv_ampdu_action, | |||
804 | __entry->action = action; | 722 | __entry->action = action; |
805 | __entry->tid = tid; | 723 | __entry->tid = tid; |
806 | __entry->ssn = ssn ? *ssn : 0; | 724 | __entry->ssn = ssn ? *ssn : 0; |
725 | __entry->buf_size = buf_size; | ||
807 | ), | 726 | ), |
808 | 727 | ||
809 | TP_printk( | 728 | TP_printk( |
810 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d", | 729 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d", |
811 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid | 730 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, |
731 | __entry->tid, __entry->buf_size | ||
812 | ) | 732 | ) |
813 | ); | 733 | ); |
814 | 734 | ||
@@ -959,22 +879,9 @@ TRACE_EVENT(drv_remain_on_channel, | |||
959 | ) | 879 | ) |
960 | ); | 880 | ); |
961 | 881 | ||
962 | TRACE_EVENT(drv_cancel_remain_on_channel, | 882 | DEFINE_EVENT(local_only_evt, drv_cancel_remain_on_channel, |
963 | TP_PROTO(struct ieee80211_local *local), | 883 | TP_PROTO(struct ieee80211_local *local), |
964 | 884 | TP_ARGS(local) | |
965 | TP_ARGS(local), | ||
966 | |||
967 | TP_STRUCT__entry( | ||
968 | LOCAL_ENTRY | ||
969 | ), | ||
970 | |||
971 | TP_fast_assign( | ||
972 | LOCAL_ASSIGN; | ||
973 | ), | ||
974 | |||
975 | TP_printk( | ||
976 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
977 | ) | ||
978 | ); | 885 | ); |
979 | 886 | ||
980 | /* | 887 | /* |
@@ -1069,23 +976,9 @@ TRACE_EVENT(api_stop_tx_ba_cb, | |||
1069 | ) | 976 | ) |
1070 | ); | 977 | ); |
1071 | 978 | ||
1072 | TRACE_EVENT(api_restart_hw, | 979 | DEFINE_EVENT(local_only_evt, api_restart_hw, |
1073 | TP_PROTO(struct ieee80211_local *local), | 980 | TP_PROTO(struct ieee80211_local *local), |
1074 | 981 | TP_ARGS(local) | |
1075 | TP_ARGS(local), | ||
1076 | |||
1077 | TP_STRUCT__entry( | ||
1078 | LOCAL_ENTRY | ||
1079 | ), | ||
1080 | |||
1081 | TP_fast_assign( | ||
1082 | LOCAL_ASSIGN; | ||
1083 | ), | ||
1084 | |||
1085 | TP_printk( | ||
1086 | LOCAL_PR_FMT, | ||
1087 | LOCAL_PR_ARG | ||
1088 | ) | ||
1089 | ); | 982 | ); |
1090 | 983 | ||
1091 | TRACE_EVENT(api_beacon_loss, | 984 | TRACE_EVENT(api_beacon_loss, |
@@ -1214,40 +1107,14 @@ TRACE_EVENT(api_chswitch_done, | |||
1214 | ) | 1107 | ) |
1215 | ); | 1108 | ); |
1216 | 1109 | ||
1217 | TRACE_EVENT(api_ready_on_channel, | 1110 | DEFINE_EVENT(local_only_evt, api_ready_on_channel, |
1218 | TP_PROTO(struct ieee80211_local *local), | 1111 | TP_PROTO(struct ieee80211_local *local), |
1219 | 1112 | TP_ARGS(local) | |
1220 | TP_ARGS(local), | ||
1221 | |||
1222 | TP_STRUCT__entry( | ||
1223 | LOCAL_ENTRY | ||
1224 | ), | ||
1225 | |||
1226 | TP_fast_assign( | ||
1227 | LOCAL_ASSIGN; | ||
1228 | ), | ||
1229 | |||
1230 | TP_printk( | ||
1231 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
1232 | ) | ||
1233 | ); | 1113 | ); |
1234 | 1114 | ||
1235 | TRACE_EVENT(api_remain_on_channel_expired, | 1115 | DEFINE_EVENT(local_only_evt, api_remain_on_channel_expired, |
1236 | TP_PROTO(struct ieee80211_local *local), | 1116 | TP_PROTO(struct ieee80211_local *local), |
1237 | 1117 | TP_ARGS(local) | |
1238 | TP_ARGS(local), | ||
1239 | |||
1240 | TP_STRUCT__entry( | ||
1241 | LOCAL_ENTRY | ||
1242 | ), | ||
1243 | |||
1244 | TP_fast_assign( | ||
1245 | LOCAL_ASSIGN; | ||
1246 | ), | ||
1247 | |||
1248 | TP_printk( | ||
1249 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
1250 | ) | ||
1251 | ); | 1118 | ); |
1252 | 1119 | ||
1253 | /* | 1120 | /* |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 53c7077ffd4f..a42aa61269ea 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -270,7 +270,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
270 | enum ieee80211_band band = rx_status->band; | 270 | enum ieee80211_band band = rx_status->band; |
271 | 271 | ||
272 | if (elems->ds_params && elems->ds_params_len == 1) | 272 | if (elems->ds_params && elems->ds_params_len == 1) |
273 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 273 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], |
274 | band); | ||
274 | else | 275 | else |
275 | freq = rx_status->freq; | 276 | freq = rx_status->freq; |
276 | 277 | ||
@@ -663,12 +664,13 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
663 | } | 664 | } |
664 | 665 | ||
665 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | 666 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, |
666 | struct ieee80211_mgmt *mgmt, | 667 | struct sk_buff *req) |
667 | size_t len) | ||
668 | { | 668 | { |
669 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req); | ||
670 | struct ieee80211_mgmt *mgmt = (void *)req->data; | ||
669 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 671 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
670 | struct ieee80211_local *local = sdata->local; | 672 | struct ieee80211_local *local = sdata->local; |
671 | int tx_last_beacon; | 673 | int tx_last_beacon, len = req->len; |
672 | struct sk_buff *skb; | 674 | struct sk_buff *skb; |
673 | struct ieee80211_mgmt *resp; | 675 | struct ieee80211_mgmt *resp; |
674 | u8 *pos, *end; | 676 | u8 *pos, *end; |
@@ -688,7 +690,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
688 | mgmt->bssid, tx_last_beacon); | 690 | mgmt->bssid, tx_last_beacon); |
689 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 691 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
690 | 692 | ||
691 | if (!tx_last_beacon) | 693 | if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH)) |
692 | return; | 694 | return; |
693 | 695 | ||
694 | if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && | 696 | if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && |
@@ -785,7 +787,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
785 | 787 | ||
786 | switch (fc & IEEE80211_FCTL_STYPE) { | 788 | switch (fc & IEEE80211_FCTL_STYPE) { |
787 | case IEEE80211_STYPE_PROBE_REQ: | 789 | case IEEE80211_STYPE_PROBE_REQ: |
788 | ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); | 790 | ieee80211_rx_mgmt_probe_req(sdata, skb); |
789 | break; | 791 | break; |
790 | case IEEE80211_STYPE_PROBE_RESP: | 792 | case IEEE80211_STYPE_PROBE_RESP: |
791 | ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, | 793 | ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 533fd32f49ff..0a570a111a84 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -225,6 +225,7 @@ struct ieee80211_if_ap { | |||
225 | struct sk_buff_head ps_bc_buf; | 225 | struct sk_buff_head ps_bc_buf; |
226 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 226 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
227 | int dtim_count; | 227 | int dtim_count; |
228 | bool dtim_bc_mc; | ||
228 | }; | 229 | }; |
229 | 230 | ||
230 | struct ieee80211_if_wds { | 231 | struct ieee80211_if_wds { |
@@ -654,8 +655,6 @@ struct tpt_led_trigger { | |||
654 | * well be on the operating channel | 655 | * well be on the operating channel |
655 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to | 656 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to |
656 | * determine if we are on the operating channel or not | 657 | * determine if we are on the operating channel or not |
657 | * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, | ||
658 | * gets only set in conjunction with SCAN_SW_SCANNING | ||
659 | * @SCAN_COMPLETED: Set for our scan work function when the driver reported | 658 | * @SCAN_COMPLETED: Set for our scan work function when the driver reported |
660 | * that the scan completed. | 659 | * that the scan completed. |
661 | * @SCAN_ABORTED: Set for our scan work function when the driver reported | 660 | * @SCAN_ABORTED: Set for our scan work function when the driver reported |
@@ -664,7 +663,6 @@ struct tpt_led_trigger { | |||
664 | enum { | 663 | enum { |
665 | SCAN_SW_SCANNING, | 664 | SCAN_SW_SCANNING, |
666 | SCAN_HW_SCANNING, | 665 | SCAN_HW_SCANNING, |
667 | SCAN_OFF_CHANNEL, | ||
668 | SCAN_COMPLETED, | 666 | SCAN_COMPLETED, |
669 | SCAN_ABORTED, | 667 | SCAN_ABORTED, |
670 | }; | 668 | }; |
@@ -1068,8 +1066,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
1068 | void ieee80211_configure_filter(struct ieee80211_local *local); | 1066 | void ieee80211_configure_filter(struct ieee80211_local *local); |
1069 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); | 1067 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
1070 | 1068 | ||
1071 | extern bool ieee80211_disable_40mhz_24ghz; | ||
1072 | |||
1073 | /* STA code */ | 1069 | /* STA code */ |
1074 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); | 1070 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
1075 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 1071 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
@@ -1147,10 +1143,14 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, | |||
1147 | struct ieee80211_bss *bss); | 1143 | struct ieee80211_bss *bss); |
1148 | 1144 | ||
1149 | /* off-channel helpers */ | 1145 | /* off-channel helpers */ |
1150 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); | 1146 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); |
1151 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local); | 1147 | void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, |
1148 | bool tell_ap); | ||
1149 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | ||
1150 | bool offchannel_ps_enable); | ||
1152 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 1151 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
1153 | bool enable_beaconing); | 1152 | bool enable_beaconing, |
1153 | bool offchannel_ps_disable); | ||
1154 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); | 1154 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); |
1155 | 1155 | ||
1156 | /* interface handling */ | 1156 | /* interface handling */ |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 7a10a8d1b2d0..4054399be907 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -382,6 +382,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
382 | struct sk_buff *skb, *tmp; | 382 | struct sk_buff *skb, *tmp; |
383 | u32 hw_reconf_flags = 0; | 383 | u32 hw_reconf_flags = 0; |
384 | int i; | 384 | int i; |
385 | enum nl80211_channel_type orig_ct; | ||
385 | 386 | ||
386 | if (local->scan_sdata == sdata) | 387 | if (local->scan_sdata == sdata) |
387 | ieee80211_scan_cancel(local); | 388 | ieee80211_scan_cancel(local); |
@@ -542,8 +543,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
542 | hw_reconf_flags = 0; | 543 | hw_reconf_flags = 0; |
543 | } | 544 | } |
544 | 545 | ||
546 | /* Re-calculate channel-type, in case there are multiple vifs | ||
547 | * on different channel types. | ||
548 | */ | ||
549 | orig_ct = local->_oper_channel_type; | ||
550 | ieee80211_set_channel_type(local, NULL, NL80211_CHAN_NO_HT); | ||
551 | |||
545 | /* do after stop to avoid reconfiguring when we stop anyway */ | 552 | /* do after stop to avoid reconfiguring when we stop anyway */ |
546 | if (hw_reconf_flags) | 553 | if (hw_reconf_flags || (orig_ct != local->_oper_channel_type)) |
547 | ieee80211_hw_config(local, hw_reconf_flags); | 554 | ieee80211_hw_config(local, hw_reconf_flags); |
548 | 555 | ||
549 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 556 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a46ff06d7cb8..2543e48bd813 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include "debugfs.h" | 34 | #include "debugfs.h" |
35 | 35 | ||
36 | 36 | ||
37 | bool ieee80211_disable_40mhz_24ghz; | 37 | static bool ieee80211_disable_40mhz_24ghz; |
38 | module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); | 38 | module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); |
39 | MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, | 39 | MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, |
40 | "Disable 40MHz support in the 2.4GHz band"); | 40 | "Disable 40MHz support in the 2.4GHz band"); |
@@ -98,6 +98,47 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | |||
98 | ieee80211_configure_filter(local); | 98 | ieee80211_configure_filter(local); |
99 | } | 99 | } |
100 | 100 | ||
101 | /* | ||
102 | * Returns true if we are logically configured to be on | ||
103 | * the operating channel AND the hardware-conf is currently | ||
104 | * configured on the operating channel. Compares channel-type | ||
105 | * as well. | ||
106 | */ | ||
107 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) | ||
108 | { | ||
109 | struct ieee80211_channel *chan, *scan_chan; | ||
110 | enum nl80211_channel_type channel_type; | ||
111 | |||
112 | /* This logic needs to match logic in ieee80211_hw_config */ | ||
113 | if (local->scan_channel) { | ||
114 | chan = local->scan_channel; | ||
115 | /* If scanning on oper channel, use whatever channel-type | ||
116 | * is currently in use. | ||
117 | */ | ||
118 | if (chan == local->oper_channel) | ||
119 | channel_type = local->_oper_channel_type; | ||
120 | else | ||
121 | channel_type = NL80211_CHAN_NO_HT; | ||
122 | } else if (local->tmp_channel) { | ||
123 | chan = scan_chan = local->tmp_channel; | ||
124 | channel_type = local->tmp_channel_type; | ||
125 | } else { | ||
126 | chan = local->oper_channel; | ||
127 | channel_type = local->_oper_channel_type; | ||
128 | } | ||
129 | |||
130 | if (chan != local->oper_channel || | ||
131 | channel_type != local->_oper_channel_type) | ||
132 | return false; | ||
133 | |||
134 | /* Check current hardware-config against oper_channel. */ | ||
135 | if ((local->oper_channel != local->hw.conf.channel) || | ||
136 | (local->_oper_channel_type != local->hw.conf.channel_type)) | ||
137 | return false; | ||
138 | |||
139 | return true; | ||
140 | } | ||
141 | |||
101 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 142 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
102 | { | 143 | { |
103 | struct ieee80211_channel *chan, *scan_chan; | 144 | struct ieee80211_channel *chan, *scan_chan; |
@@ -110,21 +151,33 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
110 | 151 | ||
111 | scan_chan = local->scan_channel; | 152 | scan_chan = local->scan_channel; |
112 | 153 | ||
154 | /* If this off-channel logic ever changes, ieee80211_on_oper_channel | ||
155 | * may need to change as well. | ||
156 | */ | ||
113 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 157 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
114 | if (scan_chan) { | 158 | if (scan_chan) { |
115 | chan = scan_chan; | 159 | chan = scan_chan; |
116 | channel_type = NL80211_CHAN_NO_HT; | 160 | /* If scanning on oper channel, use whatever channel-type |
117 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 161 | * is currently in use. |
118 | } else if (local->tmp_channel && | 162 | */ |
119 | local->oper_channel != local->tmp_channel) { | 163 | if (chan == local->oper_channel) |
164 | channel_type = local->_oper_channel_type; | ||
165 | else | ||
166 | channel_type = NL80211_CHAN_NO_HT; | ||
167 | } else if (local->tmp_channel) { | ||
120 | chan = scan_chan = local->tmp_channel; | 168 | chan = scan_chan = local->tmp_channel; |
121 | channel_type = local->tmp_channel_type; | 169 | channel_type = local->tmp_channel_type; |
122 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | ||
123 | } else { | 170 | } else { |
124 | chan = local->oper_channel; | 171 | chan = local->oper_channel; |
125 | channel_type = local->_oper_channel_type; | 172 | channel_type = local->_oper_channel_type; |
126 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | ||
127 | } | 173 | } |
174 | |||
175 | if (chan != local->oper_channel || | ||
176 | channel_type != local->_oper_channel_type) | ||
177 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | ||
178 | else | ||
179 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | ||
180 | |||
128 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 181 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
129 | 182 | ||
130 | if (offchannel_flag || chan != local->hw.conf.channel || | 183 | if (offchannel_flag || chan != local->hw.conf.channel || |
@@ -146,7 +199,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
146 | changed |= IEEE80211_CONF_CHANGE_SMPS; | 199 | changed |= IEEE80211_CONF_CHANGE_SMPS; |
147 | } | 200 | } |
148 | 201 | ||
149 | if (scan_chan) | 202 | if ((local->scanning & SCAN_SW_SCANNING) || |
203 | (local->scanning & SCAN_HW_SCANNING)) | ||
150 | power = chan->max_power; | 204 | power = chan->max_power; |
151 | else | 205 | else |
152 | power = local->power_constr_level ? | 206 | power = local->power_constr_level ? |
@@ -231,7 +285,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
231 | 285 | ||
232 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 286 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
233 | if (local->quiescing || !ieee80211_sdata_running(sdata) || | 287 | if (local->quiescing || !ieee80211_sdata_running(sdata) || |
234 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { | 288 | test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { |
235 | sdata->vif.bss_conf.enable_beacon = false; | 289 | sdata->vif.bss_conf.enable_beacon = false; |
236 | } else { | 290 | } else { |
237 | /* | 291 | /* |
@@ -554,6 +608,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
554 | local->hw.queues = 1; | 608 | local->hw.queues = 1; |
555 | local->hw.max_rates = 1; | 609 | local->hw.max_rates = 1; |
556 | local->hw.max_report_rates = 0; | 610 | local->hw.max_report_rates = 0; |
611 | local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; | ||
557 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 612 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
558 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 613 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
559 | local->user_power_level = -1; | 614 | local->user_power_level = -1; |
@@ -668,6 +723,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
668 | } | 723 | } |
669 | channels += sband->n_channels; | 724 | channels += sband->n_channels; |
670 | 725 | ||
726 | /* | ||
727 | * Since ieee80211_disable_40mhz_24ghz is global, we can | ||
728 | * modify the sband's ht data even if the driver uses a | ||
729 | * global structure for that. | ||
730 | */ | ||
731 | if (ieee80211_disable_40mhz_24ghz && | ||
732 | band == IEEE80211_BAND_2GHZ && | ||
733 | sband->ht_cap.ht_supported) { | ||
734 | sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
735 | sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
736 | } | ||
737 | |||
671 | if (max_bitrates < sband->n_bitrates) | 738 | if (max_bitrates < sband->n_bitrates) |
672 | max_bitrates = sband->n_bitrates; | 739 | max_bitrates = sband->n_bitrates; |
673 | supp_ht = supp_ht || sband->ht_cap.ht_supported; | 740 | supp_ht = supp_ht || sband->ht_cap.ht_supported; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index ca3af4685b0a..2a57cc02c618 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
574 | &elems); | 574 | &elems); |
575 | 575 | ||
576 | if (elems.ds_params && elems.ds_params_len == 1) | 576 | if (elems.ds_params && elems.ds_params_len == 1) |
577 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | 577 | freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); |
578 | else | 578 | else |
579 | freq = rx_status->freq; | 579 | freq = rx_status->freq; |
580 | 580 | ||
@@ -645,7 +645,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
645 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) | 645 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) |
646 | mesh_mpath_table_grow(); | 646 | mesh_mpath_table_grow(); |
647 | 647 | ||
648 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) | 648 | if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags)) |
649 | mesh_mpp_table_grow(); | 649 | mesh_mpp_table_grow(); |
650 | 650 | ||
651 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) | 651 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c9ceb4d57ab0..7b3f9df725bd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -28,8 +28,15 @@ | |||
28 | #include "rate.h" | 28 | #include "rate.h" |
29 | #include "led.h" | 29 | #include "led.h" |
30 | 30 | ||
31 | #define IEEE80211_MAX_NULLFUNC_TRIES 2 | 31 | static int max_nullfunc_tries = 2; |
32 | #define IEEE80211_MAX_PROBE_TRIES 5 | 32 | module_param(max_nullfunc_tries, int, 0644); |
33 | MODULE_PARM_DESC(max_nullfunc_tries, | ||
34 | "Maximum nullfunc tx tries before disconnecting (reason 4)."); | ||
35 | |||
36 | static int max_probe_tries = 5; | ||
37 | module_param(max_probe_tries, int, 0644); | ||
38 | MODULE_PARM_DESC(max_probe_tries, | ||
39 | "Maximum probe tries before disconnecting (reason 4)."); | ||
33 | 40 | ||
34 | /* | 41 | /* |
35 | * Beacon loss timeout is calculated as N frames times the | 42 | * Beacon loss timeout is calculated as N frames times the |
@@ -51,7 +58,11 @@ | |||
51 | * a probe request because of beacon loss or for | 58 | * a probe request because of beacon loss or for |
52 | * checking the connection still works. | 59 | * checking the connection still works. |
53 | */ | 60 | */ |
54 | #define IEEE80211_PROBE_WAIT (HZ / 2) | 61 | static int probe_wait_ms = 500; |
62 | module_param(probe_wait_ms, int, 0644); | ||
63 | MODULE_PARM_DESC(probe_wait_ms, | ||
64 | "Maximum time(ms) to wait for probe response" | ||
65 | " before disconnecting (reason 4)."); | ||
55 | 66 | ||
56 | /* | 67 | /* |
57 | * Weight given to the latest Beacon frame when calculating average signal | 68 | * Weight given to the latest Beacon frame when calculating average signal |
@@ -161,6 +172,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
161 | struct ieee80211_supported_band *sband; | 172 | struct ieee80211_supported_band *sband; |
162 | struct sta_info *sta; | 173 | struct sta_info *sta; |
163 | u32 changed = 0; | 174 | u32 changed = 0; |
175 | int hti_cfreq; | ||
164 | u16 ht_opmode; | 176 | u16 ht_opmode; |
165 | bool enable_ht = true; | 177 | bool enable_ht = true; |
166 | enum nl80211_channel_type prev_chantype; | 178 | enum nl80211_channel_type prev_chantype; |
@@ -174,10 +186,27 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
174 | if (!sband->ht_cap.ht_supported) | 186 | if (!sband->ht_cap.ht_supported) |
175 | enable_ht = false; | 187 | enable_ht = false; |
176 | 188 | ||
177 | /* check that channel matches the right operating channel */ | 189 | if (enable_ht) { |
178 | if (local->hw.conf.channel->center_freq != | 190 | hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan, |
179 | ieee80211_channel_to_frequency(hti->control_chan)) | 191 | sband->band); |
180 | enable_ht = false; | 192 | /* check that channel matches the right operating channel */ |
193 | if (local->hw.conf.channel->center_freq != hti_cfreq) { | ||
194 | /* Some APs mess this up, evidently. | ||
195 | * Netgear WNDR3700 sometimes reports 4 higher than | ||
196 | * the actual channel, for instance. | ||
197 | */ | ||
198 | printk(KERN_DEBUG | ||
199 | "%s: Wrong control channel in association" | ||
200 | " response: configured center-freq: %d" | ||
201 | " hti-cfreq: %d hti->control_chan: %d" | ||
202 | " band: %d. Disabling HT.\n", | ||
203 | sdata->name, | ||
204 | local->hw.conf.channel->center_freq, | ||
205 | hti_cfreq, hti->control_chan, | ||
206 | sband->band); | ||
207 | enable_ht = false; | ||
208 | } | ||
209 | } | ||
181 | 210 | ||
182 | if (enable_ht) { | 211 | if (enable_ht) { |
183 | channel_type = NL80211_CHAN_HT20; | 212 | channel_type = NL80211_CHAN_HT20; |
@@ -429,7 +458,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
429 | container_of((void *)bss, struct cfg80211_bss, priv); | 458 | container_of((void *)bss, struct cfg80211_bss, priv); |
430 | struct ieee80211_channel *new_ch; | 459 | struct ieee80211_channel *new_ch; |
431 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 460 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
432 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); | 461 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num, |
462 | cbss->channel->band); | ||
433 | 463 | ||
434 | ASSERT_MGD_MTX(ifmgd); | 464 | ASSERT_MGD_MTX(ifmgd); |
435 | 465 | ||
@@ -600,6 +630,14 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
600 | list_for_each_entry(sdata, &local->interfaces, list) { | 630 | list_for_each_entry(sdata, &local->interfaces, list) { |
601 | if (!ieee80211_sdata_running(sdata)) | 631 | if (!ieee80211_sdata_running(sdata)) |
602 | continue; | 632 | continue; |
633 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
634 | /* If an AP vif is found, then disable PS | ||
635 | * by setting the count to zero thereby setting | ||
636 | * ps_sdata to NULL. | ||
637 | */ | ||
638 | count = 0; | ||
639 | break; | ||
640 | } | ||
603 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 641 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
604 | continue; | 642 | continue; |
605 | found = sdata; | 643 | found = sdata; |
@@ -1095,7 +1133,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1095 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1133 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1096 | const u8 *ssid; | 1134 | const u8 *ssid; |
1097 | u8 *dst = ifmgd->associated->bssid; | 1135 | u8 *dst = ifmgd->associated->bssid; |
1098 | u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3); | 1136 | u8 unicast_limit = max(1, max_probe_tries - 3); |
1099 | 1137 | ||
1100 | /* | 1138 | /* |
1101 | * Try sending broadcast probe requests for the last three | 1139 | * Try sending broadcast probe requests for the last three |
@@ -1121,7 +1159,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1121 | } | 1159 | } |
1122 | 1160 | ||
1123 | ifmgd->probe_send_count++; | 1161 | ifmgd->probe_send_count++; |
1124 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | 1162 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
1125 | run_again(ifmgd, ifmgd->probe_timeout); | 1163 | run_again(ifmgd, ifmgd->probe_timeout); |
1126 | } | 1164 | } |
1127 | 1165 | ||
@@ -1222,7 +1260,8 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1222 | 1260 | ||
1223 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 1261 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1224 | 1262 | ||
1225 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | 1263 | printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n", |
1264 | sdata->name, bssid); | ||
1226 | 1265 | ||
1227 | ieee80211_set_disassoc(sdata, true, true); | 1266 | ieee80211_set_disassoc(sdata, true, true); |
1228 | mutex_unlock(&ifmgd->mtx); | 1267 | mutex_unlock(&ifmgd->mtx); |
@@ -1525,7 +1564,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1525 | } | 1564 | } |
1526 | 1565 | ||
1527 | if (elems->ds_params && elems->ds_params_len == 1) | 1566 | if (elems->ds_params && elems->ds_params_len == 1) |
1528 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 1567 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], |
1568 | rx_status->band); | ||
1529 | else | 1569 | else |
1530 | freq = rx_status->freq; | 1570 | freq = rx_status->freq; |
1531 | 1571 | ||
@@ -1966,9 +2006,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1966 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 2006 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1967 | 2007 | ||
1968 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 2008 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
1969 | max_tries = IEEE80211_MAX_NULLFUNC_TRIES; | 2009 | max_tries = max_nullfunc_tries; |
1970 | else | 2010 | else |
1971 | max_tries = IEEE80211_MAX_PROBE_TRIES; | 2011 | max_tries = max_probe_tries; |
1972 | 2012 | ||
1973 | /* ACK received for nullfunc probing frame */ | 2013 | /* ACK received for nullfunc probing frame */ |
1974 | if (!ifmgd->probe_send_count) | 2014 | if (!ifmgd->probe_send_count) |
@@ -1978,9 +2018,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1978 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2018 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1979 | wiphy_debug(local->hw.wiphy, | 2019 | wiphy_debug(local->hw.wiphy, |
1980 | "%s: No ack for nullfunc frame to" | 2020 | "%s: No ack for nullfunc frame to" |
1981 | " AP %pM, try %d\n", | 2021 | " AP %pM, try %d/%i\n", |
1982 | sdata->name, bssid, | 2022 | sdata->name, bssid, |
1983 | ifmgd->probe_send_count); | 2023 | ifmgd->probe_send_count, max_tries); |
1984 | #endif | 2024 | #endif |
1985 | ieee80211_mgd_probe_ap_send(sdata); | 2025 | ieee80211_mgd_probe_ap_send(sdata); |
1986 | } else { | 2026 | } else { |
@@ -2000,17 +2040,17 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2000 | "%s: Failed to send nullfunc to AP %pM" | 2040 | "%s: Failed to send nullfunc to AP %pM" |
2001 | " after %dms, disconnecting.\n", | 2041 | " after %dms, disconnecting.\n", |
2002 | sdata->name, | 2042 | sdata->name, |
2003 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2043 | bssid, probe_wait_ms); |
2004 | #endif | 2044 | #endif |
2005 | ieee80211_sta_connection_lost(sdata, bssid); | 2045 | ieee80211_sta_connection_lost(sdata, bssid); |
2006 | } else if (ifmgd->probe_send_count < max_tries) { | 2046 | } else if (ifmgd->probe_send_count < max_tries) { |
2007 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2047 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
2008 | wiphy_debug(local->hw.wiphy, | 2048 | wiphy_debug(local->hw.wiphy, |
2009 | "%s: No probe response from AP %pM" | 2049 | "%s: No probe response from AP %pM" |
2010 | " after %dms, try %d\n", | 2050 | " after %dms, try %d/%i\n", |
2011 | sdata->name, | 2051 | sdata->name, |
2012 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ, | 2052 | bssid, probe_wait_ms, |
2013 | ifmgd->probe_send_count); | 2053 | ifmgd->probe_send_count, max_tries); |
2014 | #endif | 2054 | #endif |
2015 | ieee80211_mgd_probe_ap_send(sdata); | 2055 | ieee80211_mgd_probe_ap_send(sdata); |
2016 | } else { | 2056 | } else { |
@@ -2022,7 +2062,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2022 | "%s: No probe response from AP %pM" | 2062 | "%s: No probe response from AP %pM" |
2023 | " after %dms, disconnecting.\n", | 2063 | " after %dms, disconnecting.\n", |
2024 | sdata->name, | 2064 | sdata->name, |
2025 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2065 | bssid, probe_wait_ms); |
2026 | 2066 | ||
2027 | ieee80211_sta_connection_lost(sdata, bssid); | 2067 | ieee80211_sta_connection_lost(sdata, bssid); |
2028 | } | 2068 | } |
@@ -2260,6 +2300,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2260 | else | 2300 | else |
2261 | wk->type = IEEE80211_WORK_DIRECT_PROBE; | 2301 | wk->type = IEEE80211_WORK_DIRECT_PROBE; |
2262 | wk->chan = req->bss->channel; | 2302 | wk->chan = req->bss->channel; |
2303 | wk->chan_type = NL80211_CHAN_NO_HT; | ||
2263 | wk->sdata = sdata; | 2304 | wk->sdata = sdata; |
2264 | wk->done = ieee80211_probe_auth_done; | 2305 | wk->done = ieee80211_probe_auth_done; |
2265 | 2306 | ||
@@ -2409,6 +2450,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2409 | memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); | 2450 | memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); |
2410 | 2451 | ||
2411 | wk->chan = req->bss->channel; | 2452 | wk->chan = req->bss->channel; |
2453 | wk->chan_type = NL80211_CHAN_NO_HT; | ||
2412 | wk->sdata = sdata; | 2454 | wk->sdata = sdata; |
2413 | wk->done = ieee80211_assoc_done; | 2455 | wk->done = ieee80211_assoc_done; |
2414 | if (!bss->dtim_period && | 2456 | if (!bss->dtim_period && |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index b4e52676f3fb..13427b194ced 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -17,10 +17,14 @@ | |||
17 | #include "driver-trace.h" | 17 | #include "driver-trace.h" |
18 | 18 | ||
19 | /* | 19 | /* |
20 | * inform AP that we will go to sleep so that it will buffer the frames | 20 | * Tell our hardware to disable PS. |
21 | * while we scan | 21 | * Optionally inform AP that we will go to sleep so that it will buffer |
22 | * the frames while we are doing off-channel work. This is optional | ||
23 | * because we *may* be doing work on-operating channel, and want our | ||
24 | * hardware unconditionally awake, but still let the AP send us normal frames. | ||
22 | */ | 25 | */ |
23 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | 26 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, |
27 | bool tell_ap) | ||
24 | { | 28 | { |
25 | struct ieee80211_local *local = sdata->local; | 29 | struct ieee80211_local *local = sdata->local; |
26 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 30 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -41,8 +45,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | |||
41 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 45 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
42 | } | 46 | } |
43 | 47 | ||
44 | if (!(local->offchannel_ps_enabled) || | 48 | if (tell_ap && (!local->offchannel_ps_enabled || |
45 | !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) | 49 | !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))) |
46 | /* | 50 | /* |
47 | * If power save was enabled, no need to send a nullfunc | 51 | * If power save was enabled, no need to send a nullfunc |
48 | * frame because AP knows that we are sleeping. But if the | 52 | * frame because AP knows that we are sleeping. But if the |
@@ -77,6 +81,9 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
77 | * we are sleeping, let's just enable power save mode in | 81 | * we are sleeping, let's just enable power save mode in |
78 | * hardware. | 82 | * hardware. |
79 | */ | 83 | */ |
84 | /* TODO: Only set hardware if CONF_PS changed? | ||
85 | * TODO: Should we set offchannel_ps_enabled to false? | ||
86 | */ | ||
80 | local->hw.conf.flags |= IEEE80211_CONF_PS; | 87 | local->hw.conf.flags |= IEEE80211_CONF_PS; |
81 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 88 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
82 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { | 89 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { |
@@ -95,63 +102,61 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
95 | ieee80211_sta_reset_conn_monitor(sdata); | 102 | ieee80211_sta_reset_conn_monitor(sdata); |
96 | } | 103 | } |
97 | 104 | ||
98 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | 105 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, |
106 | bool offchannel_ps_enable) | ||
99 | { | 107 | { |
100 | struct ieee80211_sub_if_data *sdata; | 108 | struct ieee80211_sub_if_data *sdata; |
101 | 109 | ||
110 | /* | ||
111 | * notify the AP about us leaving the channel and stop all | ||
112 | * STA interfaces. | ||
113 | */ | ||
102 | mutex_lock(&local->iflist_mtx); | 114 | mutex_lock(&local->iflist_mtx); |
103 | list_for_each_entry(sdata, &local->interfaces, list) { | 115 | list_for_each_entry(sdata, &local->interfaces, list) { |
104 | if (!ieee80211_sdata_running(sdata)) | 116 | if (!ieee80211_sdata_running(sdata)) |
105 | continue; | 117 | continue; |
106 | 118 | ||
107 | /* disable beaconing */ | 119 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
120 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
121 | |||
122 | /* Check to see if we should disable beaconing. */ | ||
108 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 123 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
109 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 124 | sdata->vif.type == NL80211_IFTYPE_ADHOC || |
110 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 125 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
111 | ieee80211_bss_info_change_notify( | 126 | ieee80211_bss_info_change_notify( |
112 | sdata, BSS_CHANGED_BEACON_ENABLED); | 127 | sdata, BSS_CHANGED_BEACON_ENABLED); |
113 | 128 | ||
114 | /* | 129 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
115 | * only handle non-STA interfaces here, STA interfaces | ||
116 | * are handled in ieee80211_offchannel_stop_station(), | ||
117 | * e.g., from the background scan state machine. | ||
118 | * | ||
119 | * In addition, do not stop monitor interface to allow it to be | ||
120 | * used from user space controlled off-channel operations. | ||
121 | */ | ||
122 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
123 | sdata->vif.type != NL80211_IFTYPE_MONITOR) { | ||
124 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
125 | netif_tx_stop_all_queues(sdata->dev); | 130 | netif_tx_stop_all_queues(sdata->dev); |
131 | if (offchannel_ps_enable && | ||
132 | (sdata->vif.type == NL80211_IFTYPE_STATION) && | ||
133 | sdata->u.mgd.associated) | ||
134 | ieee80211_offchannel_ps_enable(sdata, true); | ||
126 | } | 135 | } |
127 | } | 136 | } |
128 | mutex_unlock(&local->iflist_mtx); | 137 | mutex_unlock(&local->iflist_mtx); |
129 | } | 138 | } |
130 | 139 | ||
131 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local) | 140 | void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, |
141 | bool tell_ap) | ||
132 | { | 142 | { |
133 | struct ieee80211_sub_if_data *sdata; | 143 | struct ieee80211_sub_if_data *sdata; |
134 | 144 | ||
135 | /* | ||
136 | * notify the AP about us leaving the channel and stop all STA interfaces | ||
137 | */ | ||
138 | mutex_lock(&local->iflist_mtx); | 145 | mutex_lock(&local->iflist_mtx); |
139 | list_for_each_entry(sdata, &local->interfaces, list) { | 146 | list_for_each_entry(sdata, &local->interfaces, list) { |
140 | if (!ieee80211_sdata_running(sdata)) | 147 | if (!ieee80211_sdata_running(sdata)) |
141 | continue; | 148 | continue; |
142 | 149 | ||
143 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 150 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
144 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 151 | sdata->u.mgd.associated) |
145 | netif_tx_stop_all_queues(sdata->dev); | 152 | ieee80211_offchannel_ps_enable(sdata, tell_ap); |
146 | if (sdata->u.mgd.associated) | ||
147 | ieee80211_offchannel_ps_enable(sdata); | ||
148 | } | ||
149 | } | 153 | } |
150 | mutex_unlock(&local->iflist_mtx); | 154 | mutex_unlock(&local->iflist_mtx); |
151 | } | 155 | } |
152 | 156 | ||
153 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 157 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
154 | bool enable_beaconing) | 158 | bool enable_beaconing, |
159 | bool offchannel_ps_disable) | ||
155 | { | 160 | { |
156 | struct ieee80211_sub_if_data *sdata; | 161 | struct ieee80211_sub_if_data *sdata; |
157 | 162 | ||
@@ -161,7 +166,8 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
161 | continue; | 166 | continue; |
162 | 167 | ||
163 | /* Tell AP we're back */ | 168 | /* Tell AP we're back */ |
164 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 169 | if (offchannel_ps_disable && |
170 | sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
165 | if (sdata->u.mgd.associated) | 171 | if (sdata->u.mgd.associated) |
166 | ieee80211_offchannel_ps_disable(sdata); | 172 | ieee80211_offchannel_ps_disable(sdata); |
167 | } | 173 | } |
@@ -181,7 +187,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
181 | netif_tx_wake_all_queues(sdata->dev); | 187 | netif_tx_wake_all_queues(sdata->dev); |
182 | } | 188 | } |
183 | 189 | ||
184 | /* re-enable beaconing */ | 190 | /* Check to see if we should re-enable beaconing */ |
185 | if (enable_beaconing && | 191 | if (enable_beaconing && |
186 | (sdata->vif.type == NL80211_IFTYPE_AP || | 192 | (sdata->vif.type == NL80211_IFTYPE_AP || |
187 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 193 | sdata->vif.type == NL80211_IFTYPE_ADHOC || |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a6701ed87f0d..f502634d43af 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -85,6 +85,9 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
85 | if (len & 1) /* padding for RX_FLAGS if necessary */ | 85 | if (len & 1) /* padding for RX_FLAGS if necessary */ |
86 | len++; | 86 | len++; |
87 | 87 | ||
88 | if (status->flag & RX_FLAG_HT) /* HT info */ | ||
89 | len += 3; | ||
90 | |||
88 | return len; | 91 | return len; |
89 | } | 92 | } |
90 | 93 | ||
@@ -139,11 +142,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
139 | /* IEEE80211_RADIOTAP_RATE */ | 142 | /* IEEE80211_RADIOTAP_RATE */ |
140 | if (status->flag & RX_FLAG_HT) { | 143 | if (status->flag & RX_FLAG_HT) { |
141 | /* | 144 | /* |
142 | * TODO: add following information into radiotap header once | 145 | * MCS information is a separate field in radiotap, |
143 | * suitable fields are defined for it: | 146 | * added below. |
144 | * - MCS index (status->rate_idx) | ||
145 | * - HT40 (status->flag & RX_FLAG_40MHZ) | ||
146 | * - short-GI (status->flag & RX_FLAG_SHORT_GI) | ||
147 | */ | 147 | */ |
148 | *pos = 0; | 148 | *pos = 0; |
149 | } else { | 149 | } else { |
@@ -193,6 +193,20 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
193 | rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; | 193 | rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; |
194 | put_unaligned_le16(rx_flags, pos); | 194 | put_unaligned_le16(rx_flags, pos); |
195 | pos += 2; | 195 | pos += 2; |
196 | |||
197 | if (status->flag & RX_FLAG_HT) { | ||
198 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); | ||
199 | *pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS | | ||
200 | IEEE80211_RADIOTAP_MCS_HAVE_GI | | ||
201 | IEEE80211_RADIOTAP_MCS_HAVE_BW; | ||
202 | *pos = 0; | ||
203 | if (status->flag & RX_FLAG_SHORT_GI) | ||
204 | *pos |= IEEE80211_RADIOTAP_MCS_SGI; | ||
205 | if (status->flag & RX_FLAG_40MHZ) | ||
206 | *pos |= IEEE80211_RADIOTAP_MCS_BW_40; | ||
207 | pos++; | ||
208 | *pos++ = status->rate_idx; | ||
209 | } | ||
196 | } | 210 | } |
197 | 211 | ||
198 | /* | 212 | /* |
@@ -392,16 +406,10 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
392 | if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN))) | 406 | if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN))) |
393 | return RX_CONTINUE; | 407 | return RX_CONTINUE; |
394 | 408 | ||
395 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) | 409 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) || |
410 | test_bit(SCAN_SW_SCANNING, &local->scanning)) | ||
396 | return ieee80211_scan_rx(rx->sdata, skb); | 411 | return ieee80211_scan_rx(rx->sdata, skb); |
397 | 412 | ||
398 | if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { | ||
399 | /* drop all the other packets during a software scan anyway */ | ||
400 | if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) | ||
401 | dev_kfree_skb(skb); | ||
402 | return RX_QUEUED; | ||
403 | } | ||
404 | |||
405 | /* scanning finished during invoking of handlers */ | 413 | /* scanning finished during invoking of handlers */ |
406 | I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); | 414 | I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); |
407 | return RX_DROP_UNUSABLE; | 415 | return RX_DROP_UNUSABLE; |
@@ -798,7 +806,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
798 | rx->local->dot11FrameDuplicateCount++; | 806 | rx->local->dot11FrameDuplicateCount++; |
799 | rx->sta->num_duplicates++; | 807 | rx->sta->num_duplicates++; |
800 | } | 808 | } |
801 | return RX_DROP_MONITOR; | 809 | return RX_DROP_UNUSABLE; |
802 | } else | 810 | } else |
803 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; | 811 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; |
804 | } | 812 | } |
@@ -824,18 +832,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
824 | ieee80211_is_pspoll(hdr->frame_control)) && | 832 | ieee80211_is_pspoll(hdr->frame_control)) && |
825 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && | 833 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
826 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && | 834 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && |
827 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { | 835 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) |
828 | if ((!ieee80211_has_fromds(hdr->frame_control) && | ||
829 | !ieee80211_has_tods(hdr->frame_control) && | ||
830 | ieee80211_is_data(hdr->frame_control)) || | ||
831 | !(status->rx_flags & IEEE80211_RX_RA_MATCH)) { | ||
832 | /* Drop IBSS frames and frames for other hosts | ||
833 | * silently. */ | ||
834 | return RX_DROP_MONITOR; | ||
835 | } | ||
836 | |||
837 | return RX_DROP_MONITOR; | 836 | return RX_DROP_MONITOR; |
838 | } | ||
839 | 837 | ||
840 | return RX_CONTINUE; | 838 | return RX_CONTINUE; |
841 | } | 839 | } |
@@ -1088,7 +1086,8 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1088 | 1086 | ||
1089 | atomic_inc(&sdata->bss->num_sta_ps); | 1087 | atomic_inc(&sdata->bss->num_sta_ps); |
1090 | set_sta_flags(sta, WLAN_STA_PS_STA); | 1088 | set_sta_flags(sta, WLAN_STA_PS_STA); |
1091 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); | 1089 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
1090 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); | ||
1092 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1091 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1093 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 1092 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
1094 | sdata->name, sta->sta.addr, sta->sta.aid); | 1093 | sdata->name, sta->sta.addr, sta->sta.aid); |
@@ -1117,6 +1116,27 @@ static void ap_sta_ps_end(struct sta_info *sta) | |||
1117 | ieee80211_sta_ps_deliver_wakeup(sta); | 1116 | ieee80211_sta_ps_deliver_wakeup(sta); |
1118 | } | 1117 | } |
1119 | 1118 | ||
1119 | int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start) | ||
1120 | { | ||
1121 | struct sta_info *sta_inf = container_of(sta, struct sta_info, sta); | ||
1122 | bool in_ps; | ||
1123 | |||
1124 | WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS)); | ||
1125 | |||
1126 | /* Don't let the same PS state be set twice */ | ||
1127 | in_ps = test_sta_flags(sta_inf, WLAN_STA_PS_STA); | ||
1128 | if ((start && in_ps) || (!start && !in_ps)) | ||
1129 | return -EINVAL; | ||
1130 | |||
1131 | if (start) | ||
1132 | ap_sta_ps_start(sta_inf); | ||
1133 | else | ||
1134 | ap_sta_ps_end(sta_inf); | ||
1135 | |||
1136 | return 0; | ||
1137 | } | ||
1138 | EXPORT_SYMBOL(ieee80211_sta_ps_transition); | ||
1139 | |||
1120 | static ieee80211_rx_result debug_noinline | 1140 | static ieee80211_rx_result debug_noinline |
1121 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 1141 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
1122 | { | 1142 | { |
@@ -1161,7 +1181,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1161 | * Change STA power saving mode only at the end of a frame | 1181 | * Change STA power saving mode only at the end of a frame |
1162 | * exchange sequence. | 1182 | * exchange sequence. |
1163 | */ | 1183 | */ |
1164 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 1184 | if (!(sta->local->hw.flags & IEEE80211_HW_AP_LINK_PS) && |
1185 | !ieee80211_has_morefrags(hdr->frame_control) && | ||
1165 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | 1186 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && |
1166 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1187 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1167 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 1188 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { |
@@ -1556,17 +1577,36 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1556 | { | 1577 | { |
1557 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1578 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1558 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1579 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1580 | bool check_port_control = false; | ||
1581 | struct ethhdr *ehdr; | ||
1582 | int ret; | ||
1559 | 1583 | ||
1560 | if (ieee80211_has_a4(hdr->frame_control) && | 1584 | if (ieee80211_has_a4(hdr->frame_control) && |
1561 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) | 1585 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) |
1562 | return -1; | 1586 | return -1; |
1563 | 1587 | ||
1588 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
1589 | !!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control)) { | ||
1590 | |||
1591 | if (!sdata->u.mgd.use_4addr) | ||
1592 | return -1; | ||
1593 | else | ||
1594 | check_port_control = true; | ||
1595 | } | ||
1596 | |||
1564 | if (is_multicast_ether_addr(hdr->addr1) && | 1597 | if (is_multicast_ether_addr(hdr->addr1) && |
1565 | ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) || | 1598 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) |
1566 | (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) | 1599 | return -1; |
1600 | |||
1601 | ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); | ||
1602 | if (ret < 0 || !check_port_control) | ||
1603 | return ret; | ||
1604 | |||
1605 | ehdr = (struct ethhdr *) rx->skb->data; | ||
1606 | if (ehdr->h_proto != rx->sdata->control_port_protocol) | ||
1567 | return -1; | 1607 | return -1; |
1568 | 1608 | ||
1569 | return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); | 1609 | return 0; |
1570 | } | 1610 | } |
1571 | 1611 | ||
1572 | /* | 1612 | /* |
@@ -1893,7 +1933,10 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1893 | dev->stats.rx_bytes += rx->skb->len; | 1933 | dev->stats.rx_bytes += rx->skb->len; |
1894 | 1934 | ||
1895 | if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && | 1935 | if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && |
1896 | !is_multicast_ether_addr(((struct ethhdr *)rx->skb->data)->h_dest)) { | 1936 | !is_multicast_ether_addr( |
1937 | ((struct ethhdr *)rx->skb->data)->h_dest) && | ||
1938 | (!local->scanning && | ||
1939 | !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) { | ||
1897 | mod_timer(&local->dynamic_ps_timer, jiffies + | 1940 | mod_timer(&local->dynamic_ps_timer, jiffies + |
1898 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1941 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1899 | } | 1942 | } |
@@ -2590,7 +2633,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2590 | return 0; | 2633 | return 0; |
2591 | if (!multicast && | 2634 | if (!multicast && |
2592 | compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { | 2635 | compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { |
2593 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2636 | if (!(sdata->dev->flags & IFF_PROMISC) || |
2637 | sdata->u.mgd.use_4addr) | ||
2594 | return 0; | 2638 | return 0; |
2595 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2639 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2596 | } | 2640 | } |
@@ -2639,7 +2683,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2639 | return 0; | 2683 | return 0; |
2640 | } else if (!ieee80211_bssid_match(bssid, | 2684 | } else if (!ieee80211_bssid_match(bssid, |
2641 | sdata->vif.addr)) { | 2685 | sdata->vif.addr)) { |
2642 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN)) | 2686 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && |
2687 | !ieee80211_is_beacon(hdr->frame_control)) | ||
2643 | return 0; | 2688 | return 0; |
2644 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2689 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2645 | } | 2690 | } |
@@ -2692,7 +2737,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, | |||
2692 | if (!skb) { | 2737 | if (!skb) { |
2693 | if (net_ratelimit()) | 2738 | if (net_ratelimit()) |
2694 | wiphy_debug(local->hw.wiphy, | 2739 | wiphy_debug(local->hw.wiphy, |
2695 | "failed to copy multicast frame for %s\n", | 2740 | "failed to copy skb for %s\n", |
2696 | sdata->name); | 2741 | sdata->name); |
2697 | return true; | 2742 | return true; |
2698 | } | 2743 | } |
@@ -2730,7 +2775,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2730 | local->dot11ReceivedFragmentCount++; | 2775 | local->dot11ReceivedFragmentCount++; |
2731 | 2776 | ||
2732 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 2777 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2733 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | 2778 | test_bit(SCAN_SW_SCANNING, &local->scanning))) |
2734 | status->rx_flags |= IEEE80211_RX_IN_SCAN; | 2779 | status->rx_flags |= IEEE80211_RX_IN_SCAN; |
2735 | 2780 | ||
2736 | if (ieee80211_is_mgmt(fc)) | 2781 | if (ieee80211_is_mgmt(fc)) |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index fb274db77e3c..842954509925 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -196,7 +196,8 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
196 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); | 196 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); |
197 | 197 | ||
198 | if (elems.ds_params && elems.ds_params_len == 1) | 198 | if (elems.ds_params && elems.ds_params_len == 1) |
199 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | 199 | freq = ieee80211_channel_to_frequency(elems.ds_params[0], |
200 | rx_status->band); | ||
200 | else | 201 | else |
201 | freq = rx_status->freq; | 202 | freq = rx_status->freq; |
202 | 203 | ||
@@ -211,6 +212,14 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
211 | if (bss) | 212 | if (bss) |
212 | ieee80211_rx_bss_put(sdata->local, bss); | 213 | ieee80211_rx_bss_put(sdata->local, bss); |
213 | 214 | ||
215 | /* If we are on-operating-channel, and this packet is for the | ||
216 | * current channel, pass the pkt on up the stack so that | ||
217 | * the rest of the stack can make use of it. | ||
218 | */ | ||
219 | if (ieee80211_cfg_on_oper_channel(sdata->local) | ||
220 | && (channel == sdata->local->oper_channel)) | ||
221 | return RX_CONTINUE; | ||
222 | |||
214 | dev_kfree_skb(skb); | 223 | dev_kfree_skb(skb); |
215 | return RX_QUEUED; | 224 | return RX_QUEUED; |
216 | } | 225 | } |
@@ -292,15 +301,35 @@ static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw, | |||
292 | bool was_hw_scan) | 301 | bool was_hw_scan) |
293 | { | 302 | { |
294 | struct ieee80211_local *local = hw_to_local(hw); | 303 | struct ieee80211_local *local = hw_to_local(hw); |
304 | bool on_oper_chan; | ||
305 | bool enable_beacons = false; | ||
306 | |||
307 | mutex_lock(&local->mtx); | ||
308 | on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
309 | |||
310 | WARN_ON(local->scanning & (SCAN_SW_SCANNING | SCAN_HW_SCANNING)); | ||
311 | |||
312 | if (was_hw_scan || !on_oper_chan) { | ||
313 | if (WARN_ON(local->scan_channel)) | ||
314 | local->scan_channel = NULL; | ||
315 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
316 | } else | ||
317 | /* Set power back to normal operating levels. */ | ||
318 | ieee80211_hw_config(local, 0); | ||
295 | 319 | ||
296 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
297 | if (!was_hw_scan) { | 320 | if (!was_hw_scan) { |
321 | bool on_oper_chan2; | ||
298 | ieee80211_configure_filter(local); | 322 | ieee80211_configure_filter(local); |
299 | drv_sw_scan_complete(local); | 323 | drv_sw_scan_complete(local); |
300 | ieee80211_offchannel_return(local, true); | 324 | on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); |
325 | /* We should always be on-channel at this point. */ | ||
326 | WARN_ON(!on_oper_chan2); | ||
327 | if (on_oper_chan2 && (on_oper_chan != on_oper_chan2)) | ||
328 | enable_beacons = true; | ||
329 | |||
330 | ieee80211_offchannel_return(local, enable_beacons, true); | ||
301 | } | 331 | } |
302 | 332 | ||
303 | mutex_lock(&local->mtx); | ||
304 | ieee80211_recalc_idle(local); | 333 | ieee80211_recalc_idle(local); |
305 | mutex_unlock(&local->mtx); | 334 | mutex_unlock(&local->mtx); |
306 | 335 | ||
@@ -340,16 +369,21 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
340 | */ | 369 | */ |
341 | drv_sw_scan_start(local); | 370 | drv_sw_scan_start(local); |
342 | 371 | ||
343 | ieee80211_offchannel_stop_beaconing(local); | ||
344 | |||
345 | local->leave_oper_channel_time = 0; | 372 | local->leave_oper_channel_time = 0; |
346 | local->next_scan_state = SCAN_DECISION; | 373 | local->next_scan_state = SCAN_DECISION; |
347 | local->scan_channel_idx = 0; | 374 | local->scan_channel_idx = 0; |
348 | 375 | ||
349 | drv_flush(local, false); | 376 | /* We always want to use off-channel PS, even if we |
377 | * are not really leaving oper-channel. Don't | ||
378 | * tell the AP though, as long as we are on-channel. | ||
379 | */ | ||
380 | ieee80211_offchannel_enable_all_ps(local, false); | ||
350 | 381 | ||
351 | ieee80211_configure_filter(local); | 382 | ieee80211_configure_filter(local); |
352 | 383 | ||
384 | /* We need to set power level at maximum rate for scanning. */ | ||
385 | ieee80211_hw_config(local, 0); | ||
386 | |||
353 | ieee80211_queue_delayed_work(&local->hw, | 387 | ieee80211_queue_delayed_work(&local->hw, |
354 | &local->scan_work, | 388 | &local->scan_work, |
355 | IEEE80211_CHANNEL_TIME); | 389 | IEEE80211_CHANNEL_TIME); |
@@ -486,7 +520,20 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
486 | } | 520 | } |
487 | mutex_unlock(&local->iflist_mtx); | 521 | mutex_unlock(&local->iflist_mtx); |
488 | 522 | ||
489 | if (local->scan_channel) { | 523 | next_chan = local->scan_req->channels[local->scan_channel_idx]; |
524 | |||
525 | if (ieee80211_cfg_on_oper_channel(local)) { | ||
526 | /* We're currently on operating channel. */ | ||
527 | if (next_chan == local->oper_channel) | ||
528 | /* We don't need to move off of operating channel. */ | ||
529 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
530 | else | ||
531 | /* | ||
532 | * We do need to leave operating channel, as next | ||
533 | * scan is somewhere else. | ||
534 | */ | ||
535 | local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
536 | } else { | ||
490 | /* | 537 | /* |
491 | * we're currently scanning a different channel, let's | 538 | * we're currently scanning a different channel, let's |
492 | * see if we can scan another channel without interfering | 539 | * see if we can scan another channel without interfering |
@@ -502,7 +549,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
502 | * | 549 | * |
503 | * Otherwise switch back to the operating channel. | 550 | * Otherwise switch back to the operating channel. |
504 | */ | 551 | */ |
505 | next_chan = local->scan_req->channels[local->scan_channel_idx]; | ||
506 | 552 | ||
507 | bad_latency = time_after(jiffies + | 553 | bad_latency = time_after(jiffies + |
508 | ieee80211_scan_get_channel_time(next_chan), | 554 | ieee80211_scan_get_channel_time(next_chan), |
@@ -520,12 +566,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
520 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; | 566 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; |
521 | else | 567 | else |
522 | local->next_scan_state = SCAN_SET_CHANNEL; | 568 | local->next_scan_state = SCAN_SET_CHANNEL; |
523 | } else { | ||
524 | /* | ||
525 | * we're on the operating channel currently, let's | ||
526 | * leave that channel now to scan another one | ||
527 | */ | ||
528 | local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
529 | } | 569 | } |
530 | 570 | ||
531 | *next_delay = 0; | 571 | *next_delay = 0; |
@@ -534,9 +574,10 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
534 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | 574 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, |
535 | unsigned long *next_delay) | 575 | unsigned long *next_delay) |
536 | { | 576 | { |
537 | ieee80211_offchannel_stop_station(local); | 577 | /* PS will already be in off-channel mode, |
538 | 578 | * we do that once at the beginning of scanning. | |
539 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | 579 | */ |
580 | ieee80211_offchannel_stop_vifs(local, false); | ||
540 | 581 | ||
541 | /* | 582 | /* |
542 | * What if the nullfunc frames didn't arrive? | 583 | * What if the nullfunc frames didn't arrive? |
@@ -559,15 +600,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca | |||
559 | { | 600 | { |
560 | /* switch back to the operating channel */ | 601 | /* switch back to the operating channel */ |
561 | local->scan_channel = NULL; | 602 | local->scan_channel = NULL; |
562 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 603 | if (!ieee80211_cfg_on_oper_channel(local)) |
604 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
563 | 605 | ||
564 | /* | 606 | /* |
565 | * Only re-enable station mode interface now; beaconing will be | 607 | * Re-enable vifs and beaconing. Leave PS |
566 | * re-enabled once the full scan has been completed. | 608 | * in off-channel state..will put that back |
609 | * on-channel at the end of scanning. | ||
567 | */ | 610 | */ |
568 | ieee80211_offchannel_return(local, false); | 611 | ieee80211_offchannel_return(local, true, false); |
569 | |||
570 | __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
571 | 612 | ||
572 | *next_delay = HZ / 5; | 613 | *next_delay = HZ / 5; |
573 | local->next_scan_state = SCAN_DECISION; | 614 | local->next_scan_state = SCAN_DECISION; |
@@ -583,8 +624,11 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
583 | chan = local->scan_req->channels[local->scan_channel_idx]; | 624 | chan = local->scan_req->channels[local->scan_channel_idx]; |
584 | 625 | ||
585 | local->scan_channel = chan; | 626 | local->scan_channel = chan; |
586 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) | 627 | |
587 | skip = 1; | 628 | /* Only call hw-config if we really need to change channels. */ |
629 | if (chan != local->hw.conf.channel) | ||
630 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) | ||
631 | skip = 1; | ||
588 | 632 | ||
589 | /* advance state machine to next channel/band */ | 633 | /* advance state machine to next channel/band */ |
590 | local->scan_channel_idx++; | 634 | local->scan_channel_idx++; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c426504ed1cf..5a11078827ab 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -899,7 +899,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
899 | struct ieee80211_local *local = sdata->local; | 899 | struct ieee80211_local *local = sdata->local; |
900 | int sent, buffered; | 900 | int sent, buffered; |
901 | 901 | ||
902 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); | 902 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
903 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); | ||
903 | 904 | ||
904 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 905 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
905 | sta_info_clear_tim_bit(sta); | 906 | sta_info_clear_tim_bit(sta); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index bbdd2a86a94b..ca0b69060ef7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags { | |||
82 | * @state: session state (see above) | 82 | * @state: session state (see above) |
83 | * @stop_initiator: initiator of a session stop | 83 | * @stop_initiator: initiator of a session stop |
84 | * @tx_stop: TX DelBA frame when stopping | 84 | * @tx_stop: TX DelBA frame when stopping |
85 | * @buf_size: reorder buffer size at receiver | ||
85 | * | 86 | * |
86 | * This structure's lifetime is managed by RCU, assignments to | 87 | * This structure's lifetime is managed by RCU, assignments to |
87 | * the array holding it must hold the aggregation mutex. | 88 | * the array holding it must hold the aggregation mutex. |
@@ -101,6 +102,7 @@ struct tid_ampdu_tx { | |||
101 | u8 dialog_token; | 102 | u8 dialog_token; |
102 | u8 stop_initiator; | 103 | u8 stop_initiator; |
103 | bool tx_stop; | 104 | bool tx_stop; |
105 | u8 buf_size; | ||
104 | }; | 106 | }; |
105 | 107 | ||
106 | /** | 108 | /** |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 071ac95c4aa0..010a559bd872 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -98,6 +98,10 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
98 | * (b) always process RX events before TX status events if ordering | 98 | * (b) always process RX events before TX status events if ordering |
99 | * can be unknown, for example with different interrupt status | 99 | * can be unknown, for example with different interrupt status |
100 | * bits. | 100 | * bits. |
101 | * (c) if PS mode transitions are manual (i.e. the flag | ||
102 | * %IEEE80211_HW_AP_LINK_PS is set), always process PS state | ||
103 | * changes before calling TX status events if ordering can be | ||
104 | * unknown. | ||
101 | */ | 105 | */ |
102 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && | 106 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && |
103 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | 107 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b0beaa58246b..34edf7f22b0e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -236,6 +236,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | |||
236 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 236 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
237 | ieee80211_stop_queues_by_reason(&local->hw, | 237 | ieee80211_stop_queues_by_reason(&local->hw, |
238 | IEEE80211_QUEUE_STOP_REASON_PS); | 238 | IEEE80211_QUEUE_STOP_REASON_PS); |
239 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | ||
239 | ieee80211_queue_work(&local->hw, | 240 | ieee80211_queue_work(&local->hw, |
240 | &local->dynamic_ps_disable_work); | 241 | &local->dynamic_ps_disable_work); |
241 | } | 242 | } |
@@ -257,7 +258,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
257 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) | 258 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) |
258 | return TX_CONTINUE; | 259 | return TX_CONTINUE; |
259 | 260 | ||
260 | if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) && | 261 | if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && |
262 | test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && | ||
261 | !ieee80211_is_probe_req(hdr->frame_control) && | 263 | !ieee80211_is_probe_req(hdr->frame_control) && |
262 | !ieee80211_is_nullfunc(hdr->frame_control)) | 264 | !ieee80211_is_nullfunc(hdr->frame_control)) |
263 | /* | 265 | /* |
@@ -1394,7 +1396,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1394 | /* handlers after fragment must be aware of tx info fragmentation! */ | 1396 | /* handlers after fragment must be aware of tx info fragmentation! */ |
1395 | CALL_TXH(ieee80211_tx_h_stats); | 1397 | CALL_TXH(ieee80211_tx_h_stats); |
1396 | CALL_TXH(ieee80211_tx_h_encrypt); | 1398 | CALL_TXH(ieee80211_tx_h_encrypt); |
1397 | CALL_TXH(ieee80211_tx_h_calculate_duration); | 1399 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) |
1400 | CALL_TXH(ieee80211_tx_h_calculate_duration); | ||
1398 | #undef CALL_TXH | 1401 | #undef CALL_TXH |
1399 | 1402 | ||
1400 | txh_done: | 1403 | txh_done: |
@@ -1750,7 +1753,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1750 | __le16 fc; | 1753 | __le16 fc; |
1751 | struct ieee80211_hdr hdr; | 1754 | struct ieee80211_hdr hdr; |
1752 | struct ieee80211s_hdr mesh_hdr __maybe_unused; | 1755 | struct ieee80211s_hdr mesh_hdr __maybe_unused; |
1753 | struct mesh_path *mppath = NULL; | 1756 | struct mesh_path __maybe_unused *mppath = NULL; |
1754 | const u8 *encaps_data; | 1757 | const u8 *encaps_data; |
1755 | int encaps_len, skip_header_bytes; | 1758 | int encaps_len, skip_header_bytes; |
1756 | int nh_pos, h_pos; | 1759 | int nh_pos, h_pos; |
@@ -1815,19 +1818,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1815 | mppath = mpp_path_lookup(skb->data, sdata); | 1818 | mppath = mpp_path_lookup(skb->data, sdata); |
1816 | 1819 | ||
1817 | /* | 1820 | /* |
1818 | * Do not use address extension, if it is a packet from | 1821 | * Use address extension if it is a packet from |
1819 | * the same interface and the destination is not being | 1822 | * another interface or if we know the destination |
1820 | * proxied by any other mest point. | 1823 | * is being proxied by a portal (i.e. portal address |
1824 | * differs from proxied address) | ||
1821 | */ | 1825 | */ |
1822 | if (compare_ether_addr(sdata->vif.addr, | 1826 | if (compare_ether_addr(sdata->vif.addr, |
1823 | skb->data + ETH_ALEN) == 0 && | 1827 | skb->data + ETH_ALEN) == 0 && |
1824 | (!mppath || !compare_ether_addr(mppath->mpp, skb->data))) { | 1828 | !(mppath && compare_ether_addr(mppath->mpp, skb->data))) { |
1825 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1829 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1826 | skb->data, skb->data + ETH_ALEN); | 1830 | skb->data, skb->data + ETH_ALEN); |
1827 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1831 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1828 | sdata, NULL, NULL); | 1832 | sdata, NULL, NULL); |
1829 | } else { | 1833 | } else { |
1830 | /* packet from other interface */ | ||
1831 | int is_mesh_mcast = 1; | 1834 | int is_mesh_mcast = 1; |
1832 | const u8 *mesh_da; | 1835 | const u8 *mesh_da; |
1833 | 1836 | ||
@@ -2178,6 +2181,8 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, | |||
2178 | if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) | 2181 | if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) |
2179 | aid0 = 1; | 2182 | aid0 = 1; |
2180 | 2183 | ||
2184 | bss->dtim_bc_mc = aid0 == 1; | ||
2185 | |||
2181 | if (have_bits) { | 2186 | if (have_bits) { |
2182 | /* Find largest even number N1 so that bits numbered 1 through | 2187 | /* Find largest even number N1 so that bits numbered 1 through |
2183 | * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits | 2188 | * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits |
@@ -2241,7 +2246,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2241 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 2246 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
2242 | ap = &sdata->u.ap; | 2247 | ap = &sdata->u.ap; |
2243 | beacon = rcu_dereference(ap->beacon); | 2248 | beacon = rcu_dereference(ap->beacon); |
2244 | if (ap && beacon) { | 2249 | if (beacon) { |
2245 | /* | 2250 | /* |
2246 | * headroom, head length, | 2251 | * headroom, head length, |
2247 | * tail length and maximum TIM length | 2252 | * tail length and maximum TIM length |
@@ -2302,6 +2307,11 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2302 | struct ieee80211_mgmt *mgmt; | 2307 | struct ieee80211_mgmt *mgmt; |
2303 | u8 *pos; | 2308 | u8 *pos; |
2304 | 2309 | ||
2310 | #ifdef CONFIG_MAC80211_MESH | ||
2311 | if (!sdata->u.mesh.mesh_id_len) | ||
2312 | goto out; | ||
2313 | #endif | ||
2314 | |||
2305 | /* headroom, head length, tail length and maximum TIM length */ | 2315 | /* headroom, head length, tail length and maximum TIM length */ |
2306 | skb = dev_alloc_skb(local->tx_headroom + 400 + | 2316 | skb = dev_alloc_skb(local->tx_headroom + 400 + |
2307 | sdata->u.mesh.vendor_ie_len); | 2317 | sdata->u.mesh.vendor_ie_len); |
@@ -2543,7 +2553,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2543 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) | 2553 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) |
2544 | goto out; | 2554 | goto out; |
2545 | 2555 | ||
2546 | if (bss->dtim_count != 0) | 2556 | if (bss->dtim_count != 0 || !bss->dtim_bc_mc) |
2547 | goto out; /* send buffered bc/mc only after DTIM beacon */ | 2557 | goto out; /* send buffered bc/mc only after DTIM beacon */ |
2548 | 2558 | ||
2549 | while (1) { | 2559 | while (1) { |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d036597aabbe..556647a910ac 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -986,12 +986,6 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
986 | u16 cap = sband->ht_cap.cap; | 986 | u16 cap = sband->ht_cap.cap; |
987 | __le16 tmp; | 987 | __le16 tmp; |
988 | 988 | ||
989 | if (ieee80211_disable_40mhz_24ghz && | ||
990 | sband->band == IEEE80211_BAND_2GHZ) { | ||
991 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
992 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
993 | } | ||
994 | |||
995 | *pos++ = WLAN_EID_HT_CAPABILITY; | 989 | *pos++ = WLAN_EID_HT_CAPABILITY; |
996 | *pos++ = sizeof(struct ieee80211_ht_cap); | 990 | *pos++ = sizeof(struct ieee80211_ht_cap); |
997 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | 991 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 36305e0d06ef..204f0a4db969 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -126,12 +126,6 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | |||
126 | 126 | ||
127 | /* determine capability flags */ | 127 | /* determine capability flags */ |
128 | 128 | ||
129 | if (ieee80211_disable_40mhz_24ghz && | ||
130 | sband->band == IEEE80211_BAND_2GHZ) { | ||
131 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
132 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
133 | } | ||
134 | |||
135 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 129 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
136 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 130 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
137 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | 131 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { |
@@ -874,6 +868,44 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
874 | kfree_skb(skb); | 868 | kfree_skb(skb); |
875 | } | 869 | } |
876 | 870 | ||
871 | static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, | ||
872 | enum nl80211_channel_type oper_ct) | ||
873 | { | ||
874 | switch (wk_ct) { | ||
875 | case NL80211_CHAN_NO_HT: | ||
876 | return true; | ||
877 | case NL80211_CHAN_HT20: | ||
878 | if (oper_ct != NL80211_CHAN_NO_HT) | ||
879 | return true; | ||
880 | return false; | ||
881 | case NL80211_CHAN_HT40MINUS: | ||
882 | case NL80211_CHAN_HT40PLUS: | ||
883 | return (wk_ct == oper_ct); | ||
884 | } | ||
885 | WARN_ON(1); /* shouldn't get here */ | ||
886 | return false; | ||
887 | } | ||
888 | |||
889 | static enum nl80211_channel_type | ||
890 | ieee80211_calc_ct(enum nl80211_channel_type wk_ct, | ||
891 | enum nl80211_channel_type oper_ct) | ||
892 | { | ||
893 | switch (wk_ct) { | ||
894 | case NL80211_CHAN_NO_HT: | ||
895 | return oper_ct; | ||
896 | case NL80211_CHAN_HT20: | ||
897 | if (oper_ct != NL80211_CHAN_NO_HT) | ||
898 | return oper_ct; | ||
899 | return wk_ct; | ||
900 | case NL80211_CHAN_HT40MINUS: | ||
901 | case NL80211_CHAN_HT40PLUS: | ||
902 | return wk_ct; | ||
903 | } | ||
904 | WARN_ON(1); /* shouldn't get here */ | ||
905 | return wk_ct; | ||
906 | } | ||
907 | |||
908 | |||
877 | static void ieee80211_work_timer(unsigned long data) | 909 | static void ieee80211_work_timer(unsigned long data) |
878 | { | 910 | { |
879 | struct ieee80211_local *local = (void *) data; | 911 | struct ieee80211_local *local = (void *) data; |
@@ -924,18 +956,52 @@ static void ieee80211_work_work(struct work_struct *work) | |||
924 | } | 956 | } |
925 | 957 | ||
926 | if (!started && !local->tmp_channel) { | 958 | if (!started && !local->tmp_channel) { |
959 | bool on_oper_chan; | ||
960 | bool tmp_chan_changed = false; | ||
961 | bool on_oper_chan2; | ||
962 | enum nl80211_channel_type wk_ct; | ||
963 | on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
964 | |||
965 | /* Work with existing channel type if possible. */ | ||
966 | wk_ct = wk->chan_type; | ||
967 | if (wk->chan == local->hw.conf.channel) | ||
968 | wk_ct = ieee80211_calc_ct(wk->chan_type, | ||
969 | local->hw.conf.channel_type); | ||
970 | |||
971 | if (local->tmp_channel) | ||
972 | if ((local->tmp_channel != wk->chan) || | ||
973 | (local->tmp_channel_type != wk_ct)) | ||
974 | tmp_chan_changed = true; | ||
975 | |||
976 | local->tmp_channel = wk->chan; | ||
977 | local->tmp_channel_type = wk_ct; | ||
927 | /* | 978 | /* |
928 | * TODO: could optimize this by leaving the | 979 | * Leave the station vifs in awake mode if they |
929 | * station vifs in awake mode if they | 980 | * happen to be on the same channel as |
930 | * happen to be on the same channel as | 981 | * the requested channel. |
931 | * the requested channel | ||
932 | */ | 982 | */ |
933 | ieee80211_offchannel_stop_beaconing(local); | 983 | on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); |
934 | ieee80211_offchannel_stop_station(local); | 984 | if (on_oper_chan != on_oper_chan2) { |
985 | if (on_oper_chan2) { | ||
986 | /* going off oper channel, PS too */ | ||
987 | ieee80211_offchannel_stop_vifs(local, | ||
988 | true); | ||
989 | ieee80211_hw_config(local, 0); | ||
990 | } else { | ||
991 | /* going on channel, but leave PS | ||
992 | * off-channel. */ | ||
993 | ieee80211_hw_config(local, 0); | ||
994 | ieee80211_offchannel_return(local, | ||
995 | true, | ||
996 | false); | ||
997 | } | ||
998 | } else if (tmp_chan_changed) | ||
999 | /* Still off-channel, but on some other | ||
1000 | * channel, so update hardware. | ||
1001 | * PS should already be off-channel. | ||
1002 | */ | ||
1003 | ieee80211_hw_config(local, 0); | ||
935 | 1004 | ||
936 | local->tmp_channel = wk->chan; | ||
937 | local->tmp_channel_type = wk->chan_type; | ||
938 | ieee80211_hw_config(local, 0); | ||
939 | started = true; | 1005 | started = true; |
940 | wk->timeout = jiffies; | 1006 | wk->timeout = jiffies; |
941 | } | 1007 | } |
@@ -1005,15 +1071,34 @@ static void ieee80211_work_work(struct work_struct *work) | |||
1005 | continue; | 1071 | continue; |
1006 | if (wk->chan != local->tmp_channel) | 1072 | if (wk->chan != local->tmp_channel) |
1007 | continue; | 1073 | continue; |
1008 | if (wk->chan_type != local->tmp_channel_type) | 1074 | if (ieee80211_work_ct_coexists(wk->chan_type, |
1075 | local->tmp_channel_type)) | ||
1009 | continue; | 1076 | continue; |
1010 | remain_off_channel = true; | 1077 | remain_off_channel = true; |
1011 | } | 1078 | } |
1012 | 1079 | ||
1013 | if (!remain_off_channel && local->tmp_channel) { | 1080 | if (!remain_off_channel && local->tmp_channel) { |
1081 | bool on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
1014 | local->tmp_channel = NULL; | 1082 | local->tmp_channel = NULL; |
1015 | ieee80211_hw_config(local, 0); | 1083 | /* If tmp_channel wasn't operating channel, then |
1016 | ieee80211_offchannel_return(local, true); | 1084 | * we need to go back on-channel. |
1085 | * NOTE: If we can ever be here while scannning, | ||
1086 | * or if the hw_config() channel config logic changes, | ||
1087 | * then we may need to do a more thorough check to see if | ||
1088 | * we still need to do a hardware config. Currently, | ||
1089 | * we cannot be here while scanning, however. | ||
1090 | */ | ||
1091 | if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan) | ||
1092 | ieee80211_hw_config(local, 0); | ||
1093 | |||
1094 | /* At the least, we need to disable offchannel_ps, | ||
1095 | * so just go ahead and run the entire offchannel | ||
1096 | * return logic here. We *could* skip enabling | ||
1097 | * beaconing if we were already on-oper-channel | ||
1098 | * as a future optimization. | ||
1099 | */ | ||
1100 | ieee80211_offchannel_return(local, true, true); | ||
1101 | |||
1017 | /* give connection some time to breathe */ | 1102 | /* give connection some time to breathe */ |
1018 | run_again(local, jiffies + HZ/2); | 1103 | run_again(local, jiffies + HZ/2); |
1019 | } | 1104 | } |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bee230d8fd11..f1765de2f4bf 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -26,13 +26,12 @@ | |||
26 | ieee80211_tx_result | 26 | ieee80211_tx_result |
27 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | 27 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) |
28 | { | 28 | { |
29 | u8 *data, *key, *mic, key_offset; | 29 | u8 *data, *key, *mic; |
30 | size_t data_len; | 30 | size_t data_len; |
31 | unsigned int hdrlen; | 31 | unsigned int hdrlen; |
32 | struct ieee80211_hdr *hdr; | 32 | struct ieee80211_hdr *hdr; |
33 | struct sk_buff *skb = tx->skb; | 33 | struct sk_buff *skb = tx->skb; |
34 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 34 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
35 | int authenticator; | ||
36 | int tail; | 35 | int tail; |
37 | 36 | ||
38 | hdr = (struct ieee80211_hdr *)skb->data; | 37 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -47,6 +46,11 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
47 | data = skb->data + hdrlen; | 46 | data = skb->data + hdrlen; |
48 | data_len = skb->len - hdrlen; | 47 | data_len = skb->len - hdrlen; |
49 | 48 | ||
49 | if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) { | ||
50 | /* Need to use software crypto for the test */ | ||
51 | info->control.hw_key = NULL; | ||
52 | } | ||
53 | |||
50 | if (info->control.hw_key && | 54 | if (info->control.hw_key && |
51 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && | 55 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && |
52 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { | 56 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
@@ -62,17 +66,11 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
62 | skb_headroom(skb) < TKIP_IV_LEN)) | 66 | skb_headroom(skb) < TKIP_IV_LEN)) |
63 | return TX_DROP; | 67 | return TX_DROP; |
64 | 68 | ||
65 | #if 0 | 69 | key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]; |
66 | authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */ | ||
67 | #else | ||
68 | authenticator = 1; | ||
69 | #endif | ||
70 | key_offset = authenticator ? | ||
71 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY : | ||
72 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
73 | key = &tx->key->conf.key[key_offset]; | ||
74 | mic = skb_put(skb, MICHAEL_MIC_LEN); | 70 | mic = skb_put(skb, MICHAEL_MIC_LEN); |
75 | michael_mic(key, hdr, data, data_len, mic); | 71 | michael_mic(key, hdr, data, data_len, mic); |
72 | if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) | ||
73 | mic[0]++; | ||
76 | 74 | ||
77 | return TX_CONTINUE; | 75 | return TX_CONTINUE; |
78 | } | 76 | } |
@@ -81,14 +79,13 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
81 | ieee80211_rx_result | 79 | ieee80211_rx_result |
82 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | 80 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) |
83 | { | 81 | { |
84 | u8 *data, *key = NULL, key_offset; | 82 | u8 *data, *key = NULL; |
85 | size_t data_len; | 83 | size_t data_len; |
86 | unsigned int hdrlen; | 84 | unsigned int hdrlen; |
87 | u8 mic[MICHAEL_MIC_LEN]; | 85 | u8 mic[MICHAEL_MIC_LEN]; |
88 | struct sk_buff *skb = rx->skb; | 86 | struct sk_buff *skb = rx->skb; |
89 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 87 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
90 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 88 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
91 | int authenticator = 1, wpa_test = 0; | ||
92 | 89 | ||
93 | /* No way to verify the MIC if the hardware stripped it */ | 90 | /* No way to verify the MIC if the hardware stripped it */ |
94 | if (status->flag & RX_FLAG_MMIC_STRIPPED) | 91 | if (status->flag & RX_FLAG_MMIC_STRIPPED) |
@@ -106,17 +103,9 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
106 | data = skb->data + hdrlen; | 103 | data = skb->data + hdrlen; |
107 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; | 104 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; |
108 | 105 | ||
109 | #if 0 | 106 | key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; |
110 | authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */ | ||
111 | #else | ||
112 | authenticator = 1; | ||
113 | #endif | ||
114 | key_offset = authenticator ? | ||
115 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : | ||
116 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
117 | key = &rx->key->conf.key[key_offset]; | ||
118 | michael_mic(key, hdr, data, data_len, mic); | 107 | michael_mic(key, hdr, data, data_len, mic); |
119 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { | 108 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) { |
120 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | 109 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
121 | return RX_DROP_UNUSABLE; | 110 | return RX_DROP_UNUSABLE; |
122 | 111 | ||
@@ -208,7 +197,7 @@ ieee80211_rx_result | |||
208 | ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | 197 | ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) |
209 | { | 198 | { |
210 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 199 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
211 | int hdrlen, res, hwaccel = 0, wpa_test = 0; | 200 | int hdrlen, res, hwaccel = 0; |
212 | struct ieee80211_key *key = rx->key; | 201 | struct ieee80211_key *key = rx->key; |
213 | struct sk_buff *skb = rx->skb; | 202 | struct sk_buff *skb = rx->skb; |
214 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 203 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
@@ -235,7 +224,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
235 | hdr->addr1, hwaccel, rx->queue, | 224 | hdr->addr1, hwaccel, rx->queue, |
236 | &rx->tkip_iv32, | 225 | &rx->tkip_iv32, |
237 | &rx->tkip_iv16); | 226 | &rx->tkip_iv16); |
238 | if (res != TKIP_DECRYPT_OK || wpa_test) | 227 | if (res != TKIP_DECRYPT_OK) |
239 | return RX_DROP_UNUSABLE; | 228 | return RX_DROP_UNUSABLE; |
240 | 229 | ||
241 | /* Trim ICV */ | 230 | /* Trim ICV */ |