diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 61 | ||||
-rw-r--r-- | net/mac80211/rate.c | 9 | ||||
-rw-r--r-- | net/mac80211/rx.c | 3 | ||||
-rw-r--r-- | net/mac80211/tkip.c | 4 | ||||
-rw-r--r-- | net/mac80211/util.c | 7 |
6 files changed, 72 insertions, 13 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 158e6eb188d3..44be28cfc6c4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1267,6 +1267,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | |||
1267 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); | 1267 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); |
1268 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, | 1268 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, |
1269 | __le16 fc, bool acked); | 1269 | __le16 fc, bool acked); |
1270 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | ||
1270 | 1271 | ||
1271 | /* IBSS code */ | 1272 | /* IBSS code */ |
1272 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1273 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 29620bfc7a69..a46e490f20dd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1015,7 +1015,8 @@ static void ieee80211_chswitch_timer(unsigned long data) | |||
1015 | 1015 | ||
1016 | static void | 1016 | static void |
1017 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 1017 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
1018 | u64 timestamp, struct ieee802_11_elems *elems) | 1018 | u64 timestamp, struct ieee802_11_elems *elems, |
1019 | bool beacon) | ||
1019 | { | 1020 | { |
1020 | struct ieee80211_local *local = sdata->local; | 1021 | struct ieee80211_local *local = sdata->local; |
1021 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1022 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -1032,6 +1033,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1032 | struct cfg80211_chan_def new_vht_chandef = {}; | 1033 | struct cfg80211_chan_def new_vht_chandef = {}; |
1033 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; | 1034 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; |
1034 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; | 1035 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; |
1036 | const struct ieee80211_ht_operation *ht_oper; | ||
1035 | int secondary_channel_offset = -1; | 1037 | int secondary_channel_offset = -1; |
1036 | 1038 | ||
1037 | ASSERT_MGD_MTX(ifmgd); | 1039 | ASSERT_MGD_MTX(ifmgd); |
@@ -1048,11 +1050,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1048 | 1050 | ||
1049 | sec_chan_offs = elems->sec_chan_offs; | 1051 | sec_chan_offs = elems->sec_chan_offs; |
1050 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; | 1052 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; |
1053 | ht_oper = elems->ht_operation; | ||
1051 | 1054 | ||
1052 | if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | | 1055 | if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | |
1053 | IEEE80211_STA_DISABLE_40MHZ)) { | 1056 | IEEE80211_STA_DISABLE_40MHZ)) { |
1054 | sec_chan_offs = NULL; | 1057 | sec_chan_offs = NULL; |
1055 | wide_bw_chansw_ie = NULL; | 1058 | wide_bw_chansw_ie = NULL; |
1059 | /* only used for bandwidth here */ | ||
1060 | ht_oper = NULL; | ||
1056 | } | 1061 | } |
1057 | 1062 | ||
1058 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) | 1063 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) |
@@ -1094,10 +1099,20 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1094 | return; | 1099 | return; |
1095 | } | 1100 | } |
1096 | 1101 | ||
1097 | if (sec_chan_offs) { | 1102 | if (!beacon && sec_chan_offs) { |
1098 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; | 1103 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; |
1104 | } else if (beacon && ht_oper) { | ||
1105 | secondary_channel_offset = | ||
1106 | ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
1099 | } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | 1107 | } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { |
1100 | /* if HT is enabled and the IE not present, it's still HT */ | 1108 | /* |
1109 | * If it's not a beacon, HT is enabled and the IE not present, | ||
1110 | * it's 20 MHz, 802.11-2012 8.5.2.6: | ||
1111 | * This element [the Secondary Channel Offset Element] is | ||
1112 | * present when switching to a 40 MHz channel. It may be | ||
1113 | * present when switching to a 20 MHz channel (in which | ||
1114 | * case the secondary channel offset is set to SCN). | ||
1115 | */ | ||
1101 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | 1116 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; |
1102 | } | 1117 | } |
1103 | 1118 | ||
@@ -2796,7 +2811,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2796 | mutex_unlock(&local->iflist_mtx); | 2811 | mutex_unlock(&local->iflist_mtx); |
2797 | } | 2812 | } |
2798 | 2813 | ||
2799 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems); | 2814 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, |
2815 | elems, true); | ||
2800 | 2816 | ||
2801 | } | 2817 | } |
2802 | 2818 | ||
@@ -3210,7 +3226,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
3210 | 3226 | ||
3211 | ieee80211_sta_process_chanswitch(sdata, | 3227 | ieee80211_sta_process_chanswitch(sdata, |
3212 | rx_status->mactime, | 3228 | rx_status->mactime, |
3213 | &elems); | 3229 | &elems, false); |
3214 | } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { | 3230 | } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { |
3215 | ies_len = skb->len - | 3231 | ies_len = skb->len - |
3216 | offsetof(struct ieee80211_mgmt, | 3232 | offsetof(struct ieee80211_mgmt, |
@@ -3232,7 +3248,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
3232 | 3248 | ||
3233 | ieee80211_sta_process_chanswitch(sdata, | 3249 | ieee80211_sta_process_chanswitch(sdata, |
3234 | rx_status->mactime, | 3250 | rx_status->mactime, |
3235 | &elems); | 3251 | &elems, false); |
3236 | } | 3252 | } |
3237 | break; | 3253 | break; |
3238 | } | 3254 | } |
@@ -3623,6 +3639,31 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
3623 | } | 3639 | } |
3624 | } | 3640 | } |
3625 | 3641 | ||
3642 | #ifdef CONFIG_PM | ||
3643 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | ||
3644 | { | ||
3645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3646 | |||
3647 | mutex_lock(&ifmgd->mtx); | ||
3648 | if (!ifmgd->associated) { | ||
3649 | mutex_unlock(&ifmgd->mtx); | ||
3650 | return; | ||
3651 | } | ||
3652 | |||
3653 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { | ||
3654 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | ||
3655 | mlme_dbg(sdata, "driver requested disconnect after resume\n"); | ||
3656 | ieee80211_sta_connection_lost(sdata, | ||
3657 | ifmgd->associated->bssid, | ||
3658 | WLAN_REASON_UNSPECIFIED, | ||
3659 | true); | ||
3660 | mutex_unlock(&ifmgd->mtx); | ||
3661 | return; | ||
3662 | } | ||
3663 | mutex_unlock(&ifmgd->mtx); | ||
3664 | } | ||
3665 | #endif | ||
3666 | |||
3626 | /* interface setup */ | 3667 | /* interface setup */ |
3627 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | 3668 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) |
3628 | { | 3669 | { |
@@ -4329,7 +4370,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4329 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 4370 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
4330 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 4371 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
4331 | bool tx = !req->local_state_change; | 4372 | bool tx = !req->local_state_change; |
4332 | bool sent_frame = false; | 4373 | bool report_frame = false; |
4333 | 4374 | ||
4334 | mutex_lock(&ifmgd->mtx); | 4375 | mutex_lock(&ifmgd->mtx); |
4335 | 4376 | ||
@@ -4346,7 +4387,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4346 | ieee80211_destroy_auth_data(sdata, false); | 4387 | ieee80211_destroy_auth_data(sdata, false); |
4347 | mutex_unlock(&ifmgd->mtx); | 4388 | mutex_unlock(&ifmgd->mtx); |
4348 | 4389 | ||
4349 | sent_frame = tx; | 4390 | report_frame = true; |
4350 | goto out; | 4391 | goto out; |
4351 | } | 4392 | } |
4352 | 4393 | ||
@@ -4354,12 +4395,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4354 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | 4395 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
4355 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 4396 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
4356 | req->reason_code, tx, frame_buf); | 4397 | req->reason_code, tx, frame_buf); |
4357 | sent_frame = tx; | 4398 | report_frame = true; |
4358 | } | 4399 | } |
4359 | mutex_unlock(&ifmgd->mtx); | 4400 | mutex_unlock(&ifmgd->mtx); |
4360 | 4401 | ||
4361 | out: | 4402 | out: |
4362 | if (sent_frame) | 4403 | if (report_frame) |
4363 | __cfg80211_send_deauth(sdata->dev, frame_buf, | 4404 | __cfg80211_send_deauth(sdata->dev, frame_buf, |
4364 | IEEE80211_DEAUTH_FRAME_LEN); | 4405 | IEEE80211_DEAUTH_FRAME_LEN); |
4365 | 4406 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0d51877efdb7..d3f414fe67e0 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -688,8 +688,15 @@ int rate_control_set_rates(struct ieee80211_hw *hw, | |||
688 | struct ieee80211_sta *pubsta, | 688 | struct ieee80211_sta *pubsta, |
689 | struct ieee80211_sta_rates *rates) | 689 | struct ieee80211_sta_rates *rates) |
690 | { | 690 | { |
691 | struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates); | 691 | struct ieee80211_sta_rates *old; |
692 | 692 | ||
693 | /* | ||
694 | * mac80211 guarantees that this function will not be called | ||
695 | * concurrently, so the following RCU access is safe, even without | ||
696 | * extra locking. This can not be checked easily, so we just set | ||
697 | * the condition to true. | ||
698 | */ | ||
699 | old = rcu_dereference_protected(pubsta->rates, true); | ||
693 | rcu_assign_pointer(pubsta->rates, rates); | 700 | rcu_assign_pointer(pubsta->rates, rates); |
694 | if (old) | 701 | if (old) |
695 | kfree_rcu(old, rcu_head); | 702 | kfree_rcu(old, rcu_head); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c8447af76ead..8e2952620256 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -3036,6 +3036,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3036 | * and location updates. Note that mac80211 | 3036 | * and location updates. Note that mac80211 |
3037 | * itself never looks at these frames. | 3037 | * itself never looks at these frames. |
3038 | */ | 3038 | */ |
3039 | if (!multicast && | ||
3040 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) | ||
3041 | return 0; | ||
3039 | if (ieee80211_is_public_action(hdr, skb->len)) | 3042 | if (ieee80211_is_public_action(hdr, skb->len)) |
3040 | return 1; | 3043 | return 1; |
3041 | if (!ieee80211_is_beacon(hdr->frame_control)) | 3044 | if (!ieee80211_is_beacon(hdr->frame_control)) |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 3ed801d90f1e..124b1fdc20d0 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -208,10 +208,10 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, | |||
208 | u32 iv32 = get_unaligned_le32(&data[4]); | 208 | u32 iv32 = get_unaligned_le32(&data[4]); |
209 | u16 iv16 = data[2] | (data[0] << 8); | 209 | u16 iv16 = data[2] | (data[0] << 8); |
210 | 210 | ||
211 | spin_lock_bh(&key->u.tkip.txlock); | 211 | spin_lock(&key->u.tkip.txlock); |
212 | ieee80211_compute_tkip_p1k(key, iv32); | 212 | ieee80211_compute_tkip_p1k(key, iv32); |
213 | tkip_mixing_phase2(tk, ctx, iv16, p2k); | 213 | tkip_mixing_phase2(tk, ctx, iv16, p2k); |
214 | spin_unlock_bh(&key->u.tkip.txlock); | 214 | spin_unlock(&key->u.tkip.txlock); |
215 | } | 215 | } |
216 | EXPORT_SYMBOL(ieee80211_get_tkip_p2k); | 216 | EXPORT_SYMBOL(ieee80211_get_tkip_p2k); |
217 | 217 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3f87fa468b1f..27e07150eb46 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1740,6 +1740,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1740 | mb(); | 1740 | mb(); |
1741 | local->resuming = false; | 1741 | local->resuming = false; |
1742 | 1742 | ||
1743 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1744 | if (!ieee80211_sdata_running(sdata)) | ||
1745 | continue; | ||
1746 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
1747 | ieee80211_sta_restart(sdata); | ||
1748 | } | ||
1749 | |||
1743 | mod_timer(&local->sta_cleanup, jiffies + 1); | 1750 | mod_timer(&local->sta_cleanup, jiffies + 1); |
1744 | #else | 1751 | #else |
1745 | WARN_ON(1); | 1752 | WARN_ON(1); |