1 #include <net/mac80211.h> 2 #include <net/rtnetlink.h> 3 4 #include "ieee80211_i.h" 5 #include "mesh.h" 6 #include "driver-ops.h" 7 #include "led.h" 8 9 /* return value indicates whether the driver should be further notified */ 10 static bool ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) 11 { 12 switch (sdata->vif.type) { 13 case NL80211_IFTYPE_STATION: 14 ieee80211_sta_quiesce(sdata); 15 return true; 16 case NL80211_IFTYPE_ADHOC: 17 ieee80211_ibss_quiesce(sdata); 18 return true; 19 case NL80211_IFTYPE_MESH_POINT: 20 ieee80211_mesh_quiesce(sdata); 21 return true; 22 case NL80211_IFTYPE_AP_VLAN: 23 case NL80211_IFTYPE_MONITOR: 24 /* don't tell driver about this */ 25 return false; 26 default: 27 return true; 28 } 29 } 30 31 int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) 32 { 33 struct ieee80211_local *local = hw_to_local(hw); 34 struct ieee80211_sub_if_data *sdata; 35 struct sta_info *sta; 36 37 if (!local->open_count) 38 goto suspend; 39 40 ieee80211_scan_cancel(local); 41 42 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 43 mutex_lock(&local->sta_mtx); 44 list_for_each_entry(sta, &local->sta_list, list) { 45 set_sta_flag(sta, WLAN_STA_BLOCK_BA); 46 ieee80211_sta_tear_down_BA_sessions(sta, true); 47 } 48 mutex_unlock(&local->sta_mtx); 49 } 50 51 ieee80211_stop_queues_by_reason(hw, 52 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 53 54 /* flush out all packets */ 55 synchronize_net(); 56 57 drv_flush(local, false); 58 59 local->quiescing = true; 60 /* make quiescing visible to timers everywhere */ 61 mb(); 62 63 flush_workqueue(local->workqueue); 64 65 /* Don't try to run timers while suspended. */ 66 del_timer_sync(&local->sta_cleanup); 67 68 /* 69 * Note that this particular timer doesn't need to be 70 * restarted at resume. 71 */ 72 cancel_work_sync(&local->dynamic_ps_enable_work); 73 del_timer_sync(&local->dynamic_ps_timer); 74 75 local->wowlan = wowlan && local->open_count; 76 if (local->wowlan) { 77 int err = drv_suspend(local, wowlan); 78 if (err < 0) { 79 local->quiescing = false; 80 return err; 81 } else if (err > 0) { 82 WARN_ON(err != 1); 83 local->wowlan = false; 84 } else { 85 list_for_each_entry(sdata, &local->interfaces, list) { 86 cancel_work_sync(&sdata->work); 87 ieee80211_quiesce(sdata); 88 } 89 goto suspend; 90 } 91 } 92 93 /* disable keys */ 94 list_for_each_entry(sdata, &local->interfaces, list) 95 ieee80211_disable_keys(sdata); 96 97 /* tear down aggregation sessions and remove STAs */ 98 mutex_lock(&local->sta_mtx); 99 list_for_each_entry(sta, &local->sta_list, list) { 100 if (sta->uploaded) { 101 enum ieee80211_sta_state state; 102 103 state = sta->sta_state; 104 for (; state > IEEE80211_STA_NOTEXIST; state--) 105 WARN_ON(drv_sta_state(local, sta->sdata, sta, 106 state, state - 1)); 107 } 108 109 mesh_plink_quiesce(sta); 110 } 111 mutex_unlock(&local->sta_mtx); 112 113 /* remove all interfaces */ 114 list_for_each_entry(sdata, &local->interfaces, list) { 115 cancel_work_sync(&sdata->work); 116 117 if (!ieee80211_quiesce(sdata)) 118 continue; 119 120 if (!ieee80211_sdata_running(sdata)) 121 continue; 122 123 /* disable beaconing */ 124 ieee80211_bss_info_change_notify(sdata, 125 BSS_CHANGED_BEACON_ENABLED); 126 127 drv_remove_interface(local, sdata); 128 } 129 130 sdata = rtnl_dereference(local->monitor_sdata); 131 if (sdata) 132 drv_remove_interface(local, sdata); 133 134 /* stop hardware - this must stop RX */ 135 if (local->open_count) 136 ieee80211_stop_device(local); 137 138 suspend: 139 local->suspended = true; 140 /* need suspended to be visible before quiescing is false */ 141 barrier(); 142 local->quiescing = false; 143 144 return 0; 145 } 146 147 /* 148 * __ieee80211_resume() is a static inline which just calls 149 * ieee80211_reconfig(), which is also needed for hardware 150 * hang/firmware failure/etc. recovery. 151 */ 152