diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/mac80211/cfg.c | 2 | ||||
| -rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
| -rw-r--r-- | net/mac80211/mlme.c | 95 | ||||
| -rw-r--r-- | net/mac80211/offchannel.c | 2 | ||||
| -rw-r--r-- | net/mac80211/rate.c | 15 | ||||
| -rw-r--r-- | net/mac80211/rx.c | 3 | ||||
| -rw-r--r-- | net/mac80211/scan.c | 19 | ||||
| -rw-r--r-- | net/mac80211/status.c | 3 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 3 | ||||
| -rw-r--r-- | net/mac80211/util.c | 9 | ||||
| -rw-r--r-- | net/wireless/core.c | 23 | ||||
| -rw-r--r-- | net/wireless/core.h | 3 | ||||
| -rw-r--r-- | net/wireless/ibss.c | 3 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 4 | ||||
| -rw-r--r-- | net/wireless/radiotap.c | 7 |
15 files changed, 164 insertions, 31 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ac28af74a414..b0a651cc389f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -3564,7 +3564,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
| 3564 | return -EINVAL; | 3564 | return -EINVAL; |
| 3565 | } | 3565 | } |
| 3566 | band = chanctx_conf->def.chan->band; | 3566 | band = chanctx_conf->def.chan->band; |
| 3567 | sta = sta_info_get(sdata, peer); | 3567 | sta = sta_info_get_bss(sdata, peer); |
| 3568 | if (sta) { | 3568 | if (sta) { |
| 3569 | qos = test_sta_flag(sta, WLAN_STA_WME); | 3569 | qos = test_sta_flag(sta, WLAN_STA_WME); |
| 3570 | } else { | 3570 | } else { |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3a87c8976a32..fe48b093d4dc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -334,6 +334,7 @@ enum ieee80211_sta_flags { | |||
| 334 | IEEE80211_STA_DISABLE_VHT = BIT(11), | 334 | IEEE80211_STA_DISABLE_VHT = BIT(11), |
| 335 | IEEE80211_STA_DISABLE_80P80MHZ = BIT(12), | 335 | IEEE80211_STA_DISABLE_80P80MHZ = BIT(12), |
| 336 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), | 336 | IEEE80211_STA_DISABLE_160MHZ = BIT(13), |
| 337 | IEEE80211_STA_DISABLE_WMM = BIT(14), | ||
| 337 | }; | 338 | }; |
| 338 | 339 | ||
| 339 | struct ieee80211_mgd_auth_data { | 340 | struct ieee80211_mgd_auth_data { |
| @@ -893,6 +894,8 @@ struct tpt_led_trigger { | |||
| 893 | * that the scan completed. | 894 | * that the scan completed. |
| 894 | * @SCAN_ABORTED: Set for our scan work function when the driver reported | 895 | * @SCAN_ABORTED: Set for our scan work function when the driver reported |
| 895 | * a scan complete for an aborted scan. | 896 | * a scan complete for an aborted scan. |
| 897 | * @SCAN_HW_CANCELLED: Set for our scan work function when the scan is being | ||
| 898 | * cancelled. | ||
| 896 | */ | 899 | */ |
| 897 | enum { | 900 | enum { |
| 898 | SCAN_SW_SCANNING, | 901 | SCAN_SW_SCANNING, |
| @@ -900,6 +903,7 @@ enum { | |||
| 900 | SCAN_ONCHANNEL_SCANNING, | 903 | SCAN_ONCHANNEL_SCANNING, |
| 901 | SCAN_COMPLETED, | 904 | SCAN_COMPLETED, |
| 902 | SCAN_ABORTED, | 905 | SCAN_ABORTED, |
| 906 | SCAN_HW_CANCELLED, | ||
| 903 | }; | 907 | }; |
| 904 | 908 | ||
| 905 | /** | 909 | /** |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 91cc8281e266..d7bdc4b97dde 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -2527,7 +2527,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
| 2527 | */ | 2527 | */ |
| 2528 | ifmgd->wmm_last_param_set = -1; | 2528 | ifmgd->wmm_last_param_set = -1; |
| 2529 | 2529 | ||
| 2530 | if (elems.wmm_param) | 2530 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && elems.wmm_param) |
| 2531 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 2531 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, |
| 2532 | elems.wmm_param_len); | 2532 | elems.wmm_param_len); |
| 2533 | else | 2533 | else |
| @@ -2955,7 +2955,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 2955 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, | 2955 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, |
| 2956 | &elems, true); | 2956 | &elems, true); |
| 2957 | 2957 | ||
| 2958 | if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | 2958 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && |
| 2959 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | ||
| 2959 | elems.wmm_param_len)) | 2960 | elems.wmm_param_len)) |
| 2960 | changed |= BSS_CHANGED_QOS; | 2961 | changed |= BSS_CHANGED_QOS; |
| 2961 | 2962 | ||
| @@ -3937,6 +3938,44 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
| 3937 | return err; | 3938 | return err; |
| 3938 | } | 3939 | } |
| 3939 | 3940 | ||
| 3941 | static bool ieee80211_usable_wmm_params(struct ieee80211_sub_if_data *sdata, | ||
| 3942 | const u8 *wmm_param, int len) | ||
| 3943 | { | ||
| 3944 | const u8 *pos; | ||
| 3945 | size_t left; | ||
| 3946 | |||
| 3947 | if (len < 8) | ||
| 3948 | return false; | ||
| 3949 | |||
| 3950 | if (wmm_param[5] != 1 /* version */) | ||
| 3951 | return false; | ||
| 3952 | |||
| 3953 | pos = wmm_param + 8; | ||
| 3954 | left = len - 8; | ||
| 3955 | |||
| 3956 | for (; left >= 4; left -= 4, pos += 4) { | ||
| 3957 | u8 aifsn = pos[0] & 0x0f; | ||
| 3958 | u8 ecwmin = pos[1] & 0x0f; | ||
| 3959 | u8 ecwmax = (pos[1] & 0xf0) >> 4; | ||
| 3960 | int aci = (pos[0] >> 5) & 0x03; | ||
| 3961 | |||
| 3962 | if (aifsn < 2) { | ||
| 3963 | sdata_info(sdata, | ||
| 3964 | "AP has invalid WMM params (AIFSN=%d for ACI %d), disabling WMM\n", | ||
| 3965 | aifsn, aci); | ||
| 3966 | return false; | ||
| 3967 | } | ||
| 3968 | if (ecwmin > ecwmax) { | ||
| 3969 | sdata_info(sdata, | ||
| 3970 | "AP has invalid WMM params (ECWmin/max=%d/%d for ACI %d), disabling WMM\n", | ||
| 3971 | ecwmin, ecwmax, aci); | ||
| 3972 | return false; | ||
| 3973 | } | ||
| 3974 | } | ||
| 3975 | |||
| 3976 | return true; | ||
| 3977 | } | ||
| 3978 | |||
| 3940 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | 3979 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, |
| 3941 | struct cfg80211_assoc_request *req) | 3980 | struct cfg80211_assoc_request *req) |
| 3942 | { | 3981 | { |
| @@ -3994,9 +4033,45 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 3994 | } | 4033 | } |
| 3995 | 4034 | ||
| 3996 | /* prepare assoc data */ | 4035 | /* prepare assoc data */ |
| 3997 | 4036 | ||
| 3998 | ifmgd->beacon_crc_valid = false; | 4037 | ifmgd->beacon_crc_valid = false; |
| 3999 | 4038 | ||
| 4039 | assoc_data->wmm = bss->wmm_used && | ||
| 4040 | (local->hw.queues >= IEEE80211_NUM_ACS); | ||
| 4041 | if (assoc_data->wmm) { | ||
| 4042 | /* try to check validity of WMM params IE */ | ||
| 4043 | const struct cfg80211_bss_ies *ies; | ||
| 4044 | const u8 *wp, *start, *end; | ||
| 4045 | |||
| 4046 | rcu_read_lock(); | ||
| 4047 | ies = rcu_dereference(req->bss->ies); | ||
| 4048 | start = ies->data; | ||
| 4049 | end = start + ies->len; | ||
| 4050 | |||
| 4051 | while (true) { | ||
| 4052 | wp = cfg80211_find_vendor_ie( | ||
| 4053 | WLAN_OUI_MICROSOFT, | ||
| 4054 | WLAN_OUI_TYPE_MICROSOFT_WMM, | ||
| 4055 | start, end - start); | ||
| 4056 | if (!wp) | ||
| 4057 | break; | ||
| 4058 | start = wp + wp[1] + 2; | ||
| 4059 | /* if this IE is too short, try the next */ | ||
| 4060 | if (wp[1] <= 4) | ||
| 4061 | continue; | ||
| 4062 | /* if this IE is WMM params, we found what we wanted */ | ||
| 4063 | if (wp[6] == 1) | ||
| 4064 | break; | ||
| 4065 | } | ||
| 4066 | |||
| 4067 | if (!wp || !ieee80211_usable_wmm_params(sdata, wp + 2, | ||
| 4068 | wp[1] - 2)) { | ||
| 4069 | assoc_data->wmm = false; | ||
| 4070 | ifmgd->flags |= IEEE80211_STA_DISABLE_WMM; | ||
| 4071 | } | ||
| 4072 | rcu_read_unlock(); | ||
| 4073 | } | ||
| 4074 | |||
| 4000 | /* | 4075 | /* |
| 4001 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. | 4076 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. |
| 4002 | * We still associate in non-HT mode (11a/b/g) if any one of these | 4077 | * We still associate in non-HT mode (11a/b/g) if any one of these |
| @@ -4026,18 +4101,22 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 4026 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 4101 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
| 4027 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 4102 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
| 4028 | if (!sband->ht_cap.ht_supported || | 4103 | if (!sband->ht_cap.ht_supported || |
| 4029 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 4104 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || |
| 4105 | ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { | ||
| 4030 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; | 4106 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
| 4031 | if (!bss->wmm_used) | 4107 | if (!bss->wmm_used && |
| 4108 | !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) | ||
| 4032 | netdev_info(sdata->dev, | 4109 | netdev_info(sdata->dev, |
| 4033 | "disabling HT as WMM/QoS is not supported by the AP\n"); | 4110 | "disabling HT as WMM/QoS is not supported by the AP\n"); |
| 4034 | } | 4111 | } |
| 4035 | 4112 | ||
| 4036 | /* disable VHT if we don't support it or the AP doesn't use WMM */ | 4113 | /* disable VHT if we don't support it or the AP doesn't use WMM */ |
| 4037 | if (!sband->vht_cap.vht_supported || | 4114 | if (!sband->vht_cap.vht_supported || |
| 4038 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 4115 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || |
| 4116 | ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { | ||
| 4039 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 4117 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
| 4040 | if (!bss->wmm_used) | 4118 | if (!bss->wmm_used && |
| 4119 | !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) | ||
| 4041 | netdev_info(sdata->dev, | 4120 | netdev_info(sdata->dev, |
| 4042 | "disabling VHT as WMM/QoS is not supported by the AP\n"); | 4121 | "disabling VHT as WMM/QoS is not supported by the AP\n"); |
| 4043 | } | 4122 | } |
| @@ -4066,8 +4145,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 4066 | sdata->smps_mode = ifmgd->req_smps; | 4145 | sdata->smps_mode = ifmgd->req_smps; |
| 4067 | 4146 | ||
| 4068 | assoc_data->capability = req->bss->capability; | 4147 | assoc_data->capability = req->bss->capability; |
| 4069 | assoc_data->wmm = bss->wmm_used && | ||
| 4070 | (local->hw.queues >= IEEE80211_NUM_ACS); | ||
| 4071 | assoc_data->supp_rates = bss->supp_rates; | 4148 | assoc_data->supp_rates = bss->supp_rates; |
| 4072 | assoc_data->supp_rates_len = bss->supp_rates_len; | 4149 | assoc_data->supp_rates_len = bss->supp_rates_len; |
| 4073 | 4150 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index acd1f71adc03..0c2a29484c07 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
| @@ -394,6 +394,8 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
| 394 | 394 | ||
| 395 | if (started) | 395 | if (started) |
| 396 | ieee80211_start_next_roc(local); | 396 | ieee80211_start_next_roc(local); |
| 397 | else if (list_empty(&local->roc_list)) | ||
| 398 | ieee80211_run_deferred_scan(local); | ||
| 397 | } | 399 | } |
| 398 | 400 | ||
| 399 | out_unlock: | 401 | out_unlock: |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index e126605cec66..22b223f13c9f 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
| @@ -235,7 +235,8 @@ static void rc_send_low_basicrate(s8 *idx, u32 basic_rates, | |||
| 235 | static void __rate_control_send_low(struct ieee80211_hw *hw, | 235 | static void __rate_control_send_low(struct ieee80211_hw *hw, |
| 236 | struct ieee80211_supported_band *sband, | 236 | struct ieee80211_supported_band *sband, |
| 237 | struct ieee80211_sta *sta, | 237 | struct ieee80211_sta *sta, |
| 238 | struct ieee80211_tx_info *info) | 238 | struct ieee80211_tx_info *info, |
| 239 | u32 rate_mask) | ||
| 239 | { | 240 | { |
| 240 | int i; | 241 | int i; |
| 241 | u32 rate_flags = | 242 | u32 rate_flags = |
| @@ -247,6 +248,12 @@ static void __rate_control_send_low(struct ieee80211_hw *hw, | |||
| 247 | 248 | ||
| 248 | info->control.rates[0].idx = 0; | 249 | info->control.rates[0].idx = 0; |
| 249 | for (i = 0; i < sband->n_bitrates; i++) { | 250 | for (i = 0; i < sband->n_bitrates; i++) { |
| 251 | if (!(rate_mask & BIT(i))) | ||
| 252 | continue; | ||
| 253 | |||
| 254 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
| 255 | continue; | ||
| 256 | |||
| 250 | if (!rate_supported(sta, sband->band, i)) | 257 | if (!rate_supported(sta, sband->band, i)) |
| 251 | continue; | 258 | continue; |
| 252 | 259 | ||
| @@ -274,7 +281,8 @@ bool rate_control_send_low(struct ieee80211_sta *pubsta, | |||
| 274 | bool use_basicrate = false; | 281 | bool use_basicrate = false; |
| 275 | 282 | ||
| 276 | if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { | 283 | if (!pubsta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) { |
| 277 | __rate_control_send_low(txrc->hw, sband, pubsta, info); | 284 | __rate_control_send_low(txrc->hw, sband, pubsta, info, |
| 285 | txrc->rate_idx_mask); | ||
| 278 | 286 | ||
| 279 | if (!pubsta && txrc->bss) { | 287 | if (!pubsta && txrc->bss) { |
| 280 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; | 288 | mcast_rate = txrc->bss_conf->mcast_rate[sband->band]; |
| @@ -656,7 +664,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, | |||
| 656 | rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates); | 664 | rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates); |
| 657 | 665 | ||
| 658 | if (dest[0].idx < 0) | 666 | if (dest[0].idx < 0) |
| 659 | __rate_control_send_low(&sdata->local->hw, sband, sta, info); | 667 | __rate_control_send_low(&sdata->local->hw, sband, sta, info, |
| 668 | sdata->rc_rateidx_mask[info->band]); | ||
| 660 | 669 | ||
| 661 | if (sta) | 670 | if (sta) |
| 662 | rate_fixup_ratelist(vif, sband, info, dest, max_rates); | 671 | rate_fixup_ratelist(vif, sband, info, dest, max_rates); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f0247a43a75c..0011ac815097 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -3073,6 +3073,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
| 3073 | case NL80211_IFTYPE_ADHOC: | 3073 | case NL80211_IFTYPE_ADHOC: |
| 3074 | if (!bssid) | 3074 | if (!bssid) |
| 3075 | return 0; | 3075 | return 0; |
| 3076 | if (ether_addr_equal(sdata->vif.addr, hdr->addr2) || | ||
| 3077 | ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2)) | ||
| 3078 | return 0; | ||
| 3076 | if (ieee80211_is_beacon(hdr->frame_control)) { | 3079 | if (ieee80211_is_beacon(hdr->frame_control)) { |
| 3077 | return 1; | 3080 | return 1; |
| 3078 | } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) { | 3081 | } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) { |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index ecb57b0bf74a..5ad66a83ef7f 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
| @@ -238,6 +238,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
| 238 | enum ieee80211_band band; | 238 | enum ieee80211_band band; |
| 239 | int i, ielen, n_chans; | 239 | int i, ielen, n_chans; |
| 240 | 240 | ||
| 241 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) | ||
| 242 | return false; | ||
| 243 | |||
| 241 | do { | 244 | do { |
| 242 | if (local->hw_scan_band == IEEE80211_NUM_BANDS) | 245 | if (local->hw_scan_band == IEEE80211_NUM_BANDS) |
| 243 | return false; | 246 | return false; |
| @@ -939,7 +942,23 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
| 939 | if (!local->scan_req) | 942 | if (!local->scan_req) |
| 940 | goto out; | 943 | goto out; |
| 941 | 944 | ||
| 945 | /* | ||
| 946 | * We have a scan running and the driver already reported completion, | ||
| 947 | * but the worker hasn't run yet or is stuck on the mutex - mark it as | ||
| 948 | * cancelled. | ||
| 949 | */ | ||
| 950 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) && | ||
| 951 | test_bit(SCAN_COMPLETED, &local->scanning)) { | ||
| 952 | set_bit(SCAN_HW_CANCELLED, &local->scanning); | ||
| 953 | goto out; | ||
| 954 | } | ||
| 955 | |||
| 942 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { | 956 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { |
| 957 | /* | ||
| 958 | * Make sure that __ieee80211_scan_completed doesn't trigger a | ||
| 959 | * scan on another band. | ||
| 960 | */ | ||
| 961 | set_bit(SCAN_HW_CANCELLED, &local->scanning); | ||
| 943 | if (local->ops->cancel_hw_scan) | 962 | if (local->ops->cancel_hw_scan) |
| 944 | drv_cancel_hw_scan(local, | 963 | drv_cancel_hw_scan(local, |
| 945 | rcu_dereference_protected(local->scan_sdata, | 964 | rcu_dereference_protected(local->scan_sdata, |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 368837fe3b80..78dc2e99027e 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
| @@ -180,6 +180,9 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | |||
| 180 | struct ieee80211_local *local = sta->local; | 180 | struct ieee80211_local *local = sta->local; |
| 181 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 181 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
| 182 | 182 | ||
| 183 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | ||
| 184 | sta->last_rx = jiffies; | ||
| 185 | |||
| 183 | if (ieee80211_is_data_qos(mgmt->frame_control)) { | 186 | if (ieee80211_is_data_qos(mgmt->frame_control)) { |
| 184 | struct ieee80211_hdr *hdr = (void *) skb->data; | 187 | struct ieee80211_hdr *hdr = (void *) skb->data; |
| 185 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 188 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4fcbf634b548..9993fcb19ecd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -1120,7 +1120,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
| 1120 | tx->sta = rcu_dereference(sdata->u.vlan.sta); | 1120 | tx->sta = rcu_dereference(sdata->u.vlan.sta); |
| 1121 | if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) | 1121 | if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) |
| 1122 | return TX_DROP; | 1122 | return TX_DROP; |
| 1123 | } else if (info->flags & IEEE80211_TX_CTL_INJECTED || | 1123 | } else if (info->flags & (IEEE80211_TX_CTL_INJECTED | |
| 1124 | IEEE80211_TX_INTFL_NL80211_FRAME_TX) || | ||
| 1124 | tx->sdata->control_port_protocol == tx->skb->protocol) { | 1125 | tx->sdata->control_port_protocol == tx->skb->protocol) { |
| 1125 | tx->sta = sta_info_get_bss(sdata, hdr->addr1); | 1126 | tx->sta = sta_info_get_bss(sdata, hdr->addr1); |
| 1126 | } | 1127 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 550a6880625d..aefb9d5b9620 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -2101,7 +2101,7 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
| 2101 | { | 2101 | { |
| 2102 | struct ieee80211_local *local = sdata->local; | 2102 | struct ieee80211_local *local = sdata->local; |
| 2103 | struct ieee80211_supported_band *sband; | 2103 | struct ieee80211_supported_band *sband; |
| 2104 | int rate, skip, shift; | 2104 | int rate, shift; |
| 2105 | u8 i, exrates, *pos; | 2105 | u8 i, exrates, *pos; |
| 2106 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 2106 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
| 2107 | u32 rate_flags; | 2107 | u32 rate_flags; |
| @@ -2129,14 +2129,11 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
| 2129 | pos = skb_put(skb, exrates + 2); | 2129 | pos = skb_put(skb, exrates + 2); |
| 2130 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 2130 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
| 2131 | *pos++ = exrates; | 2131 | *pos++ = exrates; |
| 2132 | skip = 0; | ||
| 2133 | for (i = 8; i < sband->n_bitrates; i++) { | 2132 | for (i = 8; i < sband->n_bitrates; i++) { |
| 2134 | u8 basic = 0; | 2133 | u8 basic = 0; |
| 2135 | if ((rate_flags & sband->bitrates[i].flags) | 2134 | if ((rate_flags & sband->bitrates[i].flags) |
| 2136 | != rate_flags) | 2135 | != rate_flags) |
| 2137 | continue; | 2136 | continue; |
| 2138 | if (skip++ < 8) | ||
| 2139 | continue; | ||
| 2140 | if (need_basic && basic_rates & BIT(i)) | 2137 | if (need_basic && basic_rates & BIT(i)) |
| 2141 | basic = 0x80; | 2138 | basic = 0x80; |
| 2142 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, | 2139 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
| @@ -2239,6 +2236,10 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
| 2239 | } | 2236 | } |
| 2240 | 2237 | ||
| 2241 | rate = cfg80211_calculate_bitrate(&ri); | 2238 | rate = cfg80211_calculate_bitrate(&ri); |
| 2239 | if (WARN_ONCE(!rate, | ||
| 2240 | "Invalid bitrate: flags=0x%x, idx=%d, vht_nss=%d\n", | ||
| 2241 | status->flag, status->rate_idx, status->vht_nss)) | ||
| 2242 | return 0; | ||
| 2242 | 2243 | ||
| 2243 | /* rewind from end of MPDU */ | 2244 | /* rewind from end of MPDU */ |
| 2244 | if (status->flag & RX_FLAG_MACTIME_END) | 2245 | if (status->flag & RX_FLAG_MACTIME_END) |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 67153964aad2..aff959e5a1b3 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -566,18 +566,13 @@ int wiphy_register(struct wiphy *wiphy) | |||
| 566 | /* check and set up bitrates */ | 566 | /* check and set up bitrates */ |
| 567 | ieee80211_set_bitrate_flags(wiphy); | 567 | ieee80211_set_bitrate_flags(wiphy); |
| 568 | 568 | ||
| 569 | 569 | rtnl_lock(); | |
| 570 | res = device_add(&rdev->wiphy.dev); | 570 | res = device_add(&rdev->wiphy.dev); |
| 571 | if (res) | ||
| 572 | return res; | ||
| 573 | |||
| 574 | res = rfkill_register(rdev->rfkill); | ||
| 575 | if (res) { | 571 | if (res) { |
| 576 | device_del(&rdev->wiphy.dev); | 572 | rtnl_unlock(); |
| 577 | return res; | 573 | return res; |
| 578 | } | 574 | } |
| 579 | 575 | ||
| 580 | rtnl_lock(); | ||
| 581 | /* set up regulatory info */ | 576 | /* set up regulatory info */ |
| 582 | wiphy_regulatory_register(wiphy); | 577 | wiphy_regulatory_register(wiphy); |
| 583 | 578 | ||
| @@ -606,6 +601,15 @@ int wiphy_register(struct wiphy *wiphy) | |||
| 606 | 601 | ||
| 607 | rdev->wiphy.registered = true; | 602 | rdev->wiphy.registered = true; |
| 608 | rtnl_unlock(); | 603 | rtnl_unlock(); |
| 604 | |||
| 605 | res = rfkill_register(rdev->rfkill); | ||
| 606 | if (res) { | ||
| 607 | rfkill_destroy(rdev->rfkill); | ||
| 608 | rdev->rfkill = NULL; | ||
| 609 | wiphy_unregister(&rdev->wiphy); | ||
| 610 | return res; | ||
| 611 | } | ||
| 612 | |||
| 609 | return 0; | 613 | return 0; |
| 610 | } | 614 | } |
| 611 | EXPORT_SYMBOL(wiphy_register); | 615 | EXPORT_SYMBOL(wiphy_register); |
| @@ -640,7 +644,8 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
| 640 | rtnl_unlock(); | 644 | rtnl_unlock(); |
| 641 | __count == 0; })); | 645 | __count == 0; })); |
| 642 | 646 | ||
| 643 | rfkill_unregister(rdev->rfkill); | 647 | if (rdev->rfkill) |
| 648 | rfkill_unregister(rdev->rfkill); | ||
| 644 | 649 | ||
| 645 | rtnl_lock(); | 650 | rtnl_lock(); |
| 646 | rdev->wiphy.registered = false; | 651 | rdev->wiphy.registered = false; |
| @@ -953,8 +958,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
| 953 | case NETDEV_PRE_UP: | 958 | case NETDEV_PRE_UP: |
| 954 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) | 959 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) |
| 955 | return notifier_from_errno(-EOPNOTSUPP); | 960 | return notifier_from_errno(-EOPNOTSUPP); |
| 956 | if (rfkill_blocked(rdev->rfkill)) | ||
| 957 | return notifier_from_errno(-ERFKILL); | ||
| 958 | ret = cfg80211_can_add_interface(rdev, wdev->iftype); | 961 | ret = cfg80211_can_add_interface(rdev, wdev->iftype); |
| 959 | if (ret) | 962 | if (ret) |
| 960 | return notifier_from_errno(ret); | 963 | return notifier_from_errno(ret); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index b43efac4efca..eb0f7a3a25a9 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -402,6 +402,9 @@ static inline int | |||
| 402 | cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, | 402 | cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, |
| 403 | enum nl80211_iftype iftype) | 403 | enum nl80211_iftype iftype) |
| 404 | { | 404 | { |
| 405 | if (rfkill_blocked(rdev->rfkill)) | ||
| 406 | return -ERFKILL; | ||
| 407 | |||
| 405 | return cfg80211_can_change_interface(rdev, NULL, iftype); | 408 | return cfg80211_can_change_interface(rdev, NULL, iftype); |
| 406 | } | 409 | } |
| 407 | 410 | ||
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 39bff7d36768..403fe29c024d 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
| @@ -263,6 +263,8 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
| 263 | if (chan->flags & IEEE80211_CHAN_DISABLED) | 263 | if (chan->flags & IEEE80211_CHAN_DISABLED) |
| 264 | continue; | 264 | continue; |
| 265 | wdev->wext.ibss.chandef.chan = chan; | 265 | wdev->wext.ibss.chandef.chan = chan; |
| 266 | wdev->wext.ibss.chandef.center_freq1 = | ||
| 267 | chan->center_freq; | ||
| 266 | break; | 268 | break; |
| 267 | } | 269 | } |
| 268 | 270 | ||
| @@ -347,6 +349,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | |||
| 347 | if (chan) { | 349 | if (chan) { |
| 348 | wdev->wext.ibss.chandef.chan = chan; | 350 | wdev->wext.ibss.chandef.chan = chan; |
| 349 | wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | 351 | wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT; |
| 352 | wdev->wext.ibss.chandef.center_freq1 = freq; | ||
| 350 | wdev->wext.ibss.channel_fixed = true; | 353 | wdev->wext.ibss.channel_fixed = true; |
| 351 | } else { | 354 | } else { |
| 352 | /* cfg80211_ibss_wext_join will pick one if needed */ | 355 | /* cfg80211_ibss_wext_join will pick one if needed */ |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2838206ddad3..cbbef88a8ebd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -2421,7 +2421,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 2421 | change = true; | 2421 | change = true; |
| 2422 | } | 2422 | } |
| 2423 | 2423 | ||
| 2424 | if (flags && (*flags & NL80211_MNTR_FLAG_ACTIVE) && | 2424 | if (flags && (*flags & MONITOR_FLAG_ACTIVE) && |
| 2425 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | 2425 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) |
| 2426 | return -EOPNOTSUPP; | 2426 | return -EOPNOTSUPP; |
| 2427 | 2427 | ||
| @@ -2483,7 +2483,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 2483 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 2483 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, |
| 2484 | &flags); | 2484 | &flags); |
| 2485 | 2485 | ||
| 2486 | if (!err && (flags & NL80211_MNTR_FLAG_ACTIVE) && | 2486 | if (!err && (flags & MONITOR_FLAG_ACTIVE) && |
| 2487 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | 2487 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) |
| 2488 | return -EOPNOTSUPP; | 2488 | return -EOPNOTSUPP; |
| 2489 | 2489 | ||
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index 7d604c06c3dc..a271c27fac77 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c | |||
| @@ -97,6 +97,10 @@ int ieee80211_radiotap_iterator_init( | |||
| 97 | struct ieee80211_radiotap_header *radiotap_header, | 97 | struct ieee80211_radiotap_header *radiotap_header, |
| 98 | int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) | 98 | int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) |
| 99 | { | 99 | { |
| 100 | /* check the radiotap header can actually be present */ | ||
| 101 | if (max_length < sizeof(struct ieee80211_radiotap_header)) | ||
| 102 | return -EINVAL; | ||
| 103 | |||
| 100 | /* Linux only supports version 0 radiotap format */ | 104 | /* Linux only supports version 0 radiotap format */ |
| 101 | if (radiotap_header->it_version) | 105 | if (radiotap_header->it_version) |
| 102 | return -EINVAL; | 106 | return -EINVAL; |
| @@ -131,7 +135,8 @@ int ieee80211_radiotap_iterator_init( | |||
| 131 | */ | 135 | */ |
| 132 | 136 | ||
| 133 | if ((unsigned long)iterator->_arg - | 137 | if ((unsigned long)iterator->_arg - |
| 134 | (unsigned long)iterator->_rtheader > | 138 | (unsigned long)iterator->_rtheader + |
| 139 | sizeof(uint32_t) > | ||
| 135 | (unsigned long)iterator->_max_length) | 140 | (unsigned long)iterator->_max_length) |
| 136 | return -EINVAL; | 141 | return -EINVAL; |
| 137 | } | 142 | } |
