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 */
ASSERT_WORK_MTX(struct ieee80211_local * local)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  */
run_again(struct ieee80211_local * local,unsigned long timeout)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 
free_work(struct ieee80211_work * wk)62 void free_work(struct ieee80211_work *wk)
63 {
64 	kfree_rcu(wk, rcu_head);
65 }
66 
67 static enum work_action __must_check
ieee80211_remain_on_channel_timeout(struct ieee80211_work * wk)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
ieee80211_offchannel_tx(struct ieee80211_work * wk)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 
ieee80211_work_timer(unsigned long data)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 
ieee80211_work_work(struct work_struct * work)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 	if (local->scanning)
126 		return;
127 
128 	/*
129 	 * ieee80211_queue_work() should have picked up most cases,
130 	 * here we'll pick the rest.
131 	 */
132 	if (WARN(local->suspended, "work scheduled while going to suspend\n"))
133 		return;
134 
135 	mutex_lock(&local->mtx);
136 
137 	ieee80211_recalc_idle(local);
138 
139 	list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
140 		bool started = wk->started;
141 
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) {
146 			started = true;
147 			wk->timeout = jiffies;
148 		}
149 
150 		if (!started && !local->tmp_channel) {
151 			ieee80211_offchannel_stop_vifs(local);
152 
153 			local->tmp_channel = wk->chan;
154 			local->tmp_channel_type = wk->chan_type;
155 
156 			ieee80211_hw_config(local, 0);
157 
158 			started = true;
159 			wk->timeout = jiffies;
160 		}
161 
162 		/* don't try to work with items that aren't started */
163 		if (!started)
164 			continue;
165 
166 		if (time_is_after_jiffies(wk->timeout)) {
167 			/*
168 			 * This work item isn't supposed to be worked on
169 			 * right now, but take care to adjust the timer
170 			 * properly.
171 			 */
172 			run_again(local, wk->timeout);
173 			continue;
174 		}
175 
176 		switch (wk->type) {
177 		default:
178 			WARN_ON(1);
179 			/* nothing */
180 			rma = WORK_ACT_NONE;
181 			break;
182 		case IEEE80211_WORK_ABORT:
183 			rma = WORK_ACT_TIMEOUT;
184 			break;
185 		case IEEE80211_WORK_REMAIN_ON_CHANNEL:
186 			rma = ieee80211_remain_on_channel_timeout(wk);
187 			break;
188 		case IEEE80211_WORK_OFFCHANNEL_TX:
189 			rma = ieee80211_offchannel_tx(wk);
190 			break;
191 		}
192 
193 		wk->started = started;
194 
195 		switch (rma) {
196 		case WORK_ACT_NONE:
197 			/* might have changed the timeout */
198 			run_again(local, wk->timeout);
199 			break;
200 		case WORK_ACT_TIMEOUT:
201 			list_del_rcu(&wk->list);
202 			synchronize_rcu();
203 			list_add(&wk->list, &free_work);
204 			break;
205 		default:
206 			WARN(1, "unexpected: %d", rma);
207 		}
208 	}
209 
210 	list_for_each_entry(wk, &local->work_list, list) {
211 		if (!wk->started)
212 			continue;
213 		if (wk->chan != local->tmp_channel ||
214 		    wk->chan_type != local->tmp_channel_type)
215 			continue;
216 		remain_off_channel = true;
217 	}
218 
219 	if (!remain_off_channel && local->tmp_channel) {
220 		local->tmp_channel = NULL;
221 		ieee80211_hw_config(local, 0);
222 
223 		ieee80211_offchannel_return(local);
224 
225 		/* give connection some time to breathe */
226 		run_again(local, jiffies + HZ/2);
227 	}
228 
229 	if (list_empty(&local->work_list) && local->scan_req &&
230 	    !local->scanning)
231 		ieee80211_queue_delayed_work(&local->hw,
232 					     &local->scan_work,
233 					     round_jiffies_relative(0));
234 
235 	ieee80211_recalc_idle(local);
236 
237 	mutex_unlock(&local->mtx);
238 
239 	list_for_each_entry_safe(wk, tmp, &free_work, list) {
240 		wk->done(wk, NULL);
241 		list_del(&wk->list);
242 		kfree(wk);
243 	}
244 }
245 
ieee80211_add_work(struct ieee80211_work * wk)246 void ieee80211_add_work(struct ieee80211_work *wk)
247 {
248 	struct ieee80211_local *local;
249 
250 	if (WARN_ON(!wk->chan))
251 		return;
252 
253 	if (WARN_ON(!wk->sdata))
254 		return;
255 
256 	if (WARN_ON(!wk->done))
257 		return;
258 
259 	if (WARN_ON(!ieee80211_sdata_running(wk->sdata)))
260 		return;
261 
262 	wk->started = false;
263 
264 	local = wk->sdata->local;
265 	mutex_lock(&local->mtx);
266 	list_add_tail(&wk->list, &local->work_list);
267 	mutex_unlock(&local->mtx);
268 
269 	ieee80211_queue_work(&local->hw, &local->work_work);
270 }
271 
ieee80211_work_init(struct ieee80211_local * local)272 void ieee80211_work_init(struct ieee80211_local *local)
273 {
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);
278 }
279 
ieee80211_work_purge(struct ieee80211_sub_if_data * sdata)280 void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
281 {
282 	struct ieee80211_local *local = sdata->local;
283 	struct ieee80211_work *wk;
284 	bool cleanup = false;
285 
286 	mutex_lock(&local->mtx);
287 	list_for_each_entry(wk, &local->work_list, list) {
288 		if (wk->sdata != sdata)
289 			continue;
290 		cleanup = true;
291 		wk->type = IEEE80211_WORK_ABORT;
292 		wk->started = true;
293 		wk->timeout = jiffies;
294 	}
295 	mutex_unlock(&local->mtx);
296 
297 	/* run cleanups etc. */
298 	if (cleanup)
299 		ieee80211_work_work(&local->work_work);
300 
301 	mutex_lock(&local->mtx);
302 	list_for_each_entry(wk, &local->work_list, list) {
303 		if (wk->sdata != sdata)
304 			continue;
305 		WARN_ON(1);
306 		break;
307 	}
308 	mutex_unlock(&local->mtx);
309 }
310 
ieee80211_remain_done(struct ieee80211_work * wk,struct sk_buff * skb)311 static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk,
312 						   struct sk_buff *skb)
313 {
314 	/*
315 	 * We are done serving the remain-on-channel command.
316 	 */
317 	cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk,
318 					   wk->chan, wk->chan_type,
319 					   GFP_KERNEL);
320 
321 	return WORK_DONE_DESTROY;
322 }
323 
ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data * sdata,struct ieee80211_channel * chan,enum nl80211_channel_type channel_type,unsigned int duration,u64 * cookie)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)
328 {
329 	struct ieee80211_work *wk;
330 
331 	wk = kzalloc(sizeof(*wk), GFP_KERNEL);
332 	if (!wk)
333 		return -ENOMEM;
334 
335 	wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL;
336 	wk->chan = chan;
337 	wk->chan_type = channel_type;
338 	wk->sdata = sdata;
339 	wk->done = ieee80211_remain_done;
340 
341 	wk->remain.duration = duration;
342 
343 	*cookie = (unsigned long) wk;
344 
345 	ieee80211_add_work(wk);
346 
347 	return 0;
348 }
349 
ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data * sdata,u64 cookie)350 int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
351 					  u64 cookie)
352 {
353 	struct ieee80211_local *local = sdata->local;
354 	struct ieee80211_work *wk, *tmp;
355 	bool found = false;
356 
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;
361 			found = true;
362 			break;
363 		}
364 	}
365 	mutex_unlock(&local->mtx);
366 
367 	if (!found)
368 		return -ENOENT;
369 
370 	ieee80211_queue_work(&local->hw, &local->work_work);
371 
372 	return 0;
373 }
374