summaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-05-08 09:10:02 +0200
committerJohannes Berg <johannes.berg@intel.com>2014-05-08 11:57:27 +0200
commitcf8767dd7635d2209485dc765965d33537ad66eb (patch)
tree95e582416ee448ca113807688f587e5f2f06dff1 /net/mac80211
parent771bb3ddc225d6dbbef8f22838c1287c4e3cd02b (diff)
mac80211: disconnect iface if CSA unexpectedly fails
It doesn't make much sense to leave a crippled interface running. As a side effect this will unblock tx queues with CSA reason immediately after failure instead of until after userspace requests interface to stop. This also gives userspace an opportunity to indirectly see CSA failure. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> [small code cleanup] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0c87c8c47123..7d358037d4e9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3090,7 +3090,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
return 0;
}
-static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
+static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
u32 changed = 0;
@@ -3101,8 +3101,8 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
sdata->radar_required = sdata->csa_radar_required;
err = ieee80211_vif_change_channel(sdata, &changed);
- if (WARN_ON(err < 0))
- return;
+ if (err < 0)
+ return err;
if (!local->use_chanctx) {
local->_oper_chandef = sdata->csa_chandef;
@@ -3113,7 +3113,7 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
err = ieee80211_set_after_csa_beacon(sdata, &changed);
if (err)
- return;
+ return err;
ieee80211_bss_info_change_notify(sdata, changed);
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
@@ -3122,6 +3122,17 @@ static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
ieee80211_wake_queues_by_reason(&local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
+
+ return 0;
+}
+
+static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
+{
+ if (__ieee80211_csa_finalize(sdata)) {
+ sdata_info(sdata, "failed to finalize CSA, disconnecting\n");
+ cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev,
+ GFP_KERNEL);
+ }
}
void ieee80211_csa_finalize_work(struct work_struct *work)