1 #include <net/mac80211.h>
2 #include <net/rtnetlink.h>
4 #include "ieee80211_i.h"
7 int __ieee80211_suspend(struct ieee80211_hw
*hw
)
9 struct ieee80211_local
*local
= hw_to_local(hw
);
10 struct ieee80211_sub_if_data
*sdata
;
11 struct ieee80211_if_init_conf conf
;
15 ieee80211_stop_queues_by_reason(hw
,
16 IEEE80211_QUEUE_STOP_REASON_SUSPEND
);
18 flush_workqueue(local
->hw
.workqueue
);
21 list_for_each_entry(sdata
, &local
->interfaces
, list
)
22 ieee80211_disable_keys(sdata
);
24 /* Tear down aggregation sessions */
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
);
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
,
46 local
->ops
->sta_notify(hw
, &sdata
->vif
,
47 STA_NOTIFY_REMOVE
, &sta
->sta
);
49 spin_unlock_irqrestore(&local
->sta_lock
, flags
);
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
);
64 /* flush again, in case driver queued work */
65 flush_workqueue(local
->hw
.workqueue
);
68 if (local
->open_count
) {
69 ieee80211_led_radio(local
, false);
75 int __ieee80211_resume(struct ieee80211_hw
*hw
)
77 struct ieee80211_local
*local
= hw_to_local(hw
);
78 struct ieee80211_sub_if_data
*sdata
;
79 struct ieee80211_if_init_conf conf
;
84 /* restart hardware */
85 if (local
->open_count
) {
86 res
= local
->ops
->start(hw
);
88 ieee80211_led_radio(local
, hw
->conf
.radio_enabled
);
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
);
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
,
112 local
->ops
->sta_notify(hw
, &sdata
->vif
,
113 STA_NOTIFY_ADD
, &sta
->sta
);
115 spin_unlock_irqrestore(&local
->sta_lock
, flags
);
118 /* Clear Suspend state so that ADDBA requests can be processed */
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
);
131 list_for_each_entry(sdata
, &local
->interfaces
, list
)
132 if (netif_running(sdata
->dev
))
133 ieee80211_enable_keys(sdata
);
135 /* setup RTS threshold */
136 if (local
->ops
->set_rts_threshold
)
137 local
->ops
->set_rts_threshold(hw
, local
->rts_threshold
);
139 /* reconfigure hardware */
140 ieee80211_hw_config(local
, ~0);
142 netif_addr_lock_bh(local
->mdev
);
143 ieee80211_configure_filter(local
);
144 netif_addr_unlock_bh(local
->mdev
);
146 /* Finally also reconfigure all the BSS information */
147 list_for_each_entry(sdata
, &local
->interfaces
, list
) {
149 if (!netif_running(sdata
->dev
))
151 switch (sdata
->vif
.type
) {
152 case NL80211_IFTYPE_STATION
:
153 /* disable beacon change bits */
154 changed
&= ~IEEE80211_IFCC_BEACON
;
156 case NL80211_IFTYPE_ADHOC
:
157 case NL80211_IFTYPE_AP
:
158 case NL80211_IFTYPE_MESH_POINT
:
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);
167 if (ieee80211_if_config(sdata
, changed
))
168 printk(KERN_DEBUG
"%s: failed to configure interface during resume\n",
171 ieee80211_bss_info_change_notify(sdata
, ~0);
173 case NL80211_IFTYPE_WDS
:
175 case NL80211_IFTYPE_AP_VLAN
:
176 case NL80211_IFTYPE_MONITOR
:
179 case NL80211_IFTYPE_UNSPECIFIED
:
180 case __NL80211_IFTYPE_AFTER_LAST
:
186 ieee80211_wake_queues_by_reason(hw
,
187 IEEE80211_QUEUE_STOP_REASON_SUSPEND
);