Merge branch 'for-2637/i2c-all' of git://git.fluff.org/bjdooks/linux
[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
18 /*
19  * inform AP that we will go to sleep so that it will buffer the frames
20  * while we scan
21  */
22 static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
23 {
24         struct ieee80211_local *local = sdata->local;
25         struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
26
27         local->offchannel_ps_enabled = false;
28
29         /* FIXME: what to do when local->pspolling is true? */
30
31         del_timer_sync(&local->dynamic_ps_timer);
32         del_timer_sync(&ifmgd->bcn_mon_timer);
33         del_timer_sync(&ifmgd->conn_mon_timer);
34
35         cancel_work_sync(&local->dynamic_ps_enable_work);
36
37         if (local->hw.conf.flags & IEEE80211_CONF_PS) {
38                 local->offchannel_ps_enabled = true;
39                 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
40                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
41         }
42
43         if (!(local->offchannel_ps_enabled) ||
44             !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
45                 /*
46                  * If power save was enabled, no need to send a nullfunc
47                  * frame because AP knows that we are sleeping. But if the
48                  * hardware is creating the nullfunc frame for power save
49                  * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
50                  * enabled) and power save was enabled, the firmware just
51                  * sent a null frame with power save disabled. So we need
52                  * to send a new nullfunc frame to inform the AP that we
53                  * are again sleeping.
54                  */
55                 ieee80211_send_nullfunc(local, sdata, 1);
56 }
57
58 /* inform AP that we are awake again, unless power save is enabled */
59 static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
60 {
61         struct ieee80211_local *local = sdata->local;
62
63         if (!local->ps_sdata)
64                 ieee80211_send_nullfunc(local, sdata, 0);
65         else if (local->offchannel_ps_enabled) {
66                 /*
67                  * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
68                  * will send a nullfunc frame with the powersave bit set
69                  * even though the AP already knows that we are sleeping.
70                  * This could be avoided by sending a null frame with power
71                  * save bit disabled before enabling the power save, but
72                  * this doesn't gain anything.
73                  *
74                  * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
75                  * to send a nullfunc frame because AP already knows that
76                  * we are sleeping, let's just enable power save mode in
77                  * hardware.
78                  */
79                 local->hw.conf.flags |= IEEE80211_CONF_PS;
80                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
81         } else if (local->hw.conf.dynamic_ps_timeout > 0) {
82                 /*
83                  * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
84                  * had been running before leaving the operating channel,
85                  * restart the timer now and send a nullfunc frame to inform
86                  * the AP that we are awake.
87                  */
88                 ieee80211_send_nullfunc(local, sdata, 0);
89                 mod_timer(&local->dynamic_ps_timer, jiffies +
90                           msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
91         }
92
93         ieee80211_sta_reset_beacon_monitor(sdata);
94         ieee80211_sta_reset_conn_monitor(sdata);
95 }
96
97 void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
98 {
99         struct ieee80211_sub_if_data *sdata;
100
101         mutex_lock(&local->iflist_mtx);
102         list_for_each_entry(sdata, &local->interfaces, list) {
103                 if (!ieee80211_sdata_running(sdata))
104                         continue;
105
106                 /* disable beaconing */
107                 if (sdata->vif.type == NL80211_IFTYPE_AP ||
108                     sdata->vif.type == NL80211_IFTYPE_ADHOC ||
109                     sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
110                         ieee80211_bss_info_change_notify(
111                                 sdata, BSS_CHANGED_BEACON_ENABLED);
112
113                 /*
114                  * only handle non-STA interfaces here, STA interfaces
115                  * are handled in ieee80211_offchannel_stop_station(),
116                  * e.g., from the background scan state machine.
117                  *
118                  * In addition, do not stop monitor interface to allow it to be
119                  * used from user space controlled off-channel operations.
120                  */
121                 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
122                     sdata->vif.type != NL80211_IFTYPE_MONITOR) {
123                         set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
124                         netif_tx_stop_all_queues(sdata->dev);
125                 }
126         }
127         mutex_unlock(&local->iflist_mtx);
128 }
129
130 void ieee80211_offchannel_stop_station(struct ieee80211_local *local)
131 {
132         struct ieee80211_sub_if_data *sdata;
133
134         /*
135          * notify the AP about us leaving the channel and stop all STA interfaces
136          */
137         mutex_lock(&local->iflist_mtx);
138         list_for_each_entry(sdata, &local->interfaces, list) {
139                 if (!ieee80211_sdata_running(sdata))
140                         continue;
141
142                 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
143                         set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
144                         netif_tx_stop_all_queues(sdata->dev);
145                         if (sdata->u.mgd.associated)
146                                 ieee80211_offchannel_ps_enable(sdata);
147                 }
148         }
149         mutex_unlock(&local->iflist_mtx);
150 }
151
152 void ieee80211_offchannel_return(struct ieee80211_local *local,
153                                  bool enable_beaconing)
154 {
155         struct ieee80211_sub_if_data *sdata;
156
157         mutex_lock(&local->iflist_mtx);
158         list_for_each_entry(sdata, &local->interfaces, list) {
159                 if (!ieee80211_sdata_running(sdata))
160                         continue;
161
162                 /* Tell AP we're back */
163                 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
164                         if (sdata->u.mgd.associated)
165                                 ieee80211_offchannel_ps_disable(sdata);
166                 }
167
168                 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
169                         clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
170                         /*
171                          * This may wake up queues even though the driver
172                          * currently has them stopped. This is not very
173                          * likely, since the driver won't have gotten any
174                          * (or hardly any) new packets while we weren't
175                          * on the right channel, and even if it happens
176                          * it will at most lead to queueing up one more
177                          * packet per queue in mac80211 rather than on
178                          * the interface qdisc.
179                          */
180                         netif_tx_wake_all_queues(sdata->dev);
181                 }
182
183                 /* re-enable beaconing */
184                 if (enable_beaconing &&
185                     (sdata->vif.type == NL80211_IFTYPE_AP ||
186                      sdata->vif.type == NL80211_IFTYPE_ADHOC ||
187                      sdata->vif.type == NL80211_IFTYPE_MESH_POINT))
188                         ieee80211_bss_info_change_notify(
189                                 sdata, BSS_CHANGED_BEACON_ENABLED);
190         }
191         mutex_unlock(&local->iflist_mtx);
192 }