diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-02-12 15:24:14 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-12 15:24:14 -0500 |
commit | 841577c3d33b8a2bff66d1b506d8198b25900bde (patch) | |
tree | 444ca28c7b9ed796d3949f019ae97d2c8ed5bd28 | |
parent | e9c653167710e5624c5576ee7d657c6b86878caf (diff) | |
parent | 63c361f5114d81db789f8f5671c76c228c35b021 (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
70 files changed, 1151 insertions, 634 deletions
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 74f45fa6f428..27f20e0510f7 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
@@ -204,7 +204,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info, | |||
204 | break; | 204 | break; |
205 | /* 80MHZ */ | 205 | /* 80MHZ */ |
206 | case 2: | 206 | case 2: |
207 | status->flag |= RX_FLAG_80MHZ; | 207 | status->vht_flag |= RX_VHT_FLAG_80MHZ; |
208 | } | 208 | } |
209 | 209 | ||
210 | status->flag |= RX_FLAG_VHT; | 210 | status->flag |= RX_FLAG_VHT; |
@@ -266,7 +266,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) | |||
266 | status->flag & RX_FLAG_HT ? "ht" : "", | 266 | status->flag & RX_FLAG_HT ? "ht" : "", |
267 | status->flag & RX_FLAG_VHT ? "vht" : "", | 267 | status->flag & RX_FLAG_VHT ? "vht" : "", |
268 | status->flag & RX_FLAG_40MHZ ? "40" : "", | 268 | status->flag & RX_FLAG_40MHZ ? "40" : "", |
269 | status->flag & RX_FLAG_80MHZ ? "80" : "", | 269 | status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "", |
270 | status->flag & RX_FLAG_SHORT_GI ? "sgi " : "", | 270 | status->flag & RX_FLAG_SHORT_GI ? "sgi " : "", |
271 | status->rate_idx, | 271 | status->rate_idx, |
272 | status->vht_nss, | 272 | status->vht_nss, |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index fd4c89df67e1..c2c6f4604958 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
790 | if (nw_type & ADHOC_NETWORK) { | 790 | if (nw_type & ADHOC_NETWORK) { |
791 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", | 791 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", |
792 | nw_type & ADHOC_CREATOR ? "creator" : "joiner"); | 792 | nw_type & ADHOC_CREATOR ? "creator" : "joiner"); |
793 | cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); | 793 | cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL); |
794 | cfg80211_put_bss(ar->wiphy, bss); | 794 | cfg80211_put_bss(ar->wiphy, bss); |
795 | return; | 795 | return; |
796 | } | 796 | } |
@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
861 | } | 861 | } |
862 | 862 | ||
863 | if (vif->nw_type & ADHOC_NETWORK) { | 863 | if (vif->nw_type & ADHOC_NETWORK) { |
864 | if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) { | 864 | if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) |
865 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 865 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
866 | "%s: ath6k not in ibss mode\n", __func__); | 866 | "%s: ath6k not in ibss mode\n", __func__); |
867 | return; | ||
868 | } | ||
869 | memset(bssid, 0, ETH_ALEN); | ||
870 | cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); | ||
871 | return; | 867 | return; |
872 | } | 868 | } |
873 | 869 | ||
@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3256 | struct ath6kl_vif *vif = netdev_priv(dev); | 3252 | struct ath6kl_vif *vif = netdev_priv(dev); |
3257 | u16 interval; | 3253 | u16 interval; |
3258 | int ret, rssi_thold; | 3254 | int ret, rssi_thold; |
3255 | int n_match_sets = request->n_match_sets; | ||
3256 | |||
3257 | /* | ||
3258 | * If there's a matchset w/o an SSID, then assume it's just for | ||
3259 | * the RSSI (nothing else is currently supported) and ignore it. | ||
3260 | * The device only supports a global RSSI filter that we set below. | ||
3261 | */ | ||
3262 | if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len) | ||
3263 | n_match_sets = 0; | ||
3259 | 3264 | ||
3260 | if (ar->state != ATH6KL_STATE_ON) | 3265 | if (ar->state != ATH6KL_STATE_ON) |
3261 | return -EIO; | 3266 | return -EIO; |
@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3268 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, | 3273 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
3269 | request->n_ssids, | 3274 | request->n_ssids, |
3270 | request->match_sets, | 3275 | request->match_sets, |
3271 | request->n_match_sets); | 3276 | n_match_sets); |
3272 | if (ret < 0) | 3277 | if (ret < 0) |
3273 | return ret; | 3278 | return ret; |
3274 | 3279 | ||
3275 | if (!request->n_match_sets) { | 3280 | if (!n_match_sets) { |
3276 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, | 3281 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, |
3277 | ALL_BSS_FILTER, 0); | 3282 | ALL_BSS_FILTER, 0); |
3278 | if (ret < 0) | 3283 | if (ret < 0) |
@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3286 | 3291 | ||
3287 | if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, | 3292 | if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, |
3288 | ar->fw_capabilities)) { | 3293 | ar->fw_capabilities)) { |
3289 | if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF) | 3294 | if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF) |
3290 | rssi_thold = 0; | 3295 | rssi_thold = 0; |
3291 | else if (request->rssi_thold < -127) | 3296 | else if (request->min_rssi_thold < -127) |
3292 | rssi_thold = -127; | 3297 | rssi_thold = -127; |
3293 | else | 3298 | else |
3294 | rssi_thold = request->rssi_thold; | 3299 | rssi_thold = request->min_rssi_thold; |
3295 | 3300 | ||
3296 | ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx, | 3301 | ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx, |
3297 | rssi_thold); | 3302 | rssi_thold); |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index d829bb62a3fc..7b5afee141da 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1466,8 +1466,7 @@ static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, | |||
1466 | kfree(rate_priv); | 1466 | kfree(rate_priv); |
1467 | } | 1467 | } |
1468 | 1468 | ||
1469 | static struct rate_control_ops ath_rate_ops = { | 1469 | static const struct rate_control_ops ath_rate_ops = { |
1470 | .module = NULL, | ||
1471 | .name = "ath9k_rate_control", | 1470 | .name = "ath9k_rate_control", |
1472 | .tx_status = ath_tx_status, | 1471 | .tx_status = ath_tx_status, |
1473 | .get_rate = ath_get_rate, | 1472 | .get_rate = ath_get_rate, |
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index b2b60e30caaf..6846f858ef62 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c | |||
@@ -57,8 +57,7 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) | |||
57 | RX_FLAG_MMIC_STRIPPED | | 57 | RX_FLAG_MMIC_STRIPPED | |
58 | RX_FLAG_DECRYPTED; | 58 | RX_FLAG_DECRYPTED; |
59 | 59 | ||
60 | wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x status->vendor_radiotap_len=%x\n", | 60 | wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag); |
61 | status.flag, status.vendor_radiotap_len); | ||
62 | 61 | ||
63 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | 62 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); |
64 | 63 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index 22adbe311d20..59a5af5bf994 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
@@ -124,7 +124,8 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data) | |||
124 | } | 124 | } |
125 | 125 | ||
126 | static u32 | 126 | static u32 |
127 | brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen) | 127 | brcmf_create_iovar(char *name, const char *data, u32 datalen, |
128 | char *buf, u32 buflen) | ||
128 | { | 129 | { |
129 | u32 len; | 130 | u32 len; |
130 | 131 | ||
@@ -144,7 +145,7 @@ brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen) | |||
144 | 145 | ||
145 | 146 | ||
146 | s32 | 147 | s32 |
147 | brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data, | 148 | brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data, |
148 | u32 len) | 149 | u32 len) |
149 | { | 150 | { |
150 | struct brcmf_pub *drvr = ifp->drvr; | 151 | struct brcmf_pub *drvr = ifp->drvr; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h index 77eae86e55c2..a30be683f4a1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h | |||
@@ -83,7 +83,7 @@ s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); | |||
83 | s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data); | 83 | s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data); |
84 | s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data); | 84 | s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data); |
85 | 85 | ||
86 | s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data, | 86 | s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data, |
87 | u32 len); | 87 | u32 len); |
88 | s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, | 88 | s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, |
89 | u32 len); | 89 | u32 len); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index d7718a5fa2f0..1a80bf19cb89 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -351,13 +351,11 @@ u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, | |||
351 | * triples, returning a pointer to the substring whose first element | 351 | * triples, returning a pointer to the substring whose first element |
352 | * matches tag | 352 | * matches tag |
353 | */ | 353 | */ |
354 | struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) | 354 | const struct brcmf_tlv * |
355 | brcmf_parse_tlvs(const void *buf, int buflen, uint key) | ||
355 | { | 356 | { |
356 | struct brcmf_tlv *elt; | 357 | const struct brcmf_tlv *elt = buf; |
357 | int totlen; | 358 | int totlen = buflen; |
358 | |||
359 | elt = (struct brcmf_tlv *)buf; | ||
360 | totlen = buflen; | ||
361 | 359 | ||
362 | /* find tagged parameter */ | 360 | /* find tagged parameter */ |
363 | while (totlen >= TLV_HDR_LEN) { | 361 | while (totlen >= TLV_HDR_LEN) { |
@@ -378,8 +376,8 @@ struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) | |||
378 | * not update the tlvs buffer pointer/length. | 376 | * not update the tlvs buffer pointer/length. |
379 | */ | 377 | */ |
380 | static bool | 378 | static bool |
381 | brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, | 379 | brcmf_tlv_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len, |
382 | u8 *oui, u32 oui_len, u8 type) | 380 | const u8 *oui, u32 oui_len, u8 type) |
383 | { | 381 | { |
384 | /* If the contents match the OUI and the type */ | 382 | /* If the contents match the OUI and the type */ |
385 | if (ie[TLV_LEN_OFF] >= oui_len + 1 && | 383 | if (ie[TLV_LEN_OFF] >= oui_len + 1 && |
@@ -401,12 +399,12 @@ brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, | |||
401 | } | 399 | } |
402 | 400 | ||
403 | static struct brcmf_vs_tlv * | 401 | static struct brcmf_vs_tlv * |
404 | brcmf_find_wpaie(u8 *parse, u32 len) | 402 | brcmf_find_wpaie(const u8 *parse, u32 len) |
405 | { | 403 | { |
406 | struct brcmf_tlv *ie; | 404 | const struct brcmf_tlv *ie; |
407 | 405 | ||
408 | while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) { | 406 | while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) { |
409 | if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, | 407 | if (brcmf_tlv_has_ie((const u8 *)ie, &parse, &len, |
410 | WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE)) | 408 | WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE)) |
411 | return (struct brcmf_vs_tlv *)ie; | 409 | return (struct brcmf_vs_tlv *)ie; |
412 | } | 410 | } |
@@ -414,9 +412,9 @@ brcmf_find_wpaie(u8 *parse, u32 len) | |||
414 | } | 412 | } |
415 | 413 | ||
416 | static struct brcmf_vs_tlv * | 414 | static struct brcmf_vs_tlv * |
417 | brcmf_find_wpsie(u8 *parse, u32 len) | 415 | brcmf_find_wpsie(const u8 *parse, u32 len) |
418 | { | 416 | { |
419 | struct brcmf_tlv *ie; | 417 | const struct brcmf_tlv *ie; |
420 | 418 | ||
421 | while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) { | 419 | while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) { |
422 | if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, | 420 | if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, |
@@ -1562,9 +1560,9 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1562 | struct ieee80211_channel *chan = sme->channel; | 1560 | struct ieee80211_channel *chan = sme->channel; |
1563 | struct brcmf_join_params join_params; | 1561 | struct brcmf_join_params join_params; |
1564 | size_t join_params_size; | 1562 | size_t join_params_size; |
1565 | struct brcmf_tlv *rsn_ie; | 1563 | const struct brcmf_tlv *rsn_ie; |
1566 | struct brcmf_vs_tlv *wpa_ie; | 1564 | const struct brcmf_vs_tlv *wpa_ie; |
1567 | void *ie; | 1565 | const void *ie; |
1568 | u32 ie_len; | 1566 | u32 ie_len; |
1569 | struct brcmf_ext_join_params_le *ext_join_params; | 1567 | struct brcmf_ext_join_params_le *ext_join_params; |
1570 | u16 chanspec; | 1568 | u16 chanspec; |
@@ -1591,7 +1589,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1591 | ie_len = wpa_ie->len + TLV_HDR_LEN; | 1589 | ie_len = wpa_ie->len + TLV_HDR_LEN; |
1592 | } else { | 1590 | } else { |
1593 | /* find the RSN_IE */ | 1591 | /* find the RSN_IE */ |
1594 | rsn_ie = brcmf_parse_tlvs((u8 *)sme->ie, sme->ie_len, | 1592 | rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie, |
1593 | sme->ie_len, | ||
1595 | WLAN_EID_RSN); | 1594 | WLAN_EID_RSN); |
1596 | if (rsn_ie) { | 1595 | if (rsn_ie) { |
1597 | ie = rsn_ie; | 1596 | ie = rsn_ie; |
@@ -2455,7 +2454,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, | |||
2455 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev); | 2454 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev); |
2456 | struct brcmf_bss_info_le *bi; | 2455 | struct brcmf_bss_info_le *bi; |
2457 | struct brcmf_ssid *ssid; | 2456 | struct brcmf_ssid *ssid; |
2458 | struct brcmf_tlv *tim; | 2457 | const struct brcmf_tlv *tim; |
2459 | u16 beacon_interval; | 2458 | u16 beacon_interval; |
2460 | u8 dtim_period; | 2459 | u8 dtim_period; |
2461 | size_t ie_len; | 2460 | size_t ie_len; |
@@ -3220,8 +3219,9 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie) | |||
3220 | } | 3219 | } |
3221 | 3220 | ||
3222 | static s32 | 3221 | static s32 |
3223 | brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, | 3222 | brcmf_configure_wpaie(struct net_device *ndev, |
3224 | bool is_rsn_ie) | 3223 | const struct brcmf_vs_tlv *wpa_ie, |
3224 | bool is_rsn_ie) | ||
3225 | { | 3225 | { |
3226 | struct brcmf_if *ifp = netdev_priv(ndev); | 3226 | struct brcmf_if *ifp = netdev_priv(ndev); |
3227 | u32 auth = 0; /* d11 open authentication */ | 3227 | u32 auth = 0; /* d11 open authentication */ |
@@ -3707,11 +3707,11 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3707 | s32 ie_offset; | 3707 | s32 ie_offset; |
3708 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3708 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3709 | struct brcmf_if *ifp = netdev_priv(ndev); | 3709 | struct brcmf_if *ifp = netdev_priv(ndev); |
3710 | struct brcmf_tlv *ssid_ie; | 3710 | const struct brcmf_tlv *ssid_ie; |
3711 | struct brcmf_ssid_le ssid_le; | 3711 | struct brcmf_ssid_le ssid_le; |
3712 | s32 err = -EPERM; | 3712 | s32 err = -EPERM; |
3713 | struct brcmf_tlv *rsn_ie; | 3713 | const struct brcmf_tlv *rsn_ie; |
3714 | struct brcmf_vs_tlv *wpa_ie; | 3714 | const struct brcmf_vs_tlv *wpa_ie; |
3715 | struct brcmf_join_params join_params; | 3715 | struct brcmf_join_params join_params; |
3716 | enum nl80211_iftype dev_role; | 3716 | enum nl80211_iftype dev_role; |
3717 | struct brcmf_fil_bss_enable_le bss_enable; | 3717 | struct brcmf_fil_bss_enable_le bss_enable; |
@@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
4658 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 4658 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
4659 | struct net_device *ndev = ifp->ndev; | 4659 | struct net_device *ndev = ifp->ndev; |
4660 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | 4660 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; |
4661 | struct ieee80211_channel *chan; | ||
4661 | s32 err = 0; | 4662 | s32 err = 0; |
4662 | 4663 | ||
4663 | if (ifp->vif->mode == WL_MODE_AP) { | 4664 | if (ifp->vif->mode == WL_MODE_AP) { |
@@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, | |||
4665 | } else if (brcmf_is_linkup(e)) { | 4666 | } else if (brcmf_is_linkup(e)) { |
4666 | brcmf_dbg(CONN, "Linkup\n"); | 4667 | brcmf_dbg(CONN, "Linkup\n"); |
4667 | if (brcmf_is_ibssmode(ifp->vif)) { | 4668 | if (brcmf_is_ibssmode(ifp->vif)) { |
4669 | chan = ieee80211_get_channel(cfg->wiphy, cfg->channel); | ||
4668 | memcpy(profile->bssid, e->addr, ETH_ALEN); | 4670 | memcpy(profile->bssid, e->addr, ETH_ALEN); |
4669 | wl_inform_ibss(cfg, ndev, e->addr); | 4671 | wl_inform_ibss(cfg, ndev, e->addr); |
4670 | cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); | 4672 | cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL); |
4671 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, | 4673 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, |
4672 | &ifp->vif->sme_state); | 4674 | &ifp->vif->sme_state); |
4673 | set_bit(BRCMF_VIF_STATUS_CONNECTED, | 4675 | set_bit(BRCMF_VIF_STATUS_CONNECTED, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 2dc6a074e8ed..254feed2860e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | |||
@@ -491,7 +491,8 @@ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif); | |||
491 | s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, | 491 | s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, |
492 | const u8 *vndr_ie_buf, u32 vndr_ie_len); | 492 | const u8 *vndr_ie_buf, u32 vndr_ie_len); |
493 | s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif); | 493 | s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif); |
494 | struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key); | 494 | const struct brcmf_tlv * |
495 | brcmf_parse_tlvs(const void *buf, int buflen, uint key); | ||
495 | u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, | 496 | u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, |
496 | struct ieee80211_channel *ch); | 497 | struct ieee80211_channel *ch); |
497 | u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state); | 498 | u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state); |
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c index 9a45f6f626f6..76b0729ade17 100644 --- a/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/iwlegacy/3945-rs.c | |||
@@ -891,8 +891,7 @@ il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband, | |||
891 | { | 891 | { |
892 | } | 892 | } |
893 | 893 | ||
894 | static struct rate_control_ops rs_ops = { | 894 | static const struct rate_control_ops rs_ops = { |
895 | .module = NULL, | ||
896 | .name = RS_NAME, | 895 | .name = RS_NAME, |
897 | .tx_status = il3945_rs_tx_status, | 896 | .tx_status = il3945_rs_tx_status, |
898 | .get_rate = il3945_rs_get_rate, | 897 | .get_rate = il3945_rs_get_rate, |
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c index 4d5e33259ca8..eaaeea19d8c5 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c | |||
@@ -2807,8 +2807,7 @@ il4965_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband, | |||
2807 | { | 2807 | { |
2808 | } | 2808 | } |
2809 | 2809 | ||
2810 | static struct rate_control_ops rs_4965_ops = { | 2810 | static const struct rate_control_ops rs_4965_ops = { |
2811 | .module = NULL, | ||
2812 | .name = IL4965_RS_NAME, | 2811 | .name = IL4965_RS_NAME, |
2813 | .tx_status = il4965_rs_tx_status, | 2812 | .tx_status = il4965_rs_tx_status, |
2814 | .get_rate = il4965_rs_get_rate, | 2813 | .get_rate = il4965_rs_get_rate, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 5e232b925455..aa773a2da4ab 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
@@ -3318,8 +3318,8 @@ static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sba | |||
3318 | struct ieee80211_sta *sta, void *priv_sta) | 3318 | struct ieee80211_sta *sta, void *priv_sta) |
3319 | { | 3319 | { |
3320 | } | 3320 | } |
3321 | static struct rate_control_ops rs_ops = { | 3321 | |
3322 | .module = NULL, | 3322 | static const struct rate_control_ops rs_ops = { |
3323 | .name = RS_NAME, | 3323 | .name = RS_NAME, |
3324 | .tx_status = rs_tx_status, | 3324 | .tx_status = rs_tx_status, |
3325 | .get_rate = rs_get_rate, | 3325 | .get_rate = rs_get_rate, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 3b73241db24d..32bb8075121c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -2814,8 +2814,8 @@ static void rs_rate_init_stub(void *mvm_r, | |||
2814 | struct ieee80211_sta *sta, void *mvm_sta) | 2814 | struct ieee80211_sta *sta, void *mvm_sta) |
2815 | { | 2815 | { |
2816 | } | 2816 | } |
2817 | static struct rate_control_ops rs_mvm_ops = { | 2817 | |
2818 | .module = NULL, | 2818 | static const struct rate_control_ops rs_mvm_ops = { |
2819 | .name = RS_NAME, | 2819 | .name = RS_NAME, |
2820 | .tx_status = rs_tx_status, | 2820 | .tx_status = rs_tx_status, |
2821 | .get_rate = rs_get_rate, | 2821 | .get_rate = rs_get_rate, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index ef727df84da7..fa3c1393e103 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -358,10 +358,10 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
358 | rx_status.flag |= RX_FLAG_40MHZ; | 358 | rx_status.flag |= RX_FLAG_40MHZ; |
359 | break; | 359 | break; |
360 | case RATE_MCS_CHAN_WIDTH_80: | 360 | case RATE_MCS_CHAN_WIDTH_80: |
361 | rx_status.flag |= RX_FLAG_80MHZ; | 361 | rx_status.vht_flag |= RX_VHT_FLAG_80MHZ; |
362 | break; | 362 | break; |
363 | case RATE_MCS_CHAN_WIDTH_160: | 363 | case RATE_MCS_CHAN_WIDTH_160: |
364 | rx_status.flag |= RX_FLAG_160MHZ; | 364 | rx_status.vht_flag |= RX_VHT_FLAG_160MHZ; |
365 | break; | 365 | break; |
366 | } | 366 | } |
367 | if (rate_n_flags & RATE_MCS_SGI_MSK) | 367 | if (rate_n_flags & RATE_MCS_SGI_MSK) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index a827a13f9873..bf4e773c6f46 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -603,6 +603,9 @@ static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req, | |||
603 | * config match list. | 603 | * config match list. |
604 | */ | 604 | */ |
605 | for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) { | 605 | for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) { |
606 | /* skip empty SSID matchsets */ | ||
607 | if (!req->match_sets[i].ssid.ssid_len) | ||
608 | continue; | ||
606 | scan->direct_scan[i].id = WLAN_EID_SSID; | 609 | scan->direct_scan[i].id = WLAN_EID_SSID; |
607 | scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len; | 610 | scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len; |
608 | memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid, | 611 | memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid, |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 32f75007a825..2d72a6b4b93e 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_private *priv, | |||
1766 | memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); | 1766 | memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); |
1767 | priv->wdev->ssid_len = params->ssid_len; | 1767 | priv->wdev->ssid_len = params->ssid_len; |
1768 | 1768 | ||
1769 | cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL); | 1769 | cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan, |
1770 | GFP_KERNEL); | ||
1770 | 1771 | ||
1771 | /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */ | 1772 | /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */ |
1772 | priv->connect_status = LBS_CONNECTED; | 1773 | priv->connect_status = LBS_CONNECTED; |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 69d4c3179d04..f7e3562542fe 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -57,6 +57,10 @@ static bool rctbl = false; | |||
57 | module_param(rctbl, bool, 0444); | 57 | module_param(rctbl, bool, 0444); |
58 | MODULE_PARM_DESC(rctbl, "Handle rate control table"); | 58 | MODULE_PARM_DESC(rctbl, "Handle rate control table"); |
59 | 59 | ||
60 | static bool support_p2p_device = true; | ||
61 | module_param(support_p2p_device, bool, 0444); | ||
62 | MODULE_PARM_DESC(support_p2p_device, "Support P2P-Device interface type"); | ||
63 | |||
60 | /** | 64 | /** |
61 | * enum hwsim_regtest - the type of regulatory tests we offer | 65 | * enum hwsim_regtest - the type of regulatory tests we offer |
62 | * | 66 | * |
@@ -335,7 +339,8 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = { | |||
335 | #endif | 339 | #endif |
336 | BIT(NL80211_IFTYPE_AP) | | 340 | BIT(NL80211_IFTYPE_AP) | |
337 | BIT(NL80211_IFTYPE_P2P_GO) }, | 341 | BIT(NL80211_IFTYPE_P2P_GO) }, |
338 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, | 342 | /* must be last, see hwsim_if_comb */ |
343 | { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) } | ||
339 | }; | 344 | }; |
340 | 345 | ||
341 | static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = { | 346 | static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = { |
@@ -345,6 +350,27 @@ static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = { | |||
345 | static const struct ieee80211_iface_combination hwsim_if_comb[] = { | 350 | static const struct ieee80211_iface_combination hwsim_if_comb[] = { |
346 | { | 351 | { |
347 | .limits = hwsim_if_limits, | 352 | .limits = hwsim_if_limits, |
353 | /* remove the last entry which is P2P_DEVICE */ | ||
354 | .n_limits = ARRAY_SIZE(hwsim_if_limits) - 1, | ||
355 | .max_interfaces = 2048, | ||
356 | .num_different_channels = 1, | ||
357 | }, | ||
358 | { | ||
359 | .limits = hwsim_if_dfs_limits, | ||
360 | .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits), | ||
361 | .max_interfaces = 8, | ||
362 | .num_different_channels = 1, | ||
363 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | ||
364 | BIT(NL80211_CHAN_WIDTH_20) | | ||
365 | BIT(NL80211_CHAN_WIDTH_40) | | ||
366 | BIT(NL80211_CHAN_WIDTH_80) | | ||
367 | BIT(NL80211_CHAN_WIDTH_160), | ||
368 | } | ||
369 | }; | ||
370 | |||
371 | static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = { | ||
372 | { | ||
373 | .limits = hwsim_if_limits, | ||
348 | .n_limits = ARRAY_SIZE(hwsim_if_limits), | 374 | .n_limits = ARRAY_SIZE(hwsim_if_limits), |
349 | .max_interfaces = 2048, | 375 | .max_interfaces = 2048, |
350 | .num_different_channels = 1, | 376 | .num_different_channels = 1, |
@@ -451,7 +477,7 @@ static struct genl_family hwsim_genl_family = { | |||
451 | 477 | ||
452 | /* MAC80211_HWSIM netlink policy */ | 478 | /* MAC80211_HWSIM netlink policy */ |
453 | 479 | ||
454 | static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | 480 | static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { |
455 | [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, | 481 | [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, |
456 | [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, | 482 | [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, |
457 | [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY, | 483 | [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY, |
@@ -468,6 +494,7 @@ static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | |||
468 | [HWSIM_ATTR_REG_HINT_ALPHA2] = { .type = NLA_STRING, .len = 2 }, | 494 | [HWSIM_ATTR_REG_HINT_ALPHA2] = { .type = NLA_STRING, .len = 2 }, |
469 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, | 495 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, |
470 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, | 496 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, |
497 | [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, | ||
471 | }; | 498 | }; |
472 | 499 | ||
473 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | 500 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
@@ -1035,32 +1062,6 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
1035 | ack = true; | 1062 | ack = true; |
1036 | 1063 | ||
1037 | rx_status.mactime = now + data2->tsf_offset; | 1064 | rx_status.mactime = now + data2->tsf_offset; |
1038 | #if 0 | ||
1039 | /* | ||
1040 | * Don't enable this code by default as the OUI 00:00:00 | ||
1041 | * is registered to Xerox so we shouldn't use it here, it | ||
1042 | * might find its way into pcap files. | ||
1043 | * Note that this code requires the headroom in the SKB | ||
1044 | * that was allocated earlier. | ||
1045 | */ | ||
1046 | rx_status.vendor_radiotap_oui[0] = 0x00; | ||
1047 | rx_status.vendor_radiotap_oui[1] = 0x00; | ||
1048 | rx_status.vendor_radiotap_oui[2] = 0x00; | ||
1049 | rx_status.vendor_radiotap_subns = 127; | ||
1050 | /* | ||
1051 | * Radiotap vendor namespaces can (and should) also be | ||
1052 | * split into fields by using the standard radiotap | ||
1053 | * presence bitmap mechanism. Use just BIT(0) here for | ||
1054 | * the presence bitmap. | ||
1055 | */ | ||
1056 | rx_status.vendor_radiotap_bitmap = BIT(0); | ||
1057 | /* We have 8 bytes of (dummy) data */ | ||
1058 | rx_status.vendor_radiotap_len = 8; | ||
1059 | /* For testing, also require it to be aligned */ | ||
1060 | rx_status.vendor_radiotap_align = 8; | ||
1061 | /* push the data */ | ||
1062 | memcpy(skb_push(nskb, 8), "ABCDEFGH", 8); | ||
1063 | #endif | ||
1064 | 1065 | ||
1065 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 1066 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
1066 | ieee80211_rx_irqsafe(data2->hw, nskb); | 1067 | ieee80211_rx_irqsafe(data2->hw, nskb); |
@@ -1275,6 +1276,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
1275 | 1276 | ||
1276 | mac80211_hwsim_tx_frame(hw, skb, | 1277 | mac80211_hwsim_tx_frame(hw, skb, |
1277 | rcu_dereference(vif->chanctx_conf)->def.chan); | 1278 | rcu_dereference(vif->chanctx_conf)->def.chan); |
1279 | |||
1280 | if (vif->csa_active && ieee80211_csa_is_complete(vif)) | ||
1281 | ieee80211_csa_finish(vif); | ||
1278 | } | 1282 | } |
1279 | 1283 | ||
1280 | static enum hrtimer_restart | 1284 | static enum hrtimer_restart |
@@ -1936,7 +1940,7 @@ static struct ieee80211_ops mac80211_hwsim_mchan_ops; | |||
1936 | 1940 | ||
1937 | static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | 1941 | static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, |
1938 | const struct ieee80211_regdomain *regd, | 1942 | const struct ieee80211_regdomain *regd, |
1939 | bool reg_strict) | 1943 | bool reg_strict, bool p2p_device) |
1940 | { | 1944 | { |
1941 | int err; | 1945 | int err; |
1942 | u8 addr[ETH_ALEN]; | 1946 | u8 addr[ETH_ALEN]; |
@@ -2000,8 +2004,15 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2000 | /* For channels > 1 DFS is not allowed */ | 2004 | /* For channels > 1 DFS is not allowed */ |
2001 | hw->wiphy->n_iface_combinations = 1; | 2005 | hw->wiphy->n_iface_combinations = 1; |
2002 | hw->wiphy->iface_combinations = &data->if_combination; | 2006 | hw->wiphy->iface_combinations = &data->if_combination; |
2003 | data->if_combination = hwsim_if_comb[0]; | ||
2004 | data->if_combination.num_different_channels = data->channels; | 2007 | data->if_combination.num_different_channels = data->channels; |
2008 | if (p2p_device) | ||
2009 | data->if_combination = hwsim_if_comb_p2p_dev[0]; | ||
2010 | else | ||
2011 | data->if_combination = hwsim_if_comb[0]; | ||
2012 | } else if (p2p_device) { | ||
2013 | hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev; | ||
2014 | hw->wiphy->n_iface_combinations = | ||
2015 | ARRAY_SIZE(hwsim_if_comb_p2p_dev); | ||
2005 | } else { | 2016 | } else { |
2006 | hw->wiphy->iface_combinations = hwsim_if_comb; | 2017 | hw->wiphy->iface_combinations = hwsim_if_comb; |
2007 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb); | 2018 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb); |
@@ -2017,8 +2028,10 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2017 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 2028 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
2018 | BIT(NL80211_IFTYPE_P2P_GO) | | 2029 | BIT(NL80211_IFTYPE_P2P_GO) | |
2019 | BIT(NL80211_IFTYPE_ADHOC) | | 2030 | BIT(NL80211_IFTYPE_ADHOC) | |
2020 | BIT(NL80211_IFTYPE_MESH_POINT) | | 2031 | BIT(NL80211_IFTYPE_MESH_POINT); |
2021 | BIT(NL80211_IFTYPE_P2P_DEVICE); | 2032 | |
2033 | if (p2p_device) | ||
2034 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
2022 | 2035 | ||
2023 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 2036 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
2024 | IEEE80211_HW_SIGNAL_DBM | | 2037 | IEEE80211_HW_SIGNAL_DBM | |
@@ -2027,13 +2040,15 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2027 | IEEE80211_HW_AMPDU_AGGREGATION | | 2040 | IEEE80211_HW_AMPDU_AGGREGATION | |
2028 | IEEE80211_HW_WANT_MONITOR_VIF | | 2041 | IEEE80211_HW_WANT_MONITOR_VIF | |
2029 | IEEE80211_HW_QUEUE_CONTROL | | 2042 | IEEE80211_HW_QUEUE_CONTROL | |
2030 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; | 2043 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES | |
2044 | IEEE80211_HW_CHANCTX_STA_CSA; | ||
2031 | if (rctbl) | 2045 | if (rctbl) |
2032 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; | 2046 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; |
2033 | 2047 | ||
2034 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | 2048 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
2035 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | 2049 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
2036 | WIPHY_FLAG_AP_UAPSD; | 2050 | WIPHY_FLAG_AP_UAPSD | |
2051 | WIPHY_FLAG_HAS_CHANNEL_SWITCH; | ||
2037 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | 2052 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; |
2038 | 2053 | ||
2039 | /* ask mac80211 to reserve space for magic */ | 2054 | /* ask mac80211 to reserve space for magic */ |
@@ -2407,6 +2422,7 @@ static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) | |||
2407 | const char *alpha2 = NULL; | 2422 | const char *alpha2 = NULL; |
2408 | const struct ieee80211_regdomain *regd = NULL; | 2423 | const struct ieee80211_regdomain *regd = NULL; |
2409 | bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; | 2424 | bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; |
2425 | bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; | ||
2410 | 2426 | ||
2411 | if (info->attrs[HWSIM_ATTR_CHANNELS]) | 2427 | if (info->attrs[HWSIM_ATTR_CHANNELS]) |
2412 | chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); | 2428 | chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); |
@@ -2422,7 +2438,8 @@ static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) | |||
2422 | regd = hwsim_world_regdom_custom[idx]; | 2438 | regd = hwsim_world_regdom_custom[idx]; |
2423 | } | 2439 | } |
2424 | 2440 | ||
2425 | return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict); | 2441 | return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict, |
2442 | p2p_device); | ||
2426 | } | 2443 | } |
2427 | 2444 | ||
2428 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) | 2445 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) |
@@ -2640,7 +2657,8 @@ static int __init init_mac80211_hwsim(void) | |||
2640 | } | 2657 | } |
2641 | 2658 | ||
2642 | err = mac80211_hwsim_create_radio(channels, reg_alpha2, | 2659 | err = mac80211_hwsim_create_radio(channels, reg_alpha2, |
2643 | regd, reg_strict); | 2660 | regd, reg_strict, |
2661 | support_p2p_device); | ||
2644 | if (err < 0) | 2662 | if (err < 0) |
2645 | goto out_free_radios; | 2663 | goto out_free_radios; |
2646 | } | 2664 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index 2747cce5a269..6e72996ec8c1 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h | |||
@@ -107,6 +107,7 @@ enum { | |||
107 | * (nla string, length 2) | 107 | * (nla string, length 2) |
108 | * @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute) | 108 | * @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute) |
109 | * @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute) | 109 | * @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute) |
110 | * @HWSIM_ATTR_SUPPORT_P2P_DEVICE: support P2P Device virtual interface (flag) | ||
110 | * @__HWSIM_ATTR_MAX: enum limit | 111 | * @__HWSIM_ATTR_MAX: enum limit |
111 | */ | 112 | */ |
112 | 113 | ||
@@ -126,6 +127,7 @@ enum { | |||
126 | HWSIM_ATTR_REG_HINT_ALPHA2, | 127 | HWSIM_ATTR_REG_HINT_ALPHA2, |
127 | HWSIM_ATTR_REG_CUSTOM_REG, | 128 | HWSIM_ATTR_REG_CUSTOM_REG, |
128 | HWSIM_ATTR_REG_STRICT_REG, | 129 | HWSIM_ATTR_REG_STRICT_REG, |
130 | HWSIM_ATTR_SUPPORT_P2P_DEVICE, | ||
129 | __HWSIM_ATTR_MAX, | 131 | __HWSIM_ATTR_MAX, |
130 | }; | 132 | }; |
131 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) | 133 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 8bfc07cd330e..0948ebe8942e 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1583,8 +1583,9 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
1583 | * the function notifies the CFG802.11 subsystem of the new BSS connection. | 1583 | * the function notifies the CFG802.11 subsystem of the new BSS connection. |
1584 | */ | 1584 | */ |
1585 | static int | 1585 | static int |
1586 | mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | 1586 | mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, |
1587 | u8 *bssid, int mode, struct ieee80211_channel *channel, | 1587 | const u8 *ssid, const u8 *bssid, int mode, |
1588 | struct ieee80211_channel *channel, | ||
1588 | struct cfg80211_connect_params *sme, bool privacy) | 1589 | struct cfg80211_connect_params *sme, bool privacy) |
1589 | { | 1590 | { |
1590 | struct cfg80211_ssid req_ssid; | 1591 | struct cfg80211_ssid req_ssid; |
@@ -1881,7 +1882,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
1881 | params->privacy); | 1882 | params->privacy); |
1882 | done: | 1883 | done: |
1883 | if (!ret) { | 1884 | if (!ret) { |
1884 | cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); | 1885 | cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, |
1886 | params->chandef.chan, GFP_KERNEL); | ||
1885 | dev_dbg(priv->adapter->dev, | 1887 | dev_dbg(priv->adapter->dev, |
1886 | "info: joined/created adhoc network with bssid" | 1888 | "info: joined/created adhoc network with bssid" |
1887 | " %pM successfully\n", priv->cfg_bssid); | 1889 | " %pM successfully\n", priv->cfg_bssid); |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index d8ad554ce39f..29d27d9b5ebe 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -1078,7 +1078,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, | |||
1078 | const u8 *key, int key_len, u8 key_index, | 1078 | const u8 *key, int key_len, u8 key_index, |
1079 | const u8 *mac_addr, int disable); | 1079 | const u8 *mac_addr, int disable); |
1080 | 1080 | ||
1081 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); | 1081 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len); |
1082 | 1082 | ||
1083 | int mwifiex_get_ver_ext(struct mwifiex_private *priv); | 1083 | int mwifiex_get_ver_ext(struct mwifiex_private *priv); |
1084 | 1084 | ||
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index c5cb2ed19ec2..0bec94351f36 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -1391,7 +1391,7 @@ static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv, | |||
1391 | * with requisite parameters and calls the IOCTL handler. | 1391 | * with requisite parameters and calls the IOCTL handler. |
1392 | */ | 1392 | */ |
1393 | int | 1393 | int |
1394 | mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len) | 1394 | mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len) |
1395 | { | 1395 | { |
1396 | struct mwifiex_ds_misc_gen_ie gen_ie; | 1396 | struct mwifiex_ds_misc_gen_ie gen_ie; |
1397 | 1397 | ||
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 5028557aa18a..2e89a865a67d 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2835 | bssid, req_ie, req_ie_len, | 2835 | bssid, req_ie, req_ie_len, |
2836 | resp_ie, resp_ie_len, GFP_KERNEL); | 2836 | resp_ie, resp_ie_len, GFP_KERNEL); |
2837 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) | 2837 | } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) |
2838 | cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); | 2838 | cfg80211_ibss_joined(usbdev->net, bssid, |
2839 | get_current_channel(usbdev, NULL), | ||
2840 | GFP_KERNEL); | ||
2839 | 2841 | ||
2840 | kfree(info); | 2842 | kfree(info); |
2841 | 2843 | ||
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c index a98acefb8c06..ee28a1a3d010 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/rtlwifi/rc.c | |||
@@ -260,8 +260,7 @@ static void rtl_rate_free_sta(void *rtlpriv, | |||
260 | kfree(rate_priv); | 260 | kfree(rate_priv); |
261 | } | 261 | } |
262 | 262 | ||
263 | static struct rate_control_ops rtl_rate_ops = { | 263 | static const struct rate_control_ops rtl_rate_ops = { |
264 | .module = NULL, | ||
265 | .name = "rtl_rc", | 264 | .name = "rtl_rc", |
266 | .alloc = rtl_rate_alloc, | 265 | .alloc = rtl_rate_alloc, |
267 | .free = rtl_rate_free, | 266 | .free = rtl_rate_free, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c index aece6c9cccf1..27ace3054d56 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c | |||
@@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, | |||
452 | /* During testing, hdr was NULL */ | 452 | /* During testing, hdr was NULL */ |
453 | return false; | 453 | return false; |
454 | } | 454 | } |
455 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | 455 | if ((_ieee80211_is_robust_mgmt_frame(hdr)) && |
456 | (ieee80211_has_protected(hdr->frame_control))) | 456 | (ieee80211_has_protected(hdr->frame_control))) |
457 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | 457 | rx_status->flag &= ~RX_FLAG_DECRYPTED; |
458 | else | 458 | else |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 52abf0a862fa..114858d46158 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | |||
@@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
393 | /* In testing, hdr was NULL here */ | 393 | /* In testing, hdr was NULL here */ |
394 | return false; | 394 | return false; |
395 | } | 395 | } |
396 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | 396 | if ((_ieee80211_is_robust_mgmt_frame(hdr)) && |
397 | (ieee80211_has_protected(hdr->frame_control))) | 397 | (ieee80211_has_protected(hdr->frame_control))) |
398 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | 398 | rx_status->flag &= ~RX_FLAG_DECRYPTED; |
399 | else | 399 | else |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 27efbcdac6a9..163a681962c6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c | |||
@@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | |||
310 | /* during testing, hdr was NULL here */ | 310 | /* during testing, hdr was NULL here */ |
311 | return false; | 311 | return false; |
312 | } | 312 | } |
313 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | 313 | if ((_ieee80211_is_robust_mgmt_frame(hdr)) && |
314 | (ieee80211_has_protected(hdr->frame_control))) | 314 | (ieee80211_has_protected(hdr->frame_control))) |
315 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | 315 | rx_status->flag &= ~RX_FLAG_DECRYPTED; |
316 | else | 316 | else |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index 50b7be3f3a60..721162cacc3a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c | |||
@@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw, | |||
334 | /* during testing, hdr could be NULL here */ | 334 | /* during testing, hdr could be NULL here */ |
335 | return false; | 335 | return false; |
336 | } | 336 | } |
337 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | 337 | if ((_ieee80211_is_robust_mgmt_frame(hdr)) && |
338 | (ieee80211_has_protected(hdr->frame_control))) | 338 | (ieee80211_has_protected(hdr->frame_control))) |
339 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | 339 | rx_status->flag &= ~RX_FLAG_DECRYPTED; |
340 | else | 340 | else |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index e526a8cecb70..5f349355ee54 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullfunc(__le16 fc) | |||
597 | } | 597 | } |
598 | 598 | ||
599 | /** | 599 | /** |
600 | * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU | ||
601 | * @fc: frame control field in little-endian byteorder | ||
602 | */ | ||
603 | static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc) | ||
604 | { | ||
605 | /* IEEE 802.11-2012, definition of "bufferable management frame"; | ||
606 | * note that this ignores the IBSS special case. */ | ||
607 | return ieee80211_is_mgmt(fc) && | ||
608 | (ieee80211_is_action(fc) || | ||
609 | ieee80211_is_disassoc(fc) || | ||
610 | ieee80211_is_deauth(fc)); | ||
611 | } | ||
612 | |||
613 | /** | ||
600 | * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set | 614 | * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set |
601 | * @seq_ctrl: frame sequence control bytes in little-endian byteorder | 615 | * @seq_ctrl: frame sequence control bytes in little-endian byteorder |
602 | */ | 616 | */ |
@@ -1636,51 +1650,22 @@ enum ieee80211_reasoncode { | |||
1636 | enum ieee80211_eid { | 1650 | enum ieee80211_eid { |
1637 | WLAN_EID_SSID = 0, | 1651 | WLAN_EID_SSID = 0, |
1638 | WLAN_EID_SUPP_RATES = 1, | 1652 | WLAN_EID_SUPP_RATES = 1, |
1639 | WLAN_EID_FH_PARAMS = 2, | 1653 | WLAN_EID_FH_PARAMS = 2, /* reserved now */ |
1640 | WLAN_EID_DS_PARAMS = 3, | 1654 | WLAN_EID_DS_PARAMS = 3, |
1641 | WLAN_EID_CF_PARAMS = 4, | 1655 | WLAN_EID_CF_PARAMS = 4, |
1642 | WLAN_EID_TIM = 5, | 1656 | WLAN_EID_TIM = 5, |
1643 | WLAN_EID_IBSS_PARAMS = 6, | 1657 | WLAN_EID_IBSS_PARAMS = 6, |
1644 | WLAN_EID_CHALLENGE = 16, | ||
1645 | |||
1646 | WLAN_EID_COUNTRY = 7, | 1658 | WLAN_EID_COUNTRY = 7, |
1647 | WLAN_EID_HP_PARAMS = 8, | 1659 | WLAN_EID_HP_PARAMS = 8, |
1648 | WLAN_EID_HP_TABLE = 9, | 1660 | WLAN_EID_HP_TABLE = 9, |
1649 | WLAN_EID_REQUEST = 10, | 1661 | WLAN_EID_REQUEST = 10, |
1650 | |||
1651 | WLAN_EID_QBSS_LOAD = 11, | 1662 | WLAN_EID_QBSS_LOAD = 11, |
1652 | WLAN_EID_EDCA_PARAM_SET = 12, | 1663 | WLAN_EID_EDCA_PARAM_SET = 12, |
1653 | WLAN_EID_TSPEC = 13, | 1664 | WLAN_EID_TSPEC = 13, |
1654 | WLAN_EID_TCLAS = 14, | 1665 | WLAN_EID_TCLAS = 14, |
1655 | WLAN_EID_SCHEDULE = 15, | 1666 | WLAN_EID_SCHEDULE = 15, |
1656 | WLAN_EID_TS_DELAY = 43, | 1667 | WLAN_EID_CHALLENGE = 16, |
1657 | WLAN_EID_TCLAS_PROCESSING = 44, | 1668 | /* 17-31 reserved for challenge text extension */ |
1658 | WLAN_EID_QOS_CAPA = 46, | ||
1659 | /* 802.11z */ | ||
1660 | WLAN_EID_LINK_ID = 101, | ||
1661 | /* 802.11s */ | ||
1662 | WLAN_EID_MESH_CONFIG = 113, | ||
1663 | WLAN_EID_MESH_ID = 114, | ||
1664 | WLAN_EID_LINK_METRIC_REPORT = 115, | ||
1665 | WLAN_EID_CONGESTION_NOTIFICATION = 116, | ||
1666 | WLAN_EID_PEER_MGMT = 117, | ||
1667 | WLAN_EID_CHAN_SWITCH_PARAM = 118, | ||
1668 | WLAN_EID_MESH_AWAKE_WINDOW = 119, | ||
1669 | WLAN_EID_BEACON_TIMING = 120, | ||
1670 | WLAN_EID_MCCAOP_SETUP_REQ = 121, | ||
1671 | WLAN_EID_MCCAOP_SETUP_RESP = 122, | ||
1672 | WLAN_EID_MCCAOP_ADVERT = 123, | ||
1673 | WLAN_EID_MCCAOP_TEARDOWN = 124, | ||
1674 | WLAN_EID_GANN = 125, | ||
1675 | WLAN_EID_RANN = 126, | ||
1676 | WLAN_EID_PREQ = 130, | ||
1677 | WLAN_EID_PREP = 131, | ||
1678 | WLAN_EID_PERR = 132, | ||
1679 | WLAN_EID_PXU = 137, | ||
1680 | WLAN_EID_PXUC = 138, | ||
1681 | WLAN_EID_AUTH_MESH_PEER_EXCH = 139, | ||
1682 | WLAN_EID_MIC = 140, | ||
1683 | |||
1684 | WLAN_EID_PWR_CONSTRAINT = 32, | 1669 | WLAN_EID_PWR_CONSTRAINT = 32, |
1685 | WLAN_EID_PWR_CAPABILITY = 33, | 1670 | WLAN_EID_PWR_CAPABILITY = 33, |
1686 | WLAN_EID_TPC_REQUEST = 34, | 1671 | WLAN_EID_TPC_REQUEST = 34, |
@@ -1691,66 +1676,114 @@ enum ieee80211_eid { | |||
1691 | WLAN_EID_MEASURE_REPORT = 39, | 1676 | WLAN_EID_MEASURE_REPORT = 39, |
1692 | WLAN_EID_QUIET = 40, | 1677 | WLAN_EID_QUIET = 40, |
1693 | WLAN_EID_IBSS_DFS = 41, | 1678 | WLAN_EID_IBSS_DFS = 41, |
1694 | |||
1695 | WLAN_EID_ERP_INFO = 42, | 1679 | WLAN_EID_ERP_INFO = 42, |
1696 | WLAN_EID_EXT_SUPP_RATES = 50, | 1680 | WLAN_EID_TS_DELAY = 43, |
1697 | 1681 | WLAN_EID_TCLAS_PROCESSING = 44, | |
1698 | WLAN_EID_HT_CAPABILITY = 45, | 1682 | WLAN_EID_HT_CAPABILITY = 45, |
1699 | WLAN_EID_HT_OPERATION = 61, | 1683 | WLAN_EID_QOS_CAPA = 46, |
1700 | WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62, | 1684 | /* 47 reserved for Broadcom */ |
1701 | |||
1702 | WLAN_EID_RSN = 48, | 1685 | WLAN_EID_RSN = 48, |
1703 | WLAN_EID_MMIE = 76, | 1686 | WLAN_EID_802_15_COEX = 49, |
1704 | WLAN_EID_VENDOR_SPECIFIC = 221, | 1687 | WLAN_EID_EXT_SUPP_RATES = 50, |
1705 | WLAN_EID_QOS_PARAMETER = 222, | ||
1706 | |||
1707 | WLAN_EID_AP_CHAN_REPORT = 51, | 1688 | WLAN_EID_AP_CHAN_REPORT = 51, |
1708 | WLAN_EID_NEIGHBOR_REPORT = 52, | 1689 | WLAN_EID_NEIGHBOR_REPORT = 52, |
1709 | WLAN_EID_RCPI = 53, | 1690 | WLAN_EID_RCPI = 53, |
1691 | WLAN_EID_MOBILITY_DOMAIN = 54, | ||
1692 | WLAN_EID_FAST_BSS_TRANSITION = 55, | ||
1693 | WLAN_EID_TIMEOUT_INTERVAL = 56, | ||
1694 | WLAN_EID_RIC_DATA = 57, | ||
1695 | WLAN_EID_DSE_REGISTERED_LOCATION = 58, | ||
1696 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, | ||
1697 | WLAN_EID_EXT_CHANSWITCH_ANN = 60, | ||
1698 | WLAN_EID_HT_OPERATION = 61, | ||
1699 | WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62, | ||
1710 | WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, | 1700 | WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, |
1711 | WLAN_EID_ANTENNA_INFO = 64, | 1701 | WLAN_EID_ANTENNA_INFO = 64, |
1712 | WLAN_EID_RSNI = 65, | 1702 | WLAN_EID_RSNI = 65, |
1713 | WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, | 1703 | WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, |
1714 | WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, | 1704 | WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, |
1715 | WLAN_EID_BSS_AC_ACCESS_DELAY = 68, | 1705 | WLAN_EID_BSS_AC_ACCESS_DELAY = 68, |
1706 | WLAN_EID_TIME_ADVERTISEMENT = 69, | ||
1716 | WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, | 1707 | WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, |
1717 | WLAN_EID_MULTIPLE_BSSID = 71, | 1708 | WLAN_EID_MULTIPLE_BSSID = 71, |
1718 | WLAN_EID_BSS_COEX_2040 = 72, | 1709 | WLAN_EID_BSS_COEX_2040 = 72, |
1719 | WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74, | 1710 | WLAN_EID_OVERLAP_BSS_SCAN_PARAM = 74, |
1720 | WLAN_EID_EXT_CAPABILITY = 127, | ||
1721 | |||
1722 | WLAN_EID_MOBILITY_DOMAIN = 54, | ||
1723 | WLAN_EID_FAST_BSS_TRANSITION = 55, | ||
1724 | WLAN_EID_TIMEOUT_INTERVAL = 56, | ||
1725 | WLAN_EID_RIC_DATA = 57, | ||
1726 | WLAN_EID_RIC_DESCRIPTOR = 75, | 1711 | WLAN_EID_RIC_DESCRIPTOR = 75, |
1727 | 1712 | WLAN_EID_MMIE = 76, | |
1728 | WLAN_EID_DSE_REGISTERED_LOCATION = 58, | 1713 | WLAN_EID_ASSOC_COMEBACK_TIME = 77, |
1729 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, | 1714 | WLAN_EID_EVENT_REQUEST = 78, |
1730 | WLAN_EID_EXT_CHANSWITCH_ANN = 60, | 1715 | WLAN_EID_EVENT_REPORT = 79, |
1731 | 1716 | WLAN_EID_DIAGNOSTIC_REQUEST = 80, | |
1732 | WLAN_EID_VHT_CAPABILITY = 191, | 1717 | WLAN_EID_DIAGNOSTIC_REPORT = 81, |
1733 | WLAN_EID_VHT_OPERATION = 192, | 1718 | WLAN_EID_LOCATION_PARAMS = 82, |
1734 | WLAN_EID_OPMODE_NOTIF = 199, | ||
1735 | WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194, | ||
1736 | WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196, | ||
1737 | WLAN_EID_EXTENDED_BSS_LOAD = 193, | ||
1738 | WLAN_EID_VHT_TX_POWER_ENVELOPE = 195, | ||
1739 | WLAN_EID_AID = 197, | ||
1740 | WLAN_EID_QUIET_CHANNEL = 198, | ||
1741 | |||
1742 | /* 802.11ad */ | ||
1743 | WLAN_EID_NON_TX_BSSID_CAP = 83, | 1719 | WLAN_EID_NON_TX_BSSID_CAP = 83, |
1720 | WLAN_EID_SSID_LIST = 84, | ||
1721 | WLAN_EID_MULTI_BSSID_IDX = 85, | ||
1722 | WLAN_EID_FMS_DESCRIPTOR = 86, | ||
1723 | WLAN_EID_FMS_REQUEST = 87, | ||
1724 | WLAN_EID_FMS_RESPONSE = 88, | ||
1725 | WLAN_EID_QOS_TRAFFIC_CAPA = 89, | ||
1726 | WLAN_EID_BSS_MAX_IDLE_PERIOD = 90, | ||
1727 | WLAN_EID_TSF_REQUEST = 91, | ||
1728 | WLAN_EID_TSF_RESPOSNE = 92, | ||
1729 | WLAN_EID_WNM_SLEEP_MODE = 93, | ||
1730 | WLAN_EID_TIM_BCAST_REQ = 94, | ||
1731 | WLAN_EID_TIM_BCAST_RESP = 95, | ||
1732 | WLAN_EID_COLL_IF_REPORT = 96, | ||
1733 | WLAN_EID_CHANNEL_USAGE = 97, | ||
1734 | WLAN_EID_TIME_ZONE = 98, | ||
1735 | WLAN_EID_DMS_REQUEST = 99, | ||
1736 | WLAN_EID_DMS_RESPONSE = 100, | ||
1737 | WLAN_EID_LINK_ID = 101, | ||
1738 | WLAN_EID_WAKEUP_SCHEDUL = 102, | ||
1739 | /* 103 reserved */ | ||
1740 | WLAN_EID_CHAN_SWITCH_TIMING = 104, | ||
1741 | WLAN_EID_PTI_CONTROL = 105, | ||
1742 | WLAN_EID_PU_BUFFER_STATUS = 106, | ||
1743 | WLAN_EID_INTERWORKING = 107, | ||
1744 | WLAN_EID_ADVERTISEMENT_PROTOCOL = 108, | ||
1745 | WLAN_EID_EXPEDITED_BW_REQ = 109, | ||
1746 | WLAN_EID_QOS_MAP_SET = 110, | ||
1747 | WLAN_EID_ROAMING_CONSORTIUM = 111, | ||
1748 | WLAN_EID_EMERGENCY_ALERT = 112, | ||
1749 | WLAN_EID_MESH_CONFIG = 113, | ||
1750 | WLAN_EID_MESH_ID = 114, | ||
1751 | WLAN_EID_LINK_METRIC_REPORT = 115, | ||
1752 | WLAN_EID_CONGESTION_NOTIFICATION = 116, | ||
1753 | WLAN_EID_PEER_MGMT = 117, | ||
1754 | WLAN_EID_CHAN_SWITCH_PARAM = 118, | ||
1755 | WLAN_EID_MESH_AWAKE_WINDOW = 119, | ||
1756 | WLAN_EID_BEACON_TIMING = 120, | ||
1757 | WLAN_EID_MCCAOP_SETUP_REQ = 121, | ||
1758 | WLAN_EID_MCCAOP_SETUP_RESP = 122, | ||
1759 | WLAN_EID_MCCAOP_ADVERT = 123, | ||
1760 | WLAN_EID_MCCAOP_TEARDOWN = 124, | ||
1761 | WLAN_EID_GANN = 125, | ||
1762 | WLAN_EID_RANN = 126, | ||
1763 | WLAN_EID_EXT_CAPABILITY = 127, | ||
1764 | /* 128, 129 reserved for Agere */ | ||
1765 | WLAN_EID_PREQ = 130, | ||
1766 | WLAN_EID_PREP = 131, | ||
1767 | WLAN_EID_PERR = 132, | ||
1768 | /* 133-136 reserved for Cisco */ | ||
1769 | WLAN_EID_PXU = 137, | ||
1770 | WLAN_EID_PXUC = 138, | ||
1771 | WLAN_EID_AUTH_MESH_PEER_EXCH = 139, | ||
1772 | WLAN_EID_MIC = 140, | ||
1773 | WLAN_EID_DESTINATION_URI = 141, | ||
1774 | WLAN_EID_UAPSD_COEX = 142, | ||
1744 | WLAN_EID_WAKEUP_SCHEDULE = 143, | 1775 | WLAN_EID_WAKEUP_SCHEDULE = 143, |
1745 | WLAN_EID_EXT_SCHEDULE = 144, | 1776 | WLAN_EID_EXT_SCHEDULE = 144, |
1746 | WLAN_EID_STA_AVAILABILITY = 145, | 1777 | WLAN_EID_STA_AVAILABILITY = 145, |
1747 | WLAN_EID_DMG_TSPEC = 146, | 1778 | WLAN_EID_DMG_TSPEC = 146, |
1748 | WLAN_EID_DMG_AT = 147, | 1779 | WLAN_EID_DMG_AT = 147, |
1749 | WLAN_EID_DMG_CAP = 148, | 1780 | WLAN_EID_DMG_CAP = 148, |
1781 | /* 149-150 reserved for Cisco */ | ||
1750 | WLAN_EID_DMG_OPERATION = 151, | 1782 | WLAN_EID_DMG_OPERATION = 151, |
1751 | WLAN_EID_DMG_BSS_PARAM_CHANGE = 152, | 1783 | WLAN_EID_DMG_BSS_PARAM_CHANGE = 152, |
1752 | WLAN_EID_DMG_BEAM_REFINEMENT = 153, | 1784 | WLAN_EID_DMG_BEAM_REFINEMENT = 153, |
1753 | WLAN_EID_CHANNEL_MEASURE_FEEDBACK = 154, | 1785 | WLAN_EID_CHANNEL_MEASURE_FEEDBACK = 154, |
1786 | /* 155-156 reserved for Cisco */ | ||
1754 | WLAN_EID_AWAKE_WINDOW = 157, | 1787 | WLAN_EID_AWAKE_WINDOW = 157, |
1755 | WLAN_EID_MULTI_BAND = 158, | 1788 | WLAN_EID_MULTI_BAND = 158, |
1756 | WLAN_EID_ADDBA_EXT = 159, | 1789 | WLAN_EID_ADDBA_EXT = 159, |
@@ -1767,11 +1800,34 @@ enum ieee80211_eid { | |||
1767 | WLAN_EID_MULTIPLE_MAC_ADDR = 170, | 1800 | WLAN_EID_MULTIPLE_MAC_ADDR = 170, |
1768 | WLAN_EID_U_PID = 171, | 1801 | WLAN_EID_U_PID = 171, |
1769 | WLAN_EID_DMG_LINK_ADAPT_ACK = 172, | 1802 | WLAN_EID_DMG_LINK_ADAPT_ACK = 172, |
1803 | /* 173 reserved for Symbol */ | ||
1804 | WLAN_EID_MCCAOP_ADV_OVERVIEW = 174, | ||
1770 | WLAN_EID_QUIET_PERIOD_REQ = 175, | 1805 | WLAN_EID_QUIET_PERIOD_REQ = 175, |
1806 | /* 176 reserved for Symbol */ | ||
1771 | WLAN_EID_QUIET_PERIOD_RESP = 177, | 1807 | WLAN_EID_QUIET_PERIOD_RESP = 177, |
1808 | /* 178-179 reserved for Symbol */ | ||
1809 | /* 180 reserved for ISO/IEC 20011 */ | ||
1772 | WLAN_EID_EPAC_POLICY = 182, | 1810 | WLAN_EID_EPAC_POLICY = 182, |
1773 | WLAN_EID_CLISTER_TIME_OFF = 183, | 1811 | WLAN_EID_CLISTER_TIME_OFF = 183, |
1812 | WLAN_EID_INTER_AC_PRIO = 184, | ||
1813 | WLAN_EID_SCS_DESCRIPTOR = 185, | ||
1814 | WLAN_EID_QLOAD_REPORT = 186, | ||
1815 | WLAN_EID_HCCA_TXOP_UPDATE_COUNT = 187, | ||
1816 | WLAN_EID_HL_STREAM_ID = 188, | ||
1817 | WLAN_EID_GCR_GROUP_ADDR = 189, | ||
1774 | WLAN_EID_ANTENNA_SECTOR_ID_PATTERN = 190, | 1818 | WLAN_EID_ANTENNA_SECTOR_ID_PATTERN = 190, |
1819 | WLAN_EID_VHT_CAPABILITY = 191, | ||
1820 | WLAN_EID_VHT_OPERATION = 192, | ||
1821 | WLAN_EID_EXTENDED_BSS_LOAD = 193, | ||
1822 | WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194, | ||
1823 | WLAN_EID_VHT_TX_POWER_ENVELOPE = 195, | ||
1824 | WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196, | ||
1825 | WLAN_EID_AID = 197, | ||
1826 | WLAN_EID_QUIET_CHANNEL = 198, | ||
1827 | WLAN_EID_OPMODE_NOTIF = 199, | ||
1828 | |||
1829 | WLAN_EID_VENDOR_SPECIFIC = 221, | ||
1830 | WLAN_EID_QOS_PARAMETER = 222, | ||
1775 | }; | 1831 | }; |
1776 | 1832 | ||
1777 | /* Action category code */ | 1833 | /* Action category code */ |
@@ -2192,10 +2248,10 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr) | |||
2192 | } | 2248 | } |
2193 | 2249 | ||
2194 | /** | 2250 | /** |
2195 | * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame | 2251 | * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame |
2196 | * @hdr: the frame (buffer must include at least the first octet of payload) | 2252 | * @hdr: the frame (buffer must include at least the first octet of payload) |
2197 | */ | 2253 | */ |
2198 | static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) | 2254 | static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) |
2199 | { | 2255 | { |
2200 | if (ieee80211_is_disassoc(hdr->frame_control) || | 2256 | if (ieee80211_is_disassoc(hdr->frame_control) || |
2201 | ieee80211_is_deauth(hdr->frame_control)) | 2257 | ieee80211_is_deauth(hdr->frame_control)) |
@@ -2224,6 +2280,17 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) | |||
2224 | } | 2280 | } |
2225 | 2281 | ||
2226 | /** | 2282 | /** |
2283 | * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame | ||
2284 | * @skb: the skb containing the frame, length will be checked | ||
2285 | */ | ||
2286 | static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb) | ||
2287 | { | ||
2288 | if (skb->len < 25) | ||
2289 | return false; | ||
2290 | return _ieee80211_is_robust_mgmt_frame((void *)skb->data); | ||
2291 | } | ||
2292 | |||
2293 | /** | ||
2227 | * ieee80211_is_public_action - check if frame is a public action frame | 2294 | * ieee80211_is_public_action - check if frame is a public action frame |
2228 | * @hdr: the frame | 2295 | * @hdr: the frame |
2229 | * @len: length of the frame | 2296 | * @len: length of the frame |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b1f84b05c67e..9f90554e88c4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1394,10 +1394,12 @@ struct cfg80211_scan_request { | |||
1394 | /** | 1394 | /** |
1395 | * struct cfg80211_match_set - sets of attributes to match | 1395 | * struct cfg80211_match_set - sets of attributes to match |
1396 | * | 1396 | * |
1397 | * @ssid: SSID to be matched | 1397 | * @ssid: SSID to be matched; may be zero-length for no match (RSSI only) |
1398 | * @rssi_thold: don't report scan results below this threshold (in s32 dBm) | ||
1398 | */ | 1399 | */ |
1399 | struct cfg80211_match_set { | 1400 | struct cfg80211_match_set { |
1400 | struct cfg80211_ssid ssid; | 1401 | struct cfg80211_ssid ssid; |
1402 | s32 rssi_thold; | ||
1401 | }; | 1403 | }; |
1402 | 1404 | ||
1403 | /** | 1405 | /** |
@@ -1420,7 +1422,8 @@ struct cfg80211_match_set { | |||
1420 | * @dev: the interface | 1422 | * @dev: the interface |
1421 | * @scan_start: start time of the scheduled scan | 1423 | * @scan_start: start time of the scheduled scan |
1422 | * @channels: channels to scan | 1424 | * @channels: channels to scan |
1423 | * @rssi_thold: don't report scan results below this threshold (in s32 dBm) | 1425 | * @min_rssi_thold: for drivers only supporting a single threshold, this |
1426 | * contains the minimum over all matchsets | ||
1424 | */ | 1427 | */ |
1425 | struct cfg80211_sched_scan_request { | 1428 | struct cfg80211_sched_scan_request { |
1426 | struct cfg80211_ssid *ssids; | 1429 | struct cfg80211_ssid *ssids; |
@@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request { | |||
1433 | u32 flags; | 1436 | u32 flags; |
1434 | struct cfg80211_match_set *match_sets; | 1437 | struct cfg80211_match_set *match_sets; |
1435 | int n_match_sets; | 1438 | int n_match_sets; |
1436 | s32 rssi_thold; | 1439 | s32 min_rssi_thold; |
1437 | 1440 | ||
1438 | /* internal */ | 1441 | /* internal */ |
1439 | struct wiphy *wiphy; | 1442 | struct wiphy *wiphy; |
@@ -1701,8 +1704,14 @@ struct cfg80211_ibss_params { | |||
1701 | * | 1704 | * |
1702 | * @channel: The channel to use or %NULL if not specified (auto-select based | 1705 | * @channel: The channel to use or %NULL if not specified (auto-select based |
1703 | * on scan results) | 1706 | * on scan results) |
1707 | * @channel_hint: The channel of the recommended BSS for initial connection or | ||
1708 | * %NULL if not specified | ||
1704 | * @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan | 1709 | * @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan |
1705 | * results) | 1710 | * results) |
1711 | * @bssid_hint: The recommended AP BSSID for initial connection to the BSS or | ||
1712 | * %NULL if not specified. Unlike the @bssid parameter, the driver is | ||
1713 | * allowed to ignore this @bssid_hint if it has knowledge of a better BSS | ||
1714 | * to use. | ||
1706 | * @ssid: SSID | 1715 | * @ssid: SSID |
1707 | * @ssid_len: Length of ssid in octets | 1716 | * @ssid_len: Length of ssid in octets |
1708 | * @auth_type: Authentication type (algorithm) | 1717 | * @auth_type: Authentication type (algorithm) |
@@ -1725,11 +1734,13 @@ struct cfg80211_ibss_params { | |||
1725 | */ | 1734 | */ |
1726 | struct cfg80211_connect_params { | 1735 | struct cfg80211_connect_params { |
1727 | struct ieee80211_channel *channel; | 1736 | struct ieee80211_channel *channel; |
1728 | u8 *bssid; | 1737 | struct ieee80211_channel *channel_hint; |
1729 | u8 *ssid; | 1738 | const u8 *bssid; |
1739 | const u8 *bssid_hint; | ||
1740 | const u8 *ssid; | ||
1730 | size_t ssid_len; | 1741 | size_t ssid_len; |
1731 | enum nl80211_auth_type auth_type; | 1742 | enum nl80211_auth_type auth_type; |
1732 | u8 *ie; | 1743 | const u8 *ie; |
1733 | size_t ie_len; | 1744 | size_t ie_len; |
1734 | bool privacy; | 1745 | bool privacy; |
1735 | enum nl80211_mfp mfp; | 1746 | enum nl80211_mfp mfp; |
@@ -1768,6 +1779,7 @@ struct cfg80211_bitrate_mask { | |||
1768 | u32 legacy; | 1779 | u32 legacy; |
1769 | u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN]; | 1780 | u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN]; |
1770 | u16 vht_mcs[NL80211_VHT_NSS_MAX]; | 1781 | u16 vht_mcs[NL80211_VHT_NSS_MAX]; |
1782 | enum nl80211_txrate_gi gi; | ||
1771 | } control[IEEE80211_NUM_BANDS]; | 1783 | } control[IEEE80211_NUM_BANDS]; |
1772 | }; | 1784 | }; |
1773 | /** | 1785 | /** |
@@ -2875,6 +2887,11 @@ struct wiphy_vendor_command { | |||
2875 | * @n_vendor_commands: number of vendor commands | 2887 | * @n_vendor_commands: number of vendor commands |
2876 | * @vendor_events: array of vendor events supported by the hardware | 2888 | * @vendor_events: array of vendor events supported by the hardware |
2877 | * @n_vendor_events: number of vendor events | 2889 | * @n_vendor_events: number of vendor events |
2890 | * | ||
2891 | * @max_ap_assoc_sta: maximum number of associated stations supported in AP mode | ||
2892 | * (including P2P GO) or 0 to indicate no such limit is advertised. The | ||
2893 | * driver is allowed to advertise a theoretical limit that it can reach in | ||
2894 | * some cases, but may not always reach. | ||
2878 | */ | 2895 | */ |
2879 | struct wiphy { | 2896 | struct wiphy { |
2880 | /* assign these fields before you register the wiphy */ | 2897 | /* assign these fields before you register the wiphy */ |
@@ -2990,6 +3007,8 @@ struct wiphy { | |||
2990 | const struct nl80211_vendor_cmd_info *vendor_events; | 3007 | const struct nl80211_vendor_cmd_info *vendor_events; |
2991 | int n_vendor_commands, n_vendor_events; | 3008 | int n_vendor_commands, n_vendor_events; |
2992 | 3009 | ||
3010 | u16 max_ap_assoc_sta; | ||
3011 | |||
2993 | char priv[0] __aligned(NETDEV_ALIGN); | 3012 | char priv[0] __aligned(NETDEV_ALIGN); |
2994 | }; | 3013 | }; |
2995 | 3014 | ||
@@ -3127,8 +3146,8 @@ struct cfg80211_cached_keys; | |||
3127 | * @identifier: (private) Identifier used in nl80211 to identify this | 3146 | * @identifier: (private) Identifier used in nl80211 to identify this |
3128 | * wireless device if it has no netdev | 3147 | * wireless device if it has no netdev |
3129 | * @current_bss: (private) Used by the internal configuration code | 3148 | * @current_bss: (private) Used by the internal configuration code |
3130 | * @channel: (private) Used by the internal configuration code to track | 3149 | * @chandef: (private) Used by the internal configuration code to track |
3131 | * the user-set AP, monitor and WDS channel | 3150 | * the user-set channel definition. |
3132 | * @preset_chandef: (private) Used by the internal configuration code to | 3151 | * @preset_chandef: (private) Used by the internal configuration code to |
3133 | * track the channel to be used for AP later | 3152 | * track the channel to be used for AP later |
3134 | * @bssid: (private) Used by the internal configuration code | 3153 | * @bssid: (private) Used by the internal configuration code |
@@ -3192,9 +3211,7 @@ struct wireless_dev { | |||
3192 | 3211 | ||
3193 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ | 3212 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ |
3194 | struct cfg80211_chan_def preset_chandef; | 3213 | struct cfg80211_chan_def preset_chandef; |
3195 | 3214 | struct cfg80211_chan_def chandef; | |
3196 | /* for AP and mesh channel tracking */ | ||
3197 | struct ieee80211_channel *channel; | ||
3198 | 3215 | ||
3199 | bool ibss_fixed; | 3216 | bool ibss_fixed; |
3200 | bool ibss_dfs_possible; | 3217 | bool ibss_dfs_possible; |
@@ -3876,6 +3893,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, | |||
3876 | * | 3893 | * |
3877 | * @dev: network device | 3894 | * @dev: network device |
3878 | * @bssid: the BSSID of the IBSS joined | 3895 | * @bssid: the BSSID of the IBSS joined |
3896 | * @channel: the channel of the IBSS joined | ||
3879 | * @gfp: allocation flags | 3897 | * @gfp: allocation flags |
3880 | * | 3898 | * |
3881 | * This function notifies cfg80211 that the device joined an IBSS or | 3899 | * This function notifies cfg80211 that the device joined an IBSS or |
@@ -3885,7 +3903,8 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, | |||
3885 | * with the locally generated beacon -- this guarantees that there is | 3903 | * with the locally generated beacon -- this guarantees that there is |
3886 | * always a scan result for this IBSS. cfg80211 will handle the rest. | 3904 | * always a scan result for this IBSS. cfg80211 will handle the rest. |
3887 | */ | 3905 | */ |
3888 | void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); | 3906 | void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, |
3907 | struct ieee80211_channel *channel, gfp_t gfp); | ||
3889 | 3908 | ||
3890 | /** | 3909 | /** |
3891 | * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate | 3910 | * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate |
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 8b5b71433297..b0fd9476c538 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h | |||
@@ -316,6 +316,10 @@ enum ieee80211_radiotap_type { | |||
316 | #define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10 | 316 | #define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10 |
317 | #define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20 | 317 | #define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20 |
318 | 318 | ||
319 | #define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01 | ||
320 | #define IEEE80211_RADIOTAP_CODING_LDPC_USER1 0x02 | ||
321 | #define IEEE80211_RADIOTAP_CODING_LDPC_USER2 0x04 | ||
322 | #define IEEE80211_RADIOTAP_CODING_LDPC_USER3 0x08 | ||
319 | 323 | ||
320 | /* helpers */ | 324 | /* helpers */ |
321 | static inline int ieee80211_get_radiotap_len(unsigned char *data) | 325 | static inline int ieee80211_get_radiotap_len(unsigned char *data) |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f4ab2fb4d50c..4f0f29dce0aa 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -808,9 +808,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) | |||
808 | * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index | 808 | * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index |
809 | * @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index | 809 | * @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index |
810 | * @RX_FLAG_40MHZ: HT40 (40 MHz) was used | 810 | * @RX_FLAG_40MHZ: HT40 (40 MHz) was used |
811 | * @RX_FLAG_80MHZ: 80 MHz was used | ||
812 | * @RX_FLAG_80P80MHZ: 80+80 MHz was used | ||
813 | * @RX_FLAG_160MHZ: 160 MHz was used | ||
814 | * @RX_FLAG_SHORT_GI: Short guard interval was used | 811 | * @RX_FLAG_SHORT_GI: Short guard interval was used |
815 | * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present. | 812 | * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present. |
816 | * Valid only for data frames (mainly A-MPDU) | 813 | * Valid only for data frames (mainly A-MPDU) |
@@ -830,6 +827,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) | |||
830 | * on this subframe | 827 | * on this subframe |
831 | * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC | 828 | * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC |
832 | * is stored in the @ampdu_delimiter_crc field) | 829 | * is stored in the @ampdu_delimiter_crc field) |
830 | * @RX_FLAG_LDPC: LDPC was used | ||
833 | * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 | 831 | * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 |
834 | * @RX_FLAG_10MHZ: 10 MHz (half channel) was used | 832 | * @RX_FLAG_10MHZ: 10 MHz (half channel) was used |
835 | * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used | 833 | * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used |
@@ -866,9 +864,7 @@ enum mac80211_rx_flags { | |||
866 | RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20), | 864 | RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20), |
867 | RX_FLAG_MACTIME_END = BIT(21), | 865 | RX_FLAG_MACTIME_END = BIT(21), |
868 | RX_FLAG_VHT = BIT(22), | 866 | RX_FLAG_VHT = BIT(22), |
869 | RX_FLAG_80MHZ = BIT(23), | 867 | RX_FLAG_LDPC = BIT(23), |
870 | RX_FLAG_80P80MHZ = BIT(24), | ||
871 | RX_FLAG_160MHZ = BIT(25), | ||
872 | RX_FLAG_STBC_MASK = BIT(26) | BIT(27), | 868 | RX_FLAG_STBC_MASK = BIT(26) | BIT(27), |
873 | RX_FLAG_10MHZ = BIT(28), | 869 | RX_FLAG_10MHZ = BIT(28), |
874 | RX_FLAG_5MHZ = BIT(29), | 870 | RX_FLAG_5MHZ = BIT(29), |
@@ -878,6 +874,21 @@ enum mac80211_rx_flags { | |||
878 | #define RX_FLAG_STBC_SHIFT 26 | 874 | #define RX_FLAG_STBC_SHIFT 26 |
879 | 875 | ||
880 | /** | 876 | /** |
877 | * enum mac80211_rx_vht_flags - receive VHT flags | ||
878 | * | ||
879 | * These flags are used with the @vht_flag member of | ||
880 | * &struct ieee80211_rx_status. | ||
881 | * @RX_VHT_FLAG_80MHZ: 80 MHz was used | ||
882 | * @RX_VHT_FLAG_80P80MHZ: 80+80 MHz was used | ||
883 | * @RX_VHT_FLAG_160MHZ: 160 MHz was used | ||
884 | */ | ||
885 | enum mac80211_rx_vht_flags { | ||
886 | RX_VHT_FLAG_80MHZ = BIT(0), | ||
887 | RX_VHT_FLAG_80P80MHZ = BIT(1), | ||
888 | RX_VHT_FLAG_160MHZ = BIT(2), | ||
889 | }; | ||
890 | |||
891 | /** | ||
881 | * struct ieee80211_rx_status - receive status | 892 | * struct ieee80211_rx_status - receive status |
882 | * | 893 | * |
883 | * The low-level driver should provide this information (the subset | 894 | * The low-level driver should provide this information (the subset |
@@ -902,26 +913,19 @@ enum mac80211_rx_flags { | |||
902 | * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT) | 913 | * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT) |
903 | * @vht_nss: number of streams (VHT only) | 914 | * @vht_nss: number of streams (VHT only) |
904 | * @flag: %RX_FLAG_* | 915 | * @flag: %RX_FLAG_* |
916 | * @vht_flag: %RX_VHT_FLAG_* | ||
905 | * @rx_flags: internal RX flags for mac80211 | 917 | * @rx_flags: internal RX flags for mac80211 |
906 | * @ampdu_reference: A-MPDU reference number, must be a different value for | 918 | * @ampdu_reference: A-MPDU reference number, must be a different value for |
907 | * each A-MPDU but the same for each subframe within one A-MPDU | 919 | * each A-MPDU but the same for each subframe within one A-MPDU |
908 | * @ampdu_delimiter_crc: A-MPDU delimiter CRC | 920 | * @ampdu_delimiter_crc: A-MPDU delimiter CRC |
909 | * @vendor_radiotap_bitmap: radiotap vendor namespace presence bitmap | ||
910 | * @vendor_radiotap_len: radiotap vendor namespace length | ||
911 | * @vendor_radiotap_align: radiotap vendor namespace alignment. Note | ||
912 | * that the actual data must be at the start of the SKB data | ||
913 | * already. | ||
914 | * @vendor_radiotap_oui: radiotap vendor namespace OUI | ||
915 | * @vendor_radiotap_subns: radiotap vendor sub namespace | ||
916 | */ | 921 | */ |
917 | struct ieee80211_rx_status { | 922 | struct ieee80211_rx_status { |
918 | u64 mactime; | 923 | u64 mactime; |
919 | u32 device_timestamp; | 924 | u32 device_timestamp; |
920 | u32 ampdu_reference; | 925 | u32 ampdu_reference; |
921 | u32 flag; | 926 | u32 flag; |
922 | u32 vendor_radiotap_bitmap; | ||
923 | u16 vendor_radiotap_len; | ||
924 | u16 freq; | 927 | u16 freq; |
928 | u8 vht_flag; | ||
925 | u8 rate_idx; | 929 | u8 rate_idx; |
926 | u8 vht_nss; | 930 | u8 vht_nss; |
927 | u8 rx_flags; | 931 | u8 rx_flags; |
@@ -931,9 +935,6 @@ struct ieee80211_rx_status { | |||
931 | u8 chains; | 935 | u8 chains; |
932 | s8 chain_signal[IEEE80211_MAX_CHAINS]; | 936 | s8 chain_signal[IEEE80211_MAX_CHAINS]; |
933 | u8 ampdu_delimiter_crc; | 937 | u8 ampdu_delimiter_crc; |
934 | u8 vendor_radiotap_align; | ||
935 | u8 vendor_radiotap_oui[3]; | ||
936 | u8 vendor_radiotap_subns; | ||
937 | }; | 938 | }; |
938 | 939 | ||
939 | /** | 940 | /** |
@@ -2750,11 +2751,13 @@ enum ieee80211_roc_type { | |||
2750 | * @channel_switch_beacon: Starts a channel switch to a new channel. | 2751 | * @channel_switch_beacon: Starts a channel switch to a new channel. |
2751 | * Beacons are modified to include CSA or ECSA IEs before calling this | 2752 | * Beacons are modified to include CSA or ECSA IEs before calling this |
2752 | * function. The corresponding count fields in these IEs must be | 2753 | * function. The corresponding count fields in these IEs must be |
2753 | * decremented, and when they reach zero the driver must call | 2754 | * decremented, and when they reach 1 the driver must call |
2754 | * ieee80211_csa_finish(). Drivers which use ieee80211_beacon_get() | 2755 | * ieee80211_csa_finish(). Drivers which use ieee80211_beacon_get() |
2755 | * get the csa counter decremented by mac80211, but must check if it is | 2756 | * get the csa counter decremented by mac80211, but must check if it is |
2756 | * zero using ieee80211_csa_is_complete() after the beacon has been | 2757 | * 1 using ieee80211_csa_is_complete() after the beacon has been |
2757 | * transmitted and then call ieee80211_csa_finish(). | 2758 | * transmitted and then call ieee80211_csa_finish(). |
2759 | * If the CSA count starts as zero or 1, this function will not be called, | ||
2760 | * since there won't be any time to beacon before the switch anyway. | ||
2758 | * | 2761 | * |
2759 | * @join_ibss: Join an IBSS (on an IBSS interface); this is called after all | 2762 | * @join_ibss: Join an IBSS (on an IBSS interface); this is called after all |
2760 | * information in bss_conf is set up and the beacon can be retrieved. A | 2763 | * information in bss_conf is set up and the beacon can be retrieved. A |
@@ -3452,13 +3455,13 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
3452 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 3455 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
3453 | * | 3456 | * |
3454 | * After a channel switch announcement was scheduled and the counter in this | 3457 | * After a channel switch announcement was scheduled and the counter in this |
3455 | * announcement hit zero, this function must be called by the driver to | 3458 | * announcement hits 1, this function must be called by the driver to |
3456 | * notify mac80211 that the channel can be changed. | 3459 | * notify mac80211 that the channel can be changed. |
3457 | */ | 3460 | */ |
3458 | void ieee80211_csa_finish(struct ieee80211_vif *vif); | 3461 | void ieee80211_csa_finish(struct ieee80211_vif *vif); |
3459 | 3462 | ||
3460 | /** | 3463 | /** |
3461 | * ieee80211_csa_is_complete - find out if counters reached zero | 3464 | * ieee80211_csa_is_complete - find out if counters reached 1 |
3462 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 3465 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
3463 | * | 3466 | * |
3464 | * This function returns whether the channel switch counters reached zero. | 3467 | * This function returns whether the channel switch counters reached zero. |
@@ -4451,7 +4454,6 @@ struct ieee80211_tx_rate_control { | |||
4451 | }; | 4454 | }; |
4452 | 4455 | ||
4453 | struct rate_control_ops { | 4456 | struct rate_control_ops { |
4454 | struct module *module; | ||
4455 | const char *name; | 4457 | const char *name; |
4456 | void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); | 4458 | void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); |
4457 | void (*free)(void *priv); | 4459 | void (*free)(void *priv); |
@@ -4553,8 +4555,8 @@ int rate_control_set_rates(struct ieee80211_hw *hw, | |||
4553 | struct ieee80211_sta *pubsta, | 4555 | struct ieee80211_sta *pubsta, |
4554 | struct ieee80211_sta_rates *rates); | 4556 | struct ieee80211_sta_rates *rates); |
4555 | 4557 | ||
4556 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | 4558 | int ieee80211_rate_control_register(const struct rate_control_ops *ops); |
4557 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | 4559 | void ieee80211_rate_control_unregister(const struct rate_control_ops *ops); |
4558 | 4560 | ||
4559 | static inline bool | 4561 | static inline bool |
4560 | conf_is_ht20(struct ieee80211_conf *conf) | 4562 | conf_is_ht20(struct ieee80211_conf *conf) |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 91054fd660e0..a12e6cae5132 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -418,8 +418,18 @@ | |||
418 | * %NL80211_ATTR_SSID attribute, and can optionally specify the association | 418 | * %NL80211_ATTR_SSID attribute, and can optionally specify the association |
419 | * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, | 419 | * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, |
420 | * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, | 420 | * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, |
421 | * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and | 421 | * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, |
422 | * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. | 422 | * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, %NL80211_ATTR_MAC_HINT, and |
423 | * %NL80211_ATTR_WIPHY_FREQ_HINT. | ||
424 | * If included, %NL80211_ATTR_MAC and %NL80211_ATTR_WIPHY_FREQ are | ||
425 | * restrictions on BSS selection, i.e., they effectively prevent roaming | ||
426 | * within the ESS. %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT | ||
427 | * can be included to provide a recommendation of the initial BSS while | ||
428 | * allowing the driver to roam to other BSSes within the ESS and also to | ||
429 | * ignore this recommendation if the indicated BSS is not ideal. Only one | ||
430 | * set of BSSID,frequency parameters is used (i.e., either the enforcing | ||
431 | * %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict | ||
432 | * %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT). | ||
423 | * Background scan period can optionally be | 433 | * Background scan period can optionally be |
424 | * specified in %NL80211_ATTR_BG_SCAN_PERIOD, | 434 | * specified in %NL80211_ATTR_BG_SCAN_PERIOD, |
425 | * if not specified default background scan configuration | 435 | * if not specified default background scan configuration |
@@ -1555,6 +1565,16 @@ enum nl80211_commands { | |||
1555 | * data is in the format defined for the payload of the QoS Map Set element | 1565 | * data is in the format defined for the payload of the QoS Map Set element |
1556 | * in IEEE Std 802.11-2012, 8.4.2.97. | 1566 | * in IEEE Std 802.11-2012, 8.4.2.97. |
1557 | * | 1567 | * |
1568 | * @NL80211_ATTR_MAC_HINT: MAC address recommendation as initial BSS | ||
1569 | * @NL80211_ATTR_WIPHY_FREQ_HINT: frequency of the recommended initial BSS | ||
1570 | * | ||
1571 | * @NL80211_ATTR_MAX_AP_ASSOC_STA: Device attribute that indicates how many | ||
1572 | * associated stations are supported in AP mode (including P2P GO); u32. | ||
1573 | * Since drivers may not have a fixed limit on the maximum number (e.g., | ||
1574 | * other concurrent operations may affect this), drivers are allowed to | ||
1575 | * advertise values that cannot always be met. In such cases, an attempt | ||
1576 | * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. | ||
1577 | * | ||
1558 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1578 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1559 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1579 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1560 | */ | 1580 | */ |
@@ -1883,6 +1903,11 @@ enum nl80211_attrs { | |||
1883 | 1903 | ||
1884 | NL80211_ATTR_QOS_MAP, | 1904 | NL80211_ATTR_QOS_MAP, |
1885 | 1905 | ||
1906 | NL80211_ATTR_MAC_HINT, | ||
1907 | NL80211_ATTR_WIPHY_FREQ_HINT, | ||
1908 | |||
1909 | NL80211_ATTR_MAX_AP_ASSOC_STA, | ||
1910 | |||
1886 | /* add attributes here, update the policy in nl80211.c */ | 1911 | /* add attributes here, update the policy in nl80211.c */ |
1887 | 1912 | ||
1888 | __NL80211_ATTR_AFTER_LAST, | 1913 | __NL80211_ATTR_AFTER_LAST, |
@@ -2412,7 +2437,10 @@ enum nl80211_reg_type { | |||
2412 | * in KHz. This is not a center a frequency but an actual regulatory | 2437 | * in KHz. This is not a center a frequency but an actual regulatory |
2413 | * band edge. | 2438 | * band edge. |
2414 | * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this | 2439 | * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this |
2415 | * frequency range, in KHz. | 2440 | * frequency range, in KHz. If not present or 0, maximum available |
2441 | * bandwidth should be calculated base on contiguous rules and wider | ||
2442 | * channels will be allowed to cross multiple contiguous/overlapping | ||
2443 | * frequency ranges. | ||
2416 | * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain | 2444 | * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain |
2417 | * for a given frequency range. The value is in mBi (100 * dBi). | 2445 | * for a given frequency range. The value is in mBi (100 * dBi). |
2418 | * If you don't have one then don't send this. | 2446 | * If you don't have one then don't send this. |
@@ -2442,9 +2470,15 @@ enum nl80211_reg_rule_attr { | |||
2442 | * enum nl80211_sched_scan_match_attr - scheduled scan match attributes | 2470 | * enum nl80211_sched_scan_match_attr - scheduled scan match attributes |
2443 | * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved | 2471 | * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved |
2444 | * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, | 2472 | * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, |
2445 | * only report BSS with matching SSID. | 2473 | * only report BSS with matching SSID. |
2446 | * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a | 2474 | * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a |
2447 | * BSS in scan results. Filtering is turned off if not specified. | 2475 | * BSS in scan results. Filtering is turned off if not specified. Note that |
2476 | * if this attribute is in a match set of its own, then it is treated as | ||
2477 | * the default value for all matchsets with an SSID, rather than being a | ||
2478 | * matchset of its own without an RSSI filter. This is due to problems with | ||
2479 | * how this API was implemented in the past. Also, due to the same problem, | ||
2480 | * the only way to create a matchset with only an RSSI filter (with this | ||
2481 | * attribute) is if there's only a single matchset with the RSSI attribute. | ||
2448 | * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter | 2482 | * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter |
2449 | * attribute number currently defined | 2483 | * attribute number currently defined |
2450 | * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use | 2484 | * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use |
@@ -3131,6 +3165,7 @@ enum nl80211_key_attributes { | |||
3131 | * in an array of MCS numbers. | 3165 | * in an array of MCS numbers. |
3132 | * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection, | 3166 | * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection, |
3133 | * see &struct nl80211_txrate_vht | 3167 | * see &struct nl80211_txrate_vht |
3168 | * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi | ||
3134 | * @__NL80211_TXRATE_AFTER_LAST: internal | 3169 | * @__NL80211_TXRATE_AFTER_LAST: internal |
3135 | * @NL80211_TXRATE_MAX: highest TX rate attribute | 3170 | * @NL80211_TXRATE_MAX: highest TX rate attribute |
3136 | */ | 3171 | */ |
@@ -3139,6 +3174,7 @@ enum nl80211_tx_rate_attributes { | |||
3139 | NL80211_TXRATE_LEGACY, | 3174 | NL80211_TXRATE_LEGACY, |
3140 | NL80211_TXRATE_HT, | 3175 | NL80211_TXRATE_HT, |
3141 | NL80211_TXRATE_VHT, | 3176 | NL80211_TXRATE_VHT, |
3177 | NL80211_TXRATE_GI, | ||
3142 | 3178 | ||
3143 | /* keep last */ | 3179 | /* keep last */ |
3144 | __NL80211_TXRATE_AFTER_LAST, | 3180 | __NL80211_TXRATE_AFTER_LAST, |
@@ -3156,6 +3192,12 @@ struct nl80211_txrate_vht { | |||
3156 | __u16 mcs[NL80211_VHT_NSS_MAX]; | 3192 | __u16 mcs[NL80211_VHT_NSS_MAX]; |
3157 | }; | 3193 | }; |
3158 | 3194 | ||
3195 | enum nl80211_txrate_gi { | ||
3196 | NL80211_TXRATE_DEFAULT_GI, | ||
3197 | NL80211_TXRATE_FORCE_SGI, | ||
3198 | NL80211_TXRATE_FORCE_LGI, | ||
3199 | }; | ||
3200 | |||
3159 | /** | 3201 | /** |
3160 | * enum nl80211_band - Frequency band | 3202 | * enum nl80211_band - Frequency band |
3161 | * @NL80211_BAND_2GHZ: 2.4 GHz ISM band | 3203 | * @NL80211_BAND_2GHZ: 2.4 GHz ISM band |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 13b7683de5a4..ce9633a3cfb0 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -107,7 +107,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
107 | mgmt->u.action.u.addba_req.start_seq_num = | 107 | mgmt->u.action.u.addba_req.start_seq_num = |
108 | cpu_to_le16(start_seq_num << 4); | 108 | cpu_to_le16(start_seq_num << 4); |
109 | 109 | ||
110 | ieee80211_tx_skb_tid(sdata, skb, tid); | 110 | ieee80211_tx_skb(sdata, skb); |
111 | } | 111 | } |
112 | 112 | ||
113 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) | 113 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f9ae9b85d4c1..6973ccdd230b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -451,11 +451,11 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | |||
451 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 451 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
452 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | 452 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) |
453 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 453 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
454 | if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) | 454 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) |
455 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 455 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; |
456 | if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) | 456 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80P80MHZ) |
457 | rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 457 | rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; |
458 | if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) | 458 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) |
459 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 459 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; |
460 | } | 460 | } |
461 | 461 | ||
@@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
970 | /* TODO: make hostapd tell us what it wants */ | 970 | /* TODO: make hostapd tell us what it wants */ |
971 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 971 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
972 | sdata->needed_rx_chains = sdata->local->rx_chains; | 972 | sdata->needed_rx_chains = sdata->local->rx_chains; |
973 | sdata->radar_required = params->radar_required; | ||
974 | 973 | ||
975 | mutex_lock(&local->mtx); | 974 | mutex_lock(&local->mtx); |
975 | sdata->radar_required = params->radar_required; | ||
976 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, | 976 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, |
977 | IEEE80211_CHANCTX_SHARED); | 977 | IEEE80211_CHANCTX_SHARED); |
978 | mutex_unlock(&local->mtx); | 978 | mutex_unlock(&local->mtx); |
@@ -1053,6 +1053,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
1053 | int err; | 1053 | int err; |
1054 | 1054 | ||
1055 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1055 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1056 | sdata_assert_lock(sdata); | ||
1056 | 1057 | ||
1057 | /* don't allow changing the beacon while CSA is in place - offset | 1058 | /* don't allow changing the beacon while CSA is in place - offset |
1058 | * of channel switch counter may change | 1059 | * of channel switch counter may change |
@@ -1080,6 +1081,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1080 | struct probe_resp *old_probe_resp; | 1081 | struct probe_resp *old_probe_resp; |
1081 | struct cfg80211_chan_def chandef; | 1082 | struct cfg80211_chan_def chandef; |
1082 | 1083 | ||
1084 | sdata_assert_lock(sdata); | ||
1085 | |||
1083 | old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); | 1086 | old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); |
1084 | if (!old_beacon) | 1087 | if (!old_beacon) |
1085 | return -ENOENT; | 1088 | return -ENOENT; |
@@ -1341,6 +1344,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1341 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1344 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
1342 | params->vht_capa, sta); | 1345 | params->vht_capa, sta); |
1343 | 1346 | ||
1347 | if (params->opmode_notif_used) { | ||
1348 | enum ieee80211_band band = | ||
1349 | ieee80211_get_sdata_band(sdata); | ||
1350 | |||
1351 | /* returned value is only needed for rc update, but the | ||
1352 | * rc isn't initialized here yet, so ignore it | ||
1353 | */ | ||
1354 | __ieee80211_vht_handle_opmode(sdata, sta, | ||
1355 | params->opmode_notif, | ||
1356 | band, false); | ||
1357 | } | ||
1358 | |||
1344 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1359 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1345 | #ifdef CONFIG_MAC80211_MESH | 1360 | #ifdef CONFIG_MAC80211_MESH |
1346 | u32 changed = 0; | 1361 | u32 changed = 0; |
@@ -2628,6 +2643,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2628 | if (!roc) | 2643 | if (!roc) |
2629 | return -ENOMEM; | 2644 | return -ENOMEM; |
2630 | 2645 | ||
2646 | /* | ||
2647 | * If the duration is zero, then the driver | ||
2648 | * wouldn't actually do anything. Set it to | ||
2649 | * 10 for now. | ||
2650 | * | ||
2651 | * TODO: cancel the off-channel operation | ||
2652 | * when we get the SKB's TX status and | ||
2653 | * the wait time was zero before. | ||
2654 | */ | ||
2655 | if (!duration) | ||
2656 | duration = 10; | ||
2657 | |||
2631 | roc->chan = channel; | 2658 | roc->chan = channel; |
2632 | roc->duration = duration; | 2659 | roc->duration = duration; |
2633 | roc->req_duration = duration; | 2660 | roc->req_duration = duration; |
@@ -2651,18 +2678,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2651 | 2678 | ||
2652 | /* otherwise actually kick it off here (for error handling) */ | 2679 | /* otherwise actually kick it off here (for error handling) */ |
2653 | 2680 | ||
2654 | /* | ||
2655 | * If the duration is zero, then the driver | ||
2656 | * wouldn't actually do anything. Set it to | ||
2657 | * 10 for now. | ||
2658 | * | ||
2659 | * TODO: cancel the off-channel operation | ||
2660 | * when we get the SKB's TX status and | ||
2661 | * the wait time was zero before. | ||
2662 | */ | ||
2663 | if (!duration) | ||
2664 | duration = 10; | ||
2665 | |||
2666 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); | 2681 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); |
2667 | if (ret) { | 2682 | if (ret) { |
2668 | kfree(roc); | 2683 | kfree(roc); |
@@ -2988,69 +3003,88 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) | |||
2988 | return new_beacon; | 3003 | return new_beacon; |
2989 | } | 3004 | } |
2990 | 3005 | ||
2991 | void ieee80211_csa_finalize_work(struct work_struct *work) | 3006 | void ieee80211_csa_finish(struct ieee80211_vif *vif) |
3007 | { | ||
3008 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
3009 | |||
3010 | ieee80211_queue_work(&sdata->local->hw, | ||
3011 | &sdata->csa_finalize_work); | ||
3012 | } | ||
3013 | EXPORT_SYMBOL(ieee80211_csa_finish); | ||
3014 | |||
3015 | static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | ||
2992 | { | 3016 | { |
2993 | struct ieee80211_sub_if_data *sdata = | ||
2994 | container_of(work, struct ieee80211_sub_if_data, | ||
2995 | csa_finalize_work); | ||
2996 | struct ieee80211_local *local = sdata->local; | 3017 | struct ieee80211_local *local = sdata->local; |
2997 | int err, changed = 0; | 3018 | int err, changed = 0; |
2998 | 3019 | ||
2999 | sdata_lock(sdata); | 3020 | sdata_assert_lock(sdata); |
3000 | /* AP might have been stopped while waiting for the lock. */ | ||
3001 | if (!sdata->vif.csa_active) | ||
3002 | goto unlock; | ||
3003 | |||
3004 | if (!ieee80211_sdata_running(sdata)) | ||
3005 | goto unlock; | ||
3006 | 3021 | ||
3007 | sdata->radar_required = sdata->csa_radar_required; | ||
3008 | mutex_lock(&local->mtx); | 3022 | mutex_lock(&local->mtx); |
3023 | sdata->radar_required = sdata->csa_radar_required; | ||
3009 | err = ieee80211_vif_change_channel(sdata, &changed); | 3024 | err = ieee80211_vif_change_channel(sdata, &changed); |
3010 | mutex_unlock(&local->mtx); | 3025 | mutex_unlock(&local->mtx); |
3011 | if (WARN_ON(err < 0)) | 3026 | if (WARN_ON(err < 0)) |
3012 | goto unlock; | 3027 | return; |
3013 | 3028 | ||
3014 | if (!local->use_chanctx) { | 3029 | if (!local->use_chanctx) { |
3015 | local->_oper_chandef = sdata->csa_chandef; | 3030 | local->_oper_chandef = sdata->csa_chandef; |
3016 | ieee80211_hw_config(local, 0); | 3031 | ieee80211_hw_config(local, 0); |
3017 | } | 3032 | } |
3018 | 3033 | ||
3019 | ieee80211_bss_info_change_notify(sdata, changed); | ||
3020 | |||
3021 | sdata->vif.csa_active = false; | 3034 | sdata->vif.csa_active = false; |
3022 | switch (sdata->vif.type) { | 3035 | switch (sdata->vif.type) { |
3023 | case NL80211_IFTYPE_AP: | 3036 | case NL80211_IFTYPE_AP: |
3024 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 3037 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); |
3025 | if (err < 0) | ||
3026 | goto unlock; | ||
3027 | |||
3028 | changed |= err; | ||
3029 | kfree(sdata->u.ap.next_beacon); | 3038 | kfree(sdata->u.ap.next_beacon); |
3030 | sdata->u.ap.next_beacon = NULL; | 3039 | sdata->u.ap.next_beacon = NULL; |
3031 | 3040 | ||
3032 | ieee80211_bss_info_change_notify(sdata, err); | 3041 | if (err < 0) |
3042 | return; | ||
3043 | changed |= err; | ||
3033 | break; | 3044 | break; |
3034 | case NL80211_IFTYPE_ADHOC: | 3045 | case NL80211_IFTYPE_ADHOC: |
3035 | ieee80211_ibss_finish_csa(sdata); | 3046 | err = ieee80211_ibss_finish_csa(sdata); |
3047 | if (err < 0) | ||
3048 | return; | ||
3049 | changed |= err; | ||
3036 | break; | 3050 | break; |
3037 | #ifdef CONFIG_MAC80211_MESH | 3051 | #ifdef CONFIG_MAC80211_MESH |
3038 | case NL80211_IFTYPE_MESH_POINT: | 3052 | case NL80211_IFTYPE_MESH_POINT: |
3039 | err = ieee80211_mesh_finish_csa(sdata); | 3053 | err = ieee80211_mesh_finish_csa(sdata); |
3040 | if (err < 0) | 3054 | if (err < 0) |
3041 | goto unlock; | 3055 | return; |
3056 | changed |= err; | ||
3042 | break; | 3057 | break; |
3043 | #endif | 3058 | #endif |
3044 | default: | 3059 | default: |
3045 | WARN_ON(1); | 3060 | WARN_ON(1); |
3046 | goto unlock; | 3061 | return; |
3047 | } | 3062 | } |
3048 | 3063 | ||
3064 | ieee80211_bss_info_change_notify(sdata, changed); | ||
3065 | |||
3049 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 3066 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
3050 | IEEE80211_MAX_QUEUE_MAP, | 3067 | IEEE80211_MAX_QUEUE_MAP, |
3051 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3068 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3052 | 3069 | ||
3053 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); | 3070 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); |
3071 | } | ||
3072 | |||
3073 | void ieee80211_csa_finalize_work(struct work_struct *work) | ||
3074 | { | ||
3075 | struct ieee80211_sub_if_data *sdata = | ||
3076 | container_of(work, struct ieee80211_sub_if_data, | ||
3077 | csa_finalize_work); | ||
3078 | |||
3079 | sdata_lock(sdata); | ||
3080 | /* AP might have been stopped while waiting for the lock. */ | ||
3081 | if (!sdata->vif.csa_active) | ||
3082 | goto unlock; | ||
3083 | |||
3084 | if (!ieee80211_sdata_running(sdata)) | ||
3085 | goto unlock; | ||
3086 | |||
3087 | ieee80211_csa_finalize(sdata); | ||
3054 | 3088 | ||
3055 | unlock: | 3089 | unlock: |
3056 | sdata_unlock(sdata); | 3090 | sdata_unlock(sdata); |
@@ -3064,9 +3098,9 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3064 | struct ieee80211_chanctx_conf *chanctx_conf; | 3098 | struct ieee80211_chanctx_conf *chanctx_conf; |
3065 | struct ieee80211_chanctx *chanctx; | 3099 | struct ieee80211_chanctx *chanctx; |
3066 | struct ieee80211_if_mesh __maybe_unused *ifmsh; | 3100 | struct ieee80211_if_mesh __maybe_unused *ifmsh; |
3067 | int err, num_chanctx; | 3101 | int err, num_chanctx, changed = 0; |
3068 | 3102 | ||
3069 | lockdep_assert_held(&sdata->wdev.mtx); | 3103 | sdata_assert_lock(sdata); |
3070 | 3104 | ||
3071 | if (!list_empty(&local->roc_list) || local->scanning) | 3105 | if (!list_empty(&local->roc_list) || local->scanning) |
3072 | return -EBUSY; | 3106 | return -EBUSY; |
@@ -3105,19 +3139,40 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3105 | 3139 | ||
3106 | switch (sdata->vif.type) { | 3140 | switch (sdata->vif.type) { |
3107 | case NL80211_IFTYPE_AP: | 3141 | case NL80211_IFTYPE_AP: |
3108 | sdata->csa_counter_offset_beacon = | ||
3109 | params->counter_offset_beacon; | ||
3110 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | ||
3111 | sdata->u.ap.next_beacon = | 3142 | sdata->u.ap.next_beacon = |
3112 | cfg80211_beacon_dup(¶ms->beacon_after); | 3143 | cfg80211_beacon_dup(¶ms->beacon_after); |
3113 | if (!sdata->u.ap.next_beacon) | 3144 | if (!sdata->u.ap.next_beacon) |
3114 | return -ENOMEM; | 3145 | return -ENOMEM; |
3115 | 3146 | ||
3147 | /* | ||
3148 | * With a count of 0, we don't have to wait for any | ||
3149 | * TBTT before switching, so complete the CSA | ||
3150 | * immediately. In theory, with a count == 1 we | ||
3151 | * should delay the switch until just before the next | ||
3152 | * TBTT, but that would complicate things so we switch | ||
3153 | * immediately too. If we would delay the switch | ||
3154 | * until the next TBTT, we would have to set the probe | ||
3155 | * response here. | ||
3156 | * | ||
3157 | * TODO: A channel switch with count <= 1 without | ||
3158 | * sending a CSA action frame is kind of useless, | ||
3159 | * because the clients won't know we're changing | ||
3160 | * channels. The action frame must be implemented | ||
3161 | * either here or in the userspace. | ||
3162 | */ | ||
3163 | if (params->count <= 1) | ||
3164 | break; | ||
3165 | |||
3166 | sdata->csa_counter_offset_beacon = | ||
3167 | params->counter_offset_beacon; | ||
3168 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | ||
3116 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); | 3169 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); |
3117 | if (err < 0) { | 3170 | if (err < 0) { |
3118 | kfree(sdata->u.ap.next_beacon); | 3171 | kfree(sdata->u.ap.next_beacon); |
3119 | return err; | 3172 | return err; |
3120 | } | 3173 | } |
3174 | changed |= err; | ||
3175 | |||
3121 | break; | 3176 | break; |
3122 | case NL80211_IFTYPE_ADHOC: | 3177 | case NL80211_IFTYPE_ADHOC: |
3123 | if (!sdata->vif.bss_conf.ibss_joined) | 3178 | if (!sdata->vif.bss_conf.ibss_joined) |
@@ -3145,17 +3200,21 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3145 | params->chandef.chan->band) | 3200 | params->chandef.chan->band) |
3146 | return -EINVAL; | 3201 | return -EINVAL; |
3147 | 3202 | ||
3148 | err = ieee80211_ibss_csa_beacon(sdata, params); | 3203 | /* see comments in the NL80211_IFTYPE_AP block */ |
3149 | if (err < 0) | 3204 | if (params->count > 1) { |
3150 | return err; | 3205 | err = ieee80211_ibss_csa_beacon(sdata, params); |
3206 | if (err < 0) | ||
3207 | return err; | ||
3208 | changed |= err; | ||
3209 | } | ||
3210 | |||
3211 | ieee80211_send_action_csa(sdata, params); | ||
3212 | |||
3151 | break; | 3213 | break; |
3152 | #ifdef CONFIG_MAC80211_MESH | 3214 | #ifdef CONFIG_MAC80211_MESH |
3153 | case NL80211_IFTYPE_MESH_POINT: | 3215 | case NL80211_IFTYPE_MESH_POINT: |
3154 | ifmsh = &sdata->u.mesh; | 3216 | ifmsh = &sdata->u.mesh; |
3155 | 3217 | ||
3156 | if (!ifmsh->mesh_id) | ||
3157 | return -EINVAL; | ||
3158 | |||
3159 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) | 3218 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) |
3160 | return -EINVAL; | 3219 | return -EINVAL; |
3161 | 3220 | ||
@@ -3164,17 +3223,27 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3164 | params->chandef.chan->band) | 3223 | params->chandef.chan->band) |
3165 | return -EINVAL; | 3224 | return -EINVAL; |
3166 | 3225 | ||
3167 | ifmsh->chsw_init = true; | 3226 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) { |
3168 | if (!ifmsh->pre_value) | 3227 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT; |
3169 | ifmsh->pre_value = 1; | 3228 | if (!ifmsh->pre_value) |
3170 | else | 3229 | ifmsh->pre_value = 1; |
3171 | ifmsh->pre_value++; | 3230 | else |
3231 | ifmsh->pre_value++; | ||
3232 | } | ||
3172 | 3233 | ||
3173 | err = ieee80211_mesh_csa_beacon(sdata, params, true); | 3234 | /* see comments in the NL80211_IFTYPE_AP block */ |
3174 | if (err < 0) { | 3235 | if (params->count > 1) { |
3175 | ifmsh->chsw_init = false; | 3236 | err = ieee80211_mesh_csa_beacon(sdata, params); |
3176 | return err; | 3237 | if (err < 0) { |
3238 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; | ||
3239 | return err; | ||
3240 | } | ||
3241 | changed |= err; | ||
3177 | } | 3242 | } |
3243 | |||
3244 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) | ||
3245 | ieee80211_send_action_csa(sdata, params); | ||
3246 | |||
3178 | break; | 3247 | break; |
3179 | #endif | 3248 | #endif |
3180 | default: | 3249 | default: |
@@ -3191,8 +3260,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3191 | sdata->csa_chandef = params->chandef; | 3260 | sdata->csa_chandef = params->chandef; |
3192 | sdata->vif.csa_active = true; | 3261 | sdata->vif.csa_active = true; |
3193 | 3262 | ||
3194 | ieee80211_bss_info_change_notify(sdata, err); | 3263 | if (changed) { |
3195 | drv_channel_switch_beacon(sdata, ¶ms->chandef); | 3264 | ieee80211_bss_info_change_notify(sdata, changed); |
3265 | drv_channel_switch_beacon(sdata, ¶ms->chandef); | ||
3266 | } else { | ||
3267 | /* if the beacon didn't change, we can finalize immediately */ | ||
3268 | ieee80211_csa_finalize(sdata); | ||
3269 | } | ||
3196 | 3270 | ||
3197 | return 0; | 3271 | return 0; |
3198 | } | 3272 | } |
@@ -3863,7 +3937,7 @@ static int ieee80211_set_qos_map(struct wiphy *wiphy, | |||
3863 | return 0; | 3937 | return 0; |
3864 | } | 3938 | } |
3865 | 3939 | ||
3866 | struct cfg80211_ops mac80211_config_ops = { | 3940 | const struct cfg80211_ops mac80211_config_ops = { |
3867 | .add_virtual_intf = ieee80211_add_iface, | 3941 | .add_virtual_intf = ieee80211_add_iface, |
3868 | .del_virtual_intf = ieee80211_del_iface, | 3942 | .del_virtual_intf = ieee80211_del_iface, |
3869 | .change_virtual_intf = ieee80211_change_iface, | 3943 | .change_virtual_intf = ieee80211_change_iface, |
diff --git a/net/mac80211/cfg.h b/net/mac80211/cfg.h index 7d7879f5b00b..2d51f62dc76c 100644 --- a/net/mac80211/cfg.h +++ b/net/mac80211/cfg.h | |||
@@ -4,6 +4,6 @@ | |||
4 | #ifndef __CFG_H | 4 | #ifndef __CFG_H |
5 | #define __CFG_H | 5 | #define __CFG_H |
6 | 6 | ||
7 | extern struct cfg80211_ops mac80211_config_ops; | 7 | extern const struct cfg80211_ops mac80211_config_ops; |
8 | 8 | ||
9 | #endif /* __CFG_H */ | 9 | #endif /* __CFG_H */ |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f43613a97dd6..42c659229a09 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required(struct ieee80211_local *local) | |||
196 | { | 196 | { |
197 | struct ieee80211_sub_if_data *sdata; | 197 | struct ieee80211_sub_if_data *sdata; |
198 | 198 | ||
199 | lockdep_assert_held(&local->mtx); | ||
200 | |||
199 | rcu_read_lock(); | 201 | rcu_read_lock(); |
200 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 202 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
201 | if (sdata->radar_required) { | 203 | if (sdata->radar_required) { |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 80194b557a0c..2ecb4deddb5d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -195,7 +195,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
195 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, | 195 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, |
196 | size_t count, loff_t *ppos) | 196 | size_t count, loff_t *ppos) |
197 | { | 197 | { |
198 | char _buf[12], *buf = _buf; | 198 | char _buf[12] = {}, *buf = _buf; |
199 | struct sta_info *sta = file->private_data; | 199 | struct sta_info *sta = file->private_data; |
200 | bool start, tx; | 200 | bool start, tx; |
201 | unsigned long tid; | 201 | unsigned long tid; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index fab7b91923e0..dc3c28002e3e 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
375 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 375 | mgmt->u.action.u.delba.params = cpu_to_le16(params); |
376 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 376 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); |
377 | 377 | ||
378 | ieee80211_tx_skb_tid(sdata, skb, tid); | 378 | ieee80211_tx_skb(sdata, skb); |
379 | } | 379 | } |
380 | 380 | ||
381 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 381 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 771080ec7212..9c84b75f3de8 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -220,7 +220,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
220 | { | 220 | { |
221 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 221 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
222 | struct ieee80211_local *local = sdata->local; | 222 | struct ieee80211_local *local = sdata->local; |
223 | struct ieee80211_supported_band *sband; | ||
224 | struct ieee80211_mgmt *mgmt; | 223 | struct ieee80211_mgmt *mgmt; |
225 | struct cfg80211_bss *bss; | 224 | struct cfg80211_bss *bss; |
226 | u32 bss_change; | 225 | u32 bss_change; |
@@ -294,7 +293,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
294 | } | 293 | } |
295 | 294 | ||
296 | mutex_lock(&local->mtx); | 295 | mutex_lock(&local->mtx); |
297 | ieee80211_vif_release_channel(sdata); | ||
298 | if (ieee80211_vif_use_channel(sdata, &chandef, | 296 | if (ieee80211_vif_use_channel(sdata, &chandef, |
299 | ifibss->fixed_channel ? | 297 | ifibss->fixed_channel ? |
300 | IEEE80211_CHANCTX_SHARED : | 298 | IEEE80211_CHANCTX_SHARED : |
@@ -303,12 +301,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
303 | mutex_unlock(&local->mtx); | 301 | mutex_unlock(&local->mtx); |
304 | return; | 302 | return; |
305 | } | 303 | } |
304 | sdata->radar_required = radar_required; | ||
306 | mutex_unlock(&local->mtx); | 305 | mutex_unlock(&local->mtx); |
307 | 306 | ||
308 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 307 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
309 | 308 | ||
310 | sband = local->hw.wiphy->bands[chan->band]; | ||
311 | |||
312 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, | 309 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, |
313 | capability, tsf, &chandef, | 310 | capability, tsf, &chandef, |
314 | &have_higher_than_11mbit, NULL); | 311 | &have_higher_than_11mbit, NULL); |
@@ -318,7 +315,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
318 | rcu_assign_pointer(ifibss->presp, presp); | 315 | rcu_assign_pointer(ifibss->presp, presp); |
319 | mgmt = (void *)presp->head; | 316 | mgmt = (void *)presp->head; |
320 | 317 | ||
321 | sdata->radar_required = radar_required; | ||
322 | sdata->vif.bss_conf.enable_beacon = true; | 318 | sdata->vif.bss_conf.enable_beacon = true; |
323 | sdata->vif.bss_conf.beacon_int = beacon_int; | 319 | sdata->vif.bss_conf.beacon_int = beacon_int; |
324 | sdata->vif.bss_conf.basic_rates = basic_rates; | 320 | sdata->vif.bss_conf.basic_rates = basic_rates; |
@@ -386,7 +382,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
386 | presp->head_len, 0, GFP_KERNEL); | 382 | presp->head_len, 0, GFP_KERNEL); |
387 | cfg80211_put_bss(local->hw.wiphy, bss); | 383 | cfg80211_put_bss(local->hw.wiphy, bss); |
388 | netif_carrier_on(sdata->dev); | 384 | netif_carrier_on(sdata->dev); |
389 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 385 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL); |
390 | } | 386 | } |
391 | 387 | ||
392 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 388 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
@@ -521,12 +517,6 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
521 | if (old_presp) | 517 | if (old_presp) |
522 | kfree_rcu(old_presp, rcu_head); | 518 | kfree_rcu(old_presp, rcu_head); |
523 | 519 | ||
524 | /* it might not send the beacon for a while. send an action frame | ||
525 | * immediately to announce the channel switch. | ||
526 | */ | ||
527 | if (csa_settings) | ||
528 | ieee80211_send_action_csa(sdata, csa_settings); | ||
529 | |||
530 | return BSS_CHANGED_BEACON; | 520 | return BSS_CHANGED_BEACON; |
531 | out: | 521 | out: |
532 | return ret; | 522 | return ret; |
@@ -536,7 +526,7 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
536 | { | 526 | { |
537 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 527 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
538 | struct cfg80211_bss *cbss; | 528 | struct cfg80211_bss *cbss; |
539 | int err; | 529 | int err, changed = 0; |
540 | u16 capability; | 530 | u16 capability; |
541 | 531 | ||
542 | sdata_assert_lock(sdata); | 532 | sdata_assert_lock(sdata); |
@@ -568,10 +558,9 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
568 | if (err < 0) | 558 | if (err < 0) |
569 | return err; | 559 | return err; |
570 | 560 | ||
571 | if (err) | 561 | changed |= err; |
572 | ieee80211_bss_info_change_notify(sdata, err); | ||
573 | 562 | ||
574 | return 0; | 563 | return changed; |
575 | } | 564 | } |
576 | 565 | ||
577 | void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) | 566 | void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) |
@@ -802,6 +791,8 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
802 | int err; | 791 | int err; |
803 | u32 sta_flags; | 792 | u32 sta_flags; |
804 | 793 | ||
794 | sdata_assert_lock(sdata); | ||
795 | |||
805 | sta_flags = IEEE80211_STA_DISABLE_VHT; | 796 | sta_flags = IEEE80211_STA_DISABLE_VHT; |
806 | switch (ifibss->chandef.width) { | 797 | switch (ifibss->chandef.width) { |
807 | case NL80211_CHAN_WIDTH_5: | 798 | case NL80211_CHAN_WIDTH_5: |
@@ -1471,6 +1462,11 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1471 | memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); | 1462 | memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); |
1472 | ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); | 1463 | ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); |
1473 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1464 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1465 | |||
1466 | /* avoid excessive retries for probe request to wildcard SSIDs */ | ||
1467 | if (pos[1] == 0) | ||
1468 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1469 | |||
1474 | ieee80211_tx_skb(sdata, skb); | 1470 | ieee80211_tx_skb(sdata, skb); |
1475 | } | 1471 | } |
1476 | 1472 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3701930c6649..0014b5396ce5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -616,7 +616,11 @@ struct ieee80211_if_mesh { | |||
616 | struct ps_data ps; | 616 | struct ps_data ps; |
617 | /* Channel Switching Support */ | 617 | /* Channel Switching Support */ |
618 | struct mesh_csa_settings __rcu *csa; | 618 | struct mesh_csa_settings __rcu *csa; |
619 | bool chsw_init; | 619 | enum { |
620 | IEEE80211_MESH_CSA_ROLE_NONE, | ||
621 | IEEE80211_MESH_CSA_ROLE_INIT, | ||
622 | IEEE80211_MESH_CSA_ROLE_REPEATER, | ||
623 | } csa_role; | ||
620 | u8 chsw_ttl; | 624 | u8 chsw_ttl; |
621 | u16 pre_value; | 625 | u16 pre_value; |
622 | 626 | ||
@@ -1408,8 +1412,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); | |||
1408 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1412 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1409 | struct sk_buff *skb); | 1413 | struct sk_buff *skb); |
1410 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | 1414 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, |
1411 | struct cfg80211_csa_settings *csa_settings, | 1415 | struct cfg80211_csa_settings *csa_settings); |
1412 | bool csa_action); | ||
1413 | int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata); | 1416 | int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata); |
1414 | 1417 | ||
1415 | /* scan/BSS handling */ | 1418 | /* scan/BSS handling */ |
@@ -1553,6 +1556,9 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
1553 | struct sta_info *sta); | 1556 | struct sta_info *sta); |
1554 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); | 1557 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); |
1555 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); | 1558 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); |
1559 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | ||
1560 | struct sta_info *sta, u8 opmode, | ||
1561 | enum ieee80211_band band, bool nss_only); | ||
1556 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1562 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
1557 | struct sta_info *sta, u8 opmode, | 1563 | struct sta_info *sta, u8 opmode, |
1558 | enum ieee80211_band band, bool nss_only); | 1564 | enum ieee80211_band band, bool nss_only); |
@@ -1605,7 +1611,7 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) | |||
1605 | } | 1611 | } |
1606 | 1612 | ||
1607 | /* utility functions/constants */ | 1613 | /* utility functions/constants */ |
1608 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 1614 | extern const void *const mac80211_wiphy_privid; /* for wiphy privid */ |
1609 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 1615 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
1610 | enum nl80211_iftype type); | 1616 | enum nl80211_iftype type); |
1611 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | 1617 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3dfd20a453ab..8880bc8fce0d 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -822,7 +822,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
822 | cancel_work_sync(&local->dynamic_ps_enable_work); | 822 | cancel_work_sync(&local->dynamic_ps_enable_work); |
823 | 823 | ||
824 | cancel_work_sync(&sdata->recalc_smps); | 824 | cancel_work_sync(&sdata->recalc_smps); |
825 | sdata_lock(sdata); | ||
825 | sdata->vif.csa_active = false; | 826 | sdata->vif.csa_active = false; |
827 | sdata_unlock(sdata); | ||
826 | cancel_work_sync(&sdata->csa_finalize_work); | 828 | cancel_work_sync(&sdata->csa_finalize_work); |
827 | 829 | ||
828 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 830 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d767cfb9b45f..1f7d8422d62d 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -893,10 +893,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
893 | /* mac80211 supports control port protocol changing */ | 893 | /* mac80211 supports control port protocol changing */ |
894 | local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; | 894 | local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; |
895 | 895 | ||
896 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 896 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { |
897 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 897 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
898 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 898 | } else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) { |
899 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; | 899 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; |
900 | if (hw->max_signal <= 0) { | ||
901 | result = -EINVAL; | ||
902 | goto fail_wiphy_register; | ||
903 | } | ||
904 | } | ||
900 | 905 | ||
901 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | 906 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) |
902 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), | 907 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 5b919cab1de0..f70e9cd10552 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -688,7 +688,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
688 | *pos++ = csa->settings.count; | 688 | *pos++ = csa->settings.count; |
689 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; | 689 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; |
690 | *pos++ = 6; | 690 | *pos++ = 6; |
691 | if (ifmsh->chsw_init) { | 691 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) { |
692 | *pos++ = ifmsh->mshcfg.dot11MeshTTL; | 692 | *pos++ = ifmsh->mshcfg.dot11MeshTTL; |
693 | *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; | 693 | *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; |
694 | } else { | 694 | } else { |
@@ -859,18 +859,12 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
859 | { | 859 | { |
860 | struct cfg80211_csa_settings params; | 860 | struct cfg80211_csa_settings params; |
861 | struct ieee80211_csa_ie csa_ie; | 861 | struct ieee80211_csa_ie csa_ie; |
862 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
863 | struct ieee80211_chanctx *chanctx; | ||
864 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 862 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
865 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 863 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
866 | int err, num_chanctx; | 864 | int err; |
867 | u32 sta_flags; | 865 | u32 sta_flags; |
868 | 866 | ||
869 | if (sdata->vif.csa_active) | 867 | sdata_assert_lock(sdata); |
870 | return true; | ||
871 | |||
872 | if (!ifmsh->mesh_id) | ||
873 | return false; | ||
874 | 868 | ||
875 | sta_flags = IEEE80211_STA_DISABLE_VHT; | 869 | sta_flags = IEEE80211_STA_DISABLE_VHT; |
876 | switch (sdata->vif.bss_conf.chandef.width) { | 870 | switch (sdata->vif.bss_conf.chandef.width) { |
@@ -896,10 +890,6 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
896 | params.chandef = csa_ie.chandef; | 890 | params.chandef = csa_ie.chandef; |
897 | params.count = csa_ie.count; | 891 | params.count = csa_ie.count; |
898 | 892 | ||
899 | if (sdata->vif.bss_conf.chandef.chan->band != | ||
900 | params.chandef.chan->band) | ||
901 | return false; | ||
902 | |||
903 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, | 893 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, |
904 | IEEE80211_CHAN_DISABLED)) { | 894 | IEEE80211_CHAN_DISABLED)) { |
905 | sdata_info(sdata, | 895 | sdata_info(sdata, |
@@ -922,24 +912,12 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
922 | return false; | 912 | return false; |
923 | } | 913 | } |
924 | 914 | ||
925 | rcu_read_lock(); | 915 | if (cfg80211_chandef_identical(¶ms.chandef, |
926 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 916 | &sdata->vif.bss_conf.chandef)) { |
927 | if (!chanctx_conf) | 917 | mcsa_dbg(sdata, |
928 | goto failed_chswitch; | 918 | "received csa with an identical chandef, ignoring\n"); |
929 | 919 | return true; | |
930 | /* don't handle for multi-VIF cases */ | 920 | } |
931 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
932 | if (chanctx->refcount > 1) | ||
933 | goto failed_chswitch; | ||
934 | |||
935 | num_chanctx = 0; | ||
936 | list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) | ||
937 | num_chanctx++; | ||
938 | |||
939 | if (num_chanctx > 1) | ||
940 | goto failed_chswitch; | ||
941 | |||
942 | rcu_read_unlock(); | ||
943 | 921 | ||
944 | mcsa_dbg(sdata, | 922 | mcsa_dbg(sdata, |
945 | "received channel switch announcement to go to channel %d MHz\n", | 923 | "received channel switch announcement to go to channel %d MHz\n", |
@@ -953,30 +931,16 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
953 | ifmsh->pre_value = csa_ie.pre_value; | 931 | ifmsh->pre_value = csa_ie.pre_value; |
954 | } | 932 | } |
955 | 933 | ||
956 | if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) { | 934 | if (ifmsh->chsw_ttl >= ifmsh->mshcfg.dot11MeshTTL) |
957 | if (ieee80211_mesh_csa_beacon(sdata, ¶ms, false) < 0) | ||
958 | return false; | ||
959 | } else { | ||
960 | return false; | 935 | return false; |
961 | } | ||
962 | 936 | ||
963 | sdata->csa_radar_required = params.radar_required; | 937 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER; |
964 | 938 | ||
965 | if (params.block_tx) | 939 | if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev, |
966 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 940 | ¶ms) < 0) |
967 | IEEE80211_MAX_QUEUE_MAP, | 941 | return false; |
968 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
969 | |||
970 | sdata->csa_chandef = params.chandef; | ||
971 | sdata->vif.csa_active = true; | ||
972 | |||
973 | ieee80211_bss_info_change_notify(sdata, err); | ||
974 | drv_channel_switch_beacon(sdata, ¶ms.chandef); | ||
975 | 942 | ||
976 | return true; | 943 | return true; |
977 | failed_chswitch: | ||
978 | rcu_read_unlock(); | ||
979 | return false; | ||
980 | } | 944 | } |
981 | 945 | ||
982 | static void | 946 | static void |
@@ -1086,7 +1050,8 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
1086 | ifmsh->sync_ops->rx_bcn_presp(sdata, | 1050 | ifmsh->sync_ops->rx_bcn_presp(sdata, |
1087 | stype, mgmt, &elems, rx_status); | 1051 | stype, mgmt, &elems, rx_status); |
1088 | 1052 | ||
1089 | if (!ifmsh->chsw_init) | 1053 | if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT && |
1054 | !sdata->vif.csa_active) | ||
1090 | ieee80211_mesh_process_chnswitch(sdata, &elems, true); | 1055 | ieee80211_mesh_process_chnswitch(sdata, &elems, true); |
1091 | } | 1056 | } |
1092 | 1057 | ||
@@ -1095,29 +1060,30 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
1095 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1060 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1096 | struct mesh_csa_settings *tmp_csa_settings; | 1061 | struct mesh_csa_settings *tmp_csa_settings; |
1097 | int ret = 0; | 1062 | int ret = 0; |
1063 | int changed = 0; | ||
1098 | 1064 | ||
1099 | /* Reset the TTL value and Initiator flag */ | 1065 | /* Reset the TTL value and Initiator flag */ |
1100 | ifmsh->chsw_init = false; | 1066 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; |
1101 | ifmsh->chsw_ttl = 0; | 1067 | ifmsh->chsw_ttl = 0; |
1102 | 1068 | ||
1103 | /* Remove the CSA and MCSP elements from the beacon */ | 1069 | /* Remove the CSA and MCSP elements from the beacon */ |
1104 | tmp_csa_settings = rcu_dereference(ifmsh->csa); | 1070 | tmp_csa_settings = rcu_dereference(ifmsh->csa); |
1105 | rcu_assign_pointer(ifmsh->csa, NULL); | 1071 | rcu_assign_pointer(ifmsh->csa, NULL); |
1106 | kfree_rcu(tmp_csa_settings, rcu_head); | 1072 | if (tmp_csa_settings) |
1073 | kfree_rcu(tmp_csa_settings, rcu_head); | ||
1107 | ret = ieee80211_mesh_rebuild_beacon(sdata); | 1074 | ret = ieee80211_mesh_rebuild_beacon(sdata); |
1108 | if (ret) | 1075 | if (ret) |
1109 | return -EINVAL; | 1076 | return -EINVAL; |
1110 | 1077 | ||
1111 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 1078 | changed |= BSS_CHANGED_BEACON; |
1112 | 1079 | ||
1113 | mcsa_dbg(sdata, "complete switching to center freq %d MHz", | 1080 | mcsa_dbg(sdata, "complete switching to center freq %d MHz", |
1114 | sdata->vif.bss_conf.chandef.chan->center_freq); | 1081 | sdata->vif.bss_conf.chandef.chan->center_freq); |
1115 | return 0; | 1082 | return changed; |
1116 | } | 1083 | } |
1117 | 1084 | ||
1118 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | 1085 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, |
1119 | struct cfg80211_csa_settings *csa_settings, | 1086 | struct cfg80211_csa_settings *csa_settings) |
1120 | bool csa_action) | ||
1121 | { | 1087 | { |
1122 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1088 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1123 | struct mesh_csa_settings *tmp_csa_settings; | 1089 | struct mesh_csa_settings *tmp_csa_settings; |
@@ -1141,12 +1107,7 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
1141 | return ret; | 1107 | return ret; |
1142 | } | 1108 | } |
1143 | 1109 | ||
1144 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 1110 | return BSS_CHANGED_BEACON; |
1145 | |||
1146 | if (csa_action) | ||
1147 | ieee80211_send_action_csa(sdata, csa_settings); | ||
1148 | |||
1149 | return 0; | ||
1150 | } | 1111 | } |
1151 | 1112 | ||
1152 | static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, | 1113 | static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, |
@@ -1210,7 +1171,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, | |||
1210 | 1171 | ||
1211 | ifmsh->pre_value = pre_value; | 1172 | ifmsh->pre_value = pre_value; |
1212 | 1173 | ||
1213 | if (!ieee80211_mesh_process_chnswitch(sdata, &elems, false)) { | 1174 | if (!sdata->vif.csa_active && |
1175 | !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) { | ||
1214 | mcsa_dbg(sdata, "Failed to process CSA action frame"); | 1176 | mcsa_dbg(sdata, "Failed to process CSA action frame"); |
1215 | return; | 1177 | return; |
1216 | } | 1178 | } |
@@ -1257,7 +1219,7 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1257 | sdata_lock(sdata); | 1219 | sdata_lock(sdata); |
1258 | 1220 | ||
1259 | /* mesh already went down */ | 1221 | /* mesh already went down */ |
1260 | if (!sdata->wdev.mesh_id_len) | 1222 | if (!sdata->u.mesh.mesh_id_len) |
1261 | goto out; | 1223 | goto out; |
1262 | 1224 | ||
1263 | rx_status = IEEE80211_SKB_RXCB(skb); | 1225 | rx_status = IEEE80211_SKB_RXCB(skb); |
@@ -1310,7 +1272,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
1310 | sdata_lock(sdata); | 1272 | sdata_lock(sdata); |
1311 | 1273 | ||
1312 | /* mesh already went down */ | 1274 | /* mesh already went down */ |
1313 | if (!sdata->wdev.mesh_id_len) | 1275 | if (!sdata->u.mesh.mesh_id_len) |
1314 | goto out; | 1276 | goto out; |
1315 | 1277 | ||
1316 | if (ifmsh->preq_queue_len && | 1278 | if (ifmsh->preq_queue_len && |
@@ -1365,7 +1327,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
1365 | mesh_rmc_init(sdata); | 1327 | mesh_rmc_init(sdata); |
1366 | ifmsh->last_preq = jiffies; | 1328 | ifmsh->last_preq = jiffies; |
1367 | ifmsh->next_perr = jiffies; | 1329 | ifmsh->next_perr = jiffies; |
1368 | ifmsh->chsw_init = false; | 1330 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; |
1369 | /* Allocate all mesh structures when creating the first mesh interface. */ | 1331 | /* Allocate all mesh structures when creating the first mesh interface. */ |
1370 | if (!mesh_allocated) | 1332 | if (!mesh_allocated) |
1371 | ieee80211s_init(); | 1333 | ieee80211s_init(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fc1d82465b3c..61604834b914 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -508,6 +508,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
508 | u8 *pos; | 508 | u8 *pos; |
509 | u32 cap; | 509 | u32 cap; |
510 | struct ieee80211_sta_vht_cap vht_cap; | 510 | struct ieee80211_sta_vht_cap vht_cap; |
511 | u32 mask, ap_bf_sts, our_bf_sts; | ||
511 | 512 | ||
512 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); | 513 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); |
513 | 514 | ||
@@ -535,6 +536,16 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
535 | cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE))) | 536 | cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE))) |
536 | cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | 537 | cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; |
537 | 538 | ||
539 | mask = IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; | ||
540 | |||
541 | ap_bf_sts = le32_to_cpu(ap_vht_cap->vht_cap_info) & mask; | ||
542 | our_bf_sts = cap & mask; | ||
543 | |||
544 | if (ap_bf_sts < our_bf_sts) { | ||
545 | cap &= ~mask; | ||
546 | cap |= ap_bf_sts; | ||
547 | } | ||
548 | |||
538 | /* reserve and fill IE */ | 549 | /* reserve and fill IE */ |
539 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); | 550 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); |
540 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); | 551 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); |
@@ -745,6 +756,34 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
745 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 756 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
746 | sband, chan, sdata->smps_mode); | 757 | sband, chan, sdata->smps_mode); |
747 | 758 | ||
759 | /* if present, add any custom IEs that go before VHT */ | ||
760 | if (assoc_data->ie_len) { | ||
761 | static const u8 before_vht[] = { | ||
762 | WLAN_EID_SSID, | ||
763 | WLAN_EID_SUPP_RATES, | ||
764 | WLAN_EID_EXT_SUPP_RATES, | ||
765 | WLAN_EID_PWR_CAPABILITY, | ||
766 | WLAN_EID_SUPPORTED_CHANNELS, | ||
767 | WLAN_EID_RSN, | ||
768 | WLAN_EID_QOS_CAPA, | ||
769 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
770 | WLAN_EID_MOBILITY_DOMAIN, | ||
771 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
772 | WLAN_EID_HT_CAPABILITY, | ||
773 | WLAN_EID_BSS_COEX_2040, | ||
774 | WLAN_EID_EXT_CAPABILITY, | ||
775 | WLAN_EID_QOS_TRAFFIC_CAPA, | ||
776 | WLAN_EID_TIM_BCAST_REQ, | ||
777 | WLAN_EID_INTERWORKING, | ||
778 | }; | ||
779 | noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, | ||
780 | before_vht, ARRAY_SIZE(before_vht), | ||
781 | offset); | ||
782 | pos = skb_put(skb, noffset - offset); | ||
783 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | ||
784 | offset = noffset; | ||
785 | } | ||
786 | |||
748 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | 787 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
749 | ieee80211_add_vht_ie(sdata, skb, sband, | 788 | ieee80211_add_vht_ie(sdata, skb, sband, |
750 | &assoc_data->ap_vht_cap); | 789 | &assoc_data->ap_vht_cap); |
@@ -1001,7 +1040,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1001 | } | 1040 | } |
1002 | 1041 | ||
1003 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | 1042 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; |
1004 | sdata->vif.csa_active = true; | ||
1005 | 1043 | ||
1006 | mutex_lock(&local->chanctx_mtx); | 1044 | mutex_lock(&local->chanctx_mtx); |
1007 | if (local->use_chanctx) { | 1045 | if (local->use_chanctx) { |
@@ -1039,6 +1077,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1039 | mutex_unlock(&local->chanctx_mtx); | 1077 | mutex_unlock(&local->chanctx_mtx); |
1040 | 1078 | ||
1041 | sdata->csa_chandef = csa_ie.chandef; | 1079 | sdata->csa_chandef = csa_ie.chandef; |
1080 | sdata->vif.csa_active = true; | ||
1042 | 1081 | ||
1043 | if (csa_ie.mode) | 1082 | if (csa_ie.mode) |
1044 | ieee80211_stop_queues_by_reason(&local->hw, | 1083 | ieee80211_stop_queues_by_reason(&local->hw, |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 22b223f13c9f..8fdadfd94ba8 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -10,15 +10,15 @@ | |||
10 | 10 | ||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/slab.h> | ||
15 | #include "rate.h" | 15 | #include "rate.h" |
16 | #include "ieee80211_i.h" | 16 | #include "ieee80211_i.h" |
17 | #include "debugfs.h" | 17 | #include "debugfs.h" |
18 | 18 | ||
19 | struct rate_control_alg { | 19 | struct rate_control_alg { |
20 | struct list_head list; | 20 | struct list_head list; |
21 | struct rate_control_ops *ops; | 21 | const struct rate_control_ops *ops; |
22 | }; | 22 | }; |
23 | 23 | ||
24 | static LIST_HEAD(rate_ctrl_algs); | 24 | static LIST_HEAD(rate_ctrl_algs); |
@@ -29,7 +29,7 @@ module_param(ieee80211_default_rc_algo, charp, 0644); | |||
29 | MODULE_PARM_DESC(ieee80211_default_rc_algo, | 29 | MODULE_PARM_DESC(ieee80211_default_rc_algo, |
30 | "Default rate control algorithm for mac80211 to use"); | 30 | "Default rate control algorithm for mac80211 to use"); |
31 | 31 | ||
32 | int ieee80211_rate_control_register(struct rate_control_ops *ops) | 32 | int ieee80211_rate_control_register(const struct rate_control_ops *ops) |
33 | { | 33 | { |
34 | struct rate_control_alg *alg; | 34 | struct rate_control_alg *alg; |
35 | 35 | ||
@@ -60,7 +60,7 @@ int ieee80211_rate_control_register(struct rate_control_ops *ops) | |||
60 | } | 60 | } |
61 | EXPORT_SYMBOL(ieee80211_rate_control_register); | 61 | EXPORT_SYMBOL(ieee80211_rate_control_register); |
62 | 62 | ||
63 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops) | 63 | void ieee80211_rate_control_unregister(const struct rate_control_ops *ops) |
64 | { | 64 | { |
65 | struct rate_control_alg *alg; | 65 | struct rate_control_alg *alg; |
66 | 66 | ||
@@ -76,32 +76,31 @@ void ieee80211_rate_control_unregister(struct rate_control_ops *ops) | |||
76 | } | 76 | } |
77 | EXPORT_SYMBOL(ieee80211_rate_control_unregister); | 77 | EXPORT_SYMBOL(ieee80211_rate_control_unregister); |
78 | 78 | ||
79 | static struct rate_control_ops * | 79 | static const struct rate_control_ops * |
80 | ieee80211_try_rate_control_ops_get(const char *name) | 80 | ieee80211_try_rate_control_ops_get(const char *name) |
81 | { | 81 | { |
82 | struct rate_control_alg *alg; | 82 | struct rate_control_alg *alg; |
83 | struct rate_control_ops *ops = NULL; | 83 | const struct rate_control_ops *ops = NULL; |
84 | 84 | ||
85 | if (!name) | 85 | if (!name) |
86 | return NULL; | 86 | return NULL; |
87 | 87 | ||
88 | mutex_lock(&rate_ctrl_mutex); | 88 | mutex_lock(&rate_ctrl_mutex); |
89 | list_for_each_entry(alg, &rate_ctrl_algs, list) { | 89 | list_for_each_entry(alg, &rate_ctrl_algs, list) { |
90 | if (!strcmp(alg->ops->name, name)) | 90 | if (!strcmp(alg->ops->name, name)) { |
91 | if (try_module_get(alg->ops->module)) { | 91 | ops = alg->ops; |
92 | ops = alg->ops; | 92 | break; |
93 | break; | 93 | } |
94 | } | ||
95 | } | 94 | } |
96 | mutex_unlock(&rate_ctrl_mutex); | 95 | mutex_unlock(&rate_ctrl_mutex); |
97 | return ops; | 96 | return ops; |
98 | } | 97 | } |
99 | 98 | ||
100 | /* Get the rate control algorithm. */ | 99 | /* Get the rate control algorithm. */ |
101 | static struct rate_control_ops * | 100 | static const struct rate_control_ops * |
102 | ieee80211_rate_control_ops_get(const char *name) | 101 | ieee80211_rate_control_ops_get(const char *name) |
103 | { | 102 | { |
104 | struct rate_control_ops *ops; | 103 | const struct rate_control_ops *ops; |
105 | const char *alg_name; | 104 | const char *alg_name; |
106 | 105 | ||
107 | kparam_block_sysfs_write(ieee80211_default_rc_algo); | 106 | kparam_block_sysfs_write(ieee80211_default_rc_algo); |
@@ -111,10 +110,6 @@ ieee80211_rate_control_ops_get(const char *name) | |||
111 | alg_name = name; | 110 | alg_name = name; |
112 | 111 | ||
113 | ops = ieee80211_try_rate_control_ops_get(alg_name); | 112 | ops = ieee80211_try_rate_control_ops_get(alg_name); |
114 | if (!ops) { | ||
115 | request_module("rc80211_%s", alg_name); | ||
116 | ops = ieee80211_try_rate_control_ops_get(alg_name); | ||
117 | } | ||
118 | if (!ops && name) | 113 | if (!ops && name) |
119 | /* try default if specific alg requested but not found */ | 114 | /* try default if specific alg requested but not found */ |
120 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); | 115 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); |
@@ -127,11 +122,6 @@ ieee80211_rate_control_ops_get(const char *name) | |||
127 | return ops; | 122 | return ops; |
128 | } | 123 | } |
129 | 124 | ||
130 | static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) | ||
131 | { | ||
132 | module_put(ops->module); | ||
133 | } | ||
134 | |||
135 | #ifdef CONFIG_MAC80211_DEBUGFS | 125 | #ifdef CONFIG_MAC80211_DEBUGFS |
136 | static ssize_t rcname_read(struct file *file, char __user *userbuf, | 126 | static ssize_t rcname_read(struct file *file, char __user *userbuf, |
137 | size_t count, loff_t *ppos) | 127 | size_t count, loff_t *ppos) |
@@ -158,11 +148,11 @@ static struct rate_control_ref *rate_control_alloc(const char *name, | |||
158 | 148 | ||
159 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 149 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
160 | if (!ref) | 150 | if (!ref) |
161 | goto fail_ref; | 151 | return NULL; |
162 | ref->local = local; | 152 | ref->local = local; |
163 | ref->ops = ieee80211_rate_control_ops_get(name); | 153 | ref->ops = ieee80211_rate_control_ops_get(name); |
164 | if (!ref->ops) | 154 | if (!ref->ops) |
165 | goto fail_ops; | 155 | goto free; |
166 | 156 | ||
167 | #ifdef CONFIG_MAC80211_DEBUGFS | 157 | #ifdef CONFIG_MAC80211_DEBUGFS |
168 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); | 158 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); |
@@ -172,14 +162,11 @@ static struct rate_control_ref *rate_control_alloc(const char *name, | |||
172 | 162 | ||
173 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); | 163 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); |
174 | if (!ref->priv) | 164 | if (!ref->priv) |
175 | goto fail_priv; | 165 | goto free; |
176 | return ref; | 166 | return ref; |
177 | 167 | ||
178 | fail_priv: | 168 | free: |
179 | ieee80211_rate_control_ops_put(ref->ops); | ||
180 | fail_ops: | ||
181 | kfree(ref); | 169 | kfree(ref); |
182 | fail_ref: | ||
183 | return NULL; | 170 | return NULL; |
184 | } | 171 | } |
185 | 172 | ||
@@ -192,7 +179,6 @@ static void rate_control_free(struct rate_control_ref *ctrl_ref) | |||
192 | ctrl_ref->local->debugfs.rcdir = NULL; | 179 | ctrl_ref->local->debugfs.rcdir = NULL; |
193 | #endif | 180 | #endif |
194 | 181 | ||
195 | ieee80211_rate_control_ops_put(ctrl_ref->ops); | ||
196 | kfree(ctrl_ref); | 182 | kfree(ctrl_ref); |
197 | } | 183 | } |
198 | 184 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index b95e16c07081..9aa2a1190a86 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | struct rate_control_ref { | 22 | struct rate_control_ref { |
23 | struct ieee80211_local *local; | 23 | struct ieee80211_local *local; |
24 | struct rate_control_ops *ops; | 24 | const struct rate_control_ops *ops; |
25 | void *priv; | 25 | void *priv; |
26 | }; | 26 | }; |
27 | 27 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index f3d88b0c054c..26fd94fa0aed 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -657,7 +657,7 @@ minstrel_free(void *priv) | |||
657 | kfree(priv); | 657 | kfree(priv); |
658 | } | 658 | } |
659 | 659 | ||
660 | struct rate_control_ops mac80211_minstrel = { | 660 | const struct rate_control_ops mac80211_minstrel = { |
661 | .name = "minstrel", | 661 | .name = "minstrel", |
662 | .tx_status = minstrel_tx_status, | 662 | .tx_status = minstrel_tx_status, |
663 | .get_rate = minstrel_get_rate, | 663 | .get_rate = minstrel_get_rate, |
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index f4301f4b2e41..046d1bd598a8 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -123,7 +123,7 @@ struct minstrel_debugfs_info { | |||
123 | char buf[]; | 123 | char buf[]; |
124 | }; | 124 | }; |
125 | 125 | ||
126 | extern struct rate_control_ops mac80211_minstrel; | 126 | extern const struct rate_control_ops mac80211_minstrel; |
127 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 127 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
128 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | 128 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); |
129 | 129 | ||
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c1b5b73c5b91..bccaf854a309 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -124,7 +124,7 @@ const struct mcs_group minstrel_mcs_groups[] = { | |||
124 | 124 | ||
125 | #define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1) | 125 | #define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1) |
126 | 126 | ||
127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; | 127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; |
128 | 128 | ||
129 | static void | 129 | static void |
130 | minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); | 130 | minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); |
@@ -1031,7 +1031,7 @@ minstrel_ht_free(void *priv) | |||
1031 | mac80211_minstrel.free(priv); | 1031 | mac80211_minstrel.free(priv); |
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | static struct rate_control_ops mac80211_minstrel_ht = { | 1034 | static const struct rate_control_ops mac80211_minstrel_ht = { |
1035 | .name = "minstrel_ht", | 1035 | .name = "minstrel_ht", |
1036 | .tx_status = minstrel_ht_tx_status, | 1036 | .tx_status = minstrel_ht_tx_status, |
1037 | .get_rate = minstrel_ht_get_rate, | 1037 | .get_rate = minstrel_ht_get_rate, |
@@ -1048,8 +1048,7 @@ static struct rate_control_ops mac80211_minstrel_ht = { | |||
1048 | }; | 1048 | }; |
1049 | 1049 | ||
1050 | 1050 | ||
1051 | static void | 1051 | static void __init init_sample_table(void) |
1052 | init_sample_table(void) | ||
1053 | { | 1052 | { |
1054 | int col, i, new_idx; | 1053 | int col, i, new_idx; |
1055 | u8 rnd[MCS_GROUP_RATES]; | 1054 | u8 rnd[MCS_GROUP_RATES]; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 958fad07b54c..d0da2a70fe68 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -452,7 +452,7 @@ static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, | |||
452 | kfree(priv_sta); | 452 | kfree(priv_sta); |
453 | } | 453 | } |
454 | 454 | ||
455 | static struct rate_control_ops mac80211_rcpid = { | 455 | static const struct rate_control_ops mac80211_rcpid = { |
456 | .name = "pid", | 456 | .name = "pid", |
457 | .tx_status = rate_control_pid_tx_status, | 457 | .tx_status = rate_control_pid_tx_status, |
458 | .get_rate = rate_control_pid_get_rate, | 458 | .get_rate = rate_control_pid_get_rate, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c24ca0d0f469..593062109c50 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -40,8 +40,6 @@ | |||
40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | 40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, |
41 | struct sk_buff *skb) | 41 | struct sk_buff *skb) |
42 | { | 42 | { |
43 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
44 | |||
45 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 43 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
46 | if (likely(skb->len > FCS_LEN)) | 44 | if (likely(skb->len > FCS_LEN)) |
47 | __pskb_trim(skb, skb->len - FCS_LEN); | 45 | __pskb_trim(skb, skb->len - FCS_LEN); |
@@ -53,9 +51,6 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
53 | } | 51 | } |
54 | } | 52 | } |
55 | 53 | ||
56 | if (status->vendor_radiotap_len) | ||
57 | __pskb_pull(skb, status->vendor_radiotap_len); | ||
58 | |||
59 | return skb; | 54 | return skb; |
60 | } | 55 | } |
61 | 56 | ||
@@ -64,14 +59,13 @@ static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) | |||
64 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 59 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
65 | struct ieee80211_hdr *hdr; | 60 | struct ieee80211_hdr *hdr; |
66 | 61 | ||
67 | hdr = (void *)(skb->data + status->vendor_radiotap_len); | 62 | hdr = (void *)(skb->data); |
68 | 63 | ||
69 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | | 64 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | |
70 | RX_FLAG_FAILED_PLCP_CRC | | 65 | RX_FLAG_FAILED_PLCP_CRC | |
71 | RX_FLAG_AMPDU_IS_ZEROLEN)) | 66 | RX_FLAG_AMPDU_IS_ZEROLEN)) |
72 | return 1; | 67 | return 1; |
73 | if (unlikely(skb->len < 16 + present_fcs_len + | 68 | if (unlikely(skb->len < 16 + present_fcs_len)) |
74 | status->vendor_radiotap_len)) | ||
75 | return 1; | 69 | return 1; |
76 | if (ieee80211_is_ctl(hdr->frame_control) && | 70 | if (ieee80211_is_ctl(hdr->frame_control) && |
77 | !ieee80211_is_pspoll(hdr->frame_control) && | 71 | !ieee80211_is_pspoll(hdr->frame_control) && |
@@ -90,8 +84,6 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
90 | len = sizeof(struct ieee80211_radiotap_header) + 8; | 84 | len = sizeof(struct ieee80211_radiotap_header) + 8; |
91 | 85 | ||
92 | /* allocate extra bitmaps */ | 86 | /* allocate extra bitmaps */ |
93 | if (status->vendor_radiotap_len) | ||
94 | len += 4; | ||
95 | if (status->chains) | 87 | if (status->chains) |
96 | len += 4 * hweight8(status->chains); | 88 | len += 4 * hweight8(status->chains); |
97 | 89 | ||
@@ -127,18 +119,6 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
127 | len += 2 * hweight8(status->chains); | 119 | len += 2 * hweight8(status->chains); |
128 | } | 120 | } |
129 | 121 | ||
130 | if (status->vendor_radiotap_len) { | ||
131 | if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) | ||
132 | status->vendor_radiotap_align = 1; | ||
133 | /* align standard part of vendor namespace */ | ||
134 | len = ALIGN(len, 2); | ||
135 | /* allocate standard part of vendor namespace */ | ||
136 | len += 6; | ||
137 | /* align vendor-defined part */ | ||
138 | len = ALIGN(len, status->vendor_radiotap_align); | ||
139 | /* vendor-defined part is already in skb */ | ||
140 | } | ||
141 | |||
142 | return len; | 122 | return len; |
143 | } | 123 | } |
144 | 124 | ||
@@ -172,7 +152,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
172 | it_present = &rthdr->it_present; | 152 | it_present = &rthdr->it_present; |
173 | 153 | ||
174 | /* radiotap header, set always present flags */ | 154 | /* radiotap header, set always present flags */ |
175 | rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len); | 155 | rthdr->it_len = cpu_to_le16(rtap_len); |
176 | it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) | | 156 | it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) | |
177 | BIT(IEEE80211_RADIOTAP_CHANNEL) | | 157 | BIT(IEEE80211_RADIOTAP_CHANNEL) | |
178 | BIT(IEEE80211_RADIOTAP_RX_FLAGS); | 158 | BIT(IEEE80211_RADIOTAP_RX_FLAGS); |
@@ -190,14 +170,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
190 | BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); | 170 | BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); |
191 | } | 171 | } |
192 | 172 | ||
193 | if (status->vendor_radiotap_len) { | ||
194 | it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | | ||
195 | BIT(IEEE80211_RADIOTAP_EXT); | ||
196 | put_unaligned_le32(it_present_val, it_present); | ||
197 | it_present++; | ||
198 | it_present_val = status->vendor_radiotap_bitmap; | ||
199 | } | ||
200 | |||
201 | put_unaligned_le32(it_present_val, it_present); | 173 | put_unaligned_le32(it_present_val, it_present); |
202 | 174 | ||
203 | pos = (void *)(it_present + 1); | 175 | pos = (void *)(it_present + 1); |
@@ -307,6 +279,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
307 | *pos |= IEEE80211_RADIOTAP_MCS_BW_40; | 279 | *pos |= IEEE80211_RADIOTAP_MCS_BW_40; |
308 | if (status->flag & RX_FLAG_HT_GF) | 280 | if (status->flag & RX_FLAG_HT_GF) |
309 | *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; | 281 | *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; |
282 | if (status->flag & RX_FLAG_LDPC) | ||
283 | *pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC; | ||
310 | stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT; | 284 | stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT; |
311 | *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; | 285 | *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; |
312 | pos++; | 286 | pos++; |
@@ -349,20 +323,23 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
349 | 323 | ||
350 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); | 324 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); |
351 | /* known field - how to handle 80+80? */ | 325 | /* known field - how to handle 80+80? */ |
352 | if (status->flag & RX_FLAG_80P80MHZ) | 326 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
353 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | 327 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; |
354 | put_unaligned_le16(known, pos); | 328 | put_unaligned_le16(known, pos); |
355 | pos += 2; | 329 | pos += 2; |
356 | /* flags */ | 330 | /* flags */ |
357 | if (status->flag & RX_FLAG_SHORT_GI) | 331 | if (status->flag & RX_FLAG_SHORT_GI) |
358 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; | 332 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; |
333 | /* in VHT, STBC is binary */ | ||
334 | if (status->flag & RX_FLAG_STBC_MASK) | ||
335 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; | ||
359 | pos++; | 336 | pos++; |
360 | /* bandwidth */ | 337 | /* bandwidth */ |
361 | if (status->flag & RX_FLAG_80MHZ) | 338 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
362 | *pos++ = 4; | 339 | *pos++ = 4; |
363 | else if (status->flag & RX_FLAG_80P80MHZ) | 340 | else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
364 | *pos++ = 0; /* marked not known above */ | 341 | *pos++ = 0; /* marked not known above */ |
365 | else if (status->flag & RX_FLAG_160MHZ) | 342 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
366 | *pos++ = 11; | 343 | *pos++ = 11; |
367 | else if (status->flag & RX_FLAG_40MHZ) | 344 | else if (status->flag & RX_FLAG_40MHZ) |
368 | *pos++ = 1; | 345 | *pos++ = 1; |
@@ -372,6 +349,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
372 | *pos = (status->rate_idx << 4) | status->vht_nss; | 349 | *pos = (status->rate_idx << 4) | status->vht_nss; |
373 | pos += 4; | 350 | pos += 4; |
374 | /* coding field */ | 351 | /* coding field */ |
352 | if (status->flag & RX_FLAG_LDPC) | ||
353 | *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; | ||
375 | pos++; | 354 | pos++; |
376 | /* group ID */ | 355 | /* group ID */ |
377 | pos++; | 356 | pos++; |
@@ -383,21 +362,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
383 | *pos++ = status->chain_signal[chain]; | 362 | *pos++ = status->chain_signal[chain]; |
384 | *pos++ = chain; | 363 | *pos++ = chain; |
385 | } | 364 | } |
386 | |||
387 | if (status->vendor_radiotap_len) { | ||
388 | /* ensure 2 byte alignment for the vendor field as required */ | ||
389 | if ((pos - (u8 *)rthdr) & 1) | ||
390 | *pos++ = 0; | ||
391 | *pos++ = status->vendor_radiotap_oui[0]; | ||
392 | *pos++ = status->vendor_radiotap_oui[1]; | ||
393 | *pos++ = status->vendor_radiotap_oui[2]; | ||
394 | *pos++ = status->vendor_radiotap_subns; | ||
395 | put_unaligned_le16(status->vendor_radiotap_len, pos); | ||
396 | pos += 2; | ||
397 | /* align the actual payload as requested */ | ||
398 | while ((pos - (u8 *)rthdr) & (status->vendor_radiotap_align - 1)) | ||
399 | *pos++ = 0; | ||
400 | } | ||
401 | } | 365 | } |
402 | 366 | ||
403 | /* | 367 | /* |
@@ -428,8 +392,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
428 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 392 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
429 | present_fcs_len = FCS_LEN; | 393 | present_fcs_len = FCS_LEN; |
430 | 394 | ||
431 | /* ensure hdr->frame_control and vendor radiotap data are in skb head */ | 395 | /* ensure hdr->frame_control is in skb head */ |
432 | if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) { | 396 | if (!pskb_may_pull(origskb, 2)) { |
433 | dev_kfree_skb(origskb); | 397 | dev_kfree_skb(origskb); |
434 | return NULL; | 398 | return NULL; |
435 | } | 399 | } |
@@ -599,10 +563,10 @@ static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) | |||
599 | { | 563 | { |
600 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 564 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
601 | 565 | ||
602 | if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) | 566 | if (is_multicast_ether_addr(hdr->addr1)) |
603 | return 0; | 567 | return 0; |
604 | 568 | ||
605 | return ieee80211_is_robust_mgmt_frame(hdr); | 569 | return ieee80211_is_robust_mgmt_frame(skb); |
606 | } | 570 | } |
607 | 571 | ||
608 | 572 | ||
@@ -610,10 +574,10 @@ static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) | |||
610 | { | 574 | { |
611 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 575 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
612 | 576 | ||
613 | if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) | 577 | if (!is_multicast_ether_addr(hdr->addr1)) |
614 | return 0; | 578 | return 0; |
615 | 579 | ||
616 | return ieee80211_is_robust_mgmt_frame(hdr); | 580 | return ieee80211_is_robust_mgmt_frame(skb); |
617 | } | 581 | } |
618 | 582 | ||
619 | 583 | ||
@@ -626,7 +590,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | |||
626 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) | 590 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) |
627 | return -1; | 591 | return -1; |
628 | 592 | ||
629 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) | 593 | if (!ieee80211_is_robust_mgmt_frame(skb)) |
630 | return -1; /* not a robust management frame */ | 594 | return -1; /* not a robust management frame */ |
631 | 595 | ||
632 | mmie = (struct ieee80211_mmie *) | 596 | mmie = (struct ieee80211_mmie *) |
@@ -1261,6 +1225,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1261 | if (ieee80211_is_data(hdr->frame_control)) { | 1225 | if (ieee80211_is_data(hdr->frame_control)) { |
1262 | sta->last_rx_rate_idx = status->rate_idx; | 1226 | sta->last_rx_rate_idx = status->rate_idx; |
1263 | sta->last_rx_rate_flag = status->flag; | 1227 | sta->last_rx_rate_flag = status->flag; |
1228 | sta->last_rx_rate_vht_flag = status->vht_flag; | ||
1264 | sta->last_rx_rate_vht_nss = status->vht_nss; | 1229 | sta->last_rx_rate_vht_nss = status->vht_nss; |
1265 | } | 1230 | } |
1266 | } | 1231 | } |
@@ -1311,18 +1276,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1311 | !ieee80211_has_morefrags(hdr->frame_control) && | 1276 | !ieee80211_has_morefrags(hdr->frame_control) && |
1312 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | 1277 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && |
1313 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1278 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1314 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 1279 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
1280 | /* PM bit is only checked in frames where it isn't reserved, | ||
1281 | * in AP mode it's reserved in non-bufferable management frames | ||
1282 | * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) | ||
1283 | */ | ||
1284 | (!ieee80211_is_mgmt(hdr->frame_control) || | ||
1285 | ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { | ||
1315 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | 1286 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { |
1316 | /* | 1287 | if (!ieee80211_has_pm(hdr->frame_control)) |
1317 | * Ignore doze->wake transitions that are | ||
1318 | * indicated by non-data frames, the standard | ||
1319 | * is unclear here, but for example going to | ||
1320 | * PS mode and then scanning would cause a | ||
1321 | * doze->wake transition for the probe request, | ||
1322 | * and that is clearly undesirable. | ||
1323 | */ | ||
1324 | if (ieee80211_is_data(hdr->frame_control) && | ||
1325 | !ieee80211_has_pm(hdr->frame_control)) | ||
1326 | sta_ps_end(sta); | 1288 | sta_ps_end(sta); |
1327 | } else { | 1289 | } else { |
1328 | if (ieee80211_has_pm(hdr->frame_control)) | 1290 | if (ieee80211_has_pm(hdr->frame_control)) |
@@ -1845,8 +1807,7 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | |||
1845 | * having configured keys. | 1807 | * having configured keys. |
1846 | */ | 1808 | */ |
1847 | if (unlikely(ieee80211_is_action(fc) && !rx->key && | 1809 | if (unlikely(ieee80211_is_action(fc) && !rx->key && |
1848 | ieee80211_is_robust_mgmt_frame( | 1810 | ieee80211_is_robust_mgmt_frame(rx->skb))) |
1849 | (struct ieee80211_hdr *) rx->skb->data))) | ||
1850 | return -EACCES; | 1811 | return -EACCES; |
1851 | } | 1812 | } |
1852 | 1813 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d77ff7090630..d4d85de0d75d 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -261,6 +261,7 @@ struct ieee80211_tx_latency_stat { | |||
261 | * "the" transmit rate | 261 | * "the" transmit rate |
262 | * @last_rx_rate_idx: rx status rate index of the last data packet | 262 | * @last_rx_rate_idx: rx status rate index of the last data packet |
263 | * @last_rx_rate_flag: rx status flag of the last data packet | 263 | * @last_rx_rate_flag: rx status flag of the last data packet |
264 | * @last_rx_rate_vht_flag: rx status vht flag of the last data packet | ||
264 | * @last_rx_rate_vht_nss: rx status nss of last data packet | 265 | * @last_rx_rate_vht_nss: rx status nss of last data packet |
265 | * @lock: used for locking all fields that require locking, see comments | 266 | * @lock: used for locking all fields that require locking, see comments |
266 | * in the header file. | 267 | * in the header file. |
@@ -397,6 +398,7 @@ struct sta_info { | |||
397 | struct ieee80211_tx_rate last_tx_rate; | 398 | struct ieee80211_tx_rate last_tx_rate; |
398 | int last_rx_rate_idx; | 399 | int last_rx_rate_idx; |
399 | u32 last_rx_rate_flag; | 400 | u32 last_rx_rate_flag; |
401 | u32 last_rx_rate_vht_flag; | ||
400 | u8 last_rx_rate_vht_nss; | 402 | u8 last_rx_rate_vht_nss; |
401 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 403 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
402 | 404 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 1ee85c402439..e6e574a307c8 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -479,7 +479,7 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
479 | u32 msrmnt; | 479 | u32 msrmnt; |
480 | u16 tid; | 480 | u16 tid; |
481 | u8 *qc; | 481 | u8 *qc; |
482 | int i, bin_range_count, bin_count; | 482 | int i, bin_range_count; |
483 | u32 *bin_ranges; | 483 | u32 *bin_ranges; |
484 | __le16 fc; | 484 | __le16 fc; |
485 | struct ieee80211_tx_latency_stat *tx_lat; | 485 | struct ieee80211_tx_latency_stat *tx_lat; |
@@ -522,7 +522,6 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
522 | /* count how many Tx frames transmitted with the appropriate latency */ | 522 | /* count how many Tx frames transmitted with the appropriate latency */ |
523 | bin_range_count = tx_latency->n_ranges; | 523 | bin_range_count = tx_latency->n_ranges; |
524 | bin_ranges = tx_latency->ranges; | 524 | bin_ranges = tx_latency->ranges; |
525 | bin_count = tx_lat->bin_count; | ||
526 | 525 | ||
527 | for (i = 0; i < bin_range_count; i++) { | 526 | for (i = 0; i < bin_range_count; i++) { |
528 | if (msrmnt <= bin_ranges[i]) { | 527 | if (msrmnt <= bin_ranges[i]) { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 27c990bf2320..5476a69b45c9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, | |||
452 | if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) | 452 | if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) |
453 | return 0; | 453 | return 0; |
454 | 454 | ||
455 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) | 455 | if (!ieee80211_is_robust_mgmt_frame(skb)) |
456 | skb->data)) | ||
457 | return 0; | 456 | return 0; |
458 | 457 | ||
459 | return 1; | 458 | return 1; |
@@ -523,11 +522,8 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) | |||
523 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) | 522 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) |
524 | return TX_CONTINUE; | 523 | return TX_CONTINUE; |
525 | 524 | ||
526 | /* only deauth, disassoc and action are bufferable MMPDUs */ | ||
527 | if (ieee80211_is_mgmt(hdr->frame_control) && | 525 | if (ieee80211_is_mgmt(hdr->frame_control) && |
528 | !ieee80211_is_deauth(hdr->frame_control) && | 526 | !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { |
529 | !ieee80211_is_disassoc(hdr->frame_control) && | ||
530 | !ieee80211_is_action(hdr->frame_control)) { | ||
531 | if (tx->flags & IEEE80211_TX_UNICAST) | 527 | if (tx->flags & IEEE80211_TX_UNICAST) |
532 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; | 528 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; |
533 | return TX_CONTINUE; | 529 | return TX_CONTINUE; |
@@ -567,7 +563,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
567 | tx->key = key; | 563 | tx->key = key; |
568 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 564 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
569 | is_multicast_ether_addr(hdr->addr1) && | 565 | is_multicast_ether_addr(hdr->addr1) && |
570 | ieee80211_is_robust_mgmt_frame(hdr) && | 566 | ieee80211_is_robust_mgmt_frame(tx->skb) && |
571 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 567 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
572 | tx->key = key; | 568 | tx->key = key; |
573 | else if (is_multicast_ether_addr(hdr->addr1) && | 569 | else if (is_multicast_ether_addr(hdr->addr1) && |
@@ -582,12 +578,12 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
582 | tx->key = NULL; | 578 | tx->key = NULL; |
583 | else if (tx->skb->protocol == tx->sdata->control_port_protocol) | 579 | else if (tx->skb->protocol == tx->sdata->control_port_protocol) |
584 | tx->key = NULL; | 580 | tx->key = NULL; |
585 | else if (ieee80211_is_robust_mgmt_frame(hdr) && | 581 | else if (ieee80211_is_robust_mgmt_frame(tx->skb) && |
586 | !(ieee80211_is_action(hdr->frame_control) && | 582 | !(ieee80211_is_action(hdr->frame_control) && |
587 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) | 583 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) |
588 | tx->key = NULL; | 584 | tx->key = NULL; |
589 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 585 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
590 | !ieee80211_is_robust_mgmt_frame(hdr)) | 586 | !ieee80211_is_robust_mgmt_frame(tx->skb)) |
591 | tx->key = NULL; | 587 | tx->key = NULL; |
592 | else { | 588 | else { |
593 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 589 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
@@ -2402,15 +2398,6 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
2402 | return 0; | 2398 | return 0; |
2403 | } | 2399 | } |
2404 | 2400 | ||
2405 | void ieee80211_csa_finish(struct ieee80211_vif *vif) | ||
2406 | { | ||
2407 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2408 | |||
2409 | ieee80211_queue_work(&sdata->local->hw, | ||
2410 | &sdata->csa_finalize_work); | ||
2411 | } | ||
2412 | EXPORT_SYMBOL(ieee80211_csa_finish); | ||
2413 | |||
2414 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | 2401 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, |
2415 | struct beacon_data *beacon) | 2402 | struct beacon_data *beacon) |
2416 | { | 2403 | { |
@@ -2439,8 +2426,12 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | |||
2439 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) | 2426 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) |
2440 | return; | 2427 | return; |
2441 | 2428 | ||
2442 | /* warn if the driver did not check for/react to csa completeness */ | 2429 | /* Warn if the driver did not check for/react to csa |
2443 | if (WARN_ON(beacon_data[counter_offset_beacon] == 0)) | 2430 | * completeness. A beacon with CSA counter set to 0 should |
2431 | * never occur, because a counter of 1 means switch just | ||
2432 | * before the next beacon. | ||
2433 | */ | ||
2434 | if (WARN_ON(beacon_data[counter_offset_beacon] == 1)) | ||
2444 | return; | 2435 | return; |
2445 | 2436 | ||
2446 | beacon_data[counter_offset_beacon]--; | 2437 | beacon_data[counter_offset_beacon]--; |
@@ -2506,7 +2497,7 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
2506 | if (WARN_ON(counter_beacon > beacon_data_len)) | 2497 | if (WARN_ON(counter_beacon > beacon_data_len)) |
2507 | goto out; | 2498 | goto out; |
2508 | 2499 | ||
2509 | if (beacon_data[counter_beacon] == 0) | 2500 | if (beacon_data[counter_beacon] == 1) |
2510 | ret = true; | 2501 | ret = true; |
2511 | out: | 2502 | out: |
2512 | rcu_read_unlock(); | 2503 | rcu_read_unlock(); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 676dc0967f37..d842af5c8a95 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include "wep.h" | 34 | #include "wep.h" |
35 | 35 | ||
36 | /* privid for wiphys to determine whether they belong to us or not */ | 36 | /* privid for wiphys to determine whether they belong to us or not */ |
37 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; | 37 | const void *const mac80211_wiphy_privid = &mac80211_wiphy_privid; |
38 | 38 | ||
39 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) | 39 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) |
40 | { | 40 | { |
@@ -1281,13 +1281,32 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1281 | * that calculates local->scan_ies_len. | 1281 | * that calculates local->scan_ies_len. |
1282 | */ | 1282 | */ |
1283 | 1283 | ||
1284 | /* add any remaining custom IEs */ | 1284 | /* insert custom IEs that go before VHT */ |
1285 | if (ie && ie_len) { | 1285 | if (ie && ie_len) { |
1286 | noffset = ie_len; | 1286 | static const u8 before_vht[] = { |
1287 | WLAN_EID_SSID, | ||
1288 | WLAN_EID_SUPP_RATES, | ||
1289 | WLAN_EID_REQUEST, | ||
1290 | WLAN_EID_EXT_SUPP_RATES, | ||
1291 | WLAN_EID_DS_PARAMS, | ||
1292 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
1293 | WLAN_EID_HT_CAPABILITY, | ||
1294 | WLAN_EID_BSS_COEX_2040, | ||
1295 | WLAN_EID_EXT_CAPABILITY, | ||
1296 | WLAN_EID_SSID_LIST, | ||
1297 | WLAN_EID_CHANNEL_USAGE, | ||
1298 | WLAN_EID_INTERWORKING, | ||
1299 | /* mesh ID can't happen here */ | ||
1300 | /* 60 GHz can't happen here right now */ | ||
1301 | }; | ||
1302 | noffset = ieee80211_ie_split(ie, ie_len, | ||
1303 | before_vht, ARRAY_SIZE(before_vht), | ||
1304 | offset); | ||
1287 | if (end - pos < noffset - offset) | 1305 | if (end - pos < noffset - offset) |
1288 | goto out_err; | 1306 | goto out_err; |
1289 | memcpy(pos, ie + offset, noffset - offset); | 1307 | memcpy(pos, ie + offset, noffset - offset); |
1290 | pos += noffset - offset; | 1308 | pos += noffset - offset; |
1309 | offset = noffset; | ||
1291 | } | 1310 | } |
1292 | 1311 | ||
1293 | if (sband->vht_cap.vht_supported) { | 1312 | if (sband->vht_cap.vht_supported) { |
@@ -1297,6 +1316,15 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1297 | sband->vht_cap.cap); | 1316 | sband->vht_cap.cap); |
1298 | } | 1317 | } |
1299 | 1318 | ||
1319 | /* add any remaining custom IEs */ | ||
1320 | if (ie && ie_len) { | ||
1321 | noffset = ie_len; | ||
1322 | if (end - pos < noffset - offset) | ||
1323 | goto out_err; | ||
1324 | memcpy(pos, ie + offset, noffset - offset); | ||
1325 | pos += noffset - offset; | ||
1326 | } | ||
1327 | |||
1300 | return pos - buffer; | 1328 | return pos - buffer; |
1301 | out_err: | 1329 | out_err: |
1302 | WARN_ONCE(1, "not enough space for preq IEs\n"); | 1330 | WARN_ONCE(1, "not enough space for preq IEs\n"); |
@@ -1374,7 +1402,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | |||
1374 | enum ieee80211_band band, u32 *basic_rates) | 1402 | enum ieee80211_band band, u32 *basic_rates) |
1375 | { | 1403 | { |
1376 | struct ieee80211_supported_band *sband; | 1404 | struct ieee80211_supported_band *sband; |
1377 | struct ieee80211_rate *bitrates; | ||
1378 | size_t num_rates; | 1405 | size_t num_rates; |
1379 | u32 supp_rates, rate_flags; | 1406 | u32 supp_rates, rate_flags; |
1380 | int i, j, shift; | 1407 | int i, j, shift; |
@@ -1386,7 +1413,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | |||
1386 | if (WARN_ON(!sband)) | 1413 | if (WARN_ON(!sband)) |
1387 | return 1; | 1414 | return 1; |
1388 | 1415 | ||
1389 | bitrates = sband->bitrates; | ||
1390 | num_rates = sband->n_bitrates; | 1416 | num_rates = sband->n_bitrates; |
1391 | supp_rates = 0; | 1417 | supp_rates = 0; |
1392 | for (i = 0; i < elems->supp_rates_len + | 1418 | for (i = 0; i < elems->supp_rates_len + |
@@ -2272,11 +2298,11 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2272 | ri.nss = status->vht_nss; | 2298 | ri.nss = status->vht_nss; |
2273 | if (status->flag & RX_FLAG_40MHZ) | 2299 | if (status->flag & RX_FLAG_40MHZ) |
2274 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 2300 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
2275 | if (status->flag & RX_FLAG_80MHZ) | 2301 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
2276 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 2302 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; |
2277 | if (status->flag & RX_FLAG_80P80MHZ) | 2303 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
2278 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 2304 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; |
2279 | if (status->flag & RX_FLAG_160MHZ) | 2305 | if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
2280 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 2306 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; |
2281 | if (status->flag & RX_FLAG_SHORT_GI) | 2307 | if (status->flag & RX_FLAG_SHORT_GI) |
2282 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2308 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index d75f35c6e1a0..e9e36a256165 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -349,9 +349,9 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) | |||
349 | sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss); | 349 | sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss); |
350 | } | 350 | } |
351 | 351 | ||
352 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 352 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
353 | struct sta_info *sta, u8 opmode, | 353 | struct sta_info *sta, u8 opmode, |
354 | enum ieee80211_band band, bool nss_only) | 354 | enum ieee80211_band band, bool nss_only) |
355 | { | 355 | { |
356 | struct ieee80211_local *local = sdata->local; | 356 | struct ieee80211_local *local = sdata->local; |
357 | struct ieee80211_supported_band *sband; | 357 | struct ieee80211_supported_band *sband; |
@@ -363,7 +363,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
363 | 363 | ||
364 | /* ignore - no support for BF yet */ | 364 | /* ignore - no support for BF yet */ |
365 | if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) | 365 | if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) |
366 | return; | 366 | return 0; |
367 | 367 | ||
368 | nss = opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK; | 368 | nss = opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK; |
369 | nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; | 369 | nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; |
@@ -375,7 +375,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
375 | } | 375 | } |
376 | 376 | ||
377 | if (nss_only) | 377 | if (nss_only) |
378 | goto change; | 378 | return changed; |
379 | 379 | ||
380 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { | 380 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { |
381 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: | 381 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: |
@@ -398,7 +398,19 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
398 | changed |= IEEE80211_RC_BW_CHANGED; | 398 | changed |= IEEE80211_RC_BW_CHANGED; |
399 | } | 399 | } |
400 | 400 | ||
401 | change: | 401 | return changed; |
402 | if (changed) | 402 | } |
403 | |||
404 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | ||
405 | struct sta_info *sta, u8 opmode, | ||
406 | enum ieee80211_band band, bool nss_only) | ||
407 | { | ||
408 | struct ieee80211_local *local = sdata->local; | ||
409 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | ||
410 | |||
411 | u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, | ||
412 | band, nss_only); | ||
413 | |||
414 | if (changed > 0) | ||
403 | rate_control_rate_update(local, sband, sta, changed); | 415 | rate_control_rate_update(local, sband, sta, changed); |
404 | } | 416 | } |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 21448d629b15..b8600e3c29c8 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -301,8 +301,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | 303 | ||
304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, | 304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) |
305 | int encrypted) | ||
306 | { | 305 | { |
307 | __le16 mask_fc; | 306 | __le16 mask_fc; |
308 | int a4_included, mgmt; | 307 | int a4_included, mgmt; |
@@ -456,7 +455,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
456 | return 0; | 455 | return 0; |
457 | 456 | ||
458 | pos += IEEE80211_CCMP_HDR_LEN; | 457 | pos += IEEE80211_CCMP_HDR_LEN; |
459 | ccmp_special_blocks(skb, pn, b_0, aad, 0); | 458 | ccmp_special_blocks(skb, pn, b_0, aad); |
460 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, | 459 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, |
461 | skb_put(skb, IEEE80211_CCMP_MIC_LEN)); | 460 | skb_put(skb, IEEE80211_CCMP_MIC_LEN)); |
462 | 461 | ||
@@ -495,7 +494,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
495 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 494 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
496 | 495 | ||
497 | if (!ieee80211_is_data(hdr->frame_control) && | 496 | if (!ieee80211_is_data(hdr->frame_control) && |
498 | !ieee80211_is_robust_mgmt_frame(hdr)) | 497 | !ieee80211_is_robust_mgmt_frame(skb)) |
499 | return RX_CONTINUE; | 498 | return RX_CONTINUE; |
500 | 499 | ||
501 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - | 500 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - |
@@ -524,7 +523,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
524 | u8 aad[2 * AES_BLOCK_SIZE]; | 523 | u8 aad[2 * AES_BLOCK_SIZE]; |
525 | u8 b_0[AES_BLOCK_SIZE]; | 524 | u8 b_0[AES_BLOCK_SIZE]; |
526 | /* hardware didn't decrypt/verify MIC */ | 525 | /* hardware didn't decrypt/verify MIC */ |
527 | ccmp_special_blocks(skb, pn, b_0, aad, 1); | 526 | ccmp_special_blocks(skb, pn, b_0, aad); |
528 | 527 | ||
529 | if (ieee80211_aes_ccm_decrypt( | 528 | if (ieee80211_aes_ccm_decrypt( |
530 | key->u.ccmp.tfm, b_0, aad, | 529 | key->u.ccmp.tfm, b_0, aad, |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index ed7e0b4e7f90..b3b16c070a7f 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -789,7 +789,8 @@ void rfkill_resume_polling(struct rfkill *rfkill) | |||
789 | if (!rfkill->ops->poll) | 789 | if (!rfkill->ops->poll) |
790 | return; | 790 | return; |
791 | 791 | ||
792 | schedule_work(&rfkill->poll_work.work); | 792 | queue_delayed_work(system_power_efficient_wq, |
793 | &rfkill->poll_work, 0); | ||
793 | } | 794 | } |
794 | EXPORT_SYMBOL(rfkill_resume_polling); | 795 | EXPORT_SYMBOL(rfkill_resume_polling); |
795 | 796 | ||
@@ -894,7 +895,8 @@ static void rfkill_poll(struct work_struct *work) | |||
894 | */ | 895 | */ |
895 | rfkill->ops->poll(rfkill, rfkill->data); | 896 | rfkill->ops->poll(rfkill, rfkill->data); |
896 | 897 | ||
897 | schedule_delayed_work(&rfkill->poll_work, | 898 | queue_delayed_work(system_power_efficient_wq, |
899 | &rfkill->poll_work, | ||
898 | round_jiffies_relative(POLL_INTERVAL)); | 900 | round_jiffies_relative(POLL_INTERVAL)); |
899 | } | 901 | } |
900 | 902 | ||
@@ -958,7 +960,8 @@ int __must_check rfkill_register(struct rfkill *rfkill) | |||
958 | INIT_WORK(&rfkill->sync_work, rfkill_sync_work); | 960 | INIT_WORK(&rfkill->sync_work, rfkill_sync_work); |
959 | 961 | ||
960 | if (rfkill->ops->poll) | 962 | if (rfkill->ops->poll) |
961 | schedule_delayed_work(&rfkill->poll_work, | 963 | queue_delayed_work(system_power_efficient_wq, |
964 | &rfkill->poll_work, | ||
962 | round_jiffies_relative(POLL_INTERVAL)); | 965 | round_jiffies_relative(POLL_INTERVAL)); |
963 | 966 | ||
964 | if (!rfkill->persistent || rfkill_epo_lock_active) { | 967 | if (!rfkill->persistent || rfkill_epo_lock_active) { |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 11ee4ed04f73..68602be07cc1 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
@@ -27,9 +27,10 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
27 | err = rdev_stop_ap(rdev, dev); | 27 | err = rdev_stop_ap(rdev, dev); |
28 | if (!err) { | 28 | if (!err) { |
29 | wdev->beacon_interval = 0; | 29 | wdev->beacon_interval = 0; |
30 | wdev->channel = NULL; | 30 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); |
31 | wdev->ssid_len = 0; | 31 | wdev->ssid_len = 0; |
32 | rdev_set_qos_map(rdev, dev, NULL); | 32 | rdev_set_qos_map(rdev, dev, NULL); |
33 | nl80211_send_ap_stopped(wdev); | ||
33 | } | 34 | } |
34 | 35 | ||
35 | return err; | 36 | return err; |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 78559b5bbd1f..f8ab7df1ab0d 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, | |||
642 | void | 642 | void |
643 | cfg80211_get_chan_state(struct wireless_dev *wdev, | 643 | cfg80211_get_chan_state(struct wireless_dev *wdev, |
644 | struct ieee80211_channel **chan, | 644 | struct ieee80211_channel **chan, |
645 | enum cfg80211_chan_mode *chanmode) | 645 | enum cfg80211_chan_mode *chanmode, |
646 | u8 *radar_detect) | ||
646 | { | 647 | { |
647 | *chan = NULL; | 648 | *chan = NULL; |
648 | *chanmode = CHAN_MODE_UNDEFINED; | 649 | *chanmode = CHAN_MODE_UNDEFINED; |
@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
660 | !wdev->ibss_dfs_possible) | 661 | !wdev->ibss_dfs_possible) |
661 | ? CHAN_MODE_SHARED | 662 | ? CHAN_MODE_SHARED |
662 | : CHAN_MODE_EXCLUSIVE; | 663 | : CHAN_MODE_EXCLUSIVE; |
664 | |||
665 | /* consider worst-case - IBSS can try to return to the | ||
666 | * original user-specified channel as creator */ | ||
667 | if (wdev->ibss_dfs_possible) | ||
668 | *radar_detect |= BIT(wdev->chandef.width); | ||
663 | return; | 669 | return; |
664 | } | 670 | } |
665 | break; | 671 | break; |
@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
674 | case NL80211_IFTYPE_AP: | 680 | case NL80211_IFTYPE_AP: |
675 | case NL80211_IFTYPE_P2P_GO: | 681 | case NL80211_IFTYPE_P2P_GO: |
676 | if (wdev->cac_started) { | 682 | if (wdev->cac_started) { |
677 | *chan = wdev->channel; | 683 | *chan = wdev->chandef.chan; |
678 | *chanmode = CHAN_MODE_SHARED; | 684 | *chanmode = CHAN_MODE_SHARED; |
685 | *radar_detect |= BIT(wdev->chandef.width); | ||
679 | } else if (wdev->beacon_interval) { | 686 | } else if (wdev->beacon_interval) { |
680 | *chan = wdev->channel; | 687 | *chan = wdev->chandef.chan; |
681 | *chanmode = CHAN_MODE_SHARED; | 688 | *chanmode = CHAN_MODE_SHARED; |
689 | |||
690 | if (cfg80211_chandef_dfs_required(wdev->wiphy, | ||
691 | &wdev->chandef)) | ||
692 | *radar_detect |= BIT(wdev->chandef.width); | ||
682 | } | 693 | } |
683 | return; | 694 | return; |
684 | case NL80211_IFTYPE_MESH_POINT: | 695 | case NL80211_IFTYPE_MESH_POINT: |
685 | if (wdev->mesh_id_len) { | 696 | if (wdev->mesh_id_len) { |
686 | *chan = wdev->channel; | 697 | *chan = wdev->chandef.chan; |
687 | *chanmode = CHAN_MODE_SHARED; | 698 | *chanmode = CHAN_MODE_SHARED; |
699 | |||
700 | if (cfg80211_chandef_dfs_required(wdev->wiphy, | ||
701 | &wdev->chandef)) | ||
702 | *radar_detect |= BIT(wdev->chandef.width); | ||
688 | } | 703 | } |
689 | return; | 704 | return; |
690 | case NL80211_IFTYPE_MONITOR: | 705 | case NL80211_IFTYPE_MONITOR: |
diff --git a/net/wireless/core.c b/net/wireless/core.c index d89dee2259b5..b5ff39a6f6ed 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -737,7 +737,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) | |||
737 | } | 737 | } |
738 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 738 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
739 | 739 | ||
740 | static struct device_type wiphy_type = { | 740 | static const struct device_type wiphy_type = { |
741 | .name = "wlan", | 741 | .name = "wlan", |
742 | }; | 742 | }; |
743 | 743 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index 37ec16d7bb1a..9895ab16c051 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -210,6 +210,7 @@ struct cfg80211_event { | |||
210 | } dc; | 210 | } dc; |
211 | struct { | 211 | struct { |
212 | u8 bssid[ETH_ALEN]; | 212 | u8 bssid[ETH_ALEN]; |
213 | struct ieee80211_channel *channel; | ||
213 | } ij; | 214 | } ij; |
214 | }; | 215 | }; |
215 | }; | 216 | }; |
@@ -257,7 +258,8 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | |||
257 | struct net_device *dev, bool nowext); | 258 | struct net_device *dev, bool nowext); |
258 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 259 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
259 | struct net_device *dev, bool nowext); | 260 | struct net_device *dev, bool nowext); |
260 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); | 261 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, |
262 | struct ieee80211_channel *channel); | ||
261 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | 263 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, |
262 | struct wireless_dev *wdev); | 264 | struct wireless_dev *wdev); |
263 | 265 | ||
@@ -441,7 +443,8 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start) | |||
441 | void | 443 | void |
442 | cfg80211_get_chan_state(struct wireless_dev *wdev, | 444 | cfg80211_get_chan_state(struct wireless_dev *wdev, |
443 | struct ieee80211_channel **chan, | 445 | struct ieee80211_channel **chan, |
444 | enum cfg80211_chan_mode *chanmode); | 446 | enum cfg80211_chan_mode *chanmode, |
447 | u8 *radar_detect); | ||
445 | 448 | ||
446 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, | 449 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
447 | struct cfg80211_chan_def *chandef); | 450 | struct cfg80211_chan_def *chandef); |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index f911c5f9f903..1470b90e438f 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -14,7 +14,8 @@ | |||
14 | #include "rdev-ops.h" | 14 | #include "rdev-ops.h" |
15 | 15 | ||
16 | 16 | ||
17 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | 17 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, |
18 | struct ieee80211_channel *channel) | ||
18 | { | 19 | { |
19 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 20 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
20 | struct cfg80211_bss *bss; | 21 | struct cfg80211_bss *bss; |
@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
28 | if (!wdev->ssid_len) | 29 | if (!wdev->ssid_len) |
29 | return; | 30 | return; |
30 | 31 | ||
31 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | 32 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0, |
32 | wdev->ssid, wdev->ssid_len, | ||
33 | WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); | 33 | WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); |
34 | 34 | ||
35 | if (WARN_ON(!bss)) | 35 | if (WARN_ON(!bss)) |
@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
54 | #endif | 54 | #endif |
55 | } | 55 | } |
56 | 56 | ||
57 | void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) | 57 | void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, |
58 | struct ieee80211_channel *channel, gfp_t gfp) | ||
58 | { | 59 | { |
59 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 60 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
60 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 61 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
61 | struct cfg80211_event *ev; | 62 | struct cfg80211_event *ev; |
62 | unsigned long flags; | 63 | unsigned long flags; |
63 | 64 | ||
64 | trace_cfg80211_ibss_joined(dev, bssid); | 65 | trace_cfg80211_ibss_joined(dev, bssid, channel); |
66 | |||
67 | if (WARN_ON(!channel)) | ||
68 | return; | ||
65 | 69 | ||
66 | ev = kzalloc(sizeof(*ev), gfp); | 70 | ev = kzalloc(sizeof(*ev), gfp); |
67 | if (!ev) | 71 | if (!ev) |
68 | return; | 72 | return; |
69 | 73 | ||
70 | ev->type = EVENT_IBSS_JOINED; | 74 | ev->type = EVENT_IBSS_JOINED; |
71 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); | 75 | memcpy(ev->ij.bssid, bssid, ETH_ALEN); |
76 | ev->ij.channel = channel; | ||
72 | 77 | ||
73 | spin_lock_irqsave(&wdev->event_lock, flags); | 78 | spin_lock_irqsave(&wdev->event_lock, flags); |
74 | list_add_tail(&ev->list, &wdev->event_list); | 79 | list_add_tail(&ev->list, &wdev->event_list); |
@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
117 | 122 | ||
118 | wdev->ibss_fixed = params->channel_fixed; | 123 | wdev->ibss_fixed = params->channel_fixed; |
119 | wdev->ibss_dfs_possible = params->userspace_handles_dfs; | 124 | wdev->ibss_dfs_possible = params->userspace_handles_dfs; |
125 | wdev->chandef = params->chandef; | ||
120 | #ifdef CONFIG_CFG80211_WEXT | 126 | #ifdef CONFIG_CFG80211_WEXT |
121 | wdev->wext.ibss.chandef = params->chandef; | 127 | wdev->wext.ibss.chandef = params->chandef; |
122 | #endif | 128 | #endif |
@@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
200 | 206 | ||
201 | wdev->current_bss = NULL; | 207 | wdev->current_bss = NULL; |
202 | wdev->ssid_len = 0; | 208 | wdev->ssid_len = 0; |
209 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); | ||
203 | #ifdef CONFIG_CFG80211_WEXT | 210 | #ifdef CONFIG_CFG80211_WEXT |
204 | if (!nowext) | 211 | if (!nowext) |
205 | wdev->wext.ibss.ssid_len = 0; | 212 | wdev->wext.ibss.ssid_len = 0; |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 885862447b63..d42a3fcb2f67 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
195 | if (!err) { | 195 | if (!err) { |
196 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); | 196 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); |
197 | wdev->mesh_id_len = setup->mesh_id_len; | 197 | wdev->mesh_id_len = setup->mesh_id_len; |
198 | wdev->channel = setup->chandef.chan; | 198 | wdev->chandef = setup->chandef; |
199 | } | 199 | } |
200 | 200 | ||
201 | return err; | 201 | return err; |
@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
244 | err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, | 244 | err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, |
245 | chandef->chan); | 245 | chandef->chan); |
246 | if (!err) | 246 | if (!err) |
247 | wdev->channel = chandef->chan; | 247 | wdev->chandef = *chandef; |
248 | 248 | ||
249 | return err; | 249 | return err; |
250 | } | 250 | } |
@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | |||
276 | err = rdev_leave_mesh(rdev, dev); | 276 | err = rdev_leave_mesh(rdev, dev); |
277 | if (!err) { | 277 | if (!err) { |
278 | wdev->mesh_id_len = 0; | 278 | wdev->mesh_id_len = 0; |
279 | wdev->channel = NULL; | 279 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); |
280 | rdev_set_qos_map(rdev, dev, NULL); | 280 | rdev_set_qos_map(rdev, dev, NULL); |
281 | } | 281 | } |
282 | 282 | ||
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 52cca05044a8..d47c9d127b1e 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_device *netdev, | |||
772 | if (WARN_ON(!wdev->cac_started)) | 772 | if (WARN_ON(!wdev->cac_started)) |
773 | return; | 773 | return; |
774 | 774 | ||
775 | if (WARN_ON(!wdev->channel)) | 775 | if (WARN_ON(!wdev->chandef.chan)) |
776 | return; | 776 | return; |
777 | 777 | ||
778 | switch (event) { | 778 | switch (event) { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7a742594916e..ebea1a197afb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -382,6 +382,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
382 | [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, | 382 | [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, |
383 | [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY, | 383 | [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY, |
384 | .len = IEEE80211_QOS_MAP_LEN_MAX }, | 384 | .len = IEEE80211_QOS_MAP_LEN_MAX }, |
385 | [NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN }, | ||
386 | [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, | ||
385 | }; | 387 | }; |
386 | 388 | ||
387 | /* policy for the key attributes */ | 389 | /* policy for the key attributes */ |
@@ -855,6 +857,19 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) | |||
855 | return 0; | 857 | return 0; |
856 | } | 858 | } |
857 | 859 | ||
860 | static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy, | ||
861 | struct nlattr *tb) | ||
862 | { | ||
863 | struct ieee80211_channel *chan; | ||
864 | |||
865 | if (tb == NULL) | ||
866 | return NULL; | ||
867 | chan = ieee80211_get_channel(wiphy, nla_get_u32(tb)); | ||
868 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | ||
869 | return NULL; | ||
870 | return chan; | ||
871 | } | ||
872 | |||
858 | static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) | 873 | static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) |
859 | { | 874 | { |
860 | struct nlattr *nl_modes = nla_nest_start(msg, attr); | 875 | struct nlattr *nl_modes = nla_nest_start(msg, attr); |
@@ -1586,6 +1601,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1586 | (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) || | 1601 | (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) || |
1587 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ))) | 1602 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ))) |
1588 | goto nla_put_failure; | 1603 | goto nla_put_failure; |
1604 | |||
1605 | if (dev->wiphy.max_ap_assoc_sta && | ||
1606 | nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA, | ||
1607 | dev->wiphy.max_ap_assoc_sta)) | ||
1608 | goto nla_put_failure; | ||
1609 | |||
1589 | state->split_start++; | 1610 | state->split_start++; |
1590 | break; | 1611 | break; |
1591 | case 11: | 1612 | case 11: |
@@ -2034,10 +2055,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
2034 | nla_for_each_nested(nl_txq_params, | 2055 | nla_for_each_nested(nl_txq_params, |
2035 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | 2056 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], |
2036 | rem_txq_params) { | 2057 | rem_txq_params) { |
2037 | nla_parse(tb, NL80211_TXQ_ATTR_MAX, | 2058 | result = nla_parse(tb, NL80211_TXQ_ATTR_MAX, |
2038 | nla_data(nl_txq_params), | 2059 | nla_data(nl_txq_params), |
2039 | nla_len(nl_txq_params), | 2060 | nla_len(nl_txq_params), |
2040 | txq_params_policy); | 2061 | txq_params_policy); |
2062 | if (result) | ||
2063 | return result; | ||
2041 | result = parse_txq_params(tb, &txq_params); | 2064 | result = parse_txq_params(tb, &txq_params); |
2042 | if (result) | 2065 | if (result) |
2043 | return result; | 2066 | return result; |
@@ -3258,7 +3281,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
3258 | if (!err) { | 3281 | if (!err) { |
3259 | wdev->preset_chandef = params.chandef; | 3282 | wdev->preset_chandef = params.chandef; |
3260 | wdev->beacon_interval = params.beacon_interval; | 3283 | wdev->beacon_interval = params.beacon_interval; |
3261 | wdev->channel = params.chandef.chan; | 3284 | wdev->chandef = params.chandef; |
3262 | wdev->ssid_len = params.ssid_len; | 3285 | wdev->ssid_len = params.ssid_len; |
3263 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); | 3286 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); |
3264 | } | 3287 | } |
@@ -3901,8 +3924,8 @@ static struct net_device *get_vlan(struct genl_info *info, | |||
3901 | return ERR_PTR(ret); | 3924 | return ERR_PTR(ret); |
3902 | } | 3925 | } |
3903 | 3926 | ||
3904 | static struct nla_policy | 3927 | static const struct nla_policy |
3905 | nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { | 3928 | nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = { |
3906 | [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, | 3929 | [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, |
3907 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, | 3930 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, |
3908 | }; | 3931 | }; |
@@ -4603,8 +4626,6 @@ static int parse_reg_rule(struct nlattr *tb[], | |||
4603 | return -EINVAL; | 4626 | return -EINVAL; |
4604 | if (!tb[NL80211_ATTR_FREQ_RANGE_END]) | 4627 | if (!tb[NL80211_ATTR_FREQ_RANGE_END]) |
4605 | return -EINVAL; | 4628 | return -EINVAL; |
4606 | if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) | ||
4607 | return -EINVAL; | ||
4608 | if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) | 4629 | if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) |
4609 | return -EINVAL; | 4630 | return -EINVAL; |
4610 | 4631 | ||
@@ -4614,8 +4635,9 @@ static int parse_reg_rule(struct nlattr *tb[], | |||
4614 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]); | 4635 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]); |
4615 | freq_range->end_freq_khz = | 4636 | freq_range->end_freq_khz = |
4616 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]); | 4637 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]); |
4617 | freq_range->max_bandwidth_khz = | 4638 | if (tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) |
4618 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]); | 4639 | freq_range->max_bandwidth_khz = |
4640 | nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]); | ||
4619 | 4641 | ||
4620 | power_rule->max_eirp = | 4642 | power_rule->max_eirp = |
4621 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]); | 4643 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]); |
@@ -5085,6 +5107,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
5085 | const struct ieee80211_reg_rule *reg_rule; | 5107 | const struct ieee80211_reg_rule *reg_rule; |
5086 | const struct ieee80211_freq_range *freq_range; | 5108 | const struct ieee80211_freq_range *freq_range; |
5087 | const struct ieee80211_power_rule *power_rule; | 5109 | const struct ieee80211_power_rule *power_rule; |
5110 | unsigned int max_bandwidth_khz; | ||
5088 | 5111 | ||
5089 | reg_rule = ®dom->reg_rules[i]; | 5112 | reg_rule = ®dom->reg_rules[i]; |
5090 | freq_range = ®_rule->freq_range; | 5113 | freq_range = ®_rule->freq_range; |
@@ -5094,6 +5117,11 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
5094 | if (!nl_reg_rule) | 5117 | if (!nl_reg_rule) |
5095 | goto nla_put_failure_rcu; | 5118 | goto nla_put_failure_rcu; |
5096 | 5119 | ||
5120 | max_bandwidth_khz = freq_range->max_bandwidth_khz; | ||
5121 | if (!max_bandwidth_khz) | ||
5122 | max_bandwidth_khz = reg_get_max_bandwidth(regdom, | ||
5123 | reg_rule); | ||
5124 | |||
5097 | if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS, | 5125 | if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS, |
5098 | reg_rule->flags) || | 5126 | reg_rule->flags) || |
5099 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START, | 5127 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START, |
@@ -5101,7 +5129,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
5101 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END, | 5129 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END, |
5102 | freq_range->end_freq_khz) || | 5130 | freq_range->end_freq_khz) || |
5103 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, | 5131 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, |
5104 | freq_range->max_bandwidth_khz) || | 5132 | max_bandwidth_khz) || |
5105 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | 5133 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, |
5106 | power_rule->max_antenna_gain) || | 5134 | power_rule->max_antenna_gain) || |
5107 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, | 5135 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, |
@@ -5177,9 +5205,11 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
5177 | 5205 | ||
5178 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], | 5206 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], |
5179 | rem_reg_rules) { | 5207 | rem_reg_rules) { |
5180 | nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, | 5208 | r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, |
5181 | nla_data(nl_reg_rule), nla_len(nl_reg_rule), | 5209 | nla_data(nl_reg_rule), nla_len(nl_reg_rule), |
5182 | reg_rule_policy); | 5210 | reg_rule_policy); |
5211 | if (r) | ||
5212 | goto bad_reg; | ||
5183 | r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); | 5213 | r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); |
5184 | if (r) | 5214 | if (r) |
5185 | goto bad_reg; | 5215 | goto bad_reg; |
@@ -5442,6 +5472,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5442 | enum ieee80211_band band; | 5472 | enum ieee80211_band band; |
5443 | size_t ie_len; | 5473 | size_t ie_len; |
5444 | struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; | 5474 | struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; |
5475 | s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF; | ||
5445 | 5476 | ||
5446 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | 5477 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || |
5447 | !rdev->ops->sched_scan_start) | 5478 | !rdev->ops->sched_scan_start) |
@@ -5476,11 +5507,40 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5476 | if (n_ssids > wiphy->max_sched_scan_ssids) | 5507 | if (n_ssids > wiphy->max_sched_scan_ssids) |
5477 | return -EINVAL; | 5508 | return -EINVAL; |
5478 | 5509 | ||
5479 | if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) | 5510 | /* |
5511 | * First, count the number of 'real' matchsets. Due to an issue with | ||
5512 | * the old implementation, matchsets containing only the RSSI attribute | ||
5513 | * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default' | ||
5514 | * RSSI for all matchsets, rather than their own matchset for reporting | ||
5515 | * all APs with a strong RSSI. This is needed to be compatible with | ||
5516 | * older userspace that treated a matchset with only the RSSI as the | ||
5517 | * global RSSI for all other matchsets - if there are other matchsets. | ||
5518 | */ | ||
5519 | if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { | ||
5480 | nla_for_each_nested(attr, | 5520 | nla_for_each_nested(attr, |
5481 | info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], | 5521 | info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], |
5482 | tmp) | 5522 | tmp) { |
5483 | n_match_sets++; | 5523 | struct nlattr *rssi; |
5524 | |||
5525 | err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, | ||
5526 | nla_data(attr), nla_len(attr), | ||
5527 | nl80211_match_policy); | ||
5528 | if (err) | ||
5529 | return err; | ||
5530 | /* add other standalone attributes here */ | ||
5531 | if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) { | ||
5532 | n_match_sets++; | ||
5533 | continue; | ||
5534 | } | ||
5535 | rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; | ||
5536 | if (rssi) | ||
5537 | default_match_rssi = nla_get_s32(rssi); | ||
5538 | } | ||
5539 | } | ||
5540 | |||
5541 | /* However, if there's no other matchset, add the RSSI one */ | ||
5542 | if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF) | ||
5543 | n_match_sets = 1; | ||
5484 | 5544 | ||
5485 | if (n_match_sets > wiphy->max_match_sets) | 5545 | if (n_match_sets > wiphy->max_match_sets) |
5486 | return -EINVAL; | 5546 | return -EINVAL; |
@@ -5601,11 +5661,22 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5601 | tmp) { | 5661 | tmp) { |
5602 | struct nlattr *ssid, *rssi; | 5662 | struct nlattr *ssid, *rssi; |
5603 | 5663 | ||
5604 | nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, | 5664 | err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, |
5605 | nla_data(attr), nla_len(attr), | 5665 | nla_data(attr), nla_len(attr), |
5606 | nl80211_match_policy); | 5666 | nl80211_match_policy); |
5667 | if (err) | ||
5668 | goto out_free; | ||
5607 | ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]; | 5669 | ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]; |
5608 | if (ssid) { | 5670 | if (ssid) { |
5671 | if (WARN_ON(i >= n_match_sets)) { | ||
5672 | /* this indicates a programming error, | ||
5673 | * the loop above should have verified | ||
5674 | * things properly | ||
5675 | */ | ||
5676 | err = -EINVAL; | ||
5677 | goto out_free; | ||
5678 | } | ||
5679 | |||
5609 | if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { | 5680 | if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { |
5610 | err = -EINVAL; | 5681 | err = -EINVAL; |
5611 | goto out_free; | 5682 | goto out_free; |
@@ -5614,15 +5685,28 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5614 | nla_data(ssid), nla_len(ssid)); | 5685 | nla_data(ssid), nla_len(ssid)); |
5615 | request->match_sets[i].ssid.ssid_len = | 5686 | request->match_sets[i].ssid.ssid_len = |
5616 | nla_len(ssid); | 5687 | nla_len(ssid); |
5688 | /* special attribute - old implemenation w/a */ | ||
5689 | request->match_sets[i].rssi_thold = | ||
5690 | default_match_rssi; | ||
5691 | rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; | ||
5692 | if (rssi) | ||
5693 | request->match_sets[i].rssi_thold = | ||
5694 | nla_get_s32(rssi); | ||
5617 | } | 5695 | } |
5618 | rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; | ||
5619 | if (rssi) | ||
5620 | request->rssi_thold = nla_get_u32(rssi); | ||
5621 | else | ||
5622 | request->rssi_thold = | ||
5623 | NL80211_SCAN_RSSI_THOLD_OFF; | ||
5624 | i++; | 5696 | i++; |
5625 | } | 5697 | } |
5698 | |||
5699 | /* there was no other matchset, so the RSSI one is alone */ | ||
5700 | if (i == 0) | ||
5701 | request->match_sets[0].rssi_thold = default_match_rssi; | ||
5702 | |||
5703 | request->min_rssi_thold = INT_MAX; | ||
5704 | for (i = 0; i < n_match_sets; i++) | ||
5705 | request->min_rssi_thold = | ||
5706 | min(request->match_sets[i].rssi_thold, | ||
5707 | request->min_rssi_thold); | ||
5708 | } else { | ||
5709 | request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF; | ||
5626 | } | 5710 | } |
5627 | 5711 | ||
5628 | if (info->attrs[NL80211_ATTR_IE]) { | 5712 | if (info->attrs[NL80211_ATTR_IE]) { |
@@ -5718,7 +5802,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5718 | 5802 | ||
5719 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); | 5803 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); |
5720 | if (!err) { | 5804 | if (!err) { |
5721 | wdev->channel = chandef.chan; | 5805 | wdev->chandef = chandef; |
5722 | wdev->cac_started = true; | 5806 | wdev->cac_started = true; |
5723 | wdev->cac_start_time = jiffies; | 5807 | wdev->cac_start_time = jiffies; |
5724 | } | 5808 | } |
@@ -5750,10 +5834,15 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5750 | 5834 | ||
5751 | /* useless if AP is not running */ | 5835 | /* useless if AP is not running */ |
5752 | if (!wdev->beacon_interval) | 5836 | if (!wdev->beacon_interval) |
5753 | return -EINVAL; | 5837 | return -ENOTCONN; |
5754 | break; | 5838 | break; |
5755 | case NL80211_IFTYPE_ADHOC: | 5839 | case NL80211_IFTYPE_ADHOC: |
5840 | if (!wdev->ssid_len) | ||
5841 | return -ENOTCONN; | ||
5842 | break; | ||
5756 | case NL80211_IFTYPE_MESH_POINT: | 5843 | case NL80211_IFTYPE_MESH_POINT: |
5844 | if (!wdev->mesh_id_len) | ||
5845 | return -ENOTCONN; | ||
5757 | break; | 5846 | break; |
5758 | default: | 5847 | default: |
5759 | return -EOPNOTSUPP; | 5848 | return -EOPNOTSUPP; |
@@ -6191,9 +6280,9 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
6191 | return -EOPNOTSUPP; | 6280 | return -EOPNOTSUPP; |
6192 | 6281 | ||
6193 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 6282 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
6194 | chan = ieee80211_get_channel(&rdev->wiphy, | 6283 | chan = nl80211_get_valid_chan(&rdev->wiphy, |
6195 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 6284 | info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
6196 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) | 6285 | if (!chan) |
6197 | return -EINVAL; | 6286 | return -EINVAL; |
6198 | 6287 | ||
6199 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 6288 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
@@ -6346,9 +6435,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
6346 | 6435 | ||
6347 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 6436 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
6348 | 6437 | ||
6349 | chan = ieee80211_get_channel(&rdev->wiphy, | 6438 | chan = nl80211_get_valid_chan(&rdev->wiphy, |
6350 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 6439 | info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
6351 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) | 6440 | if (!chan) |
6352 | return -EINVAL; | 6441 | return -EINVAL; |
6353 | 6442 | ||
6354 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 6443 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
@@ -6984,6 +7073,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
6984 | 7073 | ||
6985 | if (info->attrs[NL80211_ATTR_MAC]) | 7074 | if (info->attrs[NL80211_ATTR_MAC]) |
6986 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 7075 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
7076 | else if (info->attrs[NL80211_ATTR_MAC_HINT]) | ||
7077 | connect.bssid_hint = | ||
7078 | nla_data(info->attrs[NL80211_ATTR_MAC_HINT]); | ||
6987 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 7079 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
6988 | connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 7080 | connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
6989 | 7081 | ||
@@ -7002,11 +7094,14 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
7002 | } | 7094 | } |
7003 | 7095 | ||
7004 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 7096 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
7005 | connect.channel = | 7097 | connect.channel = nl80211_get_valid_chan( |
7006 | ieee80211_get_channel(wiphy, | 7098 | wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
7007 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 7099 | if (!connect.channel) |
7008 | if (!connect.channel || | 7100 | return -EINVAL; |
7009 | connect.channel->flags & IEEE80211_CHAN_DISABLED) | 7101 | } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) { |
7102 | connect.channel_hint = nl80211_get_valid_chan( | ||
7103 | wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]); | ||
7104 | if (!connect.channel_hint) | ||
7010 | return -EINVAL; | 7105 | return -EINVAL; |
7011 | } | 7106 | } |
7012 | 7107 | ||
@@ -7420,6 +7515,7 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { | |||
7420 | [NL80211_TXRATE_HT] = { .type = NLA_BINARY, | 7515 | [NL80211_TXRATE_HT] = { .type = NLA_BINARY, |
7421 | .len = NL80211_MAX_SUPP_HT_RATES }, | 7516 | .len = NL80211_MAX_SUPP_HT_RATES }, |
7422 | [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)}, | 7517 | [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)}, |
7518 | [NL80211_TXRATE_GI] = { .type = NLA_U8 }, | ||
7423 | }; | 7519 | }; |
7424 | 7520 | ||
7425 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | 7521 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, |
@@ -7466,16 +7562,19 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
7466 | * directly to the enum ieee80211_band values used in cfg80211. | 7562 | * directly to the enum ieee80211_band values used in cfg80211. |
7467 | */ | 7563 | */ |
7468 | BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); | 7564 | BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); |
7469 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) | 7565 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) { |
7470 | { | ||
7471 | enum ieee80211_band band = nla_type(tx_rates); | 7566 | enum ieee80211_band band = nla_type(tx_rates); |
7567 | int err; | ||
7568 | |||
7472 | if (band < 0 || band >= IEEE80211_NUM_BANDS) | 7569 | if (band < 0 || band >= IEEE80211_NUM_BANDS) |
7473 | return -EINVAL; | 7570 | return -EINVAL; |
7474 | sband = rdev->wiphy.bands[band]; | 7571 | sband = rdev->wiphy.bands[band]; |
7475 | if (sband == NULL) | 7572 | if (sband == NULL) |
7476 | return -EINVAL; | 7573 | return -EINVAL; |
7477 | nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), | 7574 | err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), |
7478 | nla_len(tx_rates), nl80211_txattr_policy); | 7575 | nla_len(tx_rates), nl80211_txattr_policy); |
7576 | if (err) | ||
7577 | return err; | ||
7479 | if (tb[NL80211_TXRATE_LEGACY]) { | 7578 | if (tb[NL80211_TXRATE_LEGACY]) { |
7480 | mask.control[band].legacy = rateset_to_mask( | 7579 | mask.control[band].legacy = rateset_to_mask( |
7481 | sband, | 7580 | sband, |
@@ -7500,6 +7599,12 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
7500 | mask.control[band].vht_mcs)) | 7599 | mask.control[band].vht_mcs)) |
7501 | return -EINVAL; | 7600 | return -EINVAL; |
7502 | } | 7601 | } |
7602 | if (tb[NL80211_TXRATE_GI]) { | ||
7603 | mask.control[band].gi = | ||
7604 | nla_get_u8(tb[NL80211_TXRATE_GI]); | ||
7605 | if (mask.control[band].gi > NL80211_TXRATE_FORCE_LGI) | ||
7606 | return -EINVAL; | ||
7607 | } | ||
7503 | 7608 | ||
7504 | if (mask.control[band].legacy == 0) { | 7609 | if (mask.control[band].legacy == 0) { |
7505 | /* don't allow empty legacy rates if HT or VHT | 7610 | /* don't allow empty legacy rates if HT or VHT |
@@ -7776,8 +7881,8 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) | |||
7776 | return err; | 7881 | return err; |
7777 | } | 7882 | } |
7778 | 7883 | ||
7779 | static struct nla_policy | 7884 | static const struct nla_policy |
7780 | nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { | 7885 | nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { |
7781 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, | 7886 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, |
7782 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, | 7887 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, |
7783 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, | 7888 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, |
@@ -11115,7 +11220,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, | |||
11115 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | 11220 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) |
11116 | return; | 11221 | return; |
11117 | 11222 | ||
11118 | wdev->channel = chandef->chan; | 11223 | wdev->chandef = *chandef; |
11224 | wdev->preset_chandef = *chandef; | ||
11119 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | 11225 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); |
11120 | } | 11226 | } |
11121 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | 11227 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); |
@@ -11629,6 +11735,35 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp) | |||
11629 | } | 11735 | } |
11630 | EXPORT_SYMBOL(cfg80211_crit_proto_stopped); | 11736 | EXPORT_SYMBOL(cfg80211_crit_proto_stopped); |
11631 | 11737 | ||
11738 | void nl80211_send_ap_stopped(struct wireless_dev *wdev) | ||
11739 | { | ||
11740 | struct wiphy *wiphy = wdev->wiphy; | ||
11741 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
11742 | struct sk_buff *msg; | ||
11743 | void *hdr; | ||
11744 | |||
11745 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
11746 | if (!msg) | ||
11747 | return; | ||
11748 | |||
11749 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP); | ||
11750 | if (!hdr) | ||
11751 | goto out; | ||
11752 | |||
11753 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
11754 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) || | ||
11755 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) | ||
11756 | goto out; | ||
11757 | |||
11758 | genlmsg_end(msg, hdr); | ||
11759 | |||
11760 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, | ||
11761 | NL80211_MCGRP_MLME, GFP_KERNEL); | ||
11762 | return; | ||
11763 | out: | ||
11764 | nlmsg_free(msg); | ||
11765 | } | ||
11766 | |||
11632 | /* initialisation/exit functions */ | 11767 | /* initialisation/exit functions */ |
11633 | 11768 | ||
11634 | int nl80211_init(void) | 11769 | int nl80211_init(void) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b1b231324e10..cb0216e1a004 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, | |||
74 | enum nl80211_radar_event event, | 74 | enum nl80211_radar_event event, |
75 | struct net_device *netdev, gfp_t gfp); | 75 | struct net_device *netdev, gfp_t gfp); |
76 | 76 | ||
77 | void nl80211_send_ap_stopped(struct wireless_dev *wdev); | ||
78 | |||
77 | void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); | 79 | void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); |
78 | 80 | ||
79 | #endif /* __NET_WIRELESS_NL80211_H */ | 81 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 9b897fca7487..27c5253e7a61 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -91,7 +91,7 @@ static struct regulatory_request __rcu *last_request = | |||
91 | /* To trigger userspace events */ | 91 | /* To trigger userspace events */ |
92 | static struct platform_device *reg_pdev; | 92 | static struct platform_device *reg_pdev; |
93 | 93 | ||
94 | static struct device_type reg_device_type = { | 94 | static const struct device_type reg_device_type = { |
95 | .uevent = reg_device_uevent, | 95 | .uevent = reg_device_uevent, |
96 | }; | 96 | }; |
97 | 97 | ||
@@ -522,6 +522,77 @@ bool reg_is_valid_request(const char *alpha2) | |||
522 | return alpha2_equal(lr->alpha2, alpha2); | 522 | return alpha2_equal(lr->alpha2, alpha2); |
523 | } | 523 | } |
524 | 524 | ||
525 | static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy) | ||
526 | { | ||
527 | struct regulatory_request *lr = get_last_request(); | ||
528 | |||
529 | /* | ||
530 | * Follow the driver's regulatory domain, if present, unless a country | ||
531 | * IE has been processed or a user wants to help complaince further | ||
532 | */ | ||
533 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
534 | lr->initiator != NL80211_REGDOM_SET_BY_USER && | ||
535 | wiphy->regd) | ||
536 | return get_wiphy_regdom(wiphy); | ||
537 | |||
538 | return get_cfg80211_regdom(); | ||
539 | } | ||
540 | |||
541 | unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, | ||
542 | const struct ieee80211_reg_rule *rule) | ||
543 | { | ||
544 | const struct ieee80211_freq_range *freq_range = &rule->freq_range; | ||
545 | const struct ieee80211_freq_range *freq_range_tmp; | ||
546 | const struct ieee80211_reg_rule *tmp; | ||
547 | u32 start_freq, end_freq, idx, no; | ||
548 | |||
549 | for (idx = 0; idx < rd->n_reg_rules; idx++) | ||
550 | if (rule == &rd->reg_rules[idx]) | ||
551 | break; | ||
552 | |||
553 | if (idx == rd->n_reg_rules) | ||
554 | return 0; | ||
555 | |||
556 | /* get start_freq */ | ||
557 | no = idx; | ||
558 | |||
559 | while (no) { | ||
560 | tmp = &rd->reg_rules[--no]; | ||
561 | freq_range_tmp = &tmp->freq_range; | ||
562 | |||
563 | if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz) | ||
564 | break; | ||
565 | |||
566 | if (freq_range_tmp->max_bandwidth_khz) | ||
567 | break; | ||
568 | |||
569 | freq_range = freq_range_tmp; | ||
570 | } | ||
571 | |||
572 | start_freq = freq_range->start_freq_khz; | ||
573 | |||
574 | /* get end_freq */ | ||
575 | freq_range = &rule->freq_range; | ||
576 | no = idx; | ||
577 | |||
578 | while (no < rd->n_reg_rules - 1) { | ||
579 | tmp = &rd->reg_rules[++no]; | ||
580 | freq_range_tmp = &tmp->freq_range; | ||
581 | |||
582 | if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz) | ||
583 | break; | ||
584 | |||
585 | if (freq_range_tmp->max_bandwidth_khz) | ||
586 | break; | ||
587 | |||
588 | freq_range = freq_range_tmp; | ||
589 | } | ||
590 | |||
591 | end_freq = freq_range->end_freq_khz; | ||
592 | |||
593 | return end_freq - start_freq; | ||
594 | } | ||
595 | |||
525 | /* Sanity check on a regulatory rule */ | 596 | /* Sanity check on a regulatory rule */ |
526 | static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) | 597 | static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) |
527 | { | 598 | { |
@@ -630,7 +701,9 @@ reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1, | |||
630 | * Helper for regdom_intersect(), this does the real | 701 | * Helper for regdom_intersect(), this does the real |
631 | * mathematical intersection fun | 702 | * mathematical intersection fun |
632 | */ | 703 | */ |
633 | static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1, | 704 | static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, |
705 | const struct ieee80211_regdomain *rd2, | ||
706 | const struct ieee80211_reg_rule *rule1, | ||
634 | const struct ieee80211_reg_rule *rule2, | 707 | const struct ieee80211_reg_rule *rule2, |
635 | struct ieee80211_reg_rule *intersected_rule) | 708 | struct ieee80211_reg_rule *intersected_rule) |
636 | { | 709 | { |
@@ -638,7 +711,7 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1, | |||
638 | struct ieee80211_freq_range *freq_range; | 711 | struct ieee80211_freq_range *freq_range; |
639 | const struct ieee80211_power_rule *power_rule1, *power_rule2; | 712 | const struct ieee80211_power_rule *power_rule1, *power_rule2; |
640 | struct ieee80211_power_rule *power_rule; | 713 | struct ieee80211_power_rule *power_rule; |
641 | u32 freq_diff; | 714 | u32 freq_diff, max_bandwidth1, max_bandwidth2; |
642 | 715 | ||
643 | freq_range1 = &rule1->freq_range; | 716 | freq_range1 = &rule1->freq_range; |
644 | freq_range2 = &rule2->freq_range; | 717 | freq_range2 = &rule2->freq_range; |
@@ -652,8 +725,24 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1, | |||
652 | freq_range2->start_freq_khz); | 725 | freq_range2->start_freq_khz); |
653 | freq_range->end_freq_khz = min(freq_range1->end_freq_khz, | 726 | freq_range->end_freq_khz = min(freq_range1->end_freq_khz, |
654 | freq_range2->end_freq_khz); | 727 | freq_range2->end_freq_khz); |
655 | freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz, | 728 | |
656 | freq_range2->max_bandwidth_khz); | 729 | max_bandwidth1 = freq_range1->max_bandwidth_khz; |
730 | max_bandwidth2 = freq_range2->max_bandwidth_khz; | ||
731 | |||
732 | /* | ||
733 | * In case max_bandwidth1 == 0 and max_bandwith2 == 0 set | ||
734 | * output bandwidth as 0 (auto calculation). Next we will | ||
735 | * calculate this correctly in handle_channel function. | ||
736 | * In other case calculate output bandwidth here. | ||
737 | */ | ||
738 | if (max_bandwidth1 || max_bandwidth2) { | ||
739 | if (!max_bandwidth1) | ||
740 | max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1); | ||
741 | if (!max_bandwidth2) | ||
742 | max_bandwidth2 = reg_get_max_bandwidth(rd2, rule2); | ||
743 | } | ||
744 | |||
745 | freq_range->max_bandwidth_khz = min(max_bandwidth1, max_bandwidth2); | ||
657 | 746 | ||
658 | freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; | 747 | freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; |
659 | if (freq_range->max_bandwidth_khz > freq_diff) | 748 | if (freq_range->max_bandwidth_khz > freq_diff) |
@@ -713,7 +802,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1, | |||
713 | rule1 = &rd1->reg_rules[x]; | 802 | rule1 = &rd1->reg_rules[x]; |
714 | for (y = 0; y < rd2->n_reg_rules; y++) { | 803 | for (y = 0; y < rd2->n_reg_rules; y++) { |
715 | rule2 = &rd2->reg_rules[y]; | 804 | rule2 = &rd2->reg_rules[y]; |
716 | if (!reg_rules_intersect(rule1, rule2, &dummy_rule)) | 805 | if (!reg_rules_intersect(rd1, rd2, rule1, rule2, |
806 | &dummy_rule)) | ||
717 | num_rules++; | 807 | num_rules++; |
718 | } | 808 | } |
719 | } | 809 | } |
@@ -738,7 +828,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1, | |||
738 | * a memcpy() | 828 | * a memcpy() |
739 | */ | 829 | */ |
740 | intersected_rule = &rd->reg_rules[rule_idx]; | 830 | intersected_rule = &rd->reg_rules[rule_idx]; |
741 | r = reg_rules_intersect(rule1, rule2, intersected_rule); | 831 | r = reg_rules_intersect(rd1, rd2, rule1, rule2, |
832 | intersected_rule); | ||
742 | /* | 833 | /* |
743 | * No need to memset here the intersected rule here as | 834 | * No need to memset here the intersected rule here as |
744 | * we're not using the stack anymore | 835 | * we're not using the stack anymore |
@@ -821,18 +912,8 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, | |||
821 | u32 center_freq) | 912 | u32 center_freq) |
822 | { | 913 | { |
823 | const struct ieee80211_regdomain *regd; | 914 | const struct ieee80211_regdomain *regd; |
824 | struct regulatory_request *lr = get_last_request(); | ||
825 | 915 | ||
826 | /* | 916 | regd = reg_get_regdomain(wiphy); |
827 | * Follow the driver's regulatory domain, if present, unless a country | ||
828 | * IE has been processed or a user wants to help complaince further | ||
829 | */ | ||
830 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
831 | lr->initiator != NL80211_REGDOM_SET_BY_USER && | ||
832 | wiphy->regd) | ||
833 | regd = get_wiphy_regdom(wiphy); | ||
834 | else | ||
835 | regd = get_cfg80211_regdom(); | ||
836 | 917 | ||
837 | return freq_reg_info_regd(wiphy, center_freq, regd); | 918 | return freq_reg_info_regd(wiphy, center_freq, regd); |
838 | } | 919 | } |
@@ -903,6 +984,8 @@ static void handle_channel(struct wiphy *wiphy, | |||
903 | const struct ieee80211_freq_range *freq_range = NULL; | 984 | const struct ieee80211_freq_range *freq_range = NULL; |
904 | struct wiphy *request_wiphy = NULL; | 985 | struct wiphy *request_wiphy = NULL; |
905 | struct regulatory_request *lr = get_last_request(); | 986 | struct regulatory_request *lr = get_last_request(); |
987 | const struct ieee80211_regdomain *regd; | ||
988 | u32 max_bandwidth_khz; | ||
906 | 989 | ||
907 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); | 990 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); |
908 | 991 | ||
@@ -944,11 +1027,18 @@ static void handle_channel(struct wiphy *wiphy, | |||
944 | power_rule = ®_rule->power_rule; | 1027 | power_rule = ®_rule->power_rule; |
945 | freq_range = ®_rule->freq_range; | 1028 | freq_range = ®_rule->freq_range; |
946 | 1029 | ||
947 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) | 1030 | max_bandwidth_khz = freq_range->max_bandwidth_khz; |
1031 | /* Check if auto calculation requested */ | ||
1032 | if (!max_bandwidth_khz) { | ||
1033 | regd = reg_get_regdomain(wiphy); | ||
1034 | max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); | ||
1035 | } | ||
1036 | |||
1037 | if (max_bandwidth_khz < MHZ_TO_KHZ(40)) | ||
948 | bw_flags = IEEE80211_CHAN_NO_HT40; | 1038 | bw_flags = IEEE80211_CHAN_NO_HT40; |
949 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80)) | 1039 | if (max_bandwidth_khz < MHZ_TO_KHZ(80)) |
950 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; | 1040 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; |
951 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160)) | 1041 | if (max_bandwidth_khz < MHZ_TO_KHZ(160)) |
952 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; | 1042 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; |
953 | 1043 | ||
954 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 1044 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
@@ -1334,6 +1424,7 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1334 | const struct ieee80211_reg_rule *reg_rule = NULL; | 1424 | const struct ieee80211_reg_rule *reg_rule = NULL; |
1335 | const struct ieee80211_power_rule *power_rule = NULL; | 1425 | const struct ieee80211_power_rule *power_rule = NULL; |
1336 | const struct ieee80211_freq_range *freq_range = NULL; | 1426 | const struct ieee80211_freq_range *freq_range = NULL; |
1427 | u32 max_bandwidth_khz; | ||
1337 | 1428 | ||
1338 | reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), | 1429 | reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), |
1339 | regd); | 1430 | regd); |
@@ -1351,11 +1442,16 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1351 | power_rule = ®_rule->power_rule; | 1442 | power_rule = ®_rule->power_rule; |
1352 | freq_range = ®_rule->freq_range; | 1443 | freq_range = ®_rule->freq_range; |
1353 | 1444 | ||
1354 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) | 1445 | max_bandwidth_khz = freq_range->max_bandwidth_khz; |
1446 | /* Check if auto calculation requested */ | ||
1447 | if (!max_bandwidth_khz) | ||
1448 | max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); | ||
1449 | |||
1450 | if (max_bandwidth_khz < MHZ_TO_KHZ(40)) | ||
1355 | bw_flags = IEEE80211_CHAN_NO_HT40; | 1451 | bw_flags = IEEE80211_CHAN_NO_HT40; |
1356 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80)) | 1452 | if (max_bandwidth_khz < MHZ_TO_KHZ(80)) |
1357 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; | 1453 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; |
1358 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160)) | 1454 | if (max_bandwidth_khz < MHZ_TO_KHZ(160)) |
1359 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; | 1455 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; |
1360 | 1456 | ||
1361 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; | 1457 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; |
@@ -1683,17 +1779,9 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1683 | struct wiphy *wiphy = NULL; | 1779 | struct wiphy *wiphy = NULL; |
1684 | enum reg_request_treatment treatment; | 1780 | enum reg_request_treatment treatment; |
1685 | 1781 | ||
1686 | if (WARN_ON(!reg_request->alpha2)) | ||
1687 | return; | ||
1688 | |||
1689 | if (reg_request->wiphy_idx != WIPHY_IDX_INVALID) | 1782 | if (reg_request->wiphy_idx != WIPHY_IDX_INVALID) |
1690 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); | 1783 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); |
1691 | 1784 | ||
1692 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) { | ||
1693 | kfree(reg_request); | ||
1694 | return; | ||
1695 | } | ||
1696 | |||
1697 | switch (reg_request->initiator) { | 1785 | switch (reg_request->initiator) { |
1698 | case NL80211_REGDOM_SET_BY_CORE: | 1786 | case NL80211_REGDOM_SET_BY_CORE: |
1699 | reg_process_hint_core(reg_request); | 1787 | reg_process_hint_core(reg_request); |
@@ -1703,23 +1791,33 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1703 | if (treatment == REG_REQ_OK || | 1791 | if (treatment == REG_REQ_OK || |
1704 | treatment == REG_REQ_ALREADY_SET) | 1792 | treatment == REG_REQ_ALREADY_SET) |
1705 | return; | 1793 | return; |
1706 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | 1794 | queue_delayed_work(system_power_efficient_wq, |
1795 | ®_timeout, msecs_to_jiffies(3142)); | ||
1707 | return; | 1796 | return; |
1708 | case NL80211_REGDOM_SET_BY_DRIVER: | 1797 | case NL80211_REGDOM_SET_BY_DRIVER: |
1798 | if (!wiphy) | ||
1799 | goto out_free; | ||
1709 | treatment = reg_process_hint_driver(wiphy, reg_request); | 1800 | treatment = reg_process_hint_driver(wiphy, reg_request); |
1710 | break; | 1801 | break; |
1711 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 1802 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1803 | if (!wiphy) | ||
1804 | goto out_free; | ||
1712 | treatment = reg_process_hint_country_ie(wiphy, reg_request); | 1805 | treatment = reg_process_hint_country_ie(wiphy, reg_request); |
1713 | break; | 1806 | break; |
1714 | default: | 1807 | default: |
1715 | WARN(1, "invalid initiator %d\n", reg_request->initiator); | 1808 | WARN(1, "invalid initiator %d\n", reg_request->initiator); |
1716 | return; | 1809 | goto out_free; |
1717 | } | 1810 | } |
1718 | 1811 | ||
1719 | /* This is required so that the orig_* parameters are saved */ | 1812 | /* This is required so that the orig_* parameters are saved */ |
1720 | if (treatment == REG_REQ_ALREADY_SET && wiphy && | 1813 | if (treatment == REG_REQ_ALREADY_SET && wiphy && |
1721 | wiphy->regulatory_flags & REGULATORY_STRICT_REG) | 1814 | wiphy->regulatory_flags & REGULATORY_STRICT_REG) |
1722 | wiphy_update_regulatory(wiphy, reg_request->initiator); | 1815 | wiphy_update_regulatory(wiphy, reg_request->initiator); |
1816 | |||
1817 | return; | ||
1818 | |||
1819 | out_free: | ||
1820 | kfree(reg_request); | ||
1723 | } | 1821 | } |
1724 | 1822 | ||
1725 | /* | 1823 | /* |
@@ -2147,6 +2245,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
2147 | const struct ieee80211_reg_rule *reg_rule = NULL; | 2245 | const struct ieee80211_reg_rule *reg_rule = NULL; |
2148 | const struct ieee80211_freq_range *freq_range = NULL; | 2246 | const struct ieee80211_freq_range *freq_range = NULL; |
2149 | const struct ieee80211_power_rule *power_rule = NULL; | 2247 | const struct ieee80211_power_rule *power_rule = NULL; |
2248 | char bw[32]; | ||
2150 | 2249 | ||
2151 | pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n"); | 2250 | pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n"); |
2152 | 2251 | ||
@@ -2155,22 +2254,29 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
2155 | freq_range = ®_rule->freq_range; | 2254 | freq_range = ®_rule->freq_range; |
2156 | power_rule = ®_rule->power_rule; | 2255 | power_rule = ®_rule->power_rule; |
2157 | 2256 | ||
2257 | if (!freq_range->max_bandwidth_khz) | ||
2258 | snprintf(bw, 32, "%d KHz, AUTO", | ||
2259 | reg_get_max_bandwidth(rd, reg_rule)); | ||
2260 | else | ||
2261 | snprintf(bw, 32, "%d KHz", | ||
2262 | freq_range->max_bandwidth_khz); | ||
2263 | |||
2158 | /* | 2264 | /* |
2159 | * There may not be documentation for max antenna gain | 2265 | * There may not be documentation for max antenna gain |
2160 | * in certain regions | 2266 | * in certain regions |
2161 | */ | 2267 | */ |
2162 | if (power_rule->max_antenna_gain) | 2268 | if (power_rule->max_antenna_gain) |
2163 | pr_info(" (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n", | 2269 | pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n", |
2164 | freq_range->start_freq_khz, | 2270 | freq_range->start_freq_khz, |
2165 | freq_range->end_freq_khz, | 2271 | freq_range->end_freq_khz, |
2166 | freq_range->max_bandwidth_khz, | 2272 | bw, |
2167 | power_rule->max_antenna_gain, | 2273 | power_rule->max_antenna_gain, |
2168 | power_rule->max_eirp); | 2274 | power_rule->max_eirp); |
2169 | else | 2275 | else |
2170 | pr_info(" (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n", | 2276 | pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n", |
2171 | freq_range->start_freq_khz, | 2277 | freq_range->start_freq_khz, |
2172 | freq_range->end_freq_khz, | 2278 | freq_range->end_freq_khz, |
2173 | freq_range->max_bandwidth_khz, | 2279 | bw, |
2174 | power_rule->max_eirp); | 2280 | power_rule->max_eirp); |
2175 | } | 2281 | } |
2176 | } | 2282 | } |
@@ -2294,7 +2400,8 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd, | |||
2294 | 2400 | ||
2295 | request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx); | 2401 | request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx); |
2296 | if (!request_wiphy) { | 2402 | if (!request_wiphy) { |
2297 | schedule_delayed_work(®_timeout, 0); | 2403 | queue_delayed_work(system_power_efficient_wq, |
2404 | ®_timeout, 0); | ||
2298 | return -ENODEV; | 2405 | return -ENODEV; |
2299 | } | 2406 | } |
2300 | 2407 | ||
@@ -2354,7 +2461,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, | |||
2354 | 2461 | ||
2355 | request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx); | 2462 | request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx); |
2356 | if (!request_wiphy) { | 2463 | if (!request_wiphy) { |
2357 | schedule_delayed_work(®_timeout, 0); | 2464 | queue_delayed_work(system_power_efficient_wq, |
2465 | ®_timeout, 0); | ||
2358 | return -ENODEV; | 2466 | return -ENODEV; |
2359 | } | 2467 | } |
2360 | 2468 | ||
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 02bd8f4b0921..18524617ab62 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -34,6 +34,8 @@ int __init regulatory_init(void); | |||
34 | void regulatory_exit(void); | 34 | void regulatory_exit(void); |
35 | 35 | ||
36 | int set_regdom(const struct ieee80211_regdomain *rd); | 36 | int set_regdom(const struct ieee80211_regdomain *rd); |
37 | unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, | ||
38 | const struct ieee80211_reg_rule *rule); | ||
37 | 39 | ||
38 | bool reg_last_request_cell_base(void); | 40 | bool reg_last_request_cell_base(void); |
39 | 41 | ||
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index fbcc23edee54..5eaeed59db07 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt, | |||
2278 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) | 2278 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) |
2279 | ); | 2279 | ); |
2280 | 2280 | ||
2281 | DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined, | ||
2282 | TP_PROTO(struct net_device *netdev, const u8 *addr), | ||
2283 | TP_ARGS(netdev, addr) | ||
2284 | ); | ||
2285 | |||
2286 | DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame, | 2281 | DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame, |
2287 | TP_PROTO(struct net_device *netdev, const u8 *addr), | 2282 | TP_PROTO(struct net_device *netdev, const u8 *addr), |
2288 | TP_ARGS(netdev, addr) | 2283 | TP_ARGS(netdev, addr) |
@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame, | |||
2293 | TP_ARGS(netdev, addr) | 2288 | TP_ARGS(netdev, addr) |
2294 | ); | 2289 | ); |
2295 | 2290 | ||
2291 | TRACE_EVENT(cfg80211_ibss_joined, | ||
2292 | TP_PROTO(struct net_device *netdev, const u8 *bssid, | ||
2293 | struct ieee80211_channel *channel), | ||
2294 | TP_ARGS(netdev, bssid, channel), | ||
2295 | TP_STRUCT__entry( | ||
2296 | NETDEV_ENTRY | ||
2297 | MAC_ENTRY(bssid) | ||
2298 | CHAN_ENTRY | ||
2299 | ), | ||
2300 | TP_fast_assign( | ||
2301 | NETDEV_ASSIGN; | ||
2302 | MAC_ASSIGN(bssid, bssid); | ||
2303 | CHAN_ASSIGN(channel); | ||
2304 | ), | ||
2305 | TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT, | ||
2306 | NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) | ||
2307 | ); | ||
2308 | |||
2296 | TRACE_EVENT(cfg80211_probe_status, | 2309 | TRACE_EVENT(cfg80211_probe_status, |
2297 | TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie, | 2310 | TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie, |
2298 | bool acked), | 2311 | bool acked), |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d39c37104ae2..780b4546c9c7 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) | |||
820 | ev->dc.reason, true); | 820 | ev->dc.reason, true); |
821 | break; | 821 | break; |
822 | case EVENT_IBSS_JOINED: | 822 | case EVENT_IBSS_JOINED: |
823 | __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid); | 823 | __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, |
824 | ev->ij.channel); | ||
824 | break; | 825 | break; |
825 | } | 826 | } |
826 | wdev_unlock(wdev); | 827 | wdev_unlock(wdev); |
@@ -1356,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1356 | */ | 1357 | */ |
1357 | mutex_lock_nested(&wdev_iter->mtx, 1); | 1358 | mutex_lock_nested(&wdev_iter->mtx, 1); |
1358 | __acquire(wdev_iter->mtx); | 1359 | __acquire(wdev_iter->mtx); |
1359 | cfg80211_get_chan_state(wdev_iter, &ch, &chmode); | 1360 | cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect); |
1360 | wdev_unlock(wdev_iter); | 1361 | wdev_unlock(wdev_iter); |
1361 | 1362 | ||
1362 | switch (chmode) { | 1363 | switch (chmode) { |