|
@@ -3662,40 +3662,44 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
|
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
|
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
|
|
bool tx = !req->local_state_change;
|
|
|
+ bool sent_frame = false;
|
|
|
|
|
|
mutex_lock(&ifmgd->mtx);
|
|
|
|
|
|
- if (ifmgd->auth_data) {
|
|
|
- ieee80211_destroy_auth_data(sdata, false);
|
|
|
- mutex_unlock(&ifmgd->mtx);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
sdata_info(sdata,
|
|
|
"deauthenticating from %pM by local choice (reason=%d)\n",
|
|
|
req->bssid, req->reason_code);
|
|
|
|
|
|
- if (ifmgd->associated &&
|
|
|
- ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
|
|
|
- ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
|
|
- req->reason_code, tx, frame_buf);
|
|
|
- } else {
|
|
|
+ if (ifmgd->auth_data) {
|
|
|
drv_mgd_prepare_tx(sdata->local, sdata);
|
|
|
ieee80211_send_deauth_disassoc(sdata, req->bssid,
|
|
|
IEEE80211_STYPE_DEAUTH,
|
|
|
req->reason_code, tx,
|
|
|
frame_buf);
|
|
|
+ ieee80211_destroy_auth_data(sdata, false);
|
|
|
+ mutex_unlock(&ifmgd->mtx);
|
|
|
+
|
|
|
+ sent_frame = tx;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
+ if (ifmgd->associated &&
|
|
|
+ ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
|
|
|
+ ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
|
|
+ req->reason_code, tx, frame_buf);
|
|
|
+ sent_frame = tx;
|
|
|
+ }
|
|
|
mutex_unlock(&ifmgd->mtx);
|
|
|
|
|
|
- __cfg80211_send_deauth(sdata->dev, frame_buf,
|
|
|
- IEEE80211_DEAUTH_FRAME_LEN);
|
|
|
-
|
|
|
+ out:
|
|
|
mutex_lock(&sdata->local->mtx);
|
|
|
ieee80211_recalc_idle(sdata->local);
|
|
|
mutex_unlock(&sdata->local->mtx);
|
|
|
|
|
|
+ if (sent_frame)
|
|
|
+ __cfg80211_send_deauth(sdata->dev, frame_buf,
|
|
|
+ IEEE80211_DEAUTH_FRAME_LEN);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|