Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / pm.c
index d0275f34bf700397702f0f752d15388cc515d281..3d16f4e6174388f27e030f9612a64bbd752c04ea 100644 (file)
@@ -6,32 +6,11 @@
 #include "driver-ops.h"
 #include "led.h"
 
-/* return value indicates whether the driver should be further notified */
-static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata)
-{
-       switch (sdata->vif.type) {
-       case NL80211_IFTYPE_STATION:
-               ieee80211_sta_quiesce(sdata);
-               break;
-       case NL80211_IFTYPE_ADHOC:
-               ieee80211_ibss_quiesce(sdata);
-               break;
-       case NL80211_IFTYPE_MESH_POINT:
-               ieee80211_mesh_quiesce(sdata);
-               break;
-       default:
-               break;
-       }
-
-       cancel_work_sync(&sdata->work);
-}
-
 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;
@@ -51,12 +30,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
        }
 
        ieee80211_stop_queues_by_reason(hw,
-                       IEEE80211_QUEUE_STOP_REASON_SUSPEND);
+                                       IEEE80211_MAX_QUEUE_MAP,
+                                       IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
        /* flush out all packets */
        synchronize_net();
 
-       drv_flush(local, false);
+       ieee80211_flush_queues(local, NULL);
 
        local->quiescing = true;
        /* make quiescing visible to timers everywhere */
@@ -89,23 +69,17 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
                                mutex_unlock(&local->sta_mtx);
                        }
                        ieee80211_wake_queues_by_reason(hw,
+                                       IEEE80211_MAX_QUEUE_MAP,
                                        IEEE80211_QUEUE_STOP_REASON_SUSPEND);
                        return err;
                } else if (err > 0) {
                        WARN_ON(err != 1);
-                       local->wowlan = false;
+                       return err;
                } else {
-                       list_for_each_entry(sdata, &local->interfaces, list)
-                               if (ieee80211_sdata_running(sdata))
-                                       ieee80211_quiesce(sdata);
                        goto suspend;
                }
        }
 
-       /* disable keys */
-       list_for_each_entry(sdata, &local->interfaces, list)
-               ieee80211_disable_keys(sdata);
-
        /* tear down aggregation sessions and remove STAs */
        mutex_lock(&local->sta_mtx);
        list_for_each_entry(sta, &local->sta_list, list) {
@@ -117,100 +91,25 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
                                WARN_ON(drv_sta_state(local, sta->sdata, sta,
                                                      state, state - 1));
                }
-
-               mesh_plink_quiesce(sta);
        }
        mutex_unlock(&local->sta_mtx);
 
        /* remove all interfaces */
        list_for_each_entry(sdata, &local->interfaces, list) {
-               static u8 zero_addr[ETH_ALEN] = {};
-               u32 changed = 0;
-
                if (!ieee80211_sdata_running(sdata))
                        continue;
-
-               switch (sdata->vif.type) {
-               case NL80211_IFTYPE_AP_VLAN:
-               case NL80211_IFTYPE_MONITOR:
-                       /* skip these */
-                       continue;
-               case NL80211_IFTYPE_STATION:
-                       if (sdata->vif.bss_conf.assoc)
-                               changed = BSS_CHANGED_ASSOC |
-                                         BSS_CHANGED_BSSID |
-                                         BSS_CHANGED_IDLE;
-                       break;
-               case NL80211_IFTYPE_AP:
-               case NL80211_IFTYPE_ADHOC:
-               case NL80211_IFTYPE_MESH_POINT:
-                       if (sdata->vif.bss_conf.enable_beacon)
-                               changed = BSS_CHANGED_BEACON_ENABLED;
-                       break;
-               default:
-                       break;
-               }
-
-               ieee80211_quiesce(sdata);
-
-               sdata->suspend_bss_conf = sdata->vif.bss_conf;
-               memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf));
-               sdata->vif.bss_conf.idle = true;
-               if (sdata->suspend_bss_conf.bssid)
-                       sdata->vif.bss_conf.bssid = zero_addr;
-
-               /* disable beaconing or remove association */
-               ieee80211_bss_info_change_notify(sdata, changed);
-
-               if (sdata->vif.type == NL80211_IFTYPE_AP &&
-                   rcu_access_pointer(sdata->u.ap.beacon))
-                       drv_stop_ap(local, 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 (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);
-               }
-
+       if (sdata)
                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);
+       /*
+        * We disconnected on all interfaces before suspend, all channel
+        * contexts should be released.
+        */
+       WARN_ON(!list_empty(&local->chanctx_list));
 
        /* stop hardware - this must stop RX */
        if (local->open_count)