diff options
author | David S. Miller <davem@davemloft.net> | 2015-10-07 07:29:18 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-07 07:29:18 -0400 |
commit | 2579c98f0d04075ab8b041de7d5396393d2417f1 (patch) | |
tree | 094fb6486f5ede529cd772223d2fa0334a28f852 /net/mac80211 | |
parent | 390a4bee5c2ade628565dd21fb5d8656a58f7804 (diff) | |
parent | 5edfcee5ed73eb9537987c4ddb6bf062b6943b73 (diff) |
Merge tag 'mac80211-next-for-davem-2015-10-05' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg says:
====================
For the current cycle, we have the following right now:
* many internal fixes, API improvements, cleanups, etc.
* full AP client state tracking in cfg80211/mac80211 from Ayala
* VHT support (in mac80211) for mesh
* some A-MSDU in A-MPDU support from Emmanuel
* show current TX power to userspace (from RafaĆ)
* support for netlink dump in vendor commands (myself)
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-rx.c | 8 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 15 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 56 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 2 | ||||
-rw-r--r-- | net/mac80211/debugfs_key.c | 51 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 41 | ||||
-rw-r--r-- | net/mac80211/driver-ops.c | 222 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 259 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 19 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 82 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 10 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 9 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 155 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 6 | ||||
-rw-r--r-- | net/mac80211/pm.c | 3 | ||||
-rw-r--r-- | net/mac80211/rate.c | 5 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_debugfs.c | 12 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht_debugfs.c | 12 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/status.c | 108 | ||||
-rw-r--r-- | net/mac80211/tdls.c | 8 | ||||
-rw-r--r-- | net/mac80211/trace.h | 40 | ||||
-rw-r--r-- | net/mac80211/tx.c | 22 | ||||
-rw-r--r-- | net/mac80211/util.c | 11 |
26 files changed, 706 insertions, 457 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 5c564a68fb50..10ad4ac1fa0b 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -79,7 +79,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
79 | (int)reason); | 79 | (int)reason); |
80 | 80 | ||
81 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, | 81 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
82 | &sta->sta, tid, NULL, 0)) | 82 | &sta->sta, tid, NULL, 0, false)) |
83 | sdata_info(sta->sdata, | 83 | sdata_info(sta->sdata, |
84 | "HW problem - can not stop rx aggregation for %pM tid %d\n", | 84 | "HW problem - can not stop rx aggregation for %pM tid %d\n", |
85 | sta->sta.addr, tid); | 85 | sta->sta.addr, tid); |
@@ -189,6 +189,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
189 | struct ieee80211_local *local = sdata->local; | 189 | struct ieee80211_local *local = sdata->local; |
190 | struct sk_buff *skb; | 190 | struct sk_buff *skb; |
191 | struct ieee80211_mgmt *mgmt; | 191 | struct ieee80211_mgmt *mgmt; |
192 | bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU); | ||
192 | u16 capab; | 193 | u16 capab; |
193 | 194 | ||
194 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | 195 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); |
@@ -217,7 +218,8 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
217 | mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; | 218 | mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; |
218 | mgmt->u.action.u.addba_resp.dialog_token = dialog_token; | 219 | mgmt->u.action.u.addba_resp.dialog_token = dialog_token; |
219 | 220 | ||
220 | capab = (u16)(policy << 1); /* bit 1 aggregation policy */ | 221 | capab = (u16)(amsdu << 0); /* bit 0 A-MSDU support */ |
222 | capab |= (u16)(policy << 1); /* bit 1 aggregation policy */ | ||
221 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | 223 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ |
222 | capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ | 224 | capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ |
223 | 225 | ||
@@ -321,7 +323,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, | |||
321 | __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); | 323 | __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); |
322 | 324 | ||
323 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, | 325 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
324 | &sta->sta, tid, &start_seq_num, 0); | 326 | &sta->sta, tid, &start_seq_num, 0, false); |
325 | ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", | 327 | ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", |
326 | sta->sta.addr, tid, ret); | 328 | sta->sta.addr, tid, ret); |
327 | if (ret) { | 329 | if (ret) { |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c8ba2e77737c..a758eb84e8f0 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -97,7 +97,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
97 | mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; | 97 | mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; |
98 | 98 | ||
99 | mgmt->u.action.u.addba_req.dialog_token = dialog_token; | 99 | mgmt->u.action.u.addba_req.dialog_token = dialog_token; |
100 | capab = (u16)(1 << 1); /* bit 1 aggregation policy */ | 100 | capab = (u16)(1 << 0); /* bit 0 A-MSDU support */ |
101 | capab |= (u16)(1 << 1); /* bit 1 aggregation policy */ | ||
101 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | 102 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ |
102 | capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ | 103 | capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ |
103 | 104 | ||
@@ -331,7 +332,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
331 | return -EALREADY; | 332 | return -EALREADY; |
332 | ret = drv_ampdu_action(local, sta->sdata, | 333 | ret = drv_ampdu_action(local, sta->sdata, |
333 | IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, | 334 | IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, |
334 | &sta->sta, tid, NULL, 0); | 335 | &sta->sta, tid, NULL, 0, false); |
335 | WARN_ON_ONCE(ret); | 336 | WARN_ON_ONCE(ret); |
336 | return 0; | 337 | return 0; |
337 | } | 338 | } |
@@ -381,7 +382,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
381 | tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; | 382 | tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; |
382 | 383 | ||
383 | ret = drv_ampdu_action(local, sta->sdata, action, | 384 | ret = drv_ampdu_action(local, sta->sdata, action, |
384 | &sta->sta, tid, NULL, 0); | 385 | &sta->sta, tid, NULL, 0, false); |
385 | 386 | ||
386 | /* HW shall not deny going back to legacy */ | 387 | /* HW shall not deny going back to legacy */ |
387 | if (WARN_ON(ret)) { | 388 | if (WARN_ON(ret)) { |
@@ -469,7 +470,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
469 | start_seq_num = sta->tid_seq[tid] >> 4; | 470 | start_seq_num = sta->tid_seq[tid] >> 4; |
470 | 471 | ||
471 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, | 472 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, |
472 | &sta->sta, tid, &start_seq_num, 0); | 473 | &sta->sta, tid, &start_seq_num, 0, false); |
473 | if (ret) { | 474 | if (ret) { |
474 | ht_dbg(sdata, | 475 | ht_dbg(sdata, |
475 | "BA request denied - HW unavailable for %pM tid %d\n", | 476 | "BA request denied - HW unavailable for %pM tid %d\n", |
@@ -693,7 +694,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
693 | 694 | ||
694 | drv_ampdu_action(local, sta->sdata, | 695 | drv_ampdu_action(local, sta->sdata, |
695 | IEEE80211_AMPDU_TX_OPERATIONAL, | 696 | IEEE80211_AMPDU_TX_OPERATIONAL, |
696 | &sta->sta, tid, NULL, tid_tx->buf_size); | 697 | &sta->sta, tid, NULL, tid_tx->buf_size, |
698 | tid_tx->amsdu); | ||
697 | 699 | ||
698 | /* | 700 | /* |
699 | * synchronize with TX path, while splicing the TX path | 701 | * synchronize with TX path, while splicing the TX path |
@@ -918,8 +920,10 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
918 | struct tid_ampdu_tx *tid_tx; | 920 | struct tid_ampdu_tx *tid_tx; |
919 | u16 capab, tid; | 921 | u16 capab, tid; |
920 | u8 buf_size; | 922 | u8 buf_size; |
923 | bool amsdu; | ||
921 | 924 | ||
922 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 925 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
926 | amsdu = capab & IEEE80211_ADDBA_PARAM_AMSDU_MASK; | ||
923 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 927 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
924 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | 928 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; |
925 | 929 | ||
@@ -968,6 +972,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
968 | } | 972 | } |
969 | 973 | ||
970 | tid_tx->buf_size = buf_size; | 974 | tid_tx->buf_size = buf_size; |
975 | tid_tx->amsdu = amsdu; | ||
971 | 976 | ||
972 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) | 977 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) |
973 | ieee80211_agg_tx_operational(local, sta, tid); | 978 | ieee80211_agg_tx_operational(local, sta, tid); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 7a77a1470f25..68e551e263c6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -981,7 +981,7 @@ static int sta_apply_auth_flags(struct ieee80211_local *local, | |||
981 | * well. Some drivers require rate control initialized | 981 | * well. Some drivers require rate control initialized |
982 | * before drv_sta_state() is called. | 982 | * before drv_sta_state() is called. |
983 | */ | 983 | */ |
984 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 984 | if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) |
985 | rate_control_rate_init(sta); | 985 | rate_control_rate_init(sta); |
986 | 986 | ||
987 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | 987 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
@@ -1120,8 +1120,11 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1120 | local->hw.queues >= IEEE80211_NUM_ACS) | 1120 | local->hw.queues >= IEEE80211_NUM_ACS) |
1121 | sta->sta.wme = set & BIT(NL80211_STA_FLAG_WME); | 1121 | sta->sta.wme = set & BIT(NL80211_STA_FLAG_WME); |
1122 | 1122 | ||
1123 | /* auth flags will be set later for TDLS stations */ | 1123 | /* auth flags will be set later for TDLS, |
1124 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | 1124 | * and for unassociated stations that move to assocaited */ |
1125 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER) && | ||
1126 | !((mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) && | ||
1127 | (set & BIT(NL80211_STA_FLAG_ASSOCIATED)))) { | ||
1125 | ret = sta_apply_auth_flags(local, sta, mask, set); | 1128 | ret = sta_apply_auth_flags(local, sta, mask, set); |
1126 | if (ret) | 1129 | if (ret) |
1127 | return ret; | 1130 | return ret; |
@@ -1156,6 +1159,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1156 | set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH); | 1159 | set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH); |
1157 | 1160 | ||
1158 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && | 1161 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && |
1162 | !sdata->u.mgd.tdls_wider_bw_prohibited && | ||
1159 | ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) && | 1163 | ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) && |
1160 | params->ext_capab_len >= 8 && | 1164 | params->ext_capab_len >= 8 && |
1161 | params->ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) | 1165 | params->ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) |
@@ -1212,7 +1216,8 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1212 | sta_apply_mesh_params(local, sta, params); | 1216 | sta_apply_mesh_params(local, sta, params); |
1213 | 1217 | ||
1214 | /* set the STA state after all sta info from usermode has been set */ | 1218 | /* set the STA state after all sta info from usermode has been set */ |
1215 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | 1219 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) || |
1220 | set & BIT(NL80211_STA_FLAG_ASSOCIATED)) { | ||
1216 | ret = sta_apply_auth_flags(local, sta, mask, set); | 1221 | ret = sta_apply_auth_flags(local, sta, mask, set); |
1217 | if (ret) | 1222 | if (ret) |
1218 | return ret; | 1223 | return ret; |
@@ -1254,12 +1259,14 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1254 | * defaults -- if userspace wants something else we'll | 1259 | * defaults -- if userspace wants something else we'll |
1255 | * change it accordingly in sta_apply_parameters() | 1260 | * change it accordingly in sta_apply_parameters() |
1256 | */ | 1261 | */ |
1257 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { | 1262 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) && |
1263 | !(params->sta_flags_set & (BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1264 | BIT(NL80211_STA_FLAG_ASSOCIATED)))) { | ||
1258 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 1265 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
1259 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 1266 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
1260 | } else { | ||
1261 | sta->sta.tdls = true; | ||
1262 | } | 1267 | } |
1268 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | ||
1269 | sta->sta.tdls = true; | ||
1263 | 1270 | ||
1264 | err = sta_apply_parameters(local, sta, params); | 1271 | err = sta_apply_parameters(local, sta, params); |
1265 | if (err) { | 1272 | if (err) { |
@@ -1268,10 +1275,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1268 | } | 1275 | } |
1269 | 1276 | ||
1270 | /* | 1277 | /* |
1271 | * for TDLS, rate control should be initialized only when | 1278 | * for TDLS and for unassociated station, rate control should be |
1272 | * rates are known and station is marked authorized | 1279 | * initialized only when rates are known and station is marked |
1280 | * authorized/associated | ||
1273 | */ | 1281 | */ |
1274 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 1282 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER) && |
1283 | test_sta_flag(sta, WLAN_STA_ASSOC)) | ||
1275 | rate_control_rate_init(sta); | 1284 | rate_control_rate_init(sta); |
1276 | 1285 | ||
1277 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 1286 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
@@ -1346,7 +1355,10 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1346 | break; | 1355 | break; |
1347 | case NL80211_IFTYPE_AP: | 1356 | case NL80211_IFTYPE_AP: |
1348 | case NL80211_IFTYPE_AP_VLAN: | 1357 | case NL80211_IFTYPE_AP_VLAN: |
1349 | statype = CFG80211_STA_AP_CLIENT; | 1358 | if (test_sta_flag(sta, WLAN_STA_ASSOC)) |
1359 | statype = CFG80211_STA_AP_CLIENT; | ||
1360 | else | ||
1361 | statype = CFG80211_STA_AP_CLIENT_UNASSOC; | ||
1350 | break; | 1362 | break; |
1351 | default: | 1363 | default: |
1352 | err = -EOPNOTSUPP; | 1364 | err = -EOPNOTSUPP; |
@@ -3522,18 +3534,32 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | |||
3522 | u16 frame_type, bool reg) | 3534 | u16 frame_type, bool reg) |
3523 | { | 3535 | { |
3524 | struct ieee80211_local *local = wiphy_priv(wiphy); | 3536 | struct ieee80211_local *local = wiphy_priv(wiphy); |
3537 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
3525 | 3538 | ||
3526 | switch (frame_type) { | 3539 | switch (frame_type) { |
3527 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: | 3540 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: |
3528 | if (reg) | 3541 | if (reg) { |
3529 | local->probe_req_reg++; | 3542 | local->probe_req_reg++; |
3530 | else | 3543 | sdata->vif.probe_req_reg++; |
3531 | local->probe_req_reg--; | 3544 | } else { |
3545 | if (local->probe_req_reg) | ||
3546 | local->probe_req_reg--; | ||
3547 | |||
3548 | if (sdata->vif.probe_req_reg) | ||
3549 | sdata->vif.probe_req_reg--; | ||
3550 | } | ||
3532 | 3551 | ||
3533 | if (!local->open_count) | 3552 | if (!local->open_count) |
3534 | break; | 3553 | break; |
3535 | 3554 | ||
3536 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); | 3555 | if (sdata->vif.probe_req_reg == 1) |
3556 | drv_config_iface_filter(local, sdata, FIF_PROBE_REQ, | ||
3557 | FIF_PROBE_REQ); | ||
3558 | else if (sdata->vif.probe_req_reg == 0) | ||
3559 | drv_config_iface_filter(local, sdata, 0, | ||
3560 | FIF_PROBE_REQ); | ||
3561 | |||
3562 | ieee80211_configure_filter(local); | ||
3537 | break; | 3563 | break; |
3538 | default: | 3564 | default: |
3539 | break; | 3565 | break; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index ced6bf3be8d6..3636b45440ab 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -123,6 +123,8 @@ static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = { | |||
123 | FLAG(SUPPORTS_CLONED_SKBS), | 123 | FLAG(SUPPORTS_CLONED_SKBS), |
124 | FLAG(SINGLE_SCAN_ON_ALL_BANDS), | 124 | FLAG(SINGLE_SCAN_ON_ALL_BANDS), |
125 | FLAG(TDLS_WIDER_BW), | 125 | FLAG(TDLS_WIDER_BW), |
126 | FLAG(SUPPORTS_AMSDU_IN_AMPDU), | ||
127 | FLAG(BEACON_TX_STATUS), | ||
126 | 128 | ||
127 | /* keep last for the build bug below */ | 129 | /* keep last for the build bug below */ |
128 | (void *)0x1 | 130 | (void *)0x1 |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 702ca122c498..7961e7d0b61e 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Copyright 2003-2005 Devicescape Software, Inc. | 2 | * Copyright 2003-2005 Devicescape Software, Inc. |
3 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> | 3 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
4 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> |
5 | * Copyright (C) 2015 Intel Deutschland GmbH | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -34,6 +35,14 @@ static const struct file_operations key_ ##name## _ops = { \ | |||
34 | .llseek = generic_file_llseek, \ | 35 | .llseek = generic_file_llseek, \ |
35 | } | 36 | } |
36 | 37 | ||
38 | #define KEY_OPS_W(name) \ | ||
39 | static const struct file_operations key_ ##name## _ops = { \ | ||
40 | .read = key_##name##_read, \ | ||
41 | .write = key_##name##_write, \ | ||
42 | .open = simple_open, \ | ||
43 | .llseek = generic_file_llseek, \ | ||
44 | } | ||
45 | |||
37 | #define KEY_FILE(name, format) \ | 46 | #define KEY_FILE(name, format) \ |
38 | KEY_READ_##format(name) \ | 47 | KEY_READ_##format(name) \ |
39 | KEY_OPS(name) | 48 | KEY_OPS(name) |
@@ -74,6 +83,41 @@ static ssize_t key_algorithm_read(struct file *file, | |||
74 | } | 83 | } |
75 | KEY_OPS(algorithm); | 84 | KEY_OPS(algorithm); |
76 | 85 | ||
86 | static ssize_t key_tx_spec_write(struct file *file, const char __user *userbuf, | ||
87 | size_t count, loff_t *ppos) | ||
88 | { | ||
89 | struct ieee80211_key *key = file->private_data; | ||
90 | u64 pn; | ||
91 | int ret; | ||
92 | |||
93 | switch (key->conf.cipher) { | ||
94 | case WLAN_CIPHER_SUITE_WEP40: | ||
95 | case WLAN_CIPHER_SUITE_WEP104: | ||
96 | return -EINVAL; | ||
97 | case WLAN_CIPHER_SUITE_TKIP: | ||
98 | /* not supported yet */ | ||
99 | return -EOPNOTSUPP; | ||
100 | case WLAN_CIPHER_SUITE_CCMP: | ||
101 | case WLAN_CIPHER_SUITE_CCMP_256: | ||
102 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
103 | case WLAN_CIPHER_SUITE_BIP_CMAC_256: | ||
104 | case WLAN_CIPHER_SUITE_BIP_GMAC_128: | ||
105 | case WLAN_CIPHER_SUITE_BIP_GMAC_256: | ||
106 | case WLAN_CIPHER_SUITE_GCMP: | ||
107 | case WLAN_CIPHER_SUITE_GCMP_256: | ||
108 | ret = kstrtou64_from_user(userbuf, count, 16, &pn); | ||
109 | if (ret) | ||
110 | return ret; | ||
111 | /* PN is a 48-bit counter */ | ||
112 | if (pn >= (1ULL << 48)) | ||
113 | return -ERANGE; | ||
114 | atomic64_set(&key->conf.tx_pn, pn); | ||
115 | return count; | ||
116 | default: | ||
117 | return 0; | ||
118 | } | ||
119 | } | ||
120 | |||
77 | static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | 121 | static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, |
78 | size_t count, loff_t *ppos) | 122 | size_t count, loff_t *ppos) |
79 | { | 123 | { |
@@ -110,7 +154,7 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | |||
110 | } | 154 | } |
111 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | 155 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); |
112 | } | 156 | } |
113 | KEY_OPS(tx_spec); | 157 | KEY_OPS_W(tx_spec); |
114 | 158 | ||
115 | static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | 159 | static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, |
116 | size_t count, loff_t *ppos) | 160 | size_t count, loff_t *ppos) |
@@ -278,6 +322,9 @@ KEY_OPS(key); | |||
278 | #define DEBUGFS_ADD(name) \ | 322 | #define DEBUGFS_ADD(name) \ |
279 | debugfs_create_file(#name, 0400, key->debugfs.dir, \ | 323 | debugfs_create_file(#name, 0400, key->debugfs.dir, \ |
280 | key, &key_##name##_ops); | 324 | key, &key_##name##_ops); |
325 | #define DEBUGFS_ADD_W(name) \ | ||
326 | debugfs_create_file(#name, 0600, key->debugfs.dir, \ | ||
327 | key, &key_##name##_ops); | ||
281 | 328 | ||
282 | void ieee80211_debugfs_key_add(struct ieee80211_key *key) | 329 | void ieee80211_debugfs_key_add(struct ieee80211_key *key) |
283 | { | 330 | { |
@@ -310,7 +357,7 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) | |||
310 | DEBUGFS_ADD(keyidx); | 357 | DEBUGFS_ADD(keyidx); |
311 | DEBUGFS_ADD(hw_key_idx); | 358 | DEBUGFS_ADD(hw_key_idx); |
312 | DEBUGFS_ADD(algorithm); | 359 | DEBUGFS_ADD(algorithm); |
313 | DEBUGFS_ADD(tx_spec); | 360 | DEBUGFS_ADD_W(tx_spec); |
314 | DEBUGFS_ADD(rx_spec); | 361 | DEBUGFS_ADD(rx_spec); |
315 | DEBUGFS_ADD(replays); | 362 | DEBUGFS_ADD(replays); |
316 | DEBUGFS_ADD(icverrors); | 363 | DEBUGFS_ADD(icverrors); |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 1021e87c051f..37ea30e0754c 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -114,14 +114,6 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
114 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ | 114 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ |
115 | } | 115 | } |
116 | 116 | ||
117 | #define IEEE80211_IF_FMT_DEC_DIV_16(name, field) \ | ||
118 | static ssize_t ieee80211_if_fmt_##name( \ | ||
119 | const struct ieee80211_sub_if_data *sdata, \ | ||
120 | char *buf, int buflen) \ | ||
121 | { \ | ||
122 | return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \ | ||
123 | } | ||
124 | |||
125 | #define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, field) \ | 117 | #define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, field) \ |
126 | static ssize_t ieee80211_if_fmt_##name( \ | 118 | static ssize_t ieee80211_if_fmt_##name( \ |
127 | const struct ieee80211_sub_if_data *sdata, \ | 119 | const struct ieee80211_sub_if_data *sdata, \ |
@@ -247,8 +239,6 @@ IEEE80211_IF_FILE_R(hw_queues); | |||
247 | /* STA attributes */ | 239 | /* STA attributes */ |
248 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 240 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
249 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 241 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
250 | IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC); | ||
251 | IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16); | ||
252 | IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS); | 242 | IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS); |
253 | 243 | ||
254 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | 244 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, |
@@ -455,6 +445,34 @@ static ssize_t ieee80211_if_parse_uapsd_max_sp_len( | |||
455 | } | 445 | } |
456 | IEEE80211_IF_FILE_RW(uapsd_max_sp_len); | 446 | IEEE80211_IF_FILE_RW(uapsd_max_sp_len); |
457 | 447 | ||
448 | static ssize_t ieee80211_if_fmt_tdls_wider_bw( | ||
449 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
450 | { | ||
451 | const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
452 | bool tdls_wider_bw; | ||
453 | |||
454 | tdls_wider_bw = ieee80211_hw_check(&sdata->local->hw, TDLS_WIDER_BW) && | ||
455 | !ifmgd->tdls_wider_bw_prohibited; | ||
456 | |||
457 | return snprintf(buf, buflen, "%d\n", tdls_wider_bw); | ||
458 | } | ||
459 | |||
460 | static ssize_t ieee80211_if_parse_tdls_wider_bw( | ||
461 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | ||
462 | { | ||
463 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
464 | u8 val; | ||
465 | int ret; | ||
466 | |||
467 | ret = kstrtou8(buf, 0, &val); | ||
468 | if (ret) | ||
469 | return ret; | ||
470 | |||
471 | ifmgd->tdls_wider_bw_prohibited = !val; | ||
472 | return buflen; | ||
473 | } | ||
474 | IEEE80211_IF_FILE_RW(tdls_wider_bw); | ||
475 | |||
458 | /* AP attributes */ | 476 | /* AP attributes */ |
459 | IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC); | 477 | IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC); |
460 | IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC); | 478 | IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC); |
@@ -606,14 +624,13 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
606 | { | 624 | { |
607 | DEBUGFS_ADD(bssid); | 625 | DEBUGFS_ADD(bssid); |
608 | DEBUGFS_ADD(aid); | 626 | DEBUGFS_ADD(aid); |
609 | DEBUGFS_ADD(last_beacon); | ||
610 | DEBUGFS_ADD(ave_beacon); | ||
611 | DEBUGFS_ADD(beacon_timeout); | 627 | DEBUGFS_ADD(beacon_timeout); |
612 | DEBUGFS_ADD_MODE(smps, 0600); | 628 | DEBUGFS_ADD_MODE(smps, 0600); |
613 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | 629 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); |
614 | DEBUGFS_ADD_MODE(beacon_loss, 0200); | 630 | DEBUGFS_ADD_MODE(beacon_loss, 0200); |
615 | DEBUGFS_ADD_MODE(uapsd_queues, 0600); | 631 | DEBUGFS_ADD_MODE(uapsd_queues, 0600); |
616 | DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600); | 632 | DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600); |
633 | DEBUGFS_ADD_MODE(tdls_wider_bw, 0600); | ||
617 | } | 634 | } |
618 | 635 | ||
619 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 636 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index 267c3b1ca047..a1d54318f16c 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c | |||
@@ -8,6 +8,60 @@ | |||
8 | #include "trace.h" | 8 | #include "trace.h" |
9 | #include "driver-ops.h" | 9 | #include "driver-ops.h" |
10 | 10 | ||
11 | int drv_add_interface(struct ieee80211_local *local, | ||
12 | struct ieee80211_sub_if_data *sdata) | ||
13 | { | ||
14 | int ret; | ||
15 | |||
16 | might_sleep(); | ||
17 | |||
18 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
19 | (sdata->vif.type == NL80211_IFTYPE_MONITOR && | ||
20 | !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) && | ||
21 | !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)))) | ||
22 | return -EINVAL; | ||
23 | |||
24 | trace_drv_add_interface(local, sdata); | ||
25 | ret = local->ops->add_interface(&local->hw, &sdata->vif); | ||
26 | trace_drv_return_int(local, ret); | ||
27 | |||
28 | if (ret == 0) | ||
29 | sdata->flags |= IEEE80211_SDATA_IN_DRIVER; | ||
30 | |||
31 | return ret; | ||
32 | } | ||
33 | |||
34 | int drv_change_interface(struct ieee80211_local *local, | ||
35 | struct ieee80211_sub_if_data *sdata, | ||
36 | enum nl80211_iftype type, bool p2p) | ||
37 | { | ||
38 | int ret; | ||
39 | |||
40 | might_sleep(); | ||
41 | |||
42 | if (!check_sdata_in_driver(sdata)) | ||
43 | return -EIO; | ||
44 | |||
45 | trace_drv_change_interface(local, sdata, type, p2p); | ||
46 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); | ||
47 | trace_drv_return_int(local, ret); | ||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | void drv_remove_interface(struct ieee80211_local *local, | ||
52 | struct ieee80211_sub_if_data *sdata) | ||
53 | { | ||
54 | might_sleep(); | ||
55 | |||
56 | if (!check_sdata_in_driver(sdata)) | ||
57 | return; | ||
58 | |||
59 | trace_drv_remove_interface(local, sdata); | ||
60 | local->ops->remove_interface(&local->hw, &sdata->vif); | ||
61 | sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; | ||
62 | trace_drv_return_void(local); | ||
63 | } | ||
64 | |||
11 | __must_check | 65 | __must_check |
12 | int drv_sta_state(struct ieee80211_local *local, | 66 | int drv_sta_state(struct ieee80211_local *local, |
13 | struct ieee80211_sub_if_data *sdata, | 67 | struct ieee80211_sub_if_data *sdata, |
@@ -39,3 +93,171 @@ int drv_sta_state(struct ieee80211_local *local, | |||
39 | trace_drv_return_int(local, ret); | 93 | trace_drv_return_int(local, ret); |
40 | return ret; | 94 | return ret; |
41 | } | 95 | } |
96 | |||
97 | void drv_sta_rc_update(struct ieee80211_local *local, | ||
98 | struct ieee80211_sub_if_data *sdata, | ||
99 | struct ieee80211_sta *sta, u32 changed) | ||
100 | { | ||
101 | sdata = get_bss_sdata(sdata); | ||
102 | if (!check_sdata_in_driver(sdata)) | ||
103 | return; | ||
104 | |||
105 | WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && | ||
106 | (sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
107 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)); | ||
108 | |||
109 | trace_drv_sta_rc_update(local, sdata, sta, changed); | ||
110 | if (local->ops->sta_rc_update) | ||
111 | local->ops->sta_rc_update(&local->hw, &sdata->vif, | ||
112 | sta, changed); | ||
113 | |||
114 | trace_drv_return_void(local); | ||
115 | } | ||
116 | |||
117 | int drv_conf_tx(struct ieee80211_local *local, | ||
118 | struct ieee80211_sub_if_data *sdata, u16 ac, | ||
119 | const struct ieee80211_tx_queue_params *params) | ||
120 | { | ||
121 | int ret = -EOPNOTSUPP; | ||
122 | |||
123 | might_sleep(); | ||
124 | |||
125 | if (!check_sdata_in_driver(sdata)) | ||
126 | return -EIO; | ||
127 | |||
128 | if (WARN_ONCE(params->cw_min == 0 || | ||
129 | params->cw_min > params->cw_max, | ||
130 | "%s: invalid CW_min/CW_max: %d/%d\n", | ||
131 | sdata->name, params->cw_min, params->cw_max)) | ||
132 | return -EINVAL; | ||
133 | |||
134 | trace_drv_conf_tx(local, sdata, ac, params); | ||
135 | if (local->ops->conf_tx) | ||
136 | ret = local->ops->conf_tx(&local->hw, &sdata->vif, | ||
137 | ac, params); | ||
138 | trace_drv_return_int(local, ret); | ||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | u64 drv_get_tsf(struct ieee80211_local *local, | ||
143 | struct ieee80211_sub_if_data *sdata) | ||
144 | { | ||
145 | u64 ret = -1ULL; | ||
146 | |||
147 | might_sleep(); | ||
148 | |||
149 | if (!check_sdata_in_driver(sdata)) | ||
150 | return ret; | ||
151 | |||
152 | trace_drv_get_tsf(local, sdata); | ||
153 | if (local->ops->get_tsf) | ||
154 | ret = local->ops->get_tsf(&local->hw, &sdata->vif); | ||
155 | trace_drv_return_u64(local, ret); | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | void drv_set_tsf(struct ieee80211_local *local, | ||
160 | struct ieee80211_sub_if_data *sdata, | ||
161 | u64 tsf) | ||
162 | { | ||
163 | might_sleep(); | ||
164 | |||
165 | if (!check_sdata_in_driver(sdata)) | ||
166 | return; | ||
167 | |||
168 | trace_drv_set_tsf(local, sdata, tsf); | ||
169 | if (local->ops->set_tsf) | ||
170 | local->ops->set_tsf(&local->hw, &sdata->vif, tsf); | ||
171 | trace_drv_return_void(local); | ||
172 | } | ||
173 | |||
174 | void drv_reset_tsf(struct ieee80211_local *local, | ||
175 | struct ieee80211_sub_if_data *sdata) | ||
176 | { | ||
177 | might_sleep(); | ||
178 | |||
179 | if (!check_sdata_in_driver(sdata)) | ||
180 | return; | ||
181 | |||
182 | trace_drv_reset_tsf(local, sdata); | ||
183 | if (local->ops->reset_tsf) | ||
184 | local->ops->reset_tsf(&local->hw, &sdata->vif); | ||
185 | trace_drv_return_void(local); | ||
186 | } | ||
187 | |||
188 | int drv_switch_vif_chanctx(struct ieee80211_local *local, | ||
189 | struct ieee80211_vif_chanctx_switch *vifs, | ||
190 | int n_vifs, enum ieee80211_chanctx_switch_mode mode) | ||
191 | { | ||
192 | int ret = 0; | ||
193 | int i; | ||
194 | |||
195 | if (!local->ops->switch_vif_chanctx) | ||
196 | return -EOPNOTSUPP; | ||
197 | |||
198 | for (i = 0; i < n_vifs; i++) { | ||
199 | struct ieee80211_chanctx *new_ctx = | ||
200 | container_of(vifs[i].new_ctx, | ||
201 | struct ieee80211_chanctx, | ||
202 | conf); | ||
203 | struct ieee80211_chanctx *old_ctx = | ||
204 | container_of(vifs[i].old_ctx, | ||
205 | struct ieee80211_chanctx, | ||
206 | conf); | ||
207 | |||
208 | WARN_ON_ONCE(!old_ctx->driver_present); | ||
209 | WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS && | ||
210 | new_ctx->driver_present) || | ||
211 | (mode == CHANCTX_SWMODE_REASSIGN_VIF && | ||
212 | !new_ctx->driver_present)); | ||
213 | } | ||
214 | |||
215 | trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode); | ||
216 | ret = local->ops->switch_vif_chanctx(&local->hw, | ||
217 | vifs, n_vifs, mode); | ||
218 | trace_drv_return_int(local, ret); | ||
219 | |||
220 | if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { | ||
221 | for (i = 0; i < n_vifs; i++) { | ||
222 | struct ieee80211_chanctx *new_ctx = | ||
223 | container_of(vifs[i].new_ctx, | ||
224 | struct ieee80211_chanctx, | ||
225 | conf); | ||
226 | struct ieee80211_chanctx *old_ctx = | ||
227 | container_of(vifs[i].old_ctx, | ||
228 | struct ieee80211_chanctx, | ||
229 | conf); | ||
230 | |||
231 | new_ctx->driver_present = true; | ||
232 | old_ctx->driver_present = false; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | int drv_ampdu_action(struct ieee80211_local *local, | ||
240 | struct ieee80211_sub_if_data *sdata, | ||
241 | enum ieee80211_ampdu_mlme_action action, | ||
242 | struct ieee80211_sta *sta, u16 tid, | ||
243 | u16 *ssn, u8 buf_size, bool amsdu) | ||
244 | { | ||
245 | int ret = -EOPNOTSUPP; | ||
246 | |||
247 | might_sleep(); | ||
248 | |||
249 | sdata = get_bss_sdata(sdata); | ||
250 | if (!check_sdata_in_driver(sdata)) | ||
251 | return -EIO; | ||
252 | |||
253 | trace_drv_ampdu_action(local, sdata, action, sta, tid, | ||
254 | ssn, buf_size, amsdu); | ||
255 | |||
256 | if (local->ops->ampdu_action) | ||
257 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, | ||
258 | sta, tid, ssn, buf_size, amsdu); | ||
259 | |||
260 | trace_drv_return_int(local, ret); | ||
261 | |||
262 | return ret; | ||
263 | } | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 02d91332d7dd..30987099eb8f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -137,59 +137,15 @@ static inline void drv_set_wakeup(struct ieee80211_local *local, | |||
137 | } | 137 | } |
138 | #endif | 138 | #endif |
139 | 139 | ||
140 | static inline int drv_add_interface(struct ieee80211_local *local, | 140 | int drv_add_interface(struct ieee80211_local *local, |
141 | struct ieee80211_sub_if_data *sdata) | 141 | struct ieee80211_sub_if_data *sdata); |
142 | { | ||
143 | int ret; | ||
144 | |||
145 | might_sleep(); | ||
146 | |||
147 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
148 | (sdata->vif.type == NL80211_IFTYPE_MONITOR && | ||
149 | !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) && | ||
150 | !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)))) | ||
151 | return -EINVAL; | ||
152 | |||
153 | trace_drv_add_interface(local, sdata); | ||
154 | ret = local->ops->add_interface(&local->hw, &sdata->vif); | ||
155 | trace_drv_return_int(local, ret); | ||
156 | |||
157 | if (ret == 0) | ||
158 | sdata->flags |= IEEE80211_SDATA_IN_DRIVER; | ||
159 | |||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static inline int drv_change_interface(struct ieee80211_local *local, | ||
164 | struct ieee80211_sub_if_data *sdata, | ||
165 | enum nl80211_iftype type, bool p2p) | ||
166 | { | ||
167 | int ret; | ||
168 | 142 | ||
169 | might_sleep(); | 143 | int drv_change_interface(struct ieee80211_local *local, |
170 | 144 | struct ieee80211_sub_if_data *sdata, | |
171 | if (!check_sdata_in_driver(sdata)) | 145 | enum nl80211_iftype type, bool p2p); |
172 | return -EIO; | ||
173 | |||
174 | trace_drv_change_interface(local, sdata, type, p2p); | ||
175 | ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); | ||
176 | trace_drv_return_int(local, ret); | ||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | static inline void drv_remove_interface(struct ieee80211_local *local, | ||
181 | struct ieee80211_sub_if_data *sdata) | ||
182 | { | ||
183 | might_sleep(); | ||
184 | |||
185 | if (!check_sdata_in_driver(sdata)) | ||
186 | return; | ||
187 | 146 | ||
188 | trace_drv_remove_interface(local, sdata); | 147 | void drv_remove_interface(struct ieee80211_local *local, |
189 | local->ops->remove_interface(&local->hw, &sdata->vif); | 148 | struct ieee80211_sub_if_data *sdata); |
190 | sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; | ||
191 | trace_drv_return_void(local); | ||
192 | } | ||
193 | 149 | ||
194 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | 150 | static inline int drv_config(struct ieee80211_local *local, u32 changed) |
195 | { | 151 | { |
@@ -260,6 +216,22 @@ static inline void drv_configure_filter(struct ieee80211_local *local, | |||
260 | trace_drv_return_void(local); | 216 | trace_drv_return_void(local); |
261 | } | 217 | } |
262 | 218 | ||
219 | static inline void drv_config_iface_filter(struct ieee80211_local *local, | ||
220 | struct ieee80211_sub_if_data *sdata, | ||
221 | unsigned int filter_flags, | ||
222 | unsigned int changed_flags) | ||
223 | { | ||
224 | might_sleep(); | ||
225 | |||
226 | trace_drv_config_iface_filter(local, sdata, filter_flags, | ||
227 | changed_flags); | ||
228 | if (local->ops->config_iface_filter) | ||
229 | local->ops->config_iface_filter(&local->hw, &sdata->vif, | ||
230 | filter_flags, | ||
231 | changed_flags); | ||
232 | trace_drv_return_void(local); | ||
233 | } | ||
234 | |||
263 | static inline int drv_set_tim(struct ieee80211_local *local, | 235 | static inline int drv_set_tim(struct ieee80211_local *local, |
264 | struct ieee80211_sta *sta, bool set) | 236 | struct ieee80211_sta *sta, bool set) |
265 | { | 237 | { |
@@ -580,25 +552,9 @@ int drv_sta_state(struct ieee80211_local *local, | |||
580 | enum ieee80211_sta_state old_state, | 552 | enum ieee80211_sta_state old_state, |
581 | enum ieee80211_sta_state new_state); | 553 | enum ieee80211_sta_state new_state); |
582 | 554 | ||
583 | static inline void drv_sta_rc_update(struct ieee80211_local *local, | 555 | void drv_sta_rc_update(struct ieee80211_local *local, |
584 | struct ieee80211_sub_if_data *sdata, | 556 | struct ieee80211_sub_if_data *sdata, |
585 | struct ieee80211_sta *sta, u32 changed) | 557 | struct ieee80211_sta *sta, u32 changed); |
586 | { | ||
587 | sdata = get_bss_sdata(sdata); | ||
588 | if (!check_sdata_in_driver(sdata)) | ||
589 | return; | ||
590 | |||
591 | WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && | ||
592 | (sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
593 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)); | ||
594 | |||
595 | trace_drv_sta_rc_update(local, sdata, sta, changed); | ||
596 | if (local->ops->sta_rc_update) | ||
597 | local->ops->sta_rc_update(&local->hw, &sdata->vif, | ||
598 | sta, changed); | ||
599 | |||
600 | trace_drv_return_void(local); | ||
601 | } | ||
602 | 558 | ||
603 | static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local, | 559 | static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local, |
604 | struct ieee80211_sub_if_data *sdata, | 560 | struct ieee80211_sub_if_data *sdata, |
@@ -630,76 +586,17 @@ static inline void drv_sta_statistics(struct ieee80211_local *local, | |||
630 | trace_drv_return_void(local); | 586 | trace_drv_return_void(local); |
631 | } | 587 | } |
632 | 588 | ||
633 | static inline int drv_conf_tx(struct ieee80211_local *local, | 589 | int drv_conf_tx(struct ieee80211_local *local, |
634 | struct ieee80211_sub_if_data *sdata, u16 ac, | 590 | struct ieee80211_sub_if_data *sdata, u16 ac, |
635 | const struct ieee80211_tx_queue_params *params) | 591 | const struct ieee80211_tx_queue_params *params); |
636 | { | ||
637 | int ret = -EOPNOTSUPP; | ||
638 | |||
639 | might_sleep(); | ||
640 | |||
641 | if (!check_sdata_in_driver(sdata)) | ||
642 | return -EIO; | ||
643 | |||
644 | if (WARN_ONCE(params->cw_min == 0 || | ||
645 | params->cw_min > params->cw_max, | ||
646 | "%s: invalid CW_min/CW_max: %d/%d\n", | ||
647 | sdata->name, params->cw_min, params->cw_max)) | ||
648 | return -EINVAL; | ||
649 | |||
650 | trace_drv_conf_tx(local, sdata, ac, params); | ||
651 | if (local->ops->conf_tx) | ||
652 | ret = local->ops->conf_tx(&local->hw, &sdata->vif, | ||
653 | ac, params); | ||
654 | trace_drv_return_int(local, ret); | ||
655 | return ret; | ||
656 | } | ||
657 | |||
658 | static inline u64 drv_get_tsf(struct ieee80211_local *local, | ||
659 | struct ieee80211_sub_if_data *sdata) | ||
660 | { | ||
661 | u64 ret = -1ULL; | ||
662 | |||
663 | might_sleep(); | ||
664 | |||
665 | if (!check_sdata_in_driver(sdata)) | ||
666 | return ret; | ||
667 | |||
668 | trace_drv_get_tsf(local, sdata); | ||
669 | if (local->ops->get_tsf) | ||
670 | ret = local->ops->get_tsf(&local->hw, &sdata->vif); | ||
671 | trace_drv_return_u64(local, ret); | ||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | static inline void drv_set_tsf(struct ieee80211_local *local, | ||
676 | struct ieee80211_sub_if_data *sdata, | ||
677 | u64 tsf) | ||
678 | { | ||
679 | might_sleep(); | ||
680 | |||
681 | if (!check_sdata_in_driver(sdata)) | ||
682 | return; | ||
683 | |||
684 | trace_drv_set_tsf(local, sdata, tsf); | ||
685 | if (local->ops->set_tsf) | ||
686 | local->ops->set_tsf(&local->hw, &sdata->vif, tsf); | ||
687 | trace_drv_return_void(local); | ||
688 | } | ||
689 | |||
690 | static inline void drv_reset_tsf(struct ieee80211_local *local, | ||
691 | struct ieee80211_sub_if_data *sdata) | ||
692 | { | ||
693 | might_sleep(); | ||
694 | 592 | ||
695 | if (!check_sdata_in_driver(sdata)) | 593 | u64 drv_get_tsf(struct ieee80211_local *local, |
696 | return; | 594 | struct ieee80211_sub_if_data *sdata); |
697 | 595 | void drv_set_tsf(struct ieee80211_local *local, | |
698 | trace_drv_reset_tsf(local, sdata); | 596 | struct ieee80211_sub_if_data *sdata, |
699 | if (local->ops->reset_tsf) | 597 | u64 tsf); |
700 | local->ops->reset_tsf(&local->hw, &sdata->vif); | 598 | void drv_reset_tsf(struct ieee80211_local *local, |
701 | trace_drv_return_void(local); | 599 | struct ieee80211_sub_if_data *sdata); |
702 | } | ||
703 | 600 | ||
704 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 601 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
705 | { | 602 | { |
@@ -714,30 +611,11 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) | |||
714 | return ret; | 611 | return ret; |
715 | } | 612 | } |
716 | 613 | ||
717 | static inline int drv_ampdu_action(struct ieee80211_local *local, | 614 | int drv_ampdu_action(struct ieee80211_local *local, |
718 | struct ieee80211_sub_if_data *sdata, | 615 | struct ieee80211_sub_if_data *sdata, |
719 | enum ieee80211_ampdu_mlme_action action, | 616 | enum ieee80211_ampdu_mlme_action action, |
720 | struct ieee80211_sta *sta, u16 tid, | 617 | struct ieee80211_sta *sta, u16 tid, |
721 | u16 *ssn, u8 buf_size) | 618 | u16 *ssn, u8 buf_size, bool amsdu); |
722 | { | ||
723 | int ret = -EOPNOTSUPP; | ||
724 | |||
725 | might_sleep(); | ||
726 | |||
727 | sdata = get_bss_sdata(sdata); | ||
728 | if (!check_sdata_in_driver(sdata)) | ||
729 | return -EIO; | ||
730 | |||
731 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); | ||
732 | |||
733 | if (local->ops->ampdu_action) | ||
734 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, | ||
735 | sta, tid, ssn, buf_size); | ||
736 | |||
737 | trace_drv_return_int(local, ret); | ||
738 | |||
739 | return ret; | ||
740 | } | ||
741 | 619 | ||
742 | static inline int drv_get_survey(struct ieee80211_local *local, int idx, | 620 | static inline int drv_get_survey(struct ieee80211_local *local, int idx, |
743 | struct survey_info *survey) | 621 | struct survey_info *survey) |
@@ -1066,58 +944,9 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local, | |||
1066 | trace_drv_return_void(local); | 944 | trace_drv_return_void(local); |
1067 | } | 945 | } |
1068 | 946 | ||
1069 | static inline int | 947 | int drv_switch_vif_chanctx(struct ieee80211_local *local, |
1070 | drv_switch_vif_chanctx(struct ieee80211_local *local, | 948 | struct ieee80211_vif_chanctx_switch *vifs, |
1071 | struct ieee80211_vif_chanctx_switch *vifs, | 949 | int n_vifs, enum ieee80211_chanctx_switch_mode mode); |
1072 | int n_vifs, | ||
1073 | enum ieee80211_chanctx_switch_mode mode) | ||
1074 | { | ||
1075 | int ret = 0; | ||
1076 | int i; | ||
1077 | |||
1078 | if (!local->ops->switch_vif_chanctx) | ||
1079 | return -EOPNOTSUPP; | ||
1080 | |||
1081 | for (i = 0; i < n_vifs; i++) { | ||
1082 | struct ieee80211_chanctx *new_ctx = | ||
1083 | container_of(vifs[i].new_ctx, | ||
1084 | struct ieee80211_chanctx, | ||
1085 | conf); | ||
1086 | struct ieee80211_chanctx *old_ctx = | ||
1087 | container_of(vifs[i].old_ctx, | ||
1088 | struct ieee80211_chanctx, | ||
1089 | conf); | ||
1090 | |||
1091 | WARN_ON_ONCE(!old_ctx->driver_present); | ||
1092 | WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS && | ||
1093 | new_ctx->driver_present) || | ||
1094 | (mode == CHANCTX_SWMODE_REASSIGN_VIF && | ||
1095 | !new_ctx->driver_present)); | ||
1096 | } | ||
1097 | |||
1098 | trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode); | ||
1099 | ret = local->ops->switch_vif_chanctx(&local->hw, | ||
1100 | vifs, n_vifs, mode); | ||
1101 | trace_drv_return_int(local, ret); | ||
1102 | |||
1103 | if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) { | ||
1104 | for (i = 0; i < n_vifs; i++) { | ||
1105 | struct ieee80211_chanctx *new_ctx = | ||
1106 | container_of(vifs[i].new_ctx, | ||
1107 | struct ieee80211_chanctx, | ||
1108 | conf); | ||
1109 | struct ieee80211_chanctx *old_ctx = | ||
1110 | container_of(vifs[i].old_ctx, | ||
1111 | struct ieee80211_chanctx, | ||
1112 | conf); | ||
1113 | |||
1114 | new_ctx->driver_present = true; | ||
1115 | old_ctx->driver_present = false; | ||
1116 | } | ||
1117 | } | ||
1118 | |||
1119 | return ret; | ||
1120 | } | ||
1121 | 950 | ||
1122 | static inline int drv_start_ap(struct ieee80211_local *local, | 951 | static inline int drv_start_ap(struct ieee80211_local *local, |
1123 | struct ieee80211_sub_if_data *sdata) | 952 | struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6e52659f923f..f9605f13def9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -419,6 +419,8 @@ struct ieee80211_sta_tx_tspec { | |||
419 | bool downgraded; | 419 | bool downgraded; |
420 | }; | 420 | }; |
421 | 421 | ||
422 | DECLARE_EWMA(beacon_signal, 16, 4) | ||
423 | |||
422 | struct ieee80211_if_managed { | 424 | struct ieee80211_if_managed { |
423 | struct timer_list timer; | 425 | struct timer_list timer; |
424 | struct timer_list conn_mon_timer; | 426 | struct timer_list conn_mon_timer; |
@@ -490,16 +492,7 @@ struct ieee80211_if_managed { | |||
490 | 492 | ||
491 | s16 p2p_noa_index; | 493 | s16 p2p_noa_index; |
492 | 494 | ||
493 | /* Signal strength from the last Beacon frame in the current BSS. */ | 495 | struct ewma_beacon_signal ave_beacon_signal; |
494 | int last_beacon_signal; | ||
495 | |||
496 | /* | ||
497 | * Weighted average of the signal strength from Beacon frames in the | ||
498 | * current BSS. This is in units of 1/16 of the signal unit to maintain | ||
499 | * accuracy and to speed up calculations, i.e., the value need to be | ||
500 | * divided by 16 to get the actual value. | ||
501 | */ | ||
502 | int ave_beacon_signal; | ||
503 | 496 | ||
504 | /* | 497 | /* |
505 | * Number of Beacon frames used in ave_beacon_signal. This can be used | 498 | * Number of Beacon frames used in ave_beacon_signal. This can be used |
@@ -535,6 +528,7 @@ struct ieee80211_if_managed { | |||
535 | struct sk_buff *teardown_skb; /* A copy to send through the AP */ | 528 | struct sk_buff *teardown_skb; /* A copy to send through the AP */ |
536 | spinlock_t teardown_lock; /* To lock changing teardown_skb */ | 529 | spinlock_t teardown_lock; /* To lock changing teardown_skb */ |
537 | bool tdls_chan_switch_prohibited; | 530 | bool tdls_chan_switch_prohibited; |
531 | bool tdls_wider_bw_prohibited; | ||
538 | 532 | ||
539 | /* WMM-AC TSPEC support */ | 533 | /* WMM-AC TSPEC support */ |
540 | struct ieee80211_sta_tx_tspec tx_tspec[IEEE80211_NUM_ACS]; | 534 | struct ieee80211_sta_tx_tspec tx_tspec[IEEE80211_NUM_ACS]; |
@@ -1641,6 +1635,9 @@ void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, | |||
1641 | struct sk_buff * | 1635 | struct sk_buff * |
1642 | ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, | 1636 | ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, |
1643 | struct sk_buff *skb, u32 info_flags); | 1637 | struct sk_buff *skb, u32 info_flags); |
1638 | void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, | ||
1639 | struct ieee80211_supported_band *sband, | ||
1640 | int retry_count, int shift, bool send_to_cooked); | ||
1644 | 1641 | ||
1645 | void ieee80211_check_fast_xmit(struct sta_info *sta); | 1642 | void ieee80211_check_fast_xmit(struct sta_info *sta); |
1646 | void ieee80211_check_fast_xmit_all(struct ieee80211_local *local); | 1643 | void ieee80211_check_fast_xmit_all(struct ieee80211_local *local); |
@@ -1853,7 +1850,7 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work); | |||
1853 | void ieee80211_dynamic_ps_timer(unsigned long data); | 1850 | void ieee80211_dynamic_ps_timer(unsigned long data); |
1854 | void ieee80211_send_nullfunc(struct ieee80211_local *local, | 1851 | void ieee80211_send_nullfunc(struct ieee80211_local *local, |
1855 | struct ieee80211_sub_if_data *sdata, | 1852 | struct ieee80211_sub_if_data *sdata, |
1856 | int powersave); | 1853 | bool powersave); |
1857 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1854 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1858 | struct ieee80211_hdr *hdr); | 1855 | struct ieee80211_hdr *hdr); |
1859 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | 1856 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6964fc6a8ea2..42d7f0f65bd6 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1204,7 +1204,7 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
1204 | if (!ieee80211_sdata_running(sdata)) | 1204 | if (!ieee80211_sdata_running(sdata)) |
1205 | return; | 1205 | return; |
1206 | 1206 | ||
1207 | if (local->scanning) | 1207 | if (test_bit(SCAN_SW_SCANNING, &local->scanning)) |
1208 | return; | 1208 | return; |
1209 | 1209 | ||
1210 | if (!ieee80211_can_run_worker(local)) | 1210 | if (!ieee80211_can_run_worker(local)) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ff79a13d231d..9b813a2f3a75 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -543,7 +543,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, | |||
543 | NL80211_FEATURE_HT_IBSS | | 543 | NL80211_FEATURE_HT_IBSS | |
544 | NL80211_FEATURE_VIF_TXPOWER | | 544 | NL80211_FEATURE_VIF_TXPOWER | |
545 | NL80211_FEATURE_MAC_ON_CREATE | | 545 | NL80211_FEATURE_MAC_ON_CREATE | |
546 | NL80211_FEATURE_USERSPACE_MPM; | 546 | NL80211_FEATURE_USERSPACE_MPM | |
547 | NL80211_FEATURE_FULL_AP_CLIENT_STATE; | ||
547 | 548 | ||
548 | if (!ops->hw_scan) | 549 | if (!ops->hw_scan) |
549 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | | 550 | wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e06a5ca7c9a9..626e8de70842 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -94,6 +94,9 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
94 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, | 94 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, |
95 | ie->ht_operation, &sta_chan_def); | 95 | ie->ht_operation, &sta_chan_def); |
96 | 96 | ||
97 | ieee80211_vht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, | ||
98 | ie->vht_operation, &sta_chan_def); | ||
99 | |||
97 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, | 100 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, |
98 | &sta_chan_def)) | 101 | &sta_chan_def)) |
99 | return false; | 102 | return false; |
@@ -436,8 +439,6 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, | |||
436 | struct ieee80211_local *local = sdata->local; | 439 | struct ieee80211_local *local = sdata->local; |
437 | struct ieee80211_chanctx_conf *chanctx_conf; | 440 | struct ieee80211_chanctx_conf *chanctx_conf; |
438 | struct ieee80211_channel *channel; | 441 | struct ieee80211_channel *channel; |
439 | enum nl80211_channel_type channel_type = | ||
440 | cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef); | ||
441 | struct ieee80211_supported_band *sband; | 442 | struct ieee80211_supported_band *sband; |
442 | struct ieee80211_sta_ht_cap *ht_cap; | 443 | struct ieee80211_sta_ht_cap *ht_cap; |
443 | u8 *pos; | 444 | u8 *pos; |
@@ -454,7 +455,10 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, | |||
454 | sband = local->hw.wiphy->bands[channel->band]; | 455 | sband = local->hw.wiphy->bands[channel->band]; |
455 | ht_cap = &sband->ht_cap; | 456 | ht_cap = &sband->ht_cap; |
456 | 457 | ||
457 | if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT) | 458 | if (!ht_cap->ht_supported || |
459 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT || | ||
460 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 || | ||
461 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) | ||
458 | return 0; | 462 | return 0; |
459 | 463 | ||
460 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_operation)) | 464 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_operation)) |
@@ -467,6 +471,68 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, | |||
467 | return 0; | 471 | return 0; |
468 | } | 472 | } |
469 | 473 | ||
474 | int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata, | ||
475 | struct sk_buff *skb) | ||
476 | { | ||
477 | struct ieee80211_local *local = sdata->local; | ||
478 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
479 | struct ieee80211_supported_band *sband; | ||
480 | u8 *pos; | ||
481 | |||
482 | sband = local->hw.wiphy->bands[band]; | ||
483 | if (!sband->vht_cap.vht_supported || | ||
484 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT || | ||
485 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 || | ||
486 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) | ||
487 | return 0; | ||
488 | |||
489 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_vht_cap)) | ||
490 | return -ENOMEM; | ||
491 | |||
492 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_cap)); | ||
493 | ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, sband->vht_cap.cap); | ||
494 | |||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata, | ||
499 | struct sk_buff *skb) | ||
500 | { | ||
501 | struct ieee80211_local *local = sdata->local; | ||
502 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
503 | struct ieee80211_channel *channel; | ||
504 | struct ieee80211_supported_band *sband; | ||
505 | struct ieee80211_sta_vht_cap *vht_cap; | ||
506 | u8 *pos; | ||
507 | |||
508 | rcu_read_lock(); | ||
509 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
510 | if (WARN_ON(!chanctx_conf)) { | ||
511 | rcu_read_unlock(); | ||
512 | return -EINVAL; | ||
513 | } | ||
514 | channel = chanctx_conf->def.chan; | ||
515 | rcu_read_unlock(); | ||
516 | |||
517 | sband = local->hw.wiphy->bands[channel->band]; | ||
518 | vht_cap = &sband->vht_cap; | ||
519 | |||
520 | if (!vht_cap->vht_supported || | ||
521 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT || | ||
522 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 || | ||
523 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) | ||
524 | return 0; | ||
525 | |||
526 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_vht_operation)) | ||
527 | return -ENOMEM; | ||
528 | |||
529 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation)); | ||
530 | ieee80211_ie_build_vht_oper(pos, vht_cap, | ||
531 | &sdata->vif.bss_conf.chandef); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
470 | static void ieee80211_mesh_path_timer(unsigned long data) | 536 | static void ieee80211_mesh_path_timer(unsigned long data) |
471 | { | 537 | { |
472 | struct ieee80211_sub_if_data *sdata = | 538 | struct ieee80211_sub_if_data *sdata = |
@@ -540,9 +606,9 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | |||
540 | * | 606 | * |
541 | * Return the header length. | 607 | * Return the header length. |
542 | */ | 608 | */ |
543 | int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, | 609 | unsigned int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, |
544 | struct ieee80211s_hdr *meshhdr, | 610 | struct ieee80211s_hdr *meshhdr, |
545 | const char *addr4or5, const char *addr6) | 611 | const char *addr4or5, const char *addr6) |
546 | { | 612 | { |
547 | if (WARN_ON(!addr4or5 && addr6)) | 613 | if (WARN_ON(!addr4or5 && addr6)) |
548 | return 0; | 614 | return 0; |
@@ -637,6 +703,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
637 | 2 + ifmsh->mesh_id_len + | 703 | 2 + ifmsh->mesh_id_len + |
638 | 2 + sizeof(struct ieee80211_meshconf_ie) + | 704 | 2 + sizeof(struct ieee80211_meshconf_ie) + |
639 | 2 + sizeof(__le16) + /* awake window */ | 705 | 2 + sizeof(__le16) + /* awake window */ |
706 | 2 + sizeof(struct ieee80211_vht_cap) + | ||
707 | 2 + sizeof(struct ieee80211_vht_operation) + | ||
640 | ifmsh->ie_len; | 708 | ifmsh->ie_len; |
641 | 709 | ||
642 | bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL); | 710 | bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL); |
@@ -718,6 +786,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
718 | mesh_add_meshid_ie(sdata, skb) || | 786 | mesh_add_meshid_ie(sdata, skb) || |
719 | mesh_add_meshconf_ie(sdata, skb) || | 787 | mesh_add_meshconf_ie(sdata, skb) || |
720 | mesh_add_awake_window_ie(sdata, skb) || | 788 | mesh_add_awake_window_ie(sdata, skb) || |
789 | mesh_add_vht_cap_ie(sdata, skb) || | ||
790 | mesh_add_vht_oper_ie(sdata, skb) || | ||
721 | mesh_add_vendor_ies(sdata, skb)) | 791 | mesh_add_vendor_ies(sdata, skb)) |
722 | goto out_free; | 792 | goto out_free; |
723 | 793 | ||
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 50c8473cf9dc..a1596344c3ba 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -207,9 +207,9 @@ struct mesh_rmc { | |||
207 | /* Various */ | 207 | /* Various */ |
208 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 208 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
209 | const u8 *da, const u8 *sa); | 209 | const u8 *da, const u8 *sa); |
210 | int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, | 210 | unsigned int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, |
211 | struct ieee80211s_hdr *meshhdr, | 211 | struct ieee80211s_hdr *meshhdr, |
212 | const char *addr4or5, const char *addr6); | 212 | const char *addr4or5, const char *addr6); |
213 | int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, | 213 | int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, |
214 | const u8 *addr, struct ieee80211s_hdr *mesh_hdr); | 214 | const u8 *addr, struct ieee80211s_hdr *mesh_hdr); |
215 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | 215 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, |
@@ -227,6 +227,10 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, | |||
227 | struct sk_buff *skb); | 227 | struct sk_buff *skb); |
228 | int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, | 228 | int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, |
229 | struct sk_buff *skb); | 229 | struct sk_buff *skb); |
230 | int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata, | ||
231 | struct sk_buff *skb); | ||
232 | int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata, | ||
233 | struct sk_buff *skb); | ||
230 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | 234 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); |
231 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | 235 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); |
232 | void ieee80211s_init(void); | 236 | void ieee80211s_init(void); |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 58384642e03c..a360b24b7df8 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -226,6 +226,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
226 | 2 + sizeof(struct ieee80211_meshconf_ie) + | 226 | 2 + sizeof(struct ieee80211_meshconf_ie) + |
227 | 2 + sizeof(struct ieee80211_ht_cap) + | 227 | 2 + sizeof(struct ieee80211_ht_cap) + |
228 | 2 + sizeof(struct ieee80211_ht_operation) + | 228 | 2 + sizeof(struct ieee80211_ht_operation) + |
229 | 2 + sizeof(struct ieee80211_vht_cap) + | ||
230 | 2 + sizeof(struct ieee80211_vht_operation) + | ||
229 | 2 + 8 + /* peering IE */ | 231 | 2 + 8 + /* peering IE */ |
230 | sdata->u.mesh.ie_len); | 232 | sdata->u.mesh.ie_len); |
231 | if (!skb) | 233 | if (!skb) |
@@ -306,7 +308,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
306 | 308 | ||
307 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | 309 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { |
308 | if (mesh_add_ht_cap_ie(sdata, skb) || | 310 | if (mesh_add_ht_cap_ie(sdata, skb) || |
309 | mesh_add_ht_oper_ie(sdata, skb)) | 311 | mesh_add_ht_oper_ie(sdata, skb) || |
312 | mesh_add_vht_cap_ie(sdata, skb) || | ||
313 | mesh_add_vht_oper_ie(sdata, skb)) | ||
310 | goto free; | 314 | goto free; |
311 | } | 315 | } |
312 | 316 | ||
@@ -402,6 +406,9 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, | |||
402 | elems->ht_cap_elem, sta)) | 406 | elems->ht_cap_elem, sta)) |
403 | changed |= IEEE80211_RC_BW_CHANGED; | 407 | changed |= IEEE80211_RC_BW_CHANGED; |
404 | 408 | ||
409 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | ||
410 | elems->vht_cap_elem, sta); | ||
411 | |||
405 | if (bw != sta->sta.bandwidth) | 412 | if (bw != sta->sta.bandwidth) |
406 | changed |= IEEE80211_RC_BW_CHANGED; | 413 | changed |= IEEE80211_RC_BW_CHANGED; |
407 | 414 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cd7e55e08a23..56ef9a8e151c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -82,13 +82,6 @@ MODULE_PARM_DESC(probe_wait_ms, | |||
82 | " before disconnecting (reason 4)."); | 82 | " before disconnecting (reason 4)."); |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * Weight given to the latest Beacon frame when calculating average signal | ||
86 | * strength for Beacon frames received in the current BSS. This must be | ||
87 | * between 1 and 15. | ||
88 | */ | ||
89 | #define IEEE80211_SIGNAL_AVE_WEIGHT 3 | ||
90 | |||
91 | /* | ||
92 | * How many Beacon frames need to have been used in average signal strength | 85 | * How many Beacon frames need to have been used in average signal strength |
93 | * before starting to indicate signal change events. | 86 | * before starting to indicate signal change events. |
94 | */ | 87 | */ |
@@ -943,7 +936,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, | |||
943 | 936 | ||
944 | void ieee80211_send_nullfunc(struct ieee80211_local *local, | 937 | void ieee80211_send_nullfunc(struct ieee80211_local *local, |
945 | struct ieee80211_sub_if_data *sdata, | 938 | struct ieee80211_sub_if_data *sdata, |
946 | int powersave) | 939 | bool powersave) |
947 | { | 940 | { |
948 | struct sk_buff *skb; | 941 | struct sk_buff *skb; |
949 | struct ieee80211_hdr_3addr *nullfunc; | 942 | struct ieee80211_hdr_3addr *nullfunc; |
@@ -1427,7 +1420,7 @@ static void ieee80211_enable_ps(struct ieee80211_local *local, | |||
1427 | msecs_to_jiffies(conf->dynamic_ps_timeout)); | 1420 | msecs_to_jiffies(conf->dynamic_ps_timeout)); |
1428 | } else { | 1421 | } else { |
1429 | if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) | 1422 | if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) |
1430 | ieee80211_send_nullfunc(local, sdata, 1); | 1423 | ieee80211_send_nullfunc(local, sdata, true); |
1431 | 1424 | ||
1432 | if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) && | 1425 | if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) && |
1433 | ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) | 1426 | ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) |
@@ -1642,7 +1635,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
1642 | msecs_to_jiffies( | 1635 | msecs_to_jiffies( |
1643 | local->hw.conf.dynamic_ps_timeout)); | 1636 | local->hw.conf.dynamic_ps_timeout)); |
1644 | } else { | 1637 | } else { |
1645 | ieee80211_send_nullfunc(local, sdata, 1); | 1638 | ieee80211_send_nullfunc(local, sdata, true); |
1646 | /* Flush to get the tx status of nullfunc frame */ | 1639 | /* Flush to get the tx status of nullfunc frame */ |
1647 | ieee80211_flush_queues(local, sdata, false); | 1640 | ieee80211_flush_queues(local, sdata, false); |
1648 | } | 1641 | } |
@@ -2275,7 +2268,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
2275 | 2268 | ||
2276 | if (ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) { | 2269 | if (ieee80211_hw_check(&sdata->local->hw, REPORTS_TX_ACK_STATUS)) { |
2277 | ifmgd->nullfunc_failed = false; | 2270 | ifmgd->nullfunc_failed = false; |
2278 | ieee80211_send_nullfunc(sdata->local, sdata, 0); | 2271 | ieee80211_send_nullfunc(sdata->local, sdata, false); |
2279 | } else { | 2272 | } else { |
2280 | int ssid_len; | 2273 | int ssid_len; |
2281 | 2274 | ||
@@ -3262,16 +3255,6 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
3262 | if (ifmgd->associated && | 3255 | if (ifmgd->associated && |
3263 | ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) | 3256 | ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) |
3264 | ieee80211_reset_ap_probe(sdata); | 3257 | ieee80211_reset_ap_probe(sdata); |
3265 | |||
3266 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && | ||
3267 | ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) { | ||
3268 | /* got probe response, continue with auth */ | ||
3269 | sdata_info(sdata, "direct probe responded\n"); | ||
3270 | ifmgd->auth_data->tries = 0; | ||
3271 | ifmgd->auth_data->timeout = jiffies; | ||
3272 | ifmgd->auth_data->timeout_started = true; | ||
3273 | run_again(sdata, ifmgd->auth_data->timeout); | ||
3274 | } | ||
3275 | } | 3258 | } |
3276 | 3259 | ||
3277 | /* | 3260 | /* |
@@ -3374,24 +3357,21 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3374 | bssid = ifmgd->associated->bssid; | 3357 | bssid = ifmgd->associated->bssid; |
3375 | 3358 | ||
3376 | /* Track average RSSI from the Beacon frames of the current AP */ | 3359 | /* Track average RSSI from the Beacon frames of the current AP */ |
3377 | ifmgd->last_beacon_signal = rx_status->signal; | ||
3378 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { | 3360 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { |
3379 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; | 3361 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; |
3380 | ifmgd->ave_beacon_signal = rx_status->signal * 16; | 3362 | ewma_beacon_signal_init(&ifmgd->ave_beacon_signal); |
3381 | ifmgd->last_cqm_event_signal = 0; | 3363 | ifmgd->last_cqm_event_signal = 0; |
3382 | ifmgd->count_beacon_signal = 1; | 3364 | ifmgd->count_beacon_signal = 1; |
3383 | ifmgd->last_ave_beacon_signal = 0; | 3365 | ifmgd->last_ave_beacon_signal = 0; |
3384 | } else { | 3366 | } else { |
3385 | ifmgd->ave_beacon_signal = | ||
3386 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + | ||
3387 | (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * | ||
3388 | ifmgd->ave_beacon_signal) / 16; | ||
3389 | ifmgd->count_beacon_signal++; | 3367 | ifmgd->count_beacon_signal++; |
3390 | } | 3368 | } |
3391 | 3369 | ||
3370 | ewma_beacon_signal_add(&ifmgd->ave_beacon_signal, -rx_status->signal); | ||
3371 | |||
3392 | if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold && | 3372 | if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold && |
3393 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) { | 3373 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) { |
3394 | int sig = ifmgd->ave_beacon_signal; | 3374 | int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal); |
3395 | int last_sig = ifmgd->last_ave_beacon_signal; | 3375 | int last_sig = ifmgd->last_ave_beacon_signal; |
3396 | struct ieee80211_event event = { | 3376 | struct ieee80211_event event = { |
3397 | .type = RSSI_EVENT, | 3377 | .type = RSSI_EVENT, |
@@ -3418,10 +3398,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3418 | if (bss_conf->cqm_rssi_thold && | 3398 | if (bss_conf->cqm_rssi_thold && |
3419 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && | 3399 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && |
3420 | !(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) { | 3400 | !(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) { |
3421 | int sig = ifmgd->ave_beacon_signal / 16; | 3401 | int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal); |
3422 | int last_event = ifmgd->last_cqm_event_signal; | 3402 | int last_event = ifmgd->last_cqm_event_signal; |
3423 | int thold = bss_conf->cqm_rssi_thold; | 3403 | int thold = bss_conf->cqm_rssi_thold; |
3424 | int hyst = bss_conf->cqm_rssi_hyst; | 3404 | int hyst = bss_conf->cqm_rssi_hyst; |
3405 | |||
3425 | if (sig < thold && | 3406 | if (sig < thold && |
3426 | (last_event == 0 || sig < last_event - hyst)) { | 3407 | (last_event == 0 || sig < last_event - hyst)) { |
3427 | ifmgd->last_cqm_event_signal = sig; | 3408 | ifmgd->last_cqm_event_signal = sig; |
@@ -3456,31 +3437,27 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3456 | len - baselen, false, &elems, | 3437 | len - baselen, false, &elems, |
3457 | care_about_ies, ncrc); | 3438 | care_about_ies, ncrc); |
3458 | 3439 | ||
3459 | if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) { | 3440 | if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) && |
3460 | bool directed_tim = ieee80211_check_tim(elems.tim, | 3441 | ieee80211_check_tim(elems.tim, elems.tim_len, ifmgd->aid)) { |
3461 | elems.tim_len, | 3442 | if (local->hw.conf.dynamic_ps_timeout > 0) { |
3462 | ifmgd->aid); | 3443 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
3463 | if (directed_tim) { | 3444 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; |
3464 | if (local->hw.conf.dynamic_ps_timeout > 0) { | 3445 | ieee80211_hw_config(local, |
3465 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 3446 | IEEE80211_CONF_CHANGE_PS); |
3466 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
3467 | ieee80211_hw_config(local, | ||
3468 | IEEE80211_CONF_CHANGE_PS); | ||
3469 | } | ||
3470 | ieee80211_send_nullfunc(local, sdata, 0); | ||
3471 | } else if (!local->pspolling && sdata->u.mgd.powersave) { | ||
3472 | local->pspolling = true; | ||
3473 | |||
3474 | /* | ||
3475 | * Here is assumed that the driver will be | ||
3476 | * able to send ps-poll frame and receive a | ||
3477 | * response even though power save mode is | ||
3478 | * enabled, but some drivers might require | ||
3479 | * to disable power save here. This needs | ||
3480 | * to be investigated. | ||
3481 | */ | ||
3482 | ieee80211_send_pspoll(local, sdata); | ||
3483 | } | 3447 | } |
3448 | ieee80211_send_nullfunc(local, sdata, false); | ||
3449 | } else if (!local->pspolling && sdata->u.mgd.powersave) { | ||
3450 | local->pspolling = true; | ||
3451 | |||
3452 | /* | ||
3453 | * Here is assumed that the driver will be | ||
3454 | * able to send ps-poll frame and receive a | ||
3455 | * response even though power save mode is | ||
3456 | * enabled, but some drivers might require | ||
3457 | * to disable power save here. This needs | ||
3458 | * to be investigated. | ||
3459 | */ | ||
3460 | ieee80211_send_pspoll(local, sdata); | ||
3484 | } | 3461 | } |
3485 | } | 3462 | } |
3486 | 3463 | ||
@@ -3717,12 +3694,14 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
3717 | reason); | 3694 | reason); |
3718 | } | 3695 | } |
3719 | 3696 | ||
3720 | static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | 3697 | static int ieee80211_auth(struct ieee80211_sub_if_data *sdata) |
3721 | { | 3698 | { |
3722 | struct ieee80211_local *local = sdata->local; | 3699 | struct ieee80211_local *local = sdata->local; |
3723 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3700 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3724 | struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; | 3701 | struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; |
3725 | u32 tx_flags = 0; | 3702 | u32 tx_flags = 0; |
3703 | u16 trans = 1; | ||
3704 | u16 status = 0; | ||
3726 | 3705 | ||
3727 | sdata_assert_lock(sdata); | 3706 | sdata_assert_lock(sdata); |
3728 | 3707 | ||
@@ -3746,54 +3725,27 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
3746 | 3725 | ||
3747 | drv_mgd_prepare_tx(local, sdata); | 3726 | drv_mgd_prepare_tx(local, sdata); |
3748 | 3727 | ||
3749 | if (auth_data->bss->proberesp_ies) { | 3728 | sdata_info(sdata, "send auth to %pM (try %d/%d)\n", |
3750 | u16 trans = 1; | 3729 | auth_data->bss->bssid, auth_data->tries, |
3751 | u16 status = 0; | 3730 | IEEE80211_AUTH_MAX_TRIES); |
3752 | |||
3753 | sdata_info(sdata, "send auth to %pM (try %d/%d)\n", | ||
3754 | auth_data->bss->bssid, auth_data->tries, | ||
3755 | IEEE80211_AUTH_MAX_TRIES); | ||
3756 | 3731 | ||
3757 | auth_data->expected_transaction = 2; | 3732 | auth_data->expected_transaction = 2; |
3758 | 3733 | ||
3759 | if (auth_data->algorithm == WLAN_AUTH_SAE) { | 3734 | if (auth_data->algorithm == WLAN_AUTH_SAE) { |
3760 | trans = auth_data->sae_trans; | 3735 | trans = auth_data->sae_trans; |
3761 | status = auth_data->sae_status; | 3736 | status = auth_data->sae_status; |
3762 | auth_data->expected_transaction = trans; | 3737 | auth_data->expected_transaction = trans; |
3763 | } | 3738 | } |
3764 | |||
3765 | if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) | ||
3766 | tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | | ||
3767 | IEEE80211_TX_INTFL_MLME_CONN_TX; | ||
3768 | |||
3769 | ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, | ||
3770 | auth_data->data, auth_data->data_len, | ||
3771 | auth_data->bss->bssid, | ||
3772 | auth_data->bss->bssid, NULL, 0, 0, | ||
3773 | tx_flags); | ||
3774 | } else { | ||
3775 | const u8 *ssidie; | ||
3776 | 3739 | ||
3777 | sdata_info(sdata, "direct probe to %pM (try %d/%i)\n", | 3740 | if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) |
3778 | auth_data->bss->bssid, auth_data->tries, | 3741 | tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | |
3779 | IEEE80211_AUTH_MAX_TRIES); | 3742 | IEEE80211_TX_INTFL_MLME_CONN_TX; |
3780 | 3743 | ||
3781 | rcu_read_lock(); | 3744 | ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, |
3782 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); | 3745 | auth_data->data, auth_data->data_len, |
3783 | if (!ssidie) { | 3746 | auth_data->bss->bssid, |
3784 | rcu_read_unlock(); | 3747 | auth_data->bss->bssid, NULL, 0, 0, |
3785 | return -EINVAL; | 3748 | tx_flags); |
3786 | } | ||
3787 | /* | ||
3788 | * Direct probe is sent to broadcast address as some APs | ||
3789 | * will not answer to direct packet in unassociated state. | ||
3790 | */ | ||
3791 | ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL, | ||
3792 | ssidie + 2, ssidie[1], | ||
3793 | NULL, 0, (u32) -1, true, 0, | ||
3794 | auth_data->bss->channel, false); | ||
3795 | rcu_read_unlock(); | ||
3796 | } | ||
3797 | 3749 | ||
3798 | if (tx_flags == 0) { | 3750 | if (tx_flags == 0) { |
3799 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 3751 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
@@ -3874,8 +3826,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
3874 | bool status_acked = ifmgd->status_acked; | 3826 | bool status_acked = ifmgd->status_acked; |
3875 | 3827 | ||
3876 | ifmgd->status_received = false; | 3828 | ifmgd->status_received = false; |
3877 | if (ifmgd->auth_data && | 3829 | if (ifmgd->auth_data && ieee80211_is_auth(fc)) { |
3878 | (ieee80211_is_probe_req(fc) || ieee80211_is_auth(fc))) { | ||
3879 | if (status_acked) { | 3830 | if (status_acked) { |
3880 | ifmgd->auth_data->timeout = | 3831 | ifmgd->auth_data->timeout = |
3881 | jiffies + IEEE80211_AUTH_TIMEOUT_SHORT; | 3832 | jiffies + IEEE80211_AUTH_TIMEOUT_SHORT; |
@@ -3906,7 +3857,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
3906 | * so let's just kill the auth data | 3857 | * so let's just kill the auth data |
3907 | */ | 3858 | */ |
3908 | ieee80211_destroy_auth_data(sdata, false); | 3859 | ieee80211_destroy_auth_data(sdata, false); |
3909 | } else if (ieee80211_probe_auth(sdata)) { | 3860 | } else if (ieee80211_auth(sdata)) { |
3910 | u8 bssid[ETH_ALEN]; | 3861 | u8 bssid[ETH_ALEN]; |
3911 | struct ieee80211_event event = { | 3862 | struct ieee80211_event event = { |
3912 | .type = MLME_EVENT, | 3863 | .type = MLME_EVENT, |
@@ -4613,7 +4564,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
4613 | if (err) | 4564 | if (err) |
4614 | goto err_clear; | 4565 | goto err_clear; |
4615 | 4566 | ||
4616 | err = ieee80211_probe_auth(sdata); | 4567 | err = ieee80211_auth(sdata); |
4617 | if (err) { | 4568 | if (err) { |
4618 | sta_info_destroy_addr(sdata, req->bss->bssid); | 4569 | sta_info_destroy_addr(sdata, req->bss->bssid); |
4619 | goto err_clear; | 4570 | goto err_clear; |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index f2c75cf491fc..04401037140e 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -57,7 +57,7 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | |||
57 | * to send a new nullfunc frame to inform the AP that we | 57 | * to send a new nullfunc frame to inform the AP that we |
58 | * are again sleeping. | 58 | * are again sleeping. |
59 | */ | 59 | */ |
60 | ieee80211_send_nullfunc(local, sdata, 1); | 60 | ieee80211_send_nullfunc(local, sdata, true); |
61 | } | 61 | } |
62 | 62 | ||
63 | /* inform AP that we are awake again, unless power save is enabled */ | 63 | /* inform AP that we are awake again, unless power save is enabled */ |
@@ -66,7 +66,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
66 | struct ieee80211_local *local = sdata->local; | 66 | struct ieee80211_local *local = sdata->local; |
67 | 67 | ||
68 | if (!local->ps_sdata) | 68 | if (!local->ps_sdata) |
69 | ieee80211_send_nullfunc(local, sdata, 0); | 69 | ieee80211_send_nullfunc(local, sdata, false); |
70 | else if (local->offchannel_ps_enabled) { | 70 | else if (local->offchannel_ps_enabled) { |
71 | /* | 71 | /* |
72 | * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware | 72 | * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware |
@@ -93,7 +93,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
93 | * restart the timer now and send a nullfunc frame to inform | 93 | * restart the timer now and send a nullfunc frame to inform |
94 | * the AP that we are awake. | 94 | * the AP that we are awake. |
95 | */ | 95 | */ |
96 | ieee80211_send_nullfunc(local, sdata, 0); | 96 | ieee80211_send_nullfunc(local, sdata, false); |
97 | mod_timer(&local->dynamic_ps_timer, jiffies + | 97 | mod_timer(&local->dynamic_ps_timer, jiffies + |
98 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 98 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
99 | } | 99 | } |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index b676b9fa707b..ad88ad4e8eb1 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -23,7 +23,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
23 | 23 | ||
24 | ieee80211_del_virtual_monitor(local); | 24 | ieee80211_del_virtual_monitor(local); |
25 | 25 | ||
26 | if (ieee80211_hw_check(hw, AMPDU_AGGREGATION)) { | 26 | if (ieee80211_hw_check(hw, AMPDU_AGGREGATION) && |
27 | !(wowlan && wowlan->any)) { | ||
27 | mutex_lock(&local->sta_mtx); | 28 | mutex_lock(&local->sta_mtx); |
28 | list_for_each_entry(sta, &local->sta_list, list) { | 29 | list_for_each_entry(sta, &local->sta_list, list) { |
29 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); | 30 | set_sta_flag(sta, WLAN_STA_BLOCK_BA); |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 9ce8883d5f44..b07e2f748f93 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -305,7 +305,10 @@ static void __rate_control_send_low(struct ieee80211_hw *hw, | |||
305 | info->control.rates[0].idx = i; | 305 | info->control.rates[0].idx = i; |
306 | break; | 306 | break; |
307 | } | 307 | } |
308 | WARN_ON_ONCE(i == sband->n_bitrates); | 308 | WARN_ONCE(i == sband->n_bitrates, |
309 | "no supported rates (0x%x) in rate_mask 0x%x with flags 0x%x\n", | ||
310 | sta ? sta->supp_rates[sband->band] : 0, | ||
311 | rate_mask, rate_flags); | ||
309 | 312 | ||
310 | info->control.rates[0].count = | 313 | info->control.rates[0].count = |
311 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | 314 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 1db5f7c3318a..820b0abc9c0d 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -85,12 +85,10 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
85 | file->private_data = ms; | 85 | file->private_data = ms; |
86 | p = ms->buf; | 86 | p = ms->buf; |
87 | p += sprintf(p, "\n"); | 87 | p += sprintf(p, "\n"); |
88 | p += sprintf(p, "best __________rate_________ ______" | 88 | p += sprintf(p, |
89 | "statistics______ ________last_______ " | 89 | "best __________rate_________ ________statistics________ ________last_______ ______sum-of________\n"); |
90 | "______sum-of________\n"); | 90 | p += sprintf(p, |
91 | p += sprintf(p, "rate [name idx airtime max_tp] [ Ăž(tp) Ăž(prob) " | 91 | "rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n"); |
92 | "sd(prob)] [prob.|retry|suc|att] " | ||
93 | "[#success | #attempts]\n"); | ||
94 | 92 | ||
95 | for (i = 0; i < mi->n_rates; i++) { | 93 | for (i = 0; i < mi->n_rates; i++) { |
96 | struct minstrel_rate *mr = &mi->r[i]; | 94 | struct minstrel_rate *mr = &mi->r[i]; |
@@ -112,7 +110,7 @@ minstrel_stats_open(struct inode *inode, struct file *file) | |||
112 | prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); | 110 | prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); |
113 | eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); | 111 | eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); |
114 | 112 | ||
115 | p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" | 113 | p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" |
116 | " %3u.%1u %3u %3u %-3u " | 114 | " %3u.%1u %3u %3u %-3u " |
117 | "%9llu %-9llu\n", | 115 | "%9llu %-9llu\n", |
118 | tp_max / 10, tp_max % 10, | 116 | tp_max / 10, tp_max % 10, |
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index 6822ce0f95e5..5320e35ed3d0 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c | |||
@@ -86,7 +86,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) | |||
86 | prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); | 86 | prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); |
87 | eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); | 87 | eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); |
88 | 88 | ||
89 | p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" | 89 | p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" |
90 | " %3u.%1u %3u %3u %-3u " | 90 | " %3u.%1u %3u %3u %-3u " |
91 | "%9llu %-9llu\n", | 91 | "%9llu %-9llu\n", |
92 | tp_max / 10, tp_max % 10, | 92 | tp_max / 10, tp_max % 10, |
@@ -129,12 +129,10 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) | |||
129 | p = ms->buf; | 129 | p = ms->buf; |
130 | 130 | ||
131 | p += sprintf(p, "\n"); | 131 | p += sprintf(p, "\n"); |
132 | p += sprintf(p, " best ____________rate__________ " | 132 | p += sprintf(p, |
133 | "______statistics______ ________last_______ " | 133 | " best ____________rate__________ ________statistics________ ________last_______ ______sum-of________\n"); |
134 | "______sum-of________\n"); | 134 | p += sprintf(p, |
135 | p += sprintf(p, "mode guard # rate [name idx airtime max_tp] " | 135 | "mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob) sd(prob)] [prob.|retry|suc|att] [#success | #attempts]\n"); |
136 | "[ Ăž(tp) Ăž(prob) sd(prob)] [prob.|retry|suc|att] [#success | " | ||
137 | "#attempts]\n"); | ||
138 | 136 | ||
139 | p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p); | 137 | p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p); |
140 | for (i = 0; i < MINSTREL_CCK_GROUP; i++) | 138 | for (i = 0; i < MINSTREL_CCK_GROUP; i++) |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b087c71ff7fe..d5ded8749ac4 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -133,6 +133,7 @@ enum ieee80211_agg_stop_reason { | |||
133 | * @buf_size: reorder buffer size at receiver | 133 | * @buf_size: reorder buffer size at receiver |
134 | * @failed_bar_ssn: ssn of the last failed BAR tx attempt | 134 | * @failed_bar_ssn: ssn of the last failed BAR tx attempt |
135 | * @bar_pending: BAR needs to be re-sent | 135 | * @bar_pending: BAR needs to be re-sent |
136 | * @amsdu: support A-MSDU withing A-MDPU | ||
136 | * | 137 | * |
137 | * This structure's lifetime is managed by RCU, assignments to | 138 | * This structure's lifetime is managed by RCU, assignments to |
138 | * the array holding it must hold the aggregation mutex. | 139 | * the array holding it must hold the aggregation mutex. |
@@ -158,6 +159,7 @@ struct tid_ampdu_tx { | |||
158 | 159 | ||
159 | u16 failed_bar_ssn; | 160 | u16 failed_bar_ssn; |
160 | bool bar_pending; | 161 | bool bar_pending; |
162 | bool amsdu; | ||
161 | }; | 163 | }; |
162 | 164 | ||
163 | /** | 165 | /** |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 8ba583243509..98fd04c4b2a0 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -668,16 +668,70 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, | |||
668 | } | 668 | } |
669 | EXPORT_SYMBOL(ieee80211_tx_status_noskb); | 669 | EXPORT_SYMBOL(ieee80211_tx_status_noskb); |
670 | 670 | ||
671 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 671 | void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, |
672 | struct ieee80211_supported_band *sband, | ||
673 | int retry_count, int shift, bool send_to_cooked) | ||
672 | { | 674 | { |
673 | struct sk_buff *skb2; | 675 | struct sk_buff *skb2; |
676 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
677 | struct ieee80211_sub_if_data *sdata; | ||
678 | struct net_device *prev_dev = NULL; | ||
679 | int rtap_len; | ||
680 | |||
681 | /* send frame to monitor interfaces now */ | ||
682 | rtap_len = ieee80211_tx_radiotap_len(info); | ||
683 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { | ||
684 | pr_err("ieee80211_tx_status: headroom too small\n"); | ||
685 | dev_kfree_skb(skb); | ||
686 | return; | ||
687 | } | ||
688 | ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count, | ||
689 | rtap_len, shift); | ||
690 | |||
691 | /* XXX: is this sufficient for BPF? */ | ||
692 | skb_set_mac_header(skb, 0); | ||
693 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
694 | skb->pkt_type = PACKET_OTHERHOST; | ||
695 | skb->protocol = htons(ETH_P_802_2); | ||
696 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
697 | |||
698 | rcu_read_lock(); | ||
699 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
700 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { | ||
701 | if (!ieee80211_sdata_running(sdata)) | ||
702 | continue; | ||
703 | |||
704 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | ||
705 | !send_to_cooked) | ||
706 | continue; | ||
707 | |||
708 | if (prev_dev) { | ||
709 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
710 | if (skb2) { | ||
711 | skb2->dev = prev_dev; | ||
712 | netif_rx(skb2); | ||
713 | } | ||
714 | } | ||
715 | |||
716 | prev_dev = sdata->dev; | ||
717 | } | ||
718 | } | ||
719 | if (prev_dev) { | ||
720 | skb->dev = prev_dev; | ||
721 | netif_rx(skb); | ||
722 | skb = NULL; | ||
723 | } | ||
724 | rcu_read_unlock(); | ||
725 | dev_kfree_skb(skb); | ||
726 | } | ||
727 | |||
728 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
729 | { | ||
674 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 730 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
675 | struct ieee80211_local *local = hw_to_local(hw); | 731 | struct ieee80211_local *local = hw_to_local(hw); |
676 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 732 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
677 | __le16 fc; | 733 | __le16 fc; |
678 | struct ieee80211_supported_band *sband; | 734 | struct ieee80211_supported_band *sband; |
679 | struct ieee80211_sub_if_data *sdata; | ||
680 | struct net_device *prev_dev = NULL; | ||
681 | struct sta_info *sta; | 735 | struct sta_info *sta; |
682 | struct rhash_head *tmp; | 736 | struct rhash_head *tmp; |
683 | int retry_count; | 737 | int retry_count; |
@@ -685,7 +739,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
685 | bool send_to_cooked; | 739 | bool send_to_cooked; |
686 | bool acked; | 740 | bool acked; |
687 | struct ieee80211_bar *bar; | 741 | struct ieee80211_bar *bar; |
688 | int rtap_len; | ||
689 | int shift = 0; | 742 | int shift = 0; |
690 | int tid = IEEE80211_NUM_TIDS; | 743 | int tid = IEEE80211_NUM_TIDS; |
691 | const struct bucket_table *tbl; | 744 | const struct bucket_table *tbl; |
@@ -878,51 +931,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
878 | return; | 931 | return; |
879 | } | 932 | } |
880 | 933 | ||
881 | /* send frame to monitor interfaces now */ | 934 | /* send to monitor interfaces */ |
882 | rtap_len = ieee80211_tx_radiotap_len(info); | 935 | ieee80211_tx_monitor(local, skb, sband, retry_count, shift, send_to_cooked); |
883 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { | ||
884 | pr_err("ieee80211_tx_status: headroom too small\n"); | ||
885 | dev_kfree_skb(skb); | ||
886 | return; | ||
887 | } | ||
888 | ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count, | ||
889 | rtap_len, shift); | ||
890 | |||
891 | /* XXX: is this sufficient for BPF? */ | ||
892 | skb_set_mac_header(skb, 0); | ||
893 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
894 | skb->pkt_type = PACKET_OTHERHOST; | ||
895 | skb->protocol = htons(ETH_P_802_2); | ||
896 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
897 | |||
898 | rcu_read_lock(); | ||
899 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
900 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { | ||
901 | if (!ieee80211_sdata_running(sdata)) | ||
902 | continue; | ||
903 | |||
904 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | ||
905 | !send_to_cooked) | ||
906 | continue; | ||
907 | |||
908 | if (prev_dev) { | ||
909 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
910 | if (skb2) { | ||
911 | skb2->dev = prev_dev; | ||
912 | netif_rx(skb2); | ||
913 | } | ||
914 | } | ||
915 | |||
916 | prev_dev = sdata->dev; | ||
917 | } | ||
918 | } | ||
919 | if (prev_dev) { | ||
920 | skb->dev = prev_dev; | ||
921 | netif_rx(skb); | ||
922 | skb = NULL; | ||
923 | } | ||
924 | rcu_read_unlock(); | ||
925 | dev_kfree_skb(skb); | ||
926 | } | 936 | } |
927 | EXPORT_SYMBOL(ieee80211_tx_status); | 937 | EXPORT_SYMBOL(ieee80211_tx_status); |
928 | 938 | ||
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index 4e202d0679b2..ecc5e2a8f80b 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c | |||
@@ -41,9 +41,11 @@ static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata, | |||
41 | struct sk_buff *skb) | 41 | struct sk_buff *skb) |
42 | { | 42 | { |
43 | struct ieee80211_local *local = sdata->local; | 43 | struct ieee80211_local *local = sdata->local; |
44 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
44 | bool chan_switch = local->hw.wiphy->features & | 45 | bool chan_switch = local->hw.wiphy->features & |
45 | NL80211_FEATURE_TDLS_CHANNEL_SWITCH; | 46 | NL80211_FEATURE_TDLS_CHANNEL_SWITCH; |
46 | bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW); | 47 | bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) && |
48 | !ifmgd->tdls_wider_bw_prohibited; | ||
47 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 49 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
48 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | 50 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
49 | bool vht = sband && sband->vht_cap.vht_supported; | 51 | bool vht = sband && sband->vht_cap.vht_supported; |
@@ -331,8 +333,8 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata, | |||
331 | 333 | ||
332 | /* proceed to downgrade the chandef until usable or the same */ | 334 | /* proceed to downgrade the chandef until usable or the same */ |
333 | while (uc.width > max_width && | 335 | while (uc.width > max_width && |
334 | !cfg80211_reg_can_beacon(sdata->local->hw.wiphy, | 336 | !cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &uc, |
335 | &uc, sdata->wdev.iftype)) | 337 | sdata->wdev.iftype)) |
336 | ieee80211_chandef_downgrade(&uc); | 338 | ieee80211_chandef_downgrade(&uc); |
337 | 339 | ||
338 | if (!cfg80211_chandef_identical(&uc, &sta->tdls_chandef)) { | 340 | if (!cfg80211_chandef_identical(&uc, &sta->tdls_chandef)) { |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 6f14591d8ca9..314e3bd7fbdb 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -497,6 +497,36 @@ TRACE_EVENT(drv_configure_filter, | |||
497 | ) | 497 | ) |
498 | ); | 498 | ); |
499 | 499 | ||
500 | TRACE_EVENT(drv_config_iface_filter, | ||
501 | TP_PROTO(struct ieee80211_local *local, | ||
502 | struct ieee80211_sub_if_data *sdata, | ||
503 | unsigned int filter_flags, | ||
504 | unsigned int changed_flags), | ||
505 | |||
506 | TP_ARGS(local, sdata, filter_flags, changed_flags), | ||
507 | |||
508 | TP_STRUCT__entry( | ||
509 | LOCAL_ENTRY | ||
510 | VIF_ENTRY | ||
511 | __field(unsigned int, filter_flags) | ||
512 | __field(unsigned int, changed_flags) | ||
513 | ), | ||
514 | |||
515 | TP_fast_assign( | ||
516 | LOCAL_ASSIGN; | ||
517 | VIF_ASSIGN; | ||
518 | __entry->filter_flags = filter_flags; | ||
519 | __entry->changed_flags = changed_flags; | ||
520 | ), | ||
521 | |||
522 | TP_printk( | ||
523 | LOCAL_PR_FMT VIF_PR_FMT | ||
524 | " filter_flags: %#x changed_flags: %#x", | ||
525 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->filter_flags, | ||
526 | __entry->changed_flags | ||
527 | ) | ||
528 | ); | ||
529 | |||
500 | TRACE_EVENT(drv_set_tim, | 530 | TRACE_EVENT(drv_set_tim, |
501 | TP_PROTO(struct ieee80211_local *local, | 531 | TP_PROTO(struct ieee80211_local *local, |
502 | struct ieee80211_sta *sta, bool set), | 532 | struct ieee80211_sta *sta, bool set), |
@@ -944,9 +974,9 @@ TRACE_EVENT(drv_ampdu_action, | |||
944 | struct ieee80211_sub_if_data *sdata, | 974 | struct ieee80211_sub_if_data *sdata, |
945 | enum ieee80211_ampdu_mlme_action action, | 975 | enum ieee80211_ampdu_mlme_action action, |
946 | struct ieee80211_sta *sta, u16 tid, | 976 | struct ieee80211_sta *sta, u16 tid, |
947 | u16 *ssn, u8 buf_size), | 977 | u16 *ssn, u8 buf_size, bool amsdu), |
948 | 978 | ||
949 | TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size), | 979 | TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu), |
950 | 980 | ||
951 | TP_STRUCT__entry( | 981 | TP_STRUCT__entry( |
952 | LOCAL_ENTRY | 982 | LOCAL_ENTRY |
@@ -955,6 +985,7 @@ TRACE_EVENT(drv_ampdu_action, | |||
955 | __field(u16, tid) | 985 | __field(u16, tid) |
956 | __field(u16, ssn) | 986 | __field(u16, ssn) |
957 | __field(u8, buf_size) | 987 | __field(u8, buf_size) |
988 | __field(bool, amsdu) | ||
958 | VIF_ENTRY | 989 | VIF_ENTRY |
959 | ), | 990 | ), |
960 | 991 | ||
@@ -966,12 +997,13 @@ TRACE_EVENT(drv_ampdu_action, | |||
966 | __entry->tid = tid; | 997 | __entry->tid = tid; |
967 | __entry->ssn = ssn ? *ssn : 0; | 998 | __entry->ssn = ssn ? *ssn : 0; |
968 | __entry->buf_size = buf_size; | 999 | __entry->buf_size = buf_size; |
1000 | __entry->amsdu = amsdu; | ||
969 | ), | 1001 | ), |
970 | 1002 | ||
971 | TP_printk( | 1003 | TP_printk( |
972 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d", | 1004 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d", |
973 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, | 1005 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, |
974 | __entry->tid, __entry->buf_size | 1006 | __entry->tid, __entry->buf_size, __entry->amsdu |
975 | ) | 1007 | ) |
976 | ); | 1008 | ); |
977 | 1009 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 84e0e8c7fb23..464ba1a625bd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2767,7 +2767,8 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, | |||
2767 | 2767 | ||
2768 | if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { | 2768 | if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { |
2769 | *ieee80211_get_qos_ctl(hdr) = tid; | 2769 | *ieee80211_get_qos_ctl(hdr) = tid; |
2770 | hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid); | 2770 | if (!sta->sta.txq[0]) |
2771 | hdr->seq_ctrl = ieee80211_tx_next_seq(sta, tid); | ||
2771 | } else { | 2772 | } else { |
2772 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | 2773 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; |
2773 | hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number); | 2774 | hdr->seq_ctrl = cpu_to_le16(sdata->sequence_number); |
@@ -3512,6 +3513,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
3512 | { | 3513 | { |
3513 | struct ieee80211_mutable_offsets offs = {}; | 3514 | struct ieee80211_mutable_offsets offs = {}; |
3514 | struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false); | 3515 | struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false); |
3516 | struct sk_buff *copy; | ||
3517 | struct ieee80211_supported_band *sband; | ||
3518 | int shift; | ||
3519 | |||
3520 | if (!bcn) | ||
3521 | return bcn; | ||
3515 | 3522 | ||
3516 | if (tim_offset) | 3523 | if (tim_offset) |
3517 | *tim_offset = offs.tim_offset; | 3524 | *tim_offset = offs.tim_offset; |
@@ -3519,6 +3526,19 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
3519 | if (tim_length) | 3526 | if (tim_length) |
3520 | *tim_length = offs.tim_length; | 3527 | *tim_length = offs.tim_length; |
3521 | 3528 | ||
3529 | if (ieee80211_hw_check(hw, BEACON_TX_STATUS) || | ||
3530 | !hw_to_local(hw)->monitors) | ||
3531 | return bcn; | ||
3532 | |||
3533 | /* send a copy to monitor interfaces */ | ||
3534 | copy = skb_copy(bcn, GFP_ATOMIC); | ||
3535 | if (!copy) | ||
3536 | return bcn; | ||
3537 | |||
3538 | shift = ieee80211_vif_get_shift(vif); | ||
3539 | sband = hw->wiphy->bands[ieee80211_get_sdata_band(vif_to_sdata(vif))]; | ||
3540 | ieee80211_tx_monitor(hw_to_local(hw), copy, sband, 1, shift, false); | ||
3541 | |||
3522 | return bcn; | 3542 | return bcn; |
3523 | } | 3543 | } |
3524 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); | 3544 | EXPORT_SYMBOL(ieee80211_beacon_get_tim); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1104421bc525..60c4dbf92625 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1966,7 +1966,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1966 | if (!sdata->u.mgd.associated) | 1966 | if (!sdata->u.mgd.associated) |
1967 | continue; | 1967 | continue; |
1968 | 1968 | ||
1969 | ieee80211_send_nullfunc(local, sdata, 0); | 1969 | ieee80211_send_nullfunc(local, sdata, false); |
1970 | } | 1970 | } |
1971 | } | 1971 | } |
1972 | 1972 | ||
@@ -2017,8 +2017,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
2017 | mutex_lock(&local->sta_mtx); | 2017 | mutex_lock(&local->sta_mtx); |
2018 | 2018 | ||
2019 | list_for_each_entry(sta, &local->sta_list, list) { | 2019 | list_for_each_entry(sta, &local->sta_list, list) { |
2020 | ieee80211_sta_tear_down_BA_sessions( | 2020 | if (!local->resuming) |
2021 | sta, AGG_STOP_LOCAL_REQUEST); | 2021 | ieee80211_sta_tear_down_BA_sessions( |
2022 | sta, AGG_STOP_LOCAL_REQUEST); | ||
2022 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); | 2023 | clear_sta_flag(sta, WLAN_STA_BLOCK_BA); |
2023 | } | 2024 | } |
2024 | 2025 | ||
@@ -2324,6 +2325,8 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | |||
2324 | if (chandef->center_freq2) | 2325 | if (chandef->center_freq2) |
2325 | vht_oper->center_freq_seg2_idx = | 2326 | vht_oper->center_freq_seg2_idx = |
2326 | ieee80211_frequency_to_channel(chandef->center_freq2); | 2327 | ieee80211_frequency_to_channel(chandef->center_freq2); |
2328 | else | ||
2329 | vht_oper->center_freq_seg2_idx = 0x00; | ||
2327 | 2330 | ||
2328 | switch (chandef->width) { | 2331 | switch (chandef->width) { |
2329 | case NL80211_CHAN_WIDTH_160: | 2332 | case NL80211_CHAN_WIDTH_160: |
@@ -2541,7 +2544,7 @@ int ieee80211_ave_rssi(struct ieee80211_vif *vif) | |||
2541 | /* non-managed type inferfaces */ | 2544 | /* non-managed type inferfaces */ |
2542 | return 0; | 2545 | return 0; |
2543 | } | 2546 | } |
2544 | return ifmgd->ave_beacon_signal / 16; | 2547 | return -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal); |
2545 | } | 2548 | } |
2546 | EXPORT_SYMBOL_GPL(ieee80211_ave_rssi); | 2549 | EXPORT_SYMBOL_GPL(ieee80211_ave_rssi); |
2547 | 2550 | ||