2 * mac80211 work implementation
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>
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.
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>
26 #include "ieee80211_i.h"
28 #include "driver-ops.h"
37 static inline void ASSERT_WORK_MTX(struct ieee80211_local
*local
)
39 lockdep_assert_held(&local
->mtx
);
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
52 static void run_again(struct ieee80211_local
*local
,
53 unsigned long timeout
)
55 ASSERT_WORK_MTX(local
);
57 if (!timer_pending(&local
->work_timer
) ||
58 time_before(timeout
, local
->work_timer
.expires
))
59 mod_timer(&local
->work_timer
, timeout
);
62 void free_work(struct ieee80211_work
*wk
)
64 kfree_rcu(wk
, rcu_head
);
67 static enum work_action __must_check
68 ieee80211_remain_on_channel_timeout(struct ieee80211_work
*wk
)
71 * First time we run, do nothing -- the generic code will
72 * have switched to the right channel etc.
75 wk
->timeout
= jiffies
+ msecs_to_jiffies(wk
->remain
.duration
);
77 cfg80211_ready_on_channel(wk
->sdata
->dev
, (unsigned long) wk
,
78 wk
->chan
, wk
->chan_type
,
79 wk
->remain
.duration
, GFP_KERNEL
);
84 return WORK_ACT_TIMEOUT
;
87 static enum work_action __must_check
88 ieee80211_offchannel_tx(struct ieee80211_work
*wk
)
91 wk
->timeout
= jiffies
+ msecs_to_jiffies(wk
->offchan_tx
.wait
);
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.
98 ieee80211_tx_skb(wk
->sdata
, wk
->offchan_tx
.frame
);
100 return WORK_ACT_NONE
;
103 return WORK_ACT_TIMEOUT
;
106 static void ieee80211_work_timer(unsigned long data
)
108 struct ieee80211_local
*local
= (void *) data
;
110 if (local
->quiescing
)
113 ieee80211_queue_work(&local
->hw
, &local
->work_work
);
116 static void ieee80211_work_work(struct work_struct
*work
)
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;
129 * ieee80211_queue_work() should have picked up most cases,
130 * here we'll pick the rest.
132 if (WARN(local
->suspended
, "work scheduled while going to suspend\n"))
135 mutex_lock(&local
->mtx
);
137 ieee80211_recalc_idle(local
);
139 list_for_each_entry_safe(wk
, tmp
, &local
->work_list
, list
) {
140 bool started
= wk
->started
;
142 /* mark work as started if it's on the current off-channel */
143 if (!started
&& local
->tmp_channel
&&
144 wk
->chan
== local
->tmp_channel
&&
145 wk
->chan_type
== local
->tmp_channel_type
) {
147 wk
->timeout
= jiffies
;
150 if (!started
&& !local
->tmp_channel
) {
151 ieee80211_offchannel_stop_vifs(local
, true);
153 local
->tmp_channel
= wk
->chan
;
154 local
->tmp_channel_type
= wk
->chan_type
;
156 ieee80211_hw_config(local
, 0);
159 wk
->timeout
= jiffies
;
162 /* don't try to work with items that aren't started */
166 if (time_is_after_jiffies(wk
->timeout
)) {
168 * This work item isn't supposed to be worked on
169 * right now, but take care to adjust the timer
172 run_again(local
, wk
->timeout
);
182 case IEEE80211_WORK_ABORT
:
183 rma
= WORK_ACT_TIMEOUT
;
185 case IEEE80211_WORK_REMAIN_ON_CHANNEL
:
186 rma
= ieee80211_remain_on_channel_timeout(wk
);
188 case IEEE80211_WORK_OFFCHANNEL_TX
:
189 rma
= ieee80211_offchannel_tx(wk
);
193 wk
->started
= started
;
197 /* might have changed the timeout */
198 run_again(local
, wk
->timeout
);
200 case WORK_ACT_TIMEOUT
:
201 list_del_rcu(&wk
->list
);
203 list_add(&wk
->list
, &free_work
);
206 WARN(1, "unexpected: %d", rma
);
210 list_for_each_entry(wk
, &local
->work_list
, list
) {
213 if (wk
->chan
!= local
->tmp_channel
||
214 wk
->chan_type
!= local
->tmp_channel_type
)
216 remain_off_channel
= true;
219 if (!remain_off_channel
&& local
->tmp_channel
) {
220 local
->tmp_channel
= NULL
;
221 ieee80211_hw_config(local
, 0);
223 ieee80211_offchannel_return(local
, true);
225 /* give connection some time to breathe */
226 run_again(local
, jiffies
+ HZ
/2);
229 if (list_empty(&local
->work_list
) && local
->scan_req
&&
231 ieee80211_queue_delayed_work(&local
->hw
,
233 round_jiffies_relative(0));
235 ieee80211_recalc_idle(local
);
237 mutex_unlock(&local
->mtx
);
239 list_for_each_entry_safe(wk
, tmp
, &free_work
, list
) {
246 void ieee80211_add_work(struct ieee80211_work
*wk
)
248 struct ieee80211_local
*local
;
250 if (WARN_ON(!wk
->chan
))
253 if (WARN_ON(!wk
->sdata
))
256 if (WARN_ON(!wk
->done
))
259 if (WARN_ON(!ieee80211_sdata_running(wk
->sdata
)))
264 local
= wk
->sdata
->local
;
265 mutex_lock(&local
->mtx
);
266 list_add_tail(&wk
->list
, &local
->work_list
);
267 mutex_unlock(&local
->mtx
);
269 ieee80211_queue_work(&local
->hw
, &local
->work_work
);
272 void ieee80211_work_init(struct ieee80211_local
*local
)
274 INIT_LIST_HEAD(&local
->work_list
);
275 setup_timer(&local
->work_timer
, ieee80211_work_timer
,
276 (unsigned long)local
);
277 INIT_WORK(&local
->work_work
, ieee80211_work_work
);
280 void ieee80211_work_purge(struct ieee80211_sub_if_data
*sdata
)
282 struct ieee80211_local
*local
= sdata
->local
;
283 struct ieee80211_work
*wk
;
284 bool cleanup
= false;
286 mutex_lock(&local
->mtx
);
287 list_for_each_entry(wk
, &local
->work_list
, list
) {
288 if (wk
->sdata
!= sdata
)
291 wk
->type
= IEEE80211_WORK_ABORT
;
293 wk
->timeout
= jiffies
;
295 mutex_unlock(&local
->mtx
);
297 /* run cleanups etc. */
299 ieee80211_work_work(&local
->work_work
);
301 mutex_lock(&local
->mtx
);
302 list_for_each_entry(wk
, &local
->work_list
, list
) {
303 if (wk
->sdata
!= sdata
)
308 mutex_unlock(&local
->mtx
);
311 static enum work_done_result
ieee80211_remain_done(struct ieee80211_work
*wk
,
315 * We are done serving the remain-on-channel command.
317 cfg80211_remain_on_channel_expired(wk
->sdata
->dev
, (unsigned long) wk
,
318 wk
->chan
, wk
->chan_type
,
321 return WORK_DONE_DESTROY
;
324 int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data
*sdata
,
325 struct ieee80211_channel
*chan
,
326 enum nl80211_channel_type channel_type
,
327 unsigned int duration
, u64
*cookie
)
329 struct ieee80211_work
*wk
;
331 wk
= kzalloc(sizeof(*wk
), GFP_KERNEL
);
335 wk
->type
= IEEE80211_WORK_REMAIN_ON_CHANNEL
;
337 wk
->chan_type
= channel_type
;
339 wk
->done
= ieee80211_remain_done
;
341 wk
->remain
.duration
= duration
;
343 *cookie
= (unsigned long) wk
;
345 ieee80211_add_work(wk
);
350 int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data
*sdata
,
353 struct ieee80211_local
*local
= sdata
->local
;
354 struct ieee80211_work
*wk
, *tmp
;
357 mutex_lock(&local
->mtx
);
358 list_for_each_entry_safe(wk
, tmp
, &local
->work_list
, list
) {
359 if ((unsigned long) wk
== cookie
) {
360 wk
->timeout
= jiffies
;
365 mutex_unlock(&local
->mtx
);
370 ieee80211_queue_work(&local
->hw
, &local
->work_work
);