1 #include <net/mac80211.h> 2 #include <net/rtnetlink.h> 3 4 #include "ieee80211_i.h" 5 #include "led.h" 6 7 int __ieee80211_suspend(struct ieee80211_hw *hw) 8 { 9 struct ieee80211_local *local = hw_to_local(hw); 10 struct ieee80211_sub_if_data *sdata; 11 struct ieee80211_if_init_conf conf; 12 struct sta_info *sta; 13 unsigned long flags; 14 15 ieee80211_stop_queues_by_reason(hw, 16 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 17 18 flush_workqueue(local->hw.workqueue); 19 20 /* disable keys */ 21 list_for_each_entry(sdata, &local->interfaces, list) 22 ieee80211_disable_keys(sdata); 23 24 /* Tear down aggregation sessions */ 25 26 rcu_read_lock(); 27 28 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 29 list_for_each_entry_rcu(sta, &local->sta_list, list) { 30 set_sta_flags(sta, WLAN_STA_SUSPEND); 31 ieee80211_sta_tear_down_BA_sessions(sta); 32 } 33 } 34 35 rcu_read_unlock(); 36 37 /* remove STAs */ 38 if (local->ops->sta_notify) { 39 spin_lock_irqsave(&local->sta_lock, flags); 40 list_for_each_entry(sta, &local->sta_list, list) { 41 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 42 sdata = container_of(sdata->bss, 43 struct ieee80211_sub_if_data, 44 u.ap); 45 46 local->ops->sta_notify(hw, &sdata->vif, 47 STA_NOTIFY_REMOVE, &sta->sta); 48 } 49 spin_unlock_irqrestore(&local->sta_lock, flags); 50 } 51 52 /* remove all interfaces */ 53 list_for_each_entry(sdata, &local->interfaces, list) { 54 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 55 sdata->vif.type != NL80211_IFTYPE_MONITOR && 56 netif_running(sdata->dev)) { 57 conf.vif = &sdata->vif; 58 conf.type = sdata->vif.type; 59 conf.mac_addr = sdata->dev->dev_addr; 60 local->ops->remove_interface(hw, &conf); 61 } 62 } 63 64 /* flush again, in case driver queued work */ 65 flush_workqueue(local->hw.workqueue); 66 67 /* stop hardware */ 68 if (local->open_count) { 69 ieee80211_led_radio(local, false); 70 local->ops->stop(hw); 71 } 72 return 0; 73 } 74 75 int __ieee80211_resume(struct ieee80211_hw *hw) 76 { 77 struct ieee80211_local *local = hw_to_local(hw); 78 struct ieee80211_sub_if_data *sdata; 79 struct ieee80211_if_init_conf conf; 80 struct sta_info *sta; 81 unsigned long flags; 82 int res; 83 84 /* restart hardware */ 85 if (local->open_count) { 86 res = local->ops->start(hw); 87 88 ieee80211_led_radio(local, hw->conf.radio_enabled); 89 } 90 91 /* add interfaces */ 92 list_for_each_entry(sdata, &local->interfaces, list) { 93 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 94 sdata->vif.type != NL80211_IFTYPE_MONITOR && 95 netif_running(sdata->dev)) { 96 conf.vif = &sdata->vif; 97 conf.type = sdata->vif.type; 98 conf.mac_addr = sdata->dev->dev_addr; 99 res = local->ops->add_interface(hw, &conf); 100 } 101 } 102 103 /* add STAs back */ 104 if (local->ops->sta_notify) { 105 spin_lock_irqsave(&local->sta_lock, flags); 106 list_for_each_entry(sta, &local->sta_list, list) { 107 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 108 sdata = container_of(sdata->bss, 109 struct ieee80211_sub_if_data, 110 u.ap); 111 112 local->ops->sta_notify(hw, &sdata->vif, 113 STA_NOTIFY_ADD, &sta->sta); 114 } 115 spin_unlock_irqrestore(&local->sta_lock, flags); 116 } 117 118 /* Clear Suspend state so that ADDBA requests can be processed */ 119 120 rcu_read_lock(); 121 122 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 123 list_for_each_entry_rcu(sta, &local->sta_list, list) { 124 clear_sta_flags(sta, WLAN_STA_SUSPEND); 125 } 126 } 127 128 rcu_read_unlock(); 129 130 /* add back keys */ 131 list_for_each_entry(sdata, &local->interfaces, list) 132 if (netif_running(sdata->dev)) 133 ieee80211_enable_keys(sdata); 134 135 /* setup RTS threshold */ 136 if (local->ops->set_rts_threshold) 137 local->ops->set_rts_threshold(hw, local->rts_threshold); 138 139 /* reconfigure hardware */ 140 ieee80211_hw_config(local, ~0); 141 142 netif_addr_lock_bh(local->mdev); 143 ieee80211_configure_filter(local); 144 netif_addr_unlock_bh(local->mdev); 145 146 /* Finally also reconfigure all the BSS information */ 147 list_for_each_entry(sdata, &local->interfaces, list) { 148 u32 changed = ~0; 149 if (!netif_running(sdata->dev)) 150 continue; 151 switch (sdata->vif.type) { 152 case NL80211_IFTYPE_STATION: 153 /* disable beacon change bits */ 154 changed &= ~IEEE80211_IFCC_BEACON; 155 /* fall through */ 156 case NL80211_IFTYPE_ADHOC: 157 case NL80211_IFTYPE_AP: 158 case NL80211_IFTYPE_MESH_POINT: 159 /* 160 * Driver's config_interface can fail if rfkill is 161 * enabled. Accommodate this return code. 162 * FIXME: When mac80211 has knowledge of rfkill 163 * state the code below can change back to: 164 * WARN(ieee80211_if_config(sdata, changed)); 165 * ieee80211_bss_info_change_notify(sdata, ~0); 166 */ 167 if (ieee80211_if_config(sdata, changed)) 168 printk(KERN_DEBUG "%s: failed to configure interface during resume\n", 169 sdata->dev->name); 170 else 171 ieee80211_bss_info_change_notify(sdata, ~0); 172 break; 173 case NL80211_IFTYPE_WDS: 174 break; 175 case NL80211_IFTYPE_AP_VLAN: 176 case NL80211_IFTYPE_MONITOR: 177 /* ignore virtual */ 178 break; 179 case NL80211_IFTYPE_UNSPECIFIED: 180 case __NL80211_IFTYPE_AFTER_LAST: 181 WARN_ON(1); 182 break; 183 } 184 } 185 186 ieee80211_wake_queues_by_reason(hw, 187 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 188 189 return 0; 190 } 191