Merge tag 'balancenuma-v11' of git://git.kernel.org/pub/scm/linux/kernel/git/mel...
[cascardo/linux.git] / net / mac80211 / pm.c
index 0f1c434..79a48f3 100644 (file)
@@ -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;
@@ -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)