Skip to content

Commit

Permalink
mac80211: fix channel context suspend/reconfig handling
Browse files Browse the repository at this point in the history
Sujith reported warnings with suspend/resume due to
channel contexts. When I looked into it, I realised
that the code was completely broken as it unassigned
the channel contexts when suspending, which actually
means they are destroyed.

Eliad Peller then pointed out that we also need to
remove the channel contexts from the driver. When I
looked into this, I also noticed that the code isn't
handling the virtual monitor interface correctly (if
it exists.)

Fix this by calling just the driver methods (if they
are implemented) instead of using the channel context
management code. Also add reconfiguration for the
virtual monitor interface.

Reported-by: Sujith Manoharan <sujith@msujith.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Johannes Berg committed Nov 20, 2012
1 parent 4988456 commit fe5f255
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
44 changes: 41 additions & 3 deletions net/mac80211/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
struct ieee80211_chanctx *ctx;

if (!local->open_count)
goto suspend;
Expand Down Expand Up @@ -139,14 +140,51 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
rcu_access_pointer(sdata->u.ap.beacon))
drv_stop_ap(local, sdata);

/* the interface is leaving the channel and is removed */
ieee80211_vif_release_channel(sdata);
if (local->use_chanctx) {
struct ieee80211_chanctx_conf *conf;

mutex_lock(&local->chanctx_mtx);
conf = rcu_dereference_protected(
sdata->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
if (conf) {
ctx = container_of(conf,
struct ieee80211_chanctx,
conf);
drv_unassign_vif_chanctx(local, sdata, ctx);
}

mutex_unlock(&local->chanctx_mtx);
}
drv_remove_interface(local, sdata);
}

sdata = rtnl_dereference(local->monitor_sdata);
if (sdata)
if (sdata) {
if (local->use_chanctx) {
struct ieee80211_chanctx_conf *conf;

mutex_lock(&local->chanctx_mtx);
conf = rcu_dereference_protected(
sdata->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
if (conf) {
ctx = container_of(conf,
struct ieee80211_chanctx,
conf);
drv_unassign_vif_chanctx(local, sdata, ctx);
}

mutex_unlock(&local->chanctx_mtx);
}

drv_remove_interface(local, sdata);
}

mutex_lock(&local->chanctx_mtx);
list_for_each_entry(ctx, &local->chanctx_list, list)
drv_remove_chanctx(local, ctx);
mutex_unlock(&local->chanctx_mtx);

/* stop hardware - this must stop RX */
if (local->open_count)
Expand Down
15 changes: 15 additions & 0 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,21 @@ int ieee80211_reconfig(struct ieee80211_local *local)
mutex_unlock(&local->chanctx_mtx);
}

sdata = rtnl_dereference(local->monitor_sdata);
if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) {
struct ieee80211_chanctx_conf *ctx_conf;

mutex_lock(&local->chanctx_mtx);
ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
if (ctx_conf) {
ctx = container_of(ctx_conf, struct ieee80211_chanctx,
conf);
drv_assign_vif_chanctx(local, sdata, ctx);
}
mutex_unlock(&local->chanctx_mtx);
}

/* add STAs back */
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
Expand Down

0 comments on commit fe5f255

Please sign in to comment.