Merge tag 'sound-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / work.c
1 /*
2  * mac80211 work implementation
3  *
4  * Copyright 2003-2008, Jouni Malinen <j@w1.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
16 #include <linux/delay.h>
17 #include <linux/if_ether.h>
18 #include <linux/skbuff.h>
19 #include <linux/if_arp.h>
20 #include <linux/etherdevice.h>
21 #include <linux/crc32.h>
22 #include <linux/slab.h>
23 #include <net/mac80211.h>
24 #include <asm/unaligned.h>
25
26 #include "ieee80211_i.h"
27 #include "rate.h"
28 #include "driver-ops.h"
29
30 enum work_action {
31         WORK_ACT_NONE,
32         WORK_ACT_TIMEOUT,
33 };
34
35
36 /* utils */
37 static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
38 {
39         lockdep_assert_held(&local->mtx);
40 }
41
42 /*
43  * We can have multiple work items (and connection probing)
44  * scheduling this timer, but we need to take care to only
45  * reschedule it when it should fire _earlier_ than it was
46  * asked for before, or if it's not pending right now. This
47  * function ensures that. Note that it then is required to
48  * run this function for all timeouts after the first one
49  * has happened -- the work that runs from this timer will
50  * do that.
51  */
52 static void run_again(struct ieee80211_local *local,
53                       unsigned long timeout)
54 {
55         ASSERT_WORK_MTX(local);
56
57         if (!timer_pending(&local->work_timer) ||
58             time_before(timeout, local->work_timer.expires))
59                 mod_timer(&local->work_timer, timeout);
60 }
61
62 void free_work(struct ieee80211_work *wk)
63 {
64         kfree_rcu(wk, rcu_head);
65 }
66
67 static enum work_action __must_check
68 ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
69 {
70         /*
71          * First time we run, do nothing -- the generic code will
72          * have switched to the right channel etc.
73          */
74         if (!wk->started) {
75                 wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration);
76
77                 cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk,
78                                           wk->chan, wk->chan_type,
79                                           wk->remain.duration, GFP_KERNEL);
80
81                 return WORK_ACT_NONE;
82         }
83
84         return WORK_ACT_TIMEOUT;
85 }
86
87 static enum work_action __must_check
88 ieee80211_offchannel_tx(struct ieee80211_work *wk)
89 {
90         if (!wk->started) {
91                 wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait);
92
93                 /*
94                  * After this, offchan_tx.frame remains but now is no
95                  * longer a valid pointer -- we still need it as the
96                  * cookie for canceling this work/status matching.
97                  */
98                 ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame);
99
100                 return WORK_ACT_NONE;
101         }
102
103         return WORK_ACT_TIMEOUT;
104 }
105
106 static void ieee80211_work_timer(unsigned long data)
107 {
108         struct ieee80211_local *local = (void *) data;
109
110         if (local->quiescing)
111                 return;
112
113         ieee80211_queue_work(&local->hw, &local->work_work);
114 }
115
116 static void ieee80211_work_work(struct work_struct *work)
117 {
118         struct ieee80211_local *local =
119                 container_of(work, struct ieee80211_local, work_work);
120         struct ieee80211_work *wk, *tmp;
121         LIST_HEAD(free_work);
122         enum work_action rma;
123         bool remain_off_channel = false;
124
125         /*
126          * ieee80211_queue_work() should have picked up most cases,
127          * here we'll pick the rest.
128          */
129         if (WARN(local->suspended, "work scheduled while going to suspend\n"))
130                 return;
131
132         mutex_lock(&local->mtx);
133
134         if (local->scanning) {
135                 mutex_unlock(&local->mtx);
136                 return;
137         }
138
139         ieee80211_recalc_idle(local);
140
141         list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
142                 bool started = wk->started;
143
144                 /* mark work as started if it's on the current off-channel */
145                 if (!started && local->tmp_channel &&
146                     wk->chan == local->tmp_channel &&
147                     wk->chan_type == local->tmp_channel_type) {
148                         started = true;
149                         wk->timeout = jiffies;
150                 }
151
152                 if (!started && !local->tmp_channel) {
153                         ieee80211_offchannel_stop_vifs(local, true);
154
155                         local->tmp_channel = wk->chan;
156                         local->tmp_channel_type = wk->chan_type;
157
158                         ieee80211_hw_config(local, 0);
159
160                         started = true;
161                         wk->timeout = jiffies;
162                 }
163
164                 /* don't try to work with items that aren't started */
165                 if (!started)
166                         continue;
167
168                 if (time_is_after_jiffies(wk->timeout)) {
169                         /*
170                          * This work item isn't supposed to be worked on
171                          * right now, but take care to adjust the timer
172                          * properly.
173                          */
174                         run_again(local, wk->timeout);
175                         continue;
176                 }
177
178                 switch (wk->type) {
179                 default:
180                         WARN_ON(1);
181                         /* nothing */
182                         rma = WORK_ACT_NONE;
183                         break;
184                 case IEEE80211_WORK_ABORT:
185                         rma = WORK_ACT_TIMEOUT;
186                         break;
187                 case IEEE80211_WORK_REMAIN_ON_CHANNEL:
188                         rma = ieee80211_remain_on_channel_timeout(wk);
189                         break;
190                 case IEEE80211_WORK_OFFCHANNEL_TX:
191                         rma = ieee80211_offchannel_tx(wk);
192                         break;
193                 }
194
195                 wk->started = started;
196
197                 switch (rma) {
198                 case WORK_ACT_NONE:
199                         /* might have changed the timeout */
200                         run_again(local, wk->timeout);
201                         break;
202                 case WORK_ACT_TIMEOUT:
203                         list_del_rcu(&wk->list);
204                         synchronize_rcu();
205                         list_add(&wk->list, &free_work);
206                         break;
207                 default:
208                         WARN(1, "unexpected: %d", rma);
209                 }
210         }
211
212         list_for_each_entry(wk, &local->work_list, list) {
213                 if (!wk->started)
214                         continue;
215                 if (wk->chan != local->tmp_channel ||
216                     wk->chan_type != local->tmp_channel_type)
217                         continue;
218                 remain_off_channel = true;
219         }
220
221         if (!remain_off_channel && local->tmp_channel) {
222                 local->tmp_channel = NULL;
223                 ieee80211_hw_config(local, 0);
224
225                 ieee80211_offchannel_return(local, true);
226
227                 /* give connection some time to breathe */
228                 run_again(local, jiffies + HZ/2);
229         }
230
231         ieee80211_recalc_idle(local);
232         ieee80211_run_deferred_scan(local);
233
234         mutex_unlock(&local->mtx);
235
236         list_for_each_entry_safe(wk, tmp, &free_work, list) {
237                 wk->done(wk, NULL);
238                 list_del(&wk->list);
239                 kfree(wk);
240         }
241 }
242
243 void ieee80211_add_work(struct ieee80211_work *wk)
244 {
245         struct ieee80211_local *local;
246
247         if (WARN_ON(!wk->chan))
248                 return;
249
250         if (WARN_ON(!wk->sdata))
251                 return;
252
253         if (WARN_ON(!wk->done))
254                 return;
255
256         if (WARN_ON(!ieee80211_sdata_running(wk->sdata)))
257                 return;
258
259         wk->started = false;
260
261         local = wk->sdata->local;
262         mutex_lock(&local->mtx);
263         list_add_tail(&wk->list, &local->work_list);
264         mutex_unlock(&local->mtx);
265
266         ieee80211_queue_work(&local->hw, &local->work_work);
267 }
268
269 void ieee80211_work_init(struct ieee80211_local *local)
270 {
271         INIT_LIST_HEAD(&local->work_list);
272         setup_timer(&local->work_timer, ieee80211_work_timer,
273                     (unsigned long)local);
274         INIT_WORK(&local->work_work, ieee80211_work_work);
275 }
276
277 void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
278 {
279         struct ieee80211_local *local = sdata->local;
280         struct ieee80211_work *wk;
281         bool cleanup = false;
282
283         mutex_lock(&local->mtx);
284         list_for_each_entry(wk, &local->work_list, list) {
285                 if (wk->sdata != sdata)
286                         continue;
287                 cleanup = true;
288                 wk->type = IEEE80211_WORK_ABORT;
289                 wk->started = true;
290                 wk->timeout = jiffies;
291         }
292         mutex_unlock(&local->mtx);
293
294         /* run cleanups etc. */
295         if (cleanup)
296                 ieee80211_work_work(&local->work_work);
297
298         mutex_lock(&local->mtx);
299         list_for_each_entry(wk, &local->work_list, list) {
300                 if (wk->sdata != sdata)
301                         continue;
302                 WARN_ON(1);
303                 break;
304         }
305         mutex_unlock(&local->mtx);
306 }
307
308 static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk,
309                                                    struct sk_buff *skb)
310 {
311         /*
312          * We are done serving the remain-on-channel command.
313          */
314         cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk,
315                                            wk->chan, wk->chan_type,
316                                            GFP_KERNEL);
317
318         return WORK_DONE_DESTROY;
319 }
320
321 int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
322                                    struct ieee80211_channel *chan,
323                                    enum nl80211_channel_type channel_type,
324                                    unsigned int duration, u64 *cookie)
325 {
326         struct ieee80211_work *wk;
327
328         wk = kzalloc(sizeof(*wk), GFP_KERNEL);
329         if (!wk)
330                 return -ENOMEM;
331
332         wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL;
333         wk->chan = chan;
334         wk->chan_type = channel_type;
335         wk->sdata = sdata;
336         wk->done = ieee80211_remain_done;
337
338         wk->remain.duration = duration;
339
340         *cookie = (unsigned long) wk;
341
342         ieee80211_add_work(wk);
343
344         return 0;
345 }
346
347 int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
348                                           u64 cookie)
349 {
350         struct ieee80211_local *local = sdata->local;
351         struct ieee80211_work *wk, *tmp;
352         bool found = false;
353
354         mutex_lock(&local->mtx);
355         list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
356                 if ((unsigned long) wk == cookie) {
357                         wk->timeout = jiffies;
358                         found = true;
359                         break;
360                 }
361         }
362         mutex_unlock(&local->mtx);
363
364         if (!found)
365                 return -ENOENT;
366
367         ieee80211_queue_work(&local->hw, &local->work_work);
368
369         return 0;
370 }