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>
This commit is contained in:
Michal Kazior 2014-05-08 09:10:02 +02:00 committed by Johannes Berg
parent 771bb3ddc2
commit cf8767dd76
1 changed files with 15 additions and 4 deletions

View File

@ -3090,7 +3090,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
return 0; 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; struct ieee80211_local *local = sdata->local;
u32 changed = 0; 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; sdata->radar_required = sdata->csa_radar_required;
err = ieee80211_vif_change_channel(sdata, &changed); err = ieee80211_vif_change_channel(sdata, &changed);
if (WARN_ON(err < 0)) if (err < 0)
return; return err;
if (!local->use_chanctx) { if (!local->use_chanctx) {
local->_oper_chandef = sdata->csa_chandef; 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); err = ieee80211_set_after_csa_beacon(sdata, &changed);
if (err) if (err)
return; return err;
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); 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_wake_queues_by_reason(&local->hw,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA); 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) void ieee80211_csa_finalize_work(struct work_struct *work)