aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/mlme.c95
-rw-r--r--net/mac80211/offchannel.c2
-rw-r--r--net/mac80211/rate.c15
-rw-r--r--net/mac80211/rx.c3
-rw-r--r--net/mac80211/scan.c19
-rw-r--r--net/mac80211/status.c3
-rw-r--r--net/mac80211/tx.c3
-rw-r--r--net/mac80211/util.c9
-rw-r--r--net/wireless/core.c23
-rw-r--r--net/wireless/core.h3
-rw-r--r--net/wireless/ibss.c3
-rw-r--r--net/wireless/nl80211.c4
-rw-r--r--net/wireless/radiotap.c7
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
339struct ieee80211_mgd_auth_data { 340struct 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 */
897enum { 900enum {
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
3941static 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
3940int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, 3979int 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,
235static void __rate_control_send_low(struct ieee80211_hw *hw, 235static 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}
611EXPORT_SYMBOL(wiphy_register); 615EXPORT_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
402cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, 402cfg80211_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 }