Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
[pandora-kernel.git] / net / mac80211 / offchannel.c
1 /*
2  * Off-channel operation helpers
3  *
4  * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
5  * Copyright 2004, Instant802 Networks, Inc.
6  * Copyright 2005, Devicescape Software, Inc.
7  * Copyright 2006-2007  Jiri Benc <jbenc@suse.cz>
8  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9  * Copyright 2009       Johannes Berg <johannes@sipsolutions.net>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15 #include <net/mac80211.h>
16 #include "ieee80211_i.h"
17 #include "driver-trace.h"
18
19 /*
20  * inform AP that we will go to sleep so that it will buffer the frames
21  * while we scan
22  */
23 static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
24 {
25         struct ieee80211_local *local = sdata->local;
26         struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
27
28         local->offchannel_ps_enabled = false;
29
30         /* FIXME: what to do when local->pspolling is true? */
31
32         del_timer_sync(&local->dynamic_ps_timer);
33         del_timer_sync(&ifmgd->bcn_mon_timer);
34         del_timer_sync(&ifmgd->conn_mon_timer);
35
36         cancel_work_sync(&local->dynamic_ps_enable_work);
37
38         if (local->hw.conf.flags & IEEE80211_CONF_PS) {
39                 local->offchannel_ps_enabled = true;
40                 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
41                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
42         }
43
44         if (!(local->offchannel_ps_enabled) ||
45             !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
46                 /*
47                  * If power save was enabled, no need to send a nullfunc
48                  * frame because AP knows that we are sleeping. But if the
49                  * hardware is creating the nullfunc frame for power save
50                  * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
51                  * enabled) and power save was enabled, the firmware just
52                  * sent a null frame with power save disabled. So we need
53                  * to send a new nullfunc frame to inform the AP that we
54                  * are again sleeping.
55                  */
56                 ieee80211_send_nullfunc(local, sdata, 1);
57 }
58
59 /* inform AP that we are awake again, unless power save is enabled */
60 static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
61 {
62         struct ieee80211_local *local = sdata->local;
63
64         if (!local->ps_sdata)
65                 ieee80211_send_nullfunc(local, sdata, 0);
66         else if (local->offchannel_ps_enabled) {
67                 /*
68                  * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
69                  * will send a nullfunc frame with the powersave bit set
70                  * even though the AP already knows that we are sleeping.
71                  * This could be avoided by sending a null frame with power
72                  * save bit disabled before enabling the power save, but
73                  * this doesn't gain anything.
74                  *
75                  * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
76                  * to send a nullfunc frame because AP already knows that
77                  * we are sleeping, let's just enable power save mode in
78                  * hardware.
79                  */
80                 local->hw.conf.flags |= IEEE80211_CONF_PS;
81                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
82         } else if (local->hw.conf.dynamic_ps_timeout > 0) {
83                 /*
84                  * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
85                  * had been running before leaving the operating channel,
86                  * restart the timer now and send a nullfunc frame to inform
87                  * the AP that we are awake.
88                  */
89                 ieee80211_send_nullfunc(local, sdata, 0);
90                 mod_timer(&local->dynamic_ps_timer, jiffies +
91                           msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
92         }
93
94         ieee80211_sta_reset_beacon_monitor(sdata);
95         ieee80211_sta_reset_conn_monitor(sdata);
96 }
97
98 void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
99 {
100         struct ieee80211_sub_if_data *sdata;
101
102         mutex_lock(&local->iflist_mtx);
103         list_for_each_entry(sdata, &local->interfaces, list) {
104                 if (!ieee80211_sdata_running(sdata))
105                         continue;
106
107                 /* disable beaconing */
108                 if (sdata->vif.type == NL80211_IFTYPE_AP ||
109                     sdata->vif.type == NL80211_IFTYPE_ADHOC ||
110                     sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
111                         ieee80211_bss_info_change_notify(
112                                 sdata, BSS_CHANGED_BEACON_ENABLED);
113
114                 /*
115                  * only handle non-STA interfaces here, STA interfaces
116                  * are handled in ieee80211_offchannel_stop_station(),
117                  * e.g., from the background scan state machine.
118                  *
119                  * In addition, do not stop monitor interface to allow it to be
120                  * used from user space controlled off-channel operations.
121                  */
122                 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
123                     sdata->vif.type != NL80211_IFTYPE_MONITOR) {
124                         set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
125                         netif_tx_stop_all_queues(sdata->dev);
126                 }
127         }
128         mutex_unlock(&local->iflist_mtx);
129 }
130
131 void ieee80211_offchannel_stop_station(struct ieee80211_local *local)
132 {
133         struct ieee80211_sub_if_data *sdata;
134
135         /*
136          * notify the AP about us leaving the channel and stop all STA interfaces
137          */
138         mutex_lock(&local->iflist_mtx);
139         list_for_each_entry(sdata, &local->interfaces, list) {
140                 if (!ieee80211_sdata_running(sdata))
141                         continue;
142
143                 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
144                         set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
145                         netif_tx_stop_all_queues(sdata->dev);
146                         if (sdata->u.mgd.associated)
147                                 ieee80211_offchannel_ps_enable(sdata);
148                 }
149         }
150         mutex_unlock(&local->iflist_mtx);
151 }
152
153 void ieee80211_offchannel_return(struct ieee80211_local *local,
154                                  bool enable_beaconing)
155 {
156         struct ieee80211_sub_if_data *sdata;
157
158         mutex_lock(&local->iflist_mtx);
159         list_for_each_entry(sdata, &local->interfaces, list) {
160                 if (!ieee80211_sdata_running(sdata))
161                         continue;
162
163                 /* Tell AP we're back */
164                 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
165                         if (sdata->u.mgd.associated)
166                                 ieee80211_offchannel_ps_disable(sdata);
167                 }
168
169                 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
170                         clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
171                         /*
172                          * This may wake up queues even though the driver
173                          * currently has them stopped. This is not very
174                          * likely, since the driver won't have gotten any
175                          * (or hardly any) new packets while we weren't
176                          * on the right channel, and even if it happens
177                          * it will at most lead to queueing up one more
178                          * packet per queue in mac80211 rather than on
179                          * the interface qdisc.
180                          */
181                         netif_tx_wake_all_queues(sdata->dev);
182                 }
183
184                 /* re-enable beaconing */
185                 if (enable_beaconing &&
186                     (sdata->vif.type == NL80211_IFTYPE_AP ||
187                      sdata->vif.type == NL80211_IFTYPE_ADHOC ||
188                      sdata->vif.type == NL80211_IFTYPE_MESH_POINT))
189                         ieee80211_bss_info_change_notify(
190                                 sdata, BSS_CHANGED_BEACON_ENABLED);
191         }
192         mutex_unlock(&local->iflist_mtx);
193 }
194
195 static void ieee80211_hw_roc_start(struct work_struct *work)
196 {
197         struct ieee80211_local *local =
198                 container_of(work, struct ieee80211_local, hw_roc_start);
199         struct ieee80211_sub_if_data *sdata;
200
201         mutex_lock(&local->mtx);
202
203         if (!local->hw_roc_channel) {
204                 mutex_unlock(&local->mtx);
205                 return;
206         }
207
208         ieee80211_recalc_idle(local);
209
210         if (local->hw_roc_skb) {
211                 sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev);
212                 ieee80211_tx_skb(sdata, local->hw_roc_skb);
213                 local->hw_roc_skb = NULL;
214         } else {
215                 cfg80211_ready_on_channel(local->hw_roc_dev,
216                                           local->hw_roc_cookie,
217                                           local->hw_roc_channel,
218                                           local->hw_roc_channel_type,
219                                           local->hw_roc_duration,
220                                           GFP_KERNEL);
221         }
222
223         mutex_unlock(&local->mtx);
224 }
225
226 void ieee80211_ready_on_channel(struct ieee80211_hw *hw)
227 {
228         struct ieee80211_local *local = hw_to_local(hw);
229
230         trace_api_ready_on_channel(local);
231
232         ieee80211_queue_work(hw, &local->hw_roc_start);
233 }
234 EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel);
235
236 static void ieee80211_hw_roc_done(struct work_struct *work)
237 {
238         struct ieee80211_local *local =
239                 container_of(work, struct ieee80211_local, hw_roc_done);
240
241         mutex_lock(&local->mtx);
242
243         if (!local->hw_roc_channel) {
244                 mutex_unlock(&local->mtx);
245                 return;
246         }
247
248         if (!local->hw_roc_for_tx)
249                 cfg80211_remain_on_channel_expired(local->hw_roc_dev,
250                                                    local->hw_roc_cookie,
251                                                    local->hw_roc_channel,
252                                                    local->hw_roc_channel_type,
253                                                    GFP_KERNEL);
254
255         local->hw_roc_channel = NULL;
256         local->hw_roc_cookie = 0;
257
258         ieee80211_recalc_idle(local);
259
260         mutex_unlock(&local->mtx);
261 }
262
263 void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw)
264 {
265         struct ieee80211_local *local = hw_to_local(hw);
266
267         trace_api_remain_on_channel_expired(local);
268
269         ieee80211_queue_work(hw, &local->hw_roc_done);
270 }
271 EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired);
272
273 void ieee80211_hw_roc_setup(struct ieee80211_local *local)
274 {
275         INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start);
276         INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done);
277 }