| From 1a1cb744de160ee70086a77afff605bbc275d291 Mon Sep 17 00:00:00 2001 |
| From: Johannes Berg <johannes.berg@intel.com> |
| Date: Wed, 19 Mar 2014 09:55:55 +0100 |
| Subject: mac80211: fix suspend vs. authentication race |
| |
| From: Johannes Berg <johannes.berg@intel.com> |
| |
| commit 1a1cb744de160ee70086a77afff605bbc275d291 upstream. |
| |
| Since Stanislaw's patch removing the quiescing code, mac80211 had |
| a race regarding suspend vs. authentication: as cfg80211 doesn't |
| track authentication attempts, it can't abort them. Therefore the |
| attempts may be kept running while suspending, which can lead to |
| all kinds of issues, in at least some cases causing an error in |
| iwlmvm firmware. |
| |
| Fix this by aborting the authentication attempt when suspending. |
| |
| Cc: stable@vger.kernel.org |
| Fixes: 12e7f517029d ("mac80211: cleanup generic suspend/resume procedures") |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/mac80211/ieee80211_i.h | 1 + |
| net/mac80211/mlme.c | 26 ++++++++++++++++++++++++++ |
| net/mac80211/pm.c | 14 +++++++++++--- |
| 3 files changed, 38 insertions(+), 3 deletions(-) |
| |
| --- a/net/mac80211/ieee80211_i.h |
| +++ b/net/mac80211/ieee80211_i.h |
| @@ -1270,6 +1270,7 @@ void ieee80211_sta_reset_conn_monitor(st |
| void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); |
| void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, |
| __le16 fc, bool acked); |
| +void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata); |
| void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); |
| |
| /* IBSS code */ |
| --- a/net/mac80211/mlme.c |
| +++ b/net/mac80211/mlme.c |
| @@ -3754,6 +3754,32 @@ static void ieee80211_restart_sta_timer( |
| } |
| |
| #ifdef CONFIG_PM |
| +void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) |
| +{ |
| + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| + u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
| + |
| + mutex_lock(&ifmgd->mtx); |
| + |
| + if (ifmgd->auth_data) { |
| + /* |
| + * If we are trying to authenticate while suspending, cfg80211 |
| + * won't know and won't actually abort those attempts, thus we |
| + * need to do that ourselves. |
| + */ |
| + ieee80211_send_deauth_disassoc(sdata, |
| + ifmgd->auth_data->bss->bssid, |
| + IEEE80211_STYPE_DEAUTH, |
| + WLAN_REASON_DEAUTH_LEAVING, |
| + false, frame_buf); |
| + ieee80211_destroy_auth_data(sdata, false); |
| + cfg80211_send_deauth(sdata->dev, frame_buf, |
| + IEEE80211_DEAUTH_FRAME_LEN); |
| + } |
| + |
| + mutex_unlock(&ifmgd->mtx); |
| +} |
| + |
| void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) |
| { |
| struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| --- a/net/mac80211/pm.c |
| +++ b/net/mac80211/pm.c |
| @@ -101,10 +101,18 @@ int __ieee80211_suspend(struct ieee80211 |
| |
| /* remove all interfaces that were created in the driver */ |
| list_for_each_entry(sdata, &local->interfaces, list) { |
| - if (!ieee80211_sdata_running(sdata) || |
| - sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
| - sdata->vif.type == NL80211_IFTYPE_MONITOR) |
| + if (!ieee80211_sdata_running(sdata)) |
| continue; |
| + switch (sdata->vif.type) { |
| + case NL80211_IFTYPE_AP_VLAN: |
| + case NL80211_IFTYPE_MONITOR: |
| + continue; |
| + case NL80211_IFTYPE_STATION: |
| + ieee80211_mgd_quiesce(sdata); |
| + break; |
| + default: |
| + break; |
| + } |
| |
| drv_remove_interface(local, sdata); |
| } |