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 int __ieee80211_suspend(struct ieee80211_hw *hw) 10 { 11 struct ieee80211_local *local = hw_to_local(hw); 12 struct ieee80211_sub_if_data *sdata; 13 struct ieee80211_if_init_conf conf; 14 struct sta_info *sta; 15 unsigned long flags; 16 17 ieee80211_scan_cancel(local); 18 19 ieee80211_stop_queues_by_reason(hw, 20 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 21 22 /* flush out all packets */ 23 synchronize_net(); 24 25 local->quiescing = true; 26 /* make quiescing visible to timers everywhere */ 27 mb(); 28 29 flush_workqueue(local->workqueue); 30 31 /* Don't try to run timers while suspended. */ 32 del_timer_sync(&local->sta_cleanup); 33 34 /* 35 * Note that this particular timer doesn't need to be 36 * restarted at resume. 37 */ 38 cancel_work_sync(&local->dynamic_ps_enable_work); 39 del_timer_sync(&local->dynamic_ps_timer); 40 41 /* disable keys */ 42 list_for_each_entry(sdata, &local->interfaces, list) 43 ieee80211_disable_keys(sdata); 44 45 /* Tear down aggregation sessions */ 46 47 rcu_read_lock(); 48 49 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 50 list_for_each_entry_rcu(sta, &local->sta_list, list) { 51 set_sta_flags(sta, WLAN_STA_SUSPEND); 52 ieee80211_sta_tear_down_BA_sessions(sta); 53 } 54 } 55 56 rcu_read_unlock(); 57 58 /* remove STAs */ 59 spin_lock_irqsave(&local->sta_lock, flags); 60 list_for_each_entry(sta, &local->sta_list, list) { 61 if (local->ops->sta_notify) { 62 sdata = sta->sdata; 63 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 64 sdata = container_of(sdata->bss, 65 struct ieee80211_sub_if_data, 66 u.ap); 67 68 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, 69 &sta->sta); 70 } 71 72 mesh_plink_quiesce(sta); 73 } 74 spin_unlock_irqrestore(&local->sta_lock, flags); 75 76 /* remove all interfaces */ 77 list_for_each_entry(sdata, &local->interfaces, list) { 78 switch(sdata->vif.type) { 79 case NL80211_IFTYPE_STATION: 80 ieee80211_sta_quiesce(sdata); 81 break; 82 case NL80211_IFTYPE_ADHOC: 83 ieee80211_ibss_quiesce(sdata); 84 break; 85 case NL80211_IFTYPE_MESH_POINT: 86 ieee80211_mesh_quiesce(sdata); 87 break; 88 case NL80211_IFTYPE_AP_VLAN: 89 case NL80211_IFTYPE_MONITOR: 90 /* don't tell driver about this */ 91 continue; 92 default: 93 break; 94 } 95 96 if (!netif_running(sdata->dev)) 97 continue; 98 99 /* disable beaconing */ 100 ieee80211_bss_info_change_notify(sdata, 101 BSS_CHANGED_BEACON_ENABLED); 102 103 conf.vif = &sdata->vif; 104 conf.type = sdata->vif.type; 105 conf.mac_addr = sdata->dev->dev_addr; 106 drv_remove_interface(local, &conf); 107 } 108 109 /* stop hardware - this must stop RX */ 110 if (local->open_count) 111 ieee80211_stop_device(local); 112 113 local->suspended = true; 114 /* need suspended to be visible before quiescing is false */ 115 barrier(); 116 local->quiescing = false; 117 118 return 0; 119 } 120 121 /* 122 * __ieee80211_resume() is a static inline which just calls 123 * ieee80211_reconfig(), which is also needed for hardware 124 * hang/firmware failure/etc. recovery. 125 */ 126