mac80211: add suspend/resume callbacks
[linux-2.6.git] / net / mac80211 / pm.c
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
14         flush_workqueue(local->hw.workqueue);
15
16         /* disable keys */
17         list_for_each_entry(sdata, &local->interfaces, list)
18                 ieee80211_disable_keys(sdata);
19
20         /* remove STAs */
21         list_for_each_entry(sta, &local->sta_list, list) {
22
23                 if (local->ops->sta_notify) {
24                         if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
25                                 sdata = container_of(sdata->bss,
26                                              struct ieee80211_sub_if_data,
27                                              u.ap);
28
29                         local->ops->sta_notify(hw, &sdata->vif,
30                                 STA_NOTIFY_REMOVE, &sta->sta);
31                 }
32         }
33
34         /* remove all interfaces */
35         list_for_each_entry(sdata, &local->interfaces, list) {
36
37                 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
38                     sdata->vif.type != NL80211_IFTYPE_MONITOR &&
39                     netif_running(sdata->dev)) {
40                         conf.vif = &sdata->vif;
41                         conf.type = sdata->vif.type;
42                         conf.mac_addr = sdata->dev->dev_addr;
43                         local->ops->remove_interface(hw, &conf);
44                 }
45         }
46
47         /* stop hardware */
48         if (local->open_count) {
49                 ieee80211_led_radio(local, false);
50                 local->ops->stop(hw);
51         }
52         return 0;
53 }
54
55 int __ieee80211_resume(struct ieee80211_hw *hw)
56 {
57         struct ieee80211_local *local = hw_to_local(hw);
58         struct ieee80211_sub_if_data *sdata;
59         struct ieee80211_if_init_conf conf;
60         struct sta_info *sta;
61         int res;
62
63         /* restart hardware */
64         if (local->open_count) {
65                 res = local->ops->start(hw);
66
67                 ieee80211_led_radio(local, hw->conf.radio_enabled);
68         }
69
70         /* add interfaces */
71         list_for_each_entry(sdata, &local->interfaces, list) {
72
73                 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
74                     sdata->vif.type != NL80211_IFTYPE_MONITOR &&
75                     netif_running(sdata->dev)) {
76                         conf.vif = &sdata->vif;
77                         conf.type = sdata->vif.type;
78                         conf.mac_addr = sdata->dev->dev_addr;
79                         res = local->ops->add_interface(hw, &conf);
80                 }
81         }
82
83         /* add STAs back */
84         list_for_each_entry(sta, &local->sta_list, list) {
85
86                 if (local->ops->sta_notify) {
87                         if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
88                                 sdata = container_of(sdata->bss,
89                                              struct ieee80211_sub_if_data,
90                                              u.ap);
91
92                         local->ops->sta_notify(hw, &sdata->vif,
93                                 STA_NOTIFY_ADD, &sta->sta);
94                 }
95         }
96
97         /* add back keys */
98         list_for_each_entry(sdata, &local->interfaces, list)
99                 if (netif_running(sdata->dev))
100                         ieee80211_enable_keys(sdata);
101
102         /* setup RTS threshold */
103         if (local->ops->set_rts_threshold)
104                 local->ops->set_rts_threshold(hw, local->rts_threshold);
105
106         /* reconfigure hardware */
107         ieee80211_hw_config(local, ~0);
108
109         netif_addr_lock_bh(local->mdev);
110         ieee80211_configure_filter(local);
111         netif_addr_unlock_bh(local->mdev);
112
113         return 0;
114 }