aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c212
1 files changed, 147 insertions, 65 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a4b1dd332e0f..00103f36dcbf 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1168,11 +1168,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1168 if (!conf) { 1168 if (!conf) {
1169 sdata_info(sdata, 1169 sdata_info(sdata,
1170 "no channel context assigned to vif?, disconnecting\n"); 1170 "no channel context assigned to vif?, disconnecting\n");
1171 ieee80211_queue_work(&local->hw, 1171 goto drop_connection;
1172 &ifmgd->csa_connection_drop_work);
1173 mutex_unlock(&local->chanctx_mtx);
1174 mutex_unlock(&local->mtx);
1175 return;
1176 } 1172 }
1177 1173
1178 chanctx = container_of(conf, struct ieee80211_chanctx, conf); 1174 chanctx = container_of(conf, struct ieee80211_chanctx, conf);
@@ -1181,11 +1177,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1181 !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) { 1177 !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) {
1182 sdata_info(sdata, 1178 sdata_info(sdata,
1183 "driver doesn't support chan-switch with channel contexts\n"); 1179 "driver doesn't support chan-switch with channel contexts\n");
1184 ieee80211_queue_work(&local->hw, 1180 goto drop_connection;
1185 &ifmgd->csa_connection_drop_work);
1186 mutex_unlock(&local->chanctx_mtx);
1187 mutex_unlock(&local->mtx);
1188 return;
1189 } 1181 }
1190 1182
1191 ch_switch.timestamp = timestamp; 1183 ch_switch.timestamp = timestamp;
@@ -1197,11 +1189,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1197 if (drv_pre_channel_switch(sdata, &ch_switch)) { 1189 if (drv_pre_channel_switch(sdata, &ch_switch)) {
1198 sdata_info(sdata, 1190 sdata_info(sdata,
1199 "preparing for channel switch failed, disconnecting\n"); 1191 "preparing for channel switch failed, disconnecting\n");
1200 ieee80211_queue_work(&local->hw, 1192 goto drop_connection;
1201 &ifmgd->csa_connection_drop_work);
1202 mutex_unlock(&local->chanctx_mtx);
1203 mutex_unlock(&local->mtx);
1204 return;
1205 } 1193 }
1206 1194
1207 res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef, 1195 res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef,
@@ -1210,11 +1198,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1210 sdata_info(sdata, 1198 sdata_info(sdata,
1211 "failed to reserve channel context for channel switch, disconnecting (err=%d)\n", 1199 "failed to reserve channel context for channel switch, disconnecting (err=%d)\n",
1212 res); 1200 res);
1213 ieee80211_queue_work(&local->hw, 1201 goto drop_connection;
1214 &ifmgd->csa_connection_drop_work);
1215 mutex_unlock(&local->chanctx_mtx);
1216 mutex_unlock(&local->mtx);
1217 return;
1218 } 1202 }
1219 mutex_unlock(&local->chanctx_mtx); 1203 mutex_unlock(&local->chanctx_mtx);
1220 1204
@@ -1244,6 +1228,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1244 mod_timer(&ifmgd->chswitch_timer, 1228 mod_timer(&ifmgd->chswitch_timer,
1245 TU_TO_EXP_TIME((csa_ie.count - 1) * 1229 TU_TO_EXP_TIME((csa_ie.count - 1) *
1246 cbss->beacon_interval)); 1230 cbss->beacon_interval));
1231 return;
1232 drop_connection:
1233 ieee80211_queue_work(&local->hw, &ifmgd->csa_connection_drop_work);
1234 mutex_unlock(&local->chanctx_mtx);
1235 mutex_unlock(&local->mtx);
1247} 1236}
1248 1237
1249static bool 1238static bool
@@ -1633,9 +1622,6 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
1633{ 1622{
1634 struct ieee80211_local *local = (void *) data; 1623 struct ieee80211_local *local = (void *) data;
1635 1624
1636 if (local->quiescing || local->suspended)
1637 return;
1638
1639 ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work); 1625 ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
1640} 1626}
1641 1627
@@ -2260,7 +2246,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
2260 else 2246 else
2261 ssid_len = ssid[1]; 2247 ssid_len = ssid[1];
2262 2248
2263 ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL, 2249 ieee80211_send_probe_req(sdata, sdata->vif.addr, dst,
2264 ssid + 2, ssid_len, NULL, 2250 ssid + 2, ssid_len, NULL,
2265 0, (u32) -1, true, 0, 2251 0, (u32) -1, true, 0,
2266 ifmgd->associated->channel, false); 2252 ifmgd->associated->channel, false);
@@ -2372,6 +2358,24 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
2372} 2358}
2373EXPORT_SYMBOL(ieee80211_ap_probereq_get); 2359EXPORT_SYMBOL(ieee80211_ap_probereq_get);
2374 2360
2361static void ieee80211_report_disconnect(struct ieee80211_sub_if_data *sdata,
2362 const u8 *buf, size_t len, bool tx,
2363 u16 reason)
2364{
2365 struct ieee80211_event event = {
2366 .type = MLME_EVENT,
2367 .u.mlme.data = tx ? DEAUTH_TX_EVENT : DEAUTH_RX_EVENT,
2368 .u.mlme.reason = reason,
2369 };
2370
2371 if (tx)
2372 cfg80211_tx_mlme_mgmt(sdata->dev, buf, len);
2373 else
2374 cfg80211_rx_mlme_mgmt(sdata->dev, buf, len);
2375
2376 drv_event_callback(sdata->local, sdata, &event);
2377}
2378
2375static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) 2379static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
2376{ 2380{
2377 struct ieee80211_local *local = sdata->local; 2381 struct ieee80211_local *local = sdata->local;
@@ -2397,8 +2401,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
2397 } 2401 }
2398 mutex_unlock(&local->mtx); 2402 mutex_unlock(&local->mtx);
2399 2403
2400 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 2404 ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
2401 IEEE80211_DEAUTH_FRAME_LEN); 2405 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
2406
2402 sdata_unlock(sdata); 2407 sdata_unlock(sdata);
2403} 2408}
2404 2409
@@ -2522,6 +2527,10 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2522 u8 bssid[ETH_ALEN]; 2527 u8 bssid[ETH_ALEN];
2523 u16 auth_alg, auth_transaction, status_code; 2528 u16 auth_alg, auth_transaction, status_code;
2524 struct sta_info *sta; 2529 struct sta_info *sta;
2530 struct ieee80211_event event = {
2531 .type = MLME_EVENT,
2532 .u.mlme.data = AUTH_EVENT,
2533 };
2525 2534
2526 sdata_assert_lock(sdata); 2535 sdata_assert_lock(sdata);
2527 2536
@@ -2554,6 +2563,9 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2554 mgmt->sa, status_code); 2563 mgmt->sa, status_code);
2555 ieee80211_destroy_auth_data(sdata, false); 2564 ieee80211_destroy_auth_data(sdata, false);
2556 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); 2565 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2566 event.u.mlme.status = MLME_DENIED;
2567 event.u.mlme.reason = status_code;
2568 drv_event_callback(sdata->local, sdata, &event);
2557 return; 2569 return;
2558 } 2570 }
2559 2571
@@ -2576,6 +2588,8 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2576 return; 2588 return;
2577 } 2589 }
2578 2590
2591 event.u.mlme.status = MLME_SUCCESS;
2592 drv_event_callback(sdata->local, sdata, &event);
2579 sdata_info(sdata, "authenticated\n"); 2593 sdata_info(sdata, "authenticated\n");
2580 ifmgd->auth_data->done = true; 2594 ifmgd->auth_data->done = true;
2581 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; 2595 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
@@ -2694,7 +2708,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
2694 2708
2695 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 2709 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
2696 2710
2697 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); 2711 ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code);
2698} 2712}
2699 2713
2700 2714
@@ -2720,7 +2734,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
2720 2734
2721 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 2735 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
2722 2736
2723 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); 2737 ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code);
2724} 2738}
2725 2739
2726static void ieee80211_get_rates(struct ieee80211_supported_band *sband, 2740static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
@@ -2982,10 +2996,14 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2982 2996
2983 rate_control_rate_init(sta); 2997 rate_control_rate_init(sta);
2984 2998
2985 if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) 2999 if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) {
2986 set_sta_flag(sta, WLAN_STA_MFP); 3000 set_sta_flag(sta, WLAN_STA_MFP);
3001 sta->sta.mfp = true;
3002 } else {
3003 sta->sta.mfp = false;
3004 }
2987 3005
2988 sta->sta.wme = elems.wmm_param; 3006 sta->sta.wme = elems.wmm_param && local->hw.queues >= IEEE80211_NUM_ACS;
2989 3007
2990 err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); 3008 err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
2991 if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) 3009 if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
@@ -3055,6 +3073,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
3055 u8 *pos; 3073 u8 *pos;
3056 bool reassoc; 3074 bool reassoc;
3057 struct cfg80211_bss *bss; 3075 struct cfg80211_bss *bss;
3076 struct ieee80211_event event = {
3077 .type = MLME_EVENT,
3078 .u.mlme.data = ASSOC_EVENT,
3079 };
3058 3080
3059 sdata_assert_lock(sdata); 3081 sdata_assert_lock(sdata);
3060 3082
@@ -3106,6 +3128,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
3106 sdata_info(sdata, "%pM denied association (code=%d)\n", 3128 sdata_info(sdata, "%pM denied association (code=%d)\n",
3107 mgmt->sa, status_code); 3129 mgmt->sa, status_code);
3108 ieee80211_destroy_assoc_data(sdata, false); 3130 ieee80211_destroy_assoc_data(sdata, false);
3131 event.u.mlme.status = MLME_DENIED;
3132 event.u.mlme.reason = status_code;
3133 drv_event_callback(sdata->local, sdata, &event);
3109 } else { 3134 } else {
3110 if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { 3135 if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
3111 /* oops -- internal error -- send timeout for now */ 3136 /* oops -- internal error -- send timeout for now */
@@ -3113,6 +3138,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
3113 cfg80211_assoc_timeout(sdata->dev, bss); 3138 cfg80211_assoc_timeout(sdata->dev, bss);
3114 return; 3139 return;
3115 } 3140 }
3141 event.u.mlme.status = MLME_SUCCESS;
3142 drv_event_callback(sdata->local, sdata, &event);
3116 sdata_info(sdata, "associated\n"); 3143 sdata_info(sdata, "associated\n");
3117 3144
3118 /* 3145 /*
@@ -3315,6 +3342,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3315 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) { 3342 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
3316 int sig = ifmgd->ave_beacon_signal; 3343 int sig = ifmgd->ave_beacon_signal;
3317 int last_sig = ifmgd->last_ave_beacon_signal; 3344 int last_sig = ifmgd->last_ave_beacon_signal;
3345 struct ieee80211_event event = {
3346 .type = RSSI_EVENT,
3347 };
3318 3348
3319 /* 3349 /*
3320 * if signal crosses either of the boundaries, invoke callback 3350 * if signal crosses either of the boundaries, invoke callback
@@ -3323,12 +3353,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3323 if (sig > ifmgd->rssi_max_thold && 3353 if (sig > ifmgd->rssi_max_thold &&
3324 (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) { 3354 (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) {
3325 ifmgd->last_ave_beacon_signal = sig; 3355 ifmgd->last_ave_beacon_signal = sig;
3326 drv_rssi_callback(local, sdata, RSSI_EVENT_HIGH); 3356 event.u.rssi.data = RSSI_EVENT_HIGH;
3357 drv_event_callback(local, sdata, &event);
3327 } else if (sig < ifmgd->rssi_min_thold && 3358 } else if (sig < ifmgd->rssi_min_thold &&
3328 (last_sig >= ifmgd->rssi_max_thold || 3359 (last_sig >= ifmgd->rssi_max_thold ||
3329 last_sig == 0)) { 3360 last_sig == 0)) {
3330 ifmgd->last_ave_beacon_signal = sig; 3361 ifmgd->last_ave_beacon_signal = sig;
3331 drv_rssi_callback(local, sdata, RSSI_EVENT_LOW); 3362 event.u.rssi.data = RSSI_EVENT_LOW;
3363 drv_event_callback(local, sdata, &event);
3332 } 3364 }
3333 } 3365 }
3334 3366
@@ -3433,6 +3465,26 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3433 if (ifmgd->csa_waiting_bcn) 3465 if (ifmgd->csa_waiting_bcn)
3434 ieee80211_chswitch_post_beacon(sdata); 3466 ieee80211_chswitch_post_beacon(sdata);
3435 3467
3468 /*
3469 * Update beacon timing and dtim count on every beacon appearance. This
3470 * will allow the driver to use the most updated values. Do it before
3471 * comparing this one with last received beacon.
3472 * IMPORTANT: These parameters would possibly be out of sync by the time
3473 * the driver will use them. The synchronized view is currently
3474 * guaranteed only in certain callbacks.
3475 */
3476 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
3477 sdata->vif.bss_conf.sync_tsf =
3478 le64_to_cpu(mgmt->u.beacon.timestamp);
3479 sdata->vif.bss_conf.sync_device_ts =
3480 rx_status->device_timestamp;
3481 if (elems.tim)
3482 sdata->vif.bss_conf.sync_dtim_count =
3483 elems.tim->dtim_count;
3484 else
3485 sdata->vif.bss_conf.sync_dtim_count = 0;
3486 }
3487
3436 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) 3488 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
3437 return; 3489 return;
3438 ifmgd->beacon_crc = ncrc; 3490 ifmgd->beacon_crc = ncrc;
@@ -3460,18 +3512,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3460 else 3512 else
3461 bss_conf->dtim_period = 1; 3513 bss_conf->dtim_period = 1;
3462 3514
3463 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
3464 sdata->vif.bss_conf.sync_tsf =
3465 le64_to_cpu(mgmt->u.beacon.timestamp);
3466 sdata->vif.bss_conf.sync_device_ts =
3467 rx_status->device_timestamp;
3468 if (elems.tim)
3469 sdata->vif.bss_conf.sync_dtim_count =
3470 elems.tim->dtim_count;
3471 else
3472 sdata->vif.bss_conf.sync_dtim_count = 0;
3473 }
3474
3475 changed |= BSS_CHANGED_BEACON_INFO; 3515 changed |= BSS_CHANGED_BEACON_INFO;
3476 ifmgd->have_beacon = true; 3516 ifmgd->have_beacon = true;
3477 3517
@@ -3502,8 +3542,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3502 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 3542 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3503 WLAN_REASON_DEAUTH_LEAVING, 3543 WLAN_REASON_DEAUTH_LEAVING,
3504 true, deauth_buf); 3544 true, deauth_buf);
3505 cfg80211_tx_mlme_mgmt(sdata->dev, deauth_buf, 3545 ieee80211_report_disconnect(sdata, deauth_buf,
3506 sizeof(deauth_buf)); 3546 sizeof(deauth_buf), true,
3547 WLAN_REASON_DEAUTH_LEAVING);
3507 return; 3548 return;
3508 } 3549 }
3509 3550
@@ -3621,8 +3662,8 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
3621 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, 3662 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
3622 tx, frame_buf); 3663 tx, frame_buf);
3623 3664
3624 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 3665 ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
3625 IEEE80211_DEAUTH_FRAME_LEN); 3666 reason);
3626} 3667}
3627 3668
3628static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) 3669static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
@@ -3816,12 +3857,18 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3816 ieee80211_destroy_auth_data(sdata, false); 3857 ieee80211_destroy_auth_data(sdata, false);
3817 } else if (ieee80211_probe_auth(sdata)) { 3858 } else if (ieee80211_probe_auth(sdata)) {
3818 u8 bssid[ETH_ALEN]; 3859 u8 bssid[ETH_ALEN];
3860 struct ieee80211_event event = {
3861 .type = MLME_EVENT,
3862 .u.mlme.data = AUTH_EVENT,
3863 .u.mlme.status = MLME_TIMEOUT,
3864 };
3819 3865
3820 memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN); 3866 memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
3821 3867
3822 ieee80211_destroy_auth_data(sdata, false); 3868 ieee80211_destroy_auth_data(sdata, false);
3823 3869
3824 cfg80211_auth_timeout(sdata->dev, bssid); 3870 cfg80211_auth_timeout(sdata->dev, bssid);
3871 drv_event_callback(sdata->local, sdata, &event);
3825 } 3872 }
3826 } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started) 3873 } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
3827 run_again(sdata, ifmgd->auth_data->timeout); 3874 run_again(sdata, ifmgd->auth_data->timeout);
@@ -3831,9 +3878,15 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3831 if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) || 3878 if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) ||
3832 ieee80211_do_assoc(sdata)) { 3879 ieee80211_do_assoc(sdata)) {
3833 struct cfg80211_bss *bss = ifmgd->assoc_data->bss; 3880 struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
3881 struct ieee80211_event event = {
3882 .type = MLME_EVENT,
3883 .u.mlme.data = ASSOC_EVENT,
3884 .u.mlme.status = MLME_TIMEOUT,
3885 };
3834 3886
3835 ieee80211_destroy_assoc_data(sdata, false); 3887 ieee80211_destroy_assoc_data(sdata, false);
3836 cfg80211_assoc_timeout(sdata->dev, bss); 3888 cfg80211_assoc_timeout(sdata->dev, bss);
3889 drv_event_callback(sdata->local, sdata, &event);
3837 } 3890 }
3838 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) 3891 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
3839 run_again(sdata, ifmgd->assoc_data->timeout); 3892 run_again(sdata, ifmgd->assoc_data->timeout);
@@ -3905,12 +3958,8 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
3905{ 3958{
3906 struct ieee80211_sub_if_data *sdata = 3959 struct ieee80211_sub_if_data *sdata =
3907 (struct ieee80211_sub_if_data *) data; 3960 (struct ieee80211_sub_if_data *) data;
3908 struct ieee80211_local *local = sdata->local;
3909 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3961 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3910 3962
3911 if (local->quiescing)
3912 return;
3913
3914 if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn) 3963 if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
3915 return; 3964 return;
3916 3965
@@ -3926,9 +3975,6 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data)
3926 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3975 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3927 struct ieee80211_local *local = sdata->local; 3976 struct ieee80211_local *local = sdata->local;
3928 3977
3929 if (local->quiescing)
3930 return;
3931
3932 if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn) 3978 if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
3933 return; 3979 return;
3934 3980
@@ -3991,6 +4037,34 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
3991 IEEE80211_DEAUTH_FRAME_LEN); 4037 IEEE80211_DEAUTH_FRAME_LEN);
3992 } 4038 }
3993 4039
4040 /* This is a bit of a hack - we should find a better and more generic
4041 * solution to this. Normally when suspending, cfg80211 will in fact
4042 * deauthenticate. However, it doesn't (and cannot) stop an ongoing
4043 * auth (not so important) or assoc (this is the problem) process.
4044 *
4045 * As a consequence, it can happen that we are in the process of both
4046 * associating and suspending, and receive an association response
4047 * after cfg80211 has checked if it needs to disconnect, but before
4048 * we actually set the flag to drop incoming frames. This will then
4049 * cause the workqueue flush to process the association response in
4050 * the suspend, resulting in a successful association just before it
4051 * tries to remove the interface from the driver, which now though
4052 * has a channel context assigned ... this results in issues.
4053 *
4054 * To work around this (for now) simply deauth here again if we're
4055 * now connected.
4056 */
4057 if (ifmgd->associated && !sdata->local->wowlan) {
4058 u8 bssid[ETH_ALEN];
4059 struct cfg80211_deauth_request req = {
4060 .reason_code = WLAN_REASON_DEAUTH_LEAVING,
4061 .bssid = bssid,
4062 };
4063
4064 memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
4065 ieee80211_mgd_deauth(sdata, &req);
4066 }
4067
3994 sdata_unlock(sdata); 4068 sdata_unlock(sdata);
3995} 4069}
3996 4070
@@ -4379,6 +4453,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
4379 } else 4453 } else
4380 WARN_ON_ONCE(!ether_addr_equal(ifmgd->bssid, cbss->bssid)); 4454 WARN_ON_ONCE(!ether_addr_equal(ifmgd->bssid, cbss->bssid));
4381 4455
4456 /* Cancel scan to ensure that nothing interferes with connection */
4457 if (local->scanning)
4458 ieee80211_scan_cancel(local);
4459
4382 return 0; 4460 return 0;
4383} 4461}
4384 4462
@@ -4467,8 +4545,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
4467 WLAN_REASON_UNSPECIFIED, 4545 WLAN_REASON_UNSPECIFIED,
4468 false, frame_buf); 4546 false, frame_buf);
4469 4547
4470 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 4548 ieee80211_report_disconnect(sdata, frame_buf,
4471 sizeof(frame_buf)); 4549 sizeof(frame_buf), true,
4550 WLAN_REASON_UNSPECIFIED);
4472 } 4551 }
4473 4552
4474 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); 4553 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
@@ -4568,8 +4647,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4568 WLAN_REASON_UNSPECIFIED, 4647 WLAN_REASON_UNSPECIFIED,
4569 false, frame_buf); 4648 false, frame_buf);
4570 4649
4571 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 4650 ieee80211_report_disconnect(sdata, frame_buf,
4572 sizeof(frame_buf)); 4651 sizeof(frame_buf), true,
4652 WLAN_REASON_UNSPECIFIED);
4573 } 4653 }
4574 4654
4575 if (ifmgd->auth_data && !ifmgd->auth_data->done) { 4655 if (ifmgd->auth_data && !ifmgd->auth_data->done) {
@@ -4859,8 +4939,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
4859 req->reason_code, tx, 4939 req->reason_code, tx,
4860 frame_buf); 4940 frame_buf);
4861 ieee80211_destroy_auth_data(sdata, false); 4941 ieee80211_destroy_auth_data(sdata, false);
4862 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 4942 ieee80211_report_disconnect(sdata, frame_buf,
4863 IEEE80211_DEAUTH_FRAME_LEN); 4943 sizeof(frame_buf), true,
4944 req->reason_code);
4864 4945
4865 return 0; 4946 return 0;
4866 } 4947 }
@@ -4874,8 +4955,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
4874 4955
4875 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 4956 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
4876 req->reason_code, tx, frame_buf); 4957 req->reason_code, tx, frame_buf);
4877 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 4958 ieee80211_report_disconnect(sdata, frame_buf,
4878 IEEE80211_DEAUTH_FRAME_LEN); 4959 sizeof(frame_buf), true,
4960 req->reason_code);
4879 return 0; 4961 return 0;
4880 } 4962 }
4881 4963
@@ -4907,8 +4989,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
4907 req->reason_code, !req->local_state_change, 4989 req->reason_code, !req->local_state_change,
4908 frame_buf); 4990 frame_buf);
4909 4991
4910 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 4992 ieee80211_report_disconnect(sdata, frame_buf, sizeof(frame_buf), true,
4911 IEEE80211_DEAUTH_FRAME_LEN); 4993 req->reason_code);
4912 4994
4913 return 0; 4995 return 0;
4914} 4996}