aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /net/mac80211
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/driver-trace.c9
-rw-r--r--net/mac80211/driver-trace.h1492
-rw-r--r--net/mac80211/work.c1302
3 files changed, 2803 insertions, 0 deletions
diff --git a/net/mac80211/driver-trace.c b/net/mac80211/driver-trace.c
new file mode 100644
index 00000000000..8ed8711b1a6
--- /dev/null
+++ b/net/mac80211/driver-trace.c
@@ -0,0 +1,9 @@
1/* bug in tracepoint.h, it should include this */
2#include <linux/module.h>
3
4/* sparse isn't too happy with all macros... */
5#ifndef __CHECKER__
6#include "driver-ops.h"
7#define CREATE_TRACE_POINTS
8#include "driver-trace.h"
9#endif
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
new file mode 100644
index 00000000000..f47b00dc7af
--- /dev/null
+++ b/net/mac80211/driver-trace.h
@@ -0,0 +1,1492 @@
1#if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
2#define __MAC80211_DRIVER_TRACE
3
4#include <linux/tracepoint.h>
5#include <net/mac80211.h>
6#include "ieee80211_i.h"
7
8#if !defined(CONFIG_MAC80211_DRIVER_API_TRACER) || defined(__CHECKER__)
9#undef TRACE_EVENT
10#define TRACE_EVENT(name, proto, ...) \
11static inline void trace_ ## name(proto) {}
12#undef DECLARE_EVENT_CLASS
13#define DECLARE_EVENT_CLASS(...)
14#undef DEFINE_EVENT
15#define DEFINE_EVENT(evt_class, name, proto, ...) \
16static inline void trace_ ## name(proto) {}
17#endif
18
19#undef TRACE_SYSTEM
20#define TRACE_SYSTEM mac80211
21
22#define MAXNAME 32
23#define LOCAL_ENTRY __array(char, wiphy_name, 32)
24#define LOCAL_ASSIGN strlcpy(__entry->wiphy_name, wiphy_name(local->hw.wiphy), MAXNAME)
25#define LOCAL_PR_FMT "%s"
26#define LOCAL_PR_ARG __entry->wiphy_name
27
28#define STA_ENTRY __array(char, sta_addr, ETH_ALEN)
29#define STA_ASSIGN (sta ? memcpy(__entry->sta_addr, sta->addr, ETH_ALEN) : memset(__entry->sta_addr, 0, ETH_ALEN))
30#define STA_PR_FMT " sta:%pM"
31#define STA_PR_ARG __entry->sta_addr
32
33#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \
34 __field(bool, p2p) \
35 __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>")
36#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \
37 __entry->p2p = sdata->vif.p2p; \
38 __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>")
39#define VIF_PR_FMT " vif:%s(%d%s)"
40#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
41
42/*
43 * Tracing for driver callbacks.
44 */
45
46DECLARE_EVENT_CLASS(local_only_evt,
47 TP_PROTO(struct ieee80211_local *local),
48 TP_ARGS(local),
49 TP_STRUCT__entry(
50 LOCAL_ENTRY
51 ),
52 TP_fast_assign(
53 LOCAL_ASSIGN;
54 ),
55 TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG)
56);
57
58DECLARE_EVENT_CLASS(local_sdata_addr_evt,
59 TP_PROTO(struct ieee80211_local *local,
60 struct ieee80211_sub_if_data *sdata),
61 TP_ARGS(local, sdata),
62
63 TP_STRUCT__entry(
64 LOCAL_ENTRY
65 VIF_ENTRY
66 __array(char, addr, 6)
67 ),
68
69 TP_fast_assign(
70 LOCAL_ASSIGN;
71 VIF_ASSIGN;
72 memcpy(__entry->addr, sdata->vif.addr, 6);
73 ),
74
75 TP_printk(
76 LOCAL_PR_FMT VIF_PR_FMT " addr:%pM",
77 LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr
78 )
79);
80
81DECLARE_EVENT_CLASS(local_u32_evt,
82 TP_PROTO(struct ieee80211_local *local, u32 value),
83 TP_ARGS(local, value),
84
85 TP_STRUCT__entry(
86 LOCAL_ENTRY
87 __field(u32, value)
88 ),
89
90 TP_fast_assign(
91 LOCAL_ASSIGN;
92 __entry->value = value;
93 ),
94
95 TP_printk(
96 LOCAL_PR_FMT " value:%d",
97 LOCAL_PR_ARG, __entry->value
98 )
99);
100
101DECLARE_EVENT_CLASS(local_sdata_evt,
102 TP_PROTO(struct ieee80211_local *local,
103 struct ieee80211_sub_if_data *sdata),
104 TP_ARGS(local, sdata),
105
106 TP_STRUCT__entry(
107 LOCAL_ENTRY
108 VIF_ENTRY
109 ),
110
111 TP_fast_assign(
112 LOCAL_ASSIGN;
113 VIF_ASSIGN;
114 ),
115
116 TP_printk(
117 LOCAL_PR_FMT VIF_PR_FMT,
118 LOCAL_PR_ARG, VIF_PR_ARG
119 )
120);
121
122DEFINE_EVENT(local_only_evt, drv_return_void,
123 TP_PROTO(struct ieee80211_local *local),
124 TP_ARGS(local)
125);
126
127TRACE_EVENT(drv_return_int,
128 TP_PROTO(struct ieee80211_local *local, int ret),
129 TP_ARGS(local, ret),
130 TP_STRUCT__entry(
131 LOCAL_ENTRY
132 __field(int, ret)
133 ),
134 TP_fast_assign(
135 LOCAL_ASSIGN;
136 __entry->ret = ret;
137 ),
138 TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret)
139);
140
141TRACE_EVENT(drv_return_bool,
142 TP_PROTO(struct ieee80211_local *local, bool ret),
143 TP_ARGS(local, ret),
144 TP_STRUCT__entry(
145 LOCAL_ENTRY
146 __field(bool, ret)
147 ),
148 TP_fast_assign(
149 LOCAL_ASSIGN;
150 __entry->ret = ret;
151 ),
152 TP_printk(LOCAL_PR_FMT " - %s", LOCAL_PR_ARG, (__entry->ret) ?
153 "true" : "false")
154);
155
156TRACE_EVENT(drv_return_u64,
157 TP_PROTO(struct ieee80211_local *local, u64 ret),
158 TP_ARGS(local, ret),
159 TP_STRUCT__entry(
160 LOCAL_ENTRY
161 __field(u64, ret)
162 ),
163 TP_fast_assign(
164 LOCAL_ASSIGN;
165 __entry->ret = ret;
166 ),
167 TP_printk(LOCAL_PR_FMT " - %llu", LOCAL_PR_ARG, __entry->ret)
168);
169
170DEFINE_EVENT(local_only_evt, drv_start,
171 TP_PROTO(struct ieee80211_local *local),
172 TP_ARGS(local)
173);
174
175DEFINE_EVENT(local_only_evt, drv_suspend,
176 TP_PROTO(struct ieee80211_local *local),
177 TP_ARGS(local)
178);
179
180DEFINE_EVENT(local_only_evt, drv_resume,
181 TP_PROTO(struct ieee80211_local *local),
182 TP_ARGS(local)
183);
184
185DEFINE_EVENT(local_only_evt, drv_stop,
186 TP_PROTO(struct ieee80211_local *local),
187 TP_ARGS(local)
188);
189
190DEFINE_EVENT(local_sdata_addr_evt, drv_add_interface,
191 TP_PROTO(struct ieee80211_local *local,
192 struct ieee80211_sub_if_data *sdata),
193 TP_ARGS(local, sdata)
194);
195
196TRACE_EVENT(drv_change_interface,
197 TP_PROTO(struct ieee80211_local *local,
198 struct ieee80211_sub_if_data *sdata,
199 enum nl80211_iftype type, bool p2p),
200
201 TP_ARGS(local, sdata, type, p2p),
202
203 TP_STRUCT__entry(
204 LOCAL_ENTRY
205 VIF_ENTRY
206 __field(u32, new_type)
207 __field(bool, new_p2p)
208 ),
209
210 TP_fast_assign(
211 LOCAL_ASSIGN;
212 VIF_ASSIGN;
213 __entry->new_type = type;
214 __entry->new_p2p = p2p;
215 ),
216
217 TP_printk(
218 LOCAL_PR_FMT VIF_PR_FMT " new type:%d%s",
219 LOCAL_PR_ARG, VIF_PR_ARG, __entry->new_type,
220 __entry->new_p2p ? "/p2p" : ""
221 )
222);
223
224DEFINE_EVENT(local_sdata_addr_evt, drv_remove_interface,
225 TP_PROTO(struct ieee80211_local *local,
226 struct ieee80211_sub_if_data *sdata),
227 TP_ARGS(local, sdata)
228);
229
230TRACE_EVENT(drv_config,
231 TP_PROTO(struct ieee80211_local *local,
232 u32 changed),
233
234 TP_ARGS(local, changed),
235
236 TP_STRUCT__entry(
237 LOCAL_ENTRY
238 __field(u32, changed)
239 __field(u32, flags)
240 __field(int, power_level)
241 __field(int, dynamic_ps_timeout)
242 __field(int, max_sleep_period)
243 __field(u16, listen_interval)
244 __field(u8, long_frame_max_tx_count)
245 __field(u8, short_frame_max_tx_count)
246 __field(int, center_freq)
247 __field(int, channel_type)
248 __field(int, smps)
249 ),
250
251 TP_fast_assign(
252 LOCAL_ASSIGN;
253 __entry->changed = changed;
254 __entry->flags = local->hw.conf.flags;
255 __entry->power_level = local->hw.conf.power_level;
256 __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout;
257 __entry->max_sleep_period = local->hw.conf.max_sleep_period;
258 __entry->listen_interval = local->hw.conf.listen_interval;
259 __entry->long_frame_max_tx_count = local->hw.conf.long_frame_max_tx_count;
260 __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count;
261 __entry->center_freq = local->hw.conf.channel->center_freq;
262 __entry->channel_type = local->hw.conf.channel_type;
263 __entry->smps = local->hw.conf.smps_mode;
264 ),
265
266 TP_printk(
267 LOCAL_PR_FMT " ch:%#x freq:%d",
268 LOCAL_PR_ARG, __entry->changed, __entry->center_freq
269 )
270);
271
272TRACE_EVENT(drv_bss_info_changed,
273 TP_PROTO(struct ieee80211_local *local,
274 struct ieee80211_sub_if_data *sdata,
275 struct ieee80211_bss_conf *info,
276 u32 changed),
277
278 TP_ARGS(local, sdata, info, changed),
279
280 TP_STRUCT__entry(
281 LOCAL_ENTRY
282 VIF_ENTRY
283 __field(bool, assoc)
284 __field(u16, aid)
285 __field(bool, cts)
286 __field(bool, shortpre)
287 __field(bool, shortslot)
288 __field(u8, dtimper)
289 __field(u16, bcnint)
290 __field(u16, assoc_cap)
291 __field(u64, timestamp)
292 __field(u32, basic_rates)
293 __field(u32, changed)
294 __field(bool, enable_beacon)
295 __field(u16, ht_operation_mode)
296 ),
297
298 TP_fast_assign(
299 LOCAL_ASSIGN;
300 VIF_ASSIGN;
301 __entry->changed = changed;
302 __entry->aid = info->aid;
303 __entry->assoc = info->assoc;
304 __entry->shortpre = info->use_short_preamble;
305 __entry->cts = info->use_cts_prot;
306 __entry->shortslot = info->use_short_slot;
307 __entry->dtimper = info->dtim_period;
308 __entry->bcnint = info->beacon_int;
309 __entry->assoc_cap = info->assoc_capability;
310 __entry->timestamp = info->timestamp;
311 __entry->basic_rates = info->basic_rates;
312 __entry->enable_beacon = info->enable_beacon;
313 __entry->ht_operation_mode = info->ht_operation_mode;
314 ),
315
316 TP_printk(
317 LOCAL_PR_FMT VIF_PR_FMT " changed:%#x",
318 LOCAL_PR_ARG, VIF_PR_ARG, __entry->changed
319 )
320);
321
322DECLARE_EVENT_CLASS(tx_sync_evt,
323 TP_PROTO(struct ieee80211_local *local,
324 struct ieee80211_sub_if_data *sdata,
325 const u8 *bssid,
326 enum ieee80211_tx_sync_type type),
327 TP_ARGS(local, sdata, bssid, type),
328
329 TP_STRUCT__entry(
330 LOCAL_ENTRY
331 VIF_ENTRY
332 __array(char, bssid, ETH_ALEN)
333 __field(u32, sync_type)
334 ),
335
336 TP_fast_assign(
337 LOCAL_ASSIGN;
338 VIF_ASSIGN;
339 memcpy(__entry->bssid, bssid, ETH_ALEN);
340 __entry->sync_type = type;
341 ),
342
343 TP_printk(
344 LOCAL_PR_FMT VIF_PR_FMT " bssid:%pM type:%d",
345 LOCAL_PR_ARG, VIF_PR_ARG, __entry->bssid, __entry->sync_type
346 )
347);
348
349DEFINE_EVENT(tx_sync_evt, drv_tx_sync,
350 TP_PROTO(struct ieee80211_local *local,
351 struct ieee80211_sub_if_data *sdata,
352 const u8 *bssid,
353 enum ieee80211_tx_sync_type type),
354 TP_ARGS(local, sdata, bssid, type)
355);
356
357DEFINE_EVENT(tx_sync_evt, drv_finish_tx_sync,
358 TP_PROTO(struct ieee80211_local *local,
359 struct ieee80211_sub_if_data *sdata,
360 const u8 *bssid,
361 enum ieee80211_tx_sync_type type),
362 TP_ARGS(local, sdata, bssid, type)
363);
364
365TRACE_EVENT(drv_prepare_multicast,
366 TP_PROTO(struct ieee80211_local *local, int mc_count),
367
368 TP_ARGS(local, mc_count),
369
370 TP_STRUCT__entry(
371 LOCAL_ENTRY
372 __field(int, mc_count)
373 ),
374
375 TP_fast_assign(
376 LOCAL_ASSIGN;
377 __entry->mc_count = mc_count;
378 ),
379
380 TP_printk(
381 LOCAL_PR_FMT " prepare mc (%d)",
382 LOCAL_PR_ARG, __entry->mc_count
383 )
384);
385
386TRACE_EVENT(drv_configure_filter,
387 TP_PROTO(struct ieee80211_local *local,
388 unsigned int changed_flags,
389 unsigned int *total_flags,
390 u64 multicast),
391
392 TP_ARGS(local, changed_flags, total_flags, multicast),
393
394 TP_STRUCT__entry(
395 LOCAL_ENTRY
396 __field(unsigned int, changed)
397 __field(unsigned int, total)
398 __field(u64, multicast)
399 ),
400
401 TP_fast_assign(
402 LOCAL_ASSIGN;
403 __entry->changed = changed_flags;
404 __entry->total = *total_flags;
405 __entry->multicast = multicast;
406 ),
407
408 TP_printk(
409 LOCAL_PR_FMT " changed:%#x total:%#x",
410 LOCAL_PR_ARG, __entry->changed, __entry->total
411 )
412);
413
414TRACE_EVENT(drv_set_tim,
415 TP_PROTO(struct ieee80211_local *local,
416 struct ieee80211_sta *sta, bool set),
417
418 TP_ARGS(local, sta, set),
419
420 TP_STRUCT__entry(
421 LOCAL_ENTRY
422 STA_ENTRY
423 __field(bool, set)
424 ),
425
426 TP_fast_assign(
427 LOCAL_ASSIGN;
428 STA_ASSIGN;
429 __entry->set = set;
430 ),
431
432 TP_printk(
433 LOCAL_PR_FMT STA_PR_FMT " set:%d",
434 LOCAL_PR_ARG, STA_PR_FMT, __entry->set
435 )
436);
437
438TRACE_EVENT(drv_set_key,
439 TP_PROTO(struct ieee80211_local *local,
440 enum set_key_cmd cmd, struct ieee80211_sub_if_data *sdata,
441 struct ieee80211_sta *sta,
442 struct ieee80211_key_conf *key),
443
444 TP_ARGS(local, cmd, sdata, sta, key),
445
446 TP_STRUCT__entry(
447 LOCAL_ENTRY
448 VIF_ENTRY
449 STA_ENTRY
450 __field(u32, cipher)
451 __field(u8, hw_key_idx)
452 __field(u8, flags)
453 __field(s8, keyidx)
454 ),
455
456 TP_fast_assign(
457 LOCAL_ASSIGN;
458 VIF_ASSIGN;
459 STA_ASSIGN;
460 __entry->cipher = key->cipher;
461 __entry->flags = key->flags;
462 __entry->keyidx = key->keyidx;
463 __entry->hw_key_idx = key->hw_key_idx;
464 ),
465
466 TP_printk(
467 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT,
468 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG
469 )
470);
471
472TRACE_EVENT(drv_update_tkip_key,
473 TP_PROTO(struct ieee80211_local *local,
474 struct ieee80211_sub_if_data *sdata,
475 struct ieee80211_key_conf *conf,
476 struct ieee80211_sta *sta, u32 iv32),
477
478 TP_ARGS(local, sdata, conf, sta, iv32),
479
480 TP_STRUCT__entry(
481 LOCAL_ENTRY
482 VIF_ENTRY
483 STA_ENTRY
484 __field(u32, iv32)
485 ),
486
487 TP_fast_assign(
488 LOCAL_ASSIGN;
489 VIF_ASSIGN;
490 STA_ASSIGN;
491 __entry->iv32 = iv32;
492 ),
493
494 TP_printk(
495 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x",
496 LOCAL_PR_ARG,VIF_PR_ARG,STA_PR_ARG, __entry->iv32
497 )
498);
499
500DEFINE_EVENT(local_sdata_evt, drv_hw_scan,
501 TP_PROTO(struct ieee80211_local *local,
502 struct ieee80211_sub_if_data *sdata),
503 TP_ARGS(local, sdata)
504);
505
506DEFINE_EVENT(local_sdata_evt, drv_cancel_hw_scan,
507 TP_PROTO(struct ieee80211_local *local,
508 struct ieee80211_sub_if_data *sdata),
509 TP_ARGS(local, sdata)
510);
511
512DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start,
513 TP_PROTO(struct ieee80211_local *local,
514 struct ieee80211_sub_if_data *sdata),
515 TP_ARGS(local, sdata)
516);
517
518DEFINE_EVENT(local_sdata_evt, drv_sched_scan_stop,
519 TP_PROTO(struct ieee80211_local *local,
520 struct ieee80211_sub_if_data *sdata),
521 TP_ARGS(local, sdata)
522);
523
524DEFINE_EVENT(local_only_evt, drv_sw_scan_start,
525 TP_PROTO(struct ieee80211_local *local),
526 TP_ARGS(local)
527);
528
529DEFINE_EVENT(local_only_evt, drv_sw_scan_complete,
530 TP_PROTO(struct ieee80211_local *local),
531 TP_ARGS(local)
532);
533
534TRACE_EVENT(drv_get_stats,
535 TP_PROTO(struct ieee80211_local *local,
536 struct ieee80211_low_level_stats *stats,
537 int ret),
538
539 TP_ARGS(local, stats, ret),
540
541 TP_STRUCT__entry(
542 LOCAL_ENTRY
543 __field(int, ret)
544 __field(unsigned int, ackfail)
545 __field(unsigned int, rtsfail)
546 __field(unsigned int, fcserr)
547 __field(unsigned int, rtssucc)
548 ),
549
550 TP_fast_assign(
551 LOCAL_ASSIGN;
552 __entry->ret = ret;
553 __entry->ackfail = stats->dot11ACKFailureCount;
554 __entry->rtsfail = stats->dot11RTSFailureCount;
555 __entry->fcserr = stats->dot11FCSErrorCount;
556 __entry->rtssucc = stats->dot11RTSSuccessCount;
557 ),
558
559 TP_printk(
560 LOCAL_PR_FMT " ret:%d",
561 LOCAL_PR_ARG, __entry->ret
562 )
563);
564
565TRACE_EVENT(drv_get_tkip_seq,
566 TP_PROTO(struct ieee80211_local *local,
567 u8 hw_key_idx, u32 *iv32, u16 *iv16),
568
569 TP_ARGS(local, hw_key_idx, iv32, iv16),
570
571 TP_STRUCT__entry(
572 LOCAL_ENTRY
573 __field(u8, hw_key_idx)
574 __field(u32, iv32)
575 __field(u16, iv16)
576 ),
577
578 TP_fast_assign(
579 LOCAL_ASSIGN;
580 __entry->hw_key_idx = hw_key_idx;
581 __entry->iv32 = *iv32;
582 __entry->iv16 = *iv16;
583 ),
584
585 TP_printk(
586 LOCAL_PR_FMT, LOCAL_PR_ARG
587 )
588);
589
590DEFINE_EVENT(local_u32_evt, drv_set_frag_threshold,
591 TP_PROTO(struct ieee80211_local *local, u32 value),
592 TP_ARGS(local, value)
593);
594
595DEFINE_EVENT(local_u32_evt, drv_set_rts_threshold,
596 TP_PROTO(struct ieee80211_local *local, u32 value),
597 TP_ARGS(local, value)
598);
599
600TRACE_EVENT(drv_set_coverage_class,
601 TP_PROTO(struct ieee80211_local *local, u8 value),
602
603 TP_ARGS(local, value),
604
605 TP_STRUCT__entry(
606 LOCAL_ENTRY
607 __field(u8, value)
608 ),
609
610 TP_fast_assign(
611 LOCAL_ASSIGN;
612 __entry->value = value;
613 ),
614
615 TP_printk(
616 LOCAL_PR_FMT " value:%d",
617 LOCAL_PR_ARG, __entry->value
618 )
619);
620
621TRACE_EVENT(drv_sta_notify,
622 TP_PROTO(struct ieee80211_local *local,
623 struct ieee80211_sub_if_data *sdata,
624 enum sta_notify_cmd cmd,
625 struct ieee80211_sta *sta),
626
627 TP_ARGS(local, sdata, cmd, sta),
628
629 TP_STRUCT__entry(
630 LOCAL_ENTRY
631 VIF_ENTRY
632 STA_ENTRY
633 __field(u32, cmd)
634 ),
635
636 TP_fast_assign(
637 LOCAL_ASSIGN;
638 VIF_ASSIGN;
639 STA_ASSIGN;
640 __entry->cmd = cmd;
641 ),
642
643 TP_printk(
644 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " cmd:%d",
645 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->cmd
646 )
647);
648
649TRACE_EVENT(drv_sta_add,
650 TP_PROTO(struct ieee80211_local *local,
651 struct ieee80211_sub_if_data *sdata,
652 struct ieee80211_sta *sta),
653
654 TP_ARGS(local, sdata, sta),
655
656 TP_STRUCT__entry(
657 LOCAL_ENTRY
658 VIF_ENTRY
659 STA_ENTRY
660 ),
661
662 TP_fast_assign(
663 LOCAL_ASSIGN;
664 VIF_ASSIGN;
665 STA_ASSIGN;
666 ),
667
668 TP_printk(
669 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT,
670 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG
671 )
672);
673
674TRACE_EVENT(drv_sta_remove,
675 TP_PROTO(struct ieee80211_local *local,
676 struct ieee80211_sub_if_data *sdata,
677 struct ieee80211_sta *sta),
678
679 TP_ARGS(local, sdata, sta),
680
681 TP_STRUCT__entry(
682 LOCAL_ENTRY
683 VIF_ENTRY
684 STA_ENTRY
685 ),
686
687 TP_fast_assign(
688 LOCAL_ASSIGN;
689 VIF_ASSIGN;
690 STA_ASSIGN;
691 ),
692
693 TP_printk(
694 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT,
695 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG
696 )
697);
698
699TRACE_EVENT(drv_conf_tx,
700 TP_PROTO(struct ieee80211_local *local, u16 queue,
701 const struct ieee80211_tx_queue_params *params),
702
703 TP_ARGS(local, queue, params),
704
705 TP_STRUCT__entry(
706 LOCAL_ENTRY
707 __field(u16, queue)
708 __field(u16, txop)
709 __field(u16, cw_min)
710 __field(u16, cw_max)
711 __field(u8, aifs)
712 ),
713
714 TP_fast_assign(
715 LOCAL_ASSIGN;
716 __entry->queue = queue;
717 __entry->txop = params->txop;
718 __entry->cw_max = params->cw_max;
719 __entry->cw_min = params->cw_min;
720 __entry->aifs = params->aifs;
721 ),
722
723 TP_printk(
724 LOCAL_PR_FMT " queue:%d",
725 LOCAL_PR_ARG, __entry->queue
726 )
727);
728
729DEFINE_EVENT(local_only_evt, drv_get_tsf,
730 TP_PROTO(struct ieee80211_local *local),
731 TP_ARGS(local)
732);
733
734TRACE_EVENT(drv_set_tsf,
735 TP_PROTO(struct ieee80211_local *local, u64 tsf),
736
737 TP_ARGS(local, tsf),
738
739 TP_STRUCT__entry(
740 LOCAL_ENTRY
741 __field(u64, tsf)
742 ),
743
744 TP_fast_assign(
745 LOCAL_ASSIGN;
746 __entry->tsf = tsf;
747 ),
748
749 TP_printk(
750 LOCAL_PR_FMT " tsf:%llu",
751 LOCAL_PR_ARG, (unsigned long long)__entry->tsf
752 )
753);
754
755DEFINE_EVENT(local_only_evt, drv_reset_tsf,
756 TP_PROTO(struct ieee80211_local *local),
757 TP_ARGS(local)
758);
759
760DEFINE_EVENT(local_only_evt, drv_tx_last_beacon,
761 TP_PROTO(struct ieee80211_local *local),
762 TP_ARGS(local)
763);
764
765TRACE_EVENT(drv_ampdu_action,
766 TP_PROTO(struct ieee80211_local *local,
767 struct ieee80211_sub_if_data *sdata,
768 enum ieee80211_ampdu_mlme_action action,
769 struct ieee80211_sta *sta, u16 tid,
770 u16 *ssn, u8 buf_size),
771
772 TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size),
773
774 TP_STRUCT__entry(
775 LOCAL_ENTRY
776 STA_ENTRY
777 __field(u32, action)
778 __field(u16, tid)
779 __field(u16, ssn)
780 __field(u8, buf_size)
781 VIF_ENTRY
782 ),
783
784 TP_fast_assign(
785 LOCAL_ASSIGN;
786 VIF_ASSIGN;
787 STA_ASSIGN;
788 __entry->action = action;
789 __entry->tid = tid;
790 __entry->ssn = ssn ? *ssn : 0;
791 __entry->buf_size = buf_size;
792 ),
793
794 TP_printk(
795 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d",
796 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action,
797 __entry->tid, __entry->buf_size
798 )
799);
800
801TRACE_EVENT(drv_get_survey,
802 TP_PROTO(struct ieee80211_local *local, int idx,
803 struct survey_info *survey),
804
805 TP_ARGS(local, idx, survey),
806
807 TP_STRUCT__entry(
808 LOCAL_ENTRY
809 __field(int, idx)
810 ),
811
812 TP_fast_assign(
813 LOCAL_ASSIGN;
814 __entry->idx = idx;
815 ),
816
817 TP_printk(
818 LOCAL_PR_FMT " idx:%d",
819 LOCAL_PR_ARG, __entry->idx
820 )
821);
822
823TRACE_EVENT(drv_flush,
824 TP_PROTO(struct ieee80211_local *local, bool drop),
825
826 TP_ARGS(local, drop),
827
828 TP_STRUCT__entry(
829 LOCAL_ENTRY
830 __field(bool, drop)
831 ),
832
833 TP_fast_assign(
834 LOCAL_ASSIGN;
835 __entry->drop = drop;
836 ),
837
838 TP_printk(
839 LOCAL_PR_FMT " drop:%d",
840 LOCAL_PR_ARG, __entry->drop
841 )
842);
843
844TRACE_EVENT(drv_channel_switch,
845 TP_PROTO(struct ieee80211_local *local,
846 struct ieee80211_channel_switch *ch_switch),
847
848 TP_ARGS(local, ch_switch),
849
850 TP_STRUCT__entry(
851 LOCAL_ENTRY
852 __field(u64, timestamp)
853 __field(bool, block_tx)
854 __field(u16, freq)
855 __field(u8, count)
856 ),
857
858 TP_fast_assign(
859 LOCAL_ASSIGN;
860 __entry->timestamp = ch_switch->timestamp;
861 __entry->block_tx = ch_switch->block_tx;
862 __entry->freq = ch_switch->channel->center_freq;
863 __entry->count = ch_switch->count;
864 ),
865
866 TP_printk(
867 LOCAL_PR_FMT " new freq:%u count:%d",
868 LOCAL_PR_ARG, __entry->freq, __entry->count
869 )
870);
871
872TRACE_EVENT(drv_set_antenna,
873 TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret),
874
875 TP_ARGS(local, tx_ant, rx_ant, ret),
876
877 TP_STRUCT__entry(
878 LOCAL_ENTRY
879 __field(u32, tx_ant)
880 __field(u32, rx_ant)
881 __field(int, ret)
882 ),
883
884 TP_fast_assign(
885 LOCAL_ASSIGN;
886 __entry->tx_ant = tx_ant;
887 __entry->rx_ant = rx_ant;
888 __entry->ret = ret;
889 ),
890
891 TP_printk(
892 LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d",
893 LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret
894 )
895);
896
897TRACE_EVENT(drv_get_antenna,
898 TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret),
899
900 TP_ARGS(local, tx_ant, rx_ant, ret),
901
902 TP_STRUCT__entry(
903 LOCAL_ENTRY
904 __field(u32, tx_ant)
905 __field(u32, rx_ant)
906 __field(int, ret)
907 ),
908
909 TP_fast_assign(
910 LOCAL_ASSIGN;
911 __entry->tx_ant = tx_ant;
912 __entry->rx_ant = rx_ant;
913 __entry->ret = ret;
914 ),
915
916 TP_printk(
917 LOCAL_PR_FMT " tx_ant:%d rx_ant:%d ret:%d",
918 LOCAL_PR_ARG, __entry->tx_ant, __entry->rx_ant, __entry->ret
919 )
920);
921
922TRACE_EVENT(drv_remain_on_channel,
923 TP_PROTO(struct ieee80211_local *local, struct ieee80211_channel *chan,
924 enum nl80211_channel_type chantype, unsigned int duration),
925
926 TP_ARGS(local, chan, chantype, duration),
927
928 TP_STRUCT__entry(
929 LOCAL_ENTRY
930 __field(int, center_freq)
931 __field(int, channel_type)
932 __field(unsigned int, duration)
933 ),
934
935 TP_fast_assign(
936 LOCAL_ASSIGN;
937 __entry->center_freq = chan->center_freq;
938 __entry->channel_type = chantype;
939 __entry->duration = duration;
940 ),
941
942 TP_printk(
943 LOCAL_PR_FMT " freq:%dMHz duration:%dms",
944 LOCAL_PR_ARG, __entry->center_freq, __entry->duration
945 )
946);
947
948DEFINE_EVENT(local_only_evt, drv_cancel_remain_on_channel,
949 TP_PROTO(struct ieee80211_local *local),
950 TP_ARGS(local)
951);
952
953TRACE_EVENT(drv_offchannel_tx,
954 TP_PROTO(struct ieee80211_local *local, struct sk_buff *skb,
955 struct ieee80211_channel *chan,
956 enum nl80211_channel_type channel_type,
957 unsigned int wait),
958
959 TP_ARGS(local, skb, chan, channel_type, wait),
960
961 TP_STRUCT__entry(
962 LOCAL_ENTRY
963 __field(int, center_freq)
964 __field(int, channel_type)
965 __field(unsigned int, wait)
966 ),
967
968 TP_fast_assign(
969 LOCAL_ASSIGN;
970 __entry->center_freq = chan->center_freq;
971 __entry->channel_type = channel_type;
972 __entry->wait = wait;
973 ),
974
975 TP_printk(
976 LOCAL_PR_FMT " freq:%dMHz, wait:%dms",
977 LOCAL_PR_ARG, __entry->center_freq, __entry->wait
978 )
979);
980
981TRACE_EVENT(drv_set_ringparam,
982 TP_PROTO(struct ieee80211_local *local, u32 tx, u32 rx),
983
984 TP_ARGS(local, tx, rx),
985
986 TP_STRUCT__entry(
987 LOCAL_ENTRY
988 __field(u32, tx)
989 __field(u32, rx)
990 ),
991
992 TP_fast_assign(
993 LOCAL_ASSIGN;
994 __entry->tx = tx;
995 __entry->rx = rx;
996 ),
997
998 TP_printk(
999 LOCAL_PR_FMT " tx:%d rx %d",
1000 LOCAL_PR_ARG, __entry->tx, __entry->rx
1001 )
1002);
1003
1004TRACE_EVENT(drv_get_ringparam,
1005 TP_PROTO(struct ieee80211_local *local, u32 *tx, u32 *tx_max,
1006 u32 *rx, u32 *rx_max),
1007
1008 TP_ARGS(local, tx, tx_max, rx, rx_max),
1009
1010 TP_STRUCT__entry(
1011 LOCAL_ENTRY
1012 __field(u32, tx)
1013 __field(u32, tx_max)
1014 __field(u32, rx)
1015 __field(u32, rx_max)
1016 ),
1017
1018 TP_fast_assign(
1019 LOCAL_ASSIGN;
1020 __entry->tx = *tx;
1021 __entry->tx_max = *tx_max;
1022 __entry->rx = *rx;
1023 __entry->rx_max = *rx_max;
1024 ),
1025
1026 TP_printk(
1027 LOCAL_PR_FMT " tx:%d tx_max %d rx %d rx_max %d",
1028 LOCAL_PR_ARG,
1029 __entry->tx, __entry->tx_max, __entry->rx, __entry->rx_max
1030 )
1031);
1032
1033DEFINE_EVENT(local_only_evt, drv_tx_frames_pending,
1034 TP_PROTO(struct ieee80211_local *local),
1035 TP_ARGS(local)
1036);
1037
1038DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait,
1039 TP_PROTO(struct ieee80211_local *local),
1040 TP_ARGS(local)
1041);
1042
1043TRACE_EVENT(drv_set_bitrate_mask,
1044 TP_PROTO(struct ieee80211_local *local,
1045 struct ieee80211_sub_if_data *sdata,
1046 const struct cfg80211_bitrate_mask *mask),
1047
1048 TP_ARGS(local, sdata, mask),
1049
1050 TP_STRUCT__entry(
1051 LOCAL_ENTRY
1052 VIF_ENTRY
1053 __field(u32, legacy_2g)
1054 __field(u32, legacy_5g)
1055 ),
1056
1057 TP_fast_assign(
1058 LOCAL_ASSIGN;
1059 VIF_ASSIGN;
1060 __entry->legacy_2g = mask->control[IEEE80211_BAND_2GHZ].legacy;
1061 __entry->legacy_5g = mask->control[IEEE80211_BAND_5GHZ].legacy;
1062 ),
1063
1064 TP_printk(
1065 LOCAL_PR_FMT VIF_PR_FMT " 2G Mask:0x%x 5G Mask:0x%x",
1066 LOCAL_PR_ARG, VIF_PR_ARG, __entry->legacy_2g, __entry->legacy_5g
1067 )
1068);
1069
1070TRACE_EVENT(drv_set_rekey_data,
1071 TP_PROTO(struct ieee80211_local *local,
1072 struct ieee80211_sub_if_data *sdata,
1073 struct cfg80211_gtk_rekey_data *data),
1074
1075 TP_ARGS(local, sdata, data),
1076
1077 TP_STRUCT__entry(
1078 LOCAL_ENTRY
1079 VIF_ENTRY
1080 __array(u8, kek, NL80211_KEK_LEN)
1081 __array(u8, kck, NL80211_KCK_LEN)
1082 __array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN)
1083 ),
1084
1085 TP_fast_assign(
1086 LOCAL_ASSIGN;
1087 VIF_ASSIGN;
1088 memcpy(__entry->kek, data->kek, NL80211_KEK_LEN);
1089 memcpy(__entry->kck, data->kck, NL80211_KCK_LEN);
1090 memcpy(__entry->replay_ctr, data->replay_ctr,
1091 NL80211_REPLAY_CTR_LEN);
1092 ),
1093
1094 TP_printk(LOCAL_PR_FMT VIF_PR_FMT,
1095 LOCAL_PR_ARG, VIF_PR_ARG)
1096);
1097
1098TRACE_EVENT(drv_rssi_callback,
1099 TP_PROTO(struct ieee80211_local *local,
1100 enum ieee80211_rssi_event rssi_event),
1101
1102 TP_ARGS(local, rssi_event),
1103
1104 TP_STRUCT__entry(
1105 LOCAL_ENTRY
1106 __field(u32, rssi_event)
1107 ),
1108
1109 TP_fast_assign(
1110 LOCAL_ASSIGN;
1111 __entry->rssi_event = rssi_event;
1112 ),
1113
1114 TP_printk(
1115 LOCAL_PR_FMT " rssi_event:%d",
1116 LOCAL_PR_ARG, __entry->rssi_event
1117 )
1118);
1119
1120/*
1121 * Tracing for API calls that drivers call.
1122 */
1123
1124TRACE_EVENT(api_start_tx_ba_session,
1125 TP_PROTO(struct ieee80211_sta *sta, u16 tid),
1126
1127 TP_ARGS(sta, tid),
1128
1129 TP_STRUCT__entry(
1130 STA_ENTRY
1131 __field(u16, tid)
1132 ),
1133
1134 TP_fast_assign(
1135 STA_ASSIGN;
1136 __entry->tid = tid;
1137 ),
1138
1139 TP_printk(
1140 STA_PR_FMT " tid:%d",
1141 STA_PR_ARG, __entry->tid
1142 )
1143);
1144
1145TRACE_EVENT(api_start_tx_ba_cb,
1146 TP_PROTO(struct ieee80211_sub_if_data *sdata, const u8 *ra, u16 tid),
1147
1148 TP_ARGS(sdata, ra, tid),
1149
1150 TP_STRUCT__entry(
1151 VIF_ENTRY
1152 __array(u8, ra, ETH_ALEN)
1153 __field(u16, tid)
1154 ),
1155
1156 TP_fast_assign(
1157 VIF_ASSIGN;
1158 memcpy(__entry->ra, ra, ETH_ALEN);
1159 __entry->tid = tid;
1160 ),
1161
1162 TP_printk(
1163 VIF_PR_FMT " ra:%pM tid:%d",
1164 VIF_PR_ARG, __entry->ra, __entry->tid
1165 )
1166);
1167
1168TRACE_EVENT(api_stop_tx_ba_session,
1169 TP_PROTO(struct ieee80211_sta *sta, u16 tid),
1170
1171 TP_ARGS(sta, tid),
1172
1173 TP_STRUCT__entry(
1174 STA_ENTRY
1175 __field(u16, tid)
1176 ),
1177
1178 TP_fast_assign(
1179 STA_ASSIGN;
1180 __entry->tid = tid;
1181 ),
1182
1183 TP_printk(
1184 STA_PR_FMT " tid:%d",
1185 STA_PR_ARG, __entry->tid
1186 )
1187);
1188
1189TRACE_EVENT(api_stop_tx_ba_cb,
1190 TP_PROTO(struct ieee80211_sub_if_data *sdata, const u8 *ra, u16 tid),
1191
1192 TP_ARGS(sdata, ra, tid),
1193
1194 TP_STRUCT__entry(
1195 VIF_ENTRY
1196 __array(u8, ra, ETH_ALEN)
1197 __field(u16, tid)
1198 ),
1199
1200 TP_fast_assign(
1201 VIF_ASSIGN;
1202 memcpy(__entry->ra, ra, ETH_ALEN);
1203 __entry->tid = tid;
1204 ),
1205
1206 TP_printk(
1207 VIF_PR_FMT " ra:%pM tid:%d",
1208 VIF_PR_ARG, __entry->ra, __entry->tid
1209 )
1210);
1211
1212DEFINE_EVENT(local_only_evt, api_restart_hw,
1213 TP_PROTO(struct ieee80211_local *local),
1214 TP_ARGS(local)
1215);
1216
1217TRACE_EVENT(api_beacon_loss,
1218 TP_PROTO(struct ieee80211_sub_if_data *sdata),
1219
1220 TP_ARGS(sdata),
1221
1222 TP_STRUCT__entry(
1223 VIF_ENTRY
1224 ),
1225
1226 TP_fast_assign(
1227 VIF_ASSIGN;
1228 ),
1229
1230 TP_printk(
1231 VIF_PR_FMT,
1232 VIF_PR_ARG
1233 )
1234);
1235
1236TRACE_EVENT(api_connection_loss,
1237 TP_PROTO(struct ieee80211_sub_if_data *sdata),
1238
1239 TP_ARGS(sdata),
1240
1241 TP_STRUCT__entry(
1242 VIF_ENTRY
1243 ),
1244
1245 TP_fast_assign(
1246 VIF_ASSIGN;
1247 ),
1248
1249 TP_printk(
1250 VIF_PR_FMT,
1251 VIF_PR_ARG
1252 )
1253);
1254
1255TRACE_EVENT(api_cqm_rssi_notify,
1256 TP_PROTO(struct ieee80211_sub_if_data *sdata,
1257 enum nl80211_cqm_rssi_threshold_event rssi_event),
1258
1259 TP_ARGS(sdata, rssi_event),
1260
1261 TP_STRUCT__entry(
1262 VIF_ENTRY
1263 __field(u32, rssi_event)
1264 ),
1265
1266 TP_fast_assign(
1267 VIF_ASSIGN;
1268 __entry->rssi_event = rssi_event;
1269 ),
1270
1271 TP_printk(
1272 VIF_PR_FMT " event:%d",
1273 VIF_PR_ARG, __entry->rssi_event
1274 )
1275);
1276
1277TRACE_EVENT(api_scan_completed,
1278 TP_PROTO(struct ieee80211_local *local, bool aborted),
1279
1280 TP_ARGS(local, aborted),
1281
1282 TP_STRUCT__entry(
1283 LOCAL_ENTRY
1284 __field(bool, aborted)
1285 ),
1286
1287 TP_fast_assign(
1288 LOCAL_ASSIGN;
1289 __entry->aborted = aborted;
1290 ),
1291
1292 TP_printk(
1293 LOCAL_PR_FMT " aborted:%d",
1294 LOCAL_PR_ARG, __entry->aborted
1295 )
1296);
1297
1298TRACE_EVENT(api_sched_scan_results,
1299 TP_PROTO(struct ieee80211_local *local),
1300
1301 TP_ARGS(local),
1302
1303 TP_STRUCT__entry(
1304 LOCAL_ENTRY
1305 ),
1306
1307 TP_fast_assign(
1308 LOCAL_ASSIGN;
1309 ),
1310
1311 TP_printk(
1312 LOCAL_PR_FMT, LOCAL_PR_ARG
1313 )
1314);
1315
1316TRACE_EVENT(api_sched_scan_stopped,
1317 TP_PROTO(struct ieee80211_local *local),
1318
1319 TP_ARGS(local),
1320
1321 TP_STRUCT__entry(
1322 LOCAL_ENTRY
1323 ),
1324
1325 TP_fast_assign(
1326 LOCAL_ASSIGN;
1327 ),
1328
1329 TP_printk(
1330 LOCAL_PR_FMT, LOCAL_PR_ARG
1331 )
1332);
1333
1334TRACE_EVENT(api_sta_block_awake,
1335 TP_PROTO(struct ieee80211_local *local,
1336 struct ieee80211_sta *sta, bool block),
1337
1338 TP_ARGS(local, sta, block),
1339
1340 TP_STRUCT__entry(
1341 LOCAL_ENTRY
1342 STA_ENTRY
1343 __field(bool, block)
1344 ),
1345
1346 TP_fast_assign(
1347 LOCAL_ASSIGN;
1348 STA_ASSIGN;
1349 __entry->block = block;
1350 ),
1351
1352 TP_printk(
1353 LOCAL_PR_FMT STA_PR_FMT " block:%d",
1354 LOCAL_PR_ARG, STA_PR_FMT, __entry->block
1355 )
1356);
1357
1358TRACE_EVENT(api_chswitch_done,
1359 TP_PROTO(struct ieee80211_sub_if_data *sdata, bool success),
1360
1361 TP_ARGS(sdata, success),
1362
1363 TP_STRUCT__entry(
1364 VIF_ENTRY
1365 __field(bool, success)
1366 ),
1367
1368 TP_fast_assign(
1369 VIF_ASSIGN;
1370 __entry->success = success;
1371 ),
1372
1373 TP_printk(
1374 VIF_PR_FMT " success=%d",
1375 VIF_PR_ARG, __entry->success
1376 )
1377);
1378
1379DEFINE_EVENT(local_only_evt, api_ready_on_channel,
1380 TP_PROTO(struct ieee80211_local *local),
1381 TP_ARGS(local)
1382);
1383
1384DEFINE_EVENT(local_only_evt, api_remain_on_channel_expired,
1385 TP_PROTO(struct ieee80211_local *local),
1386 TP_ARGS(local)
1387);
1388
1389TRACE_EVENT(api_gtk_rekey_notify,
1390 TP_PROTO(struct ieee80211_sub_if_data *sdata,
1391 const u8 *bssid, const u8 *replay_ctr),
1392
1393 TP_ARGS(sdata, bssid, replay_ctr),
1394
1395 TP_STRUCT__entry(
1396 VIF_ENTRY
1397 __array(u8, bssid, ETH_ALEN)
1398 __array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN)
1399 ),
1400
1401 TP_fast_assign(
1402 VIF_ASSIGN;
1403 memcpy(__entry->bssid, bssid, ETH_ALEN);
1404 memcpy(__entry->replay_ctr, replay_ctr, NL80211_REPLAY_CTR_LEN);
1405 ),
1406
1407 TP_printk(VIF_PR_FMT, VIF_PR_ARG)
1408);
1409
1410TRACE_EVENT(api_enable_rssi_reports,
1411 TP_PROTO(struct ieee80211_sub_if_data *sdata,
1412 int rssi_min_thold, int rssi_max_thold),
1413
1414 TP_ARGS(sdata, rssi_min_thold, rssi_max_thold),
1415
1416 TP_STRUCT__entry(
1417 VIF_ENTRY
1418 __field(int, rssi_min_thold)
1419 __field(int, rssi_max_thold)
1420 ),
1421
1422 TP_fast_assign(
1423 VIF_ASSIGN;
1424 __entry->rssi_min_thold = rssi_min_thold;
1425 __entry->rssi_max_thold = rssi_max_thold;
1426 ),
1427
1428 TP_printk(
1429 VIF_PR_FMT " rssi_min_thold =%d, rssi_max_thold = %d",
1430 VIF_PR_ARG, __entry->rssi_min_thold, __entry->rssi_max_thold
1431 )
1432);
1433
1434/*
1435 * Tracing for internal functions
1436 * (which may also be called in response to driver calls)
1437 */
1438
1439TRACE_EVENT(wake_queue,
1440 TP_PROTO(struct ieee80211_local *local, u16 queue,
1441 enum queue_stop_reason reason),
1442
1443 TP_ARGS(local, queue, reason),
1444
1445 TP_STRUCT__entry(
1446 LOCAL_ENTRY
1447 __field(u16, queue)
1448 __field(u32, reason)
1449 ),
1450
1451 TP_fast_assign(
1452 LOCAL_ASSIGN;
1453 __entry->queue = queue;
1454 __entry->reason = reason;
1455 ),
1456
1457 TP_printk(
1458 LOCAL_PR_FMT " queue:%d, reason:%d",
1459 LOCAL_PR_ARG, __entry->queue, __entry->reason
1460 )
1461);
1462
1463TRACE_EVENT(stop_queue,
1464 TP_PROTO(struct ieee80211_local *local, u16 queue,
1465 enum queue_stop_reason reason),
1466
1467 TP_ARGS(local, queue, reason),
1468
1469 TP_STRUCT__entry(
1470 LOCAL_ENTRY
1471 __field(u16, queue)
1472 __field(u32, reason)
1473 ),
1474
1475 TP_fast_assign(
1476 LOCAL_ASSIGN;
1477 __entry->queue = queue;
1478 __entry->reason = reason;
1479 ),
1480
1481 TP_printk(
1482 LOCAL_PR_FMT " queue:%d, reason:%d",
1483 LOCAL_PR_ARG, __entry->queue, __entry->reason
1484 )
1485);
1486#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
1487
1488#undef TRACE_INCLUDE_PATH
1489#define TRACE_INCLUDE_PATH .
1490#undef TRACE_INCLUDE_FILE
1491#define TRACE_INCLUDE_FILE driver-trace
1492#include <trace/define_trace.h>
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
new file mode 100644
index 00000000000..7737f204d3f
--- /dev/null
+++ b/net/mac80211/work.c
@@ -0,0 +1,1302 @@
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#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
31#define IEEE80211_AUTH_MAX_TRIES 3
32#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
33#define IEEE80211_ASSOC_MAX_TRIES 3
34
35enum work_action {
36 WORK_ACT_MISMATCH,
37 WORK_ACT_NONE,
38 WORK_ACT_TIMEOUT,
39 WORK_ACT_DONE,
40};
41
42
43/* utils */
44static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
45{
46 lockdep_assert_held(&local->mtx);
47}
48
49/*
50 * We can have multiple work items (and connection probing)
51 * scheduling this timer, but we need to take care to only
52 * reschedule it when it should fire _earlier_ than it was
53 * asked for before, or if it's not pending right now. This
54 * function ensures that. Note that it then is required to
55 * run this function for all timeouts after the first one
56 * has happened -- the work that runs from this timer will
57 * do that.
58 */
59static void run_again(struct ieee80211_local *local,
60 unsigned long timeout)
61{
62 ASSERT_WORK_MTX(local);
63
64 if (!timer_pending(&local->work_timer) ||
65 time_before(timeout, local->work_timer.expires))
66 mod_timer(&local->work_timer, timeout);
67}
68
69void free_work(struct ieee80211_work *wk)
70{
71 kfree_rcu(wk, rcu_head);
72}
73
74static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
75 struct ieee80211_supported_band *sband,
76 u32 *rates)
77{
78 int i, j, count;
79 *rates = 0;
80 count = 0;
81 for (i = 0; i < supp_rates_len; i++) {
82 int rate = (supp_rates[i] & 0x7F) * 5;
83
84 for (j = 0; j < sband->n_bitrates; j++)
85 if (sband->bitrates[j].bitrate == rate) {
86 *rates |= BIT(j);
87 count++;
88 break;
89 }
90 }
91
92 return count;
93}
94
95/* frame sending functions */
96
97static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
98 struct ieee80211_supported_band *sband,
99 struct ieee80211_channel *channel,
100 enum ieee80211_smps_mode smps)
101{
102 struct ieee80211_ht_info *ht_info;
103 u8 *pos;
104 u32 flags = channel->flags;
105 u16 cap = sband->ht_cap.cap;
106 __le16 tmp;
107
108 if (!sband->ht_cap.ht_supported)
109 return;
110
111 if (!ht_info_ie)
112 return;
113
114 if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
115 return;
116
117 ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
118
119 /* determine capability flags */
120
121 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
122 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
123 if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
124 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
125 cap &= ~IEEE80211_HT_CAP_SGI_40;
126 }
127 break;
128 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
129 if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
130 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
131 cap &= ~IEEE80211_HT_CAP_SGI_40;
132 }
133 break;
134 }
135
136 /* set SM PS mode properly */
137 cap &= ~IEEE80211_HT_CAP_SM_PS;
138 switch (smps) {
139 case IEEE80211_SMPS_AUTOMATIC:
140 case IEEE80211_SMPS_NUM_MODES:
141 WARN_ON(1);
142 case IEEE80211_SMPS_OFF:
143 cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
144 IEEE80211_HT_CAP_SM_PS_SHIFT;
145 break;
146 case IEEE80211_SMPS_STATIC:
147 cap |= WLAN_HT_CAP_SM_PS_STATIC <<
148 IEEE80211_HT_CAP_SM_PS_SHIFT;
149 break;
150 case IEEE80211_SMPS_DYNAMIC:
151 cap |= WLAN_HT_CAP_SM_PS_DYNAMIC <<
152 IEEE80211_HT_CAP_SM_PS_SHIFT;
153 break;
154 }
155
156 /* reserve and fill IE */
157
158 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
159 *pos++ = WLAN_EID_HT_CAPABILITY;
160 *pos++ = sizeof(struct ieee80211_ht_cap);
161 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
162
163 /* capability flags */
164 tmp = cpu_to_le16(cap);
165 memcpy(pos, &tmp, sizeof(u16));
166 pos += sizeof(u16);
167
168 /* AMPDU parameters */
169 *pos++ = sband->ht_cap.ampdu_factor |
170 (sband->ht_cap.ampdu_density <<
171 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
172
173 /* MCS set */
174 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
175 pos += sizeof(sband->ht_cap.mcs);
176
177 /* extended capabilities */
178 pos += sizeof(__le16);
179
180 /* BF capabilities */
181 pos += sizeof(__le32);
182
183 /* antenna selection */
184 pos += sizeof(u8);
185}
186
187static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
188 struct ieee80211_work *wk)
189{
190 struct ieee80211_local *local = sdata->local;
191 struct sk_buff *skb;
192 struct ieee80211_mgmt *mgmt;
193 u8 *pos, qos_info;
194 size_t offset = 0, noffset;
195 int i, count, rates_len, supp_rates_len;
196 u16 capab;
197 struct ieee80211_supported_band *sband;
198 u32 rates = 0;
199
200 sband = local->hw.wiphy->bands[wk->chan->band];
201
202 if (wk->assoc.supp_rates_len) {
203 /*
204 * Get all rates supported by the device and the AP as
205 * some APs don't like getting a superset of their rates
206 * in the association request (e.g. D-Link DAP 1353 in
207 * b-only mode)...
208 */
209 rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates,
210 wk->assoc.supp_rates_len,
211 sband, &rates);
212 } else {
213 /*
214 * In case AP not provide any supported rates information
215 * before association, we send information element(s) with
216 * all rates that we support.
217 */
218 rates = ~0;
219 rates_len = sband->n_bitrates;
220 }
221
222 skb = alloc_skb(local->hw.extra_tx_headroom +
223 sizeof(*mgmt) + /* bit too much but doesn't matter */
224 2 + wk->assoc.ssid_len + /* SSID */
225 4 + rates_len + /* (extended) rates */
226 4 + /* power capability */
227 2 + 2 * sband->n_channels + /* supported channels */
228 2 + sizeof(struct ieee80211_ht_cap) + /* HT */
229 wk->ie_len + /* extra IEs */
230 9, /* WMM */
231 GFP_KERNEL);
232 if (!skb) {
233 printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
234 "frame\n", sdata->name);
235 return;
236 }
237 skb_reserve(skb, local->hw.extra_tx_headroom);
238
239 capab = WLAN_CAPABILITY_ESS;
240
241 if (sband->band == IEEE80211_BAND_2GHZ) {
242 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
243 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
244 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
245 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
246 }
247
248 if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY)
249 capab |= WLAN_CAPABILITY_PRIVACY;
250
251 if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
252 (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
253 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
254
255 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
256 memset(mgmt, 0, 24);
257 memcpy(mgmt->da, wk->filter_ta, ETH_ALEN);
258 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
259 memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN);
260
261 if (!is_zero_ether_addr(wk->assoc.prev_bssid)) {
262 skb_put(skb, 10);
263 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
264 IEEE80211_STYPE_REASSOC_REQ);
265 mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
266 mgmt->u.reassoc_req.listen_interval =
267 cpu_to_le16(local->hw.conf.listen_interval);
268 memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid,
269 ETH_ALEN);
270 } else {
271 skb_put(skb, 4);
272 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
273 IEEE80211_STYPE_ASSOC_REQ);
274 mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
275 mgmt->u.assoc_req.listen_interval =
276 cpu_to_le16(local->hw.conf.listen_interval);
277 }
278
279 /* SSID */
280 pos = skb_put(skb, 2 + wk->assoc.ssid_len);
281 *pos++ = WLAN_EID_SSID;
282 *pos++ = wk->assoc.ssid_len;
283 memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len);
284
285 /* add all rates which were marked to be used above */
286 supp_rates_len = rates_len;
287 if (supp_rates_len > 8)
288 supp_rates_len = 8;
289
290 pos = skb_put(skb, supp_rates_len + 2);
291 *pos++ = WLAN_EID_SUPP_RATES;
292 *pos++ = supp_rates_len;
293
294 count = 0;
295 for (i = 0; i < sband->n_bitrates; i++) {
296 if (BIT(i) & rates) {
297 int rate = sband->bitrates[i].bitrate;
298 *pos++ = (u8) (rate / 5);
299 if (++count == 8)
300 break;
301 }
302 }
303
304 if (rates_len > count) {
305 pos = skb_put(skb, rates_len - count + 2);
306 *pos++ = WLAN_EID_EXT_SUPP_RATES;
307 *pos++ = rates_len - count;
308
309 for (i++; i < sband->n_bitrates; i++) {
310 if (BIT(i) & rates) {
311 int rate = sband->bitrates[i].bitrate;
312 *pos++ = (u8) (rate / 5);
313 }
314 }
315 }
316
317 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
318 /* 1. power capabilities */
319 pos = skb_put(skb, 4);
320 *pos++ = WLAN_EID_PWR_CAPABILITY;
321 *pos++ = 2;
322 *pos++ = 0; /* min tx power */
323 *pos++ = wk->chan->max_power; /* max tx power */
324
325 /* 2. supported channels */
326 /* TODO: get this in reg domain format */
327 pos = skb_put(skb, 2 * sband->n_channels + 2);
328 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
329 *pos++ = 2 * sband->n_channels;
330 for (i = 0; i < sband->n_channels; i++) {
331 *pos++ = ieee80211_frequency_to_channel(
332 sband->channels[i].center_freq);
333 *pos++ = 1; /* one channel in the subband*/
334 }
335 }
336
337 /* if present, add any custom IEs that go before HT */
338 if (wk->ie_len && wk->ie) {
339 static const u8 before_ht[] = {
340 WLAN_EID_SSID,
341 WLAN_EID_SUPP_RATES,
342 WLAN_EID_EXT_SUPP_RATES,
343 WLAN_EID_PWR_CAPABILITY,
344 WLAN_EID_SUPPORTED_CHANNELS,
345 WLAN_EID_RSN,
346 WLAN_EID_QOS_CAPA,
347 WLAN_EID_RRM_ENABLED_CAPABILITIES,
348 WLAN_EID_MOBILITY_DOMAIN,
349 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
350 };
351 noffset = ieee80211_ie_split(wk->ie, wk->ie_len,
352 before_ht, ARRAY_SIZE(before_ht),
353 offset);
354 pos = skb_put(skb, noffset - offset);
355 memcpy(pos, wk->ie + offset, noffset - offset);
356 offset = noffset;
357 }
358
359 if (wk->assoc.use_11n && wk->assoc.wmm_used &&
360 local->hw.queues >= 4)
361 ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie,
362 sband, wk->chan, wk->assoc.smps);
363
364 /* if present, add any custom non-vendor IEs that go after HT */
365 if (wk->ie_len && wk->ie) {
366 noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len,
367 offset);
368 pos = skb_put(skb, noffset - offset);
369 memcpy(pos, wk->ie + offset, noffset - offset);
370 offset = noffset;
371 }
372
373 if (wk->assoc.wmm_used && local->hw.queues >= 4) {
374 if (wk->assoc.uapsd_used) {
375 qos_info = local->uapsd_queues;
376 qos_info |= (local->uapsd_max_sp_len <<
377 IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
378 } else {
379 qos_info = 0;
380 }
381
382 pos = skb_put(skb, 9);
383 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
384 *pos++ = 7; /* len */
385 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
386 *pos++ = 0x50;
387 *pos++ = 0xf2;
388 *pos++ = 2; /* WME */
389 *pos++ = 0; /* WME info */
390 *pos++ = 1; /* WME ver */
391 *pos++ = qos_info;
392 }
393
394 /* add any remaining custom (i.e. vendor specific here) IEs */
395 if (wk->ie_len && wk->ie) {
396 noffset = wk->ie_len;
397 pos = skb_put(skb, noffset - offset);
398 memcpy(pos, wk->ie + offset, noffset - offset);
399 }
400
401 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
402 ieee80211_tx_skb(sdata, skb);
403}
404
405static void ieee80211_remove_auth_bss(struct ieee80211_local *local,
406 struct ieee80211_work *wk)
407{
408 struct cfg80211_bss *cbss;
409 u16 capa_val = WLAN_CAPABILITY_ESS;
410
411 if (wk->probe_auth.privacy)
412 capa_val |= WLAN_CAPABILITY_PRIVACY;
413
414 cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta,
415 wk->probe_auth.ssid, wk->probe_auth.ssid_len,
416 WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
417 capa_val);
418 if (!cbss)
419 return;
420
421 cfg80211_unlink_bss(local->hw.wiphy, cbss);
422 cfg80211_put_bss(cbss);
423}
424
425static enum work_action __must_check
426ieee80211_direct_probe(struct ieee80211_work *wk)
427{
428 struct ieee80211_sub_if_data *sdata = wk->sdata;
429 struct ieee80211_local *local = sdata->local;
430
431 if (!wk->probe_auth.synced) {
432 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
433 IEEE80211_TX_SYNC_AUTH);
434 if (ret)
435 return WORK_ACT_TIMEOUT;
436 }
437 wk->probe_auth.synced = true;
438
439 wk->probe_auth.tries++;
440 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
441 printk(KERN_DEBUG "%s: direct probe to %pM timed out\n",
442 sdata->name, wk->filter_ta);
443
444 /*
445 * Most likely AP is not in the range so remove the
446 * bss struct for that AP.
447 */
448 ieee80211_remove_auth_bss(local, wk);
449
450 return WORK_ACT_TIMEOUT;
451 }
452
453 printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n",
454 sdata->name, wk->filter_ta, wk->probe_auth.tries,
455 IEEE80211_AUTH_MAX_TRIES);
456
457 /*
458 * Direct probe is sent to broadcast address as some APs
459 * will not answer to direct packet in unassociated state.
460 */
461 ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid,
462 wk->probe_auth.ssid_len, NULL, 0,
463 (u32) -1, true);
464
465 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
466 run_again(local, wk->timeout);
467
468 return WORK_ACT_NONE;
469}
470
471
472static enum work_action __must_check
473ieee80211_authenticate(struct ieee80211_work *wk)
474{
475 struct ieee80211_sub_if_data *sdata = wk->sdata;
476 struct ieee80211_local *local = sdata->local;
477
478 if (!wk->probe_auth.synced) {
479 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
480 IEEE80211_TX_SYNC_AUTH);
481 if (ret)
482 return WORK_ACT_TIMEOUT;
483 }
484 wk->probe_auth.synced = true;
485
486 wk->probe_auth.tries++;
487 if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
488 printk(KERN_DEBUG "%s: authentication with %pM"
489 " timed out\n", sdata->name, wk->filter_ta);
490
491 /*
492 * Most likely AP is not in the range so remove the
493 * bss struct for that AP.
494 */
495 ieee80211_remove_auth_bss(local, wk);
496
497 return WORK_ACT_TIMEOUT;
498 }
499
500 printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n",
501 sdata->name, wk->filter_ta, wk->probe_auth.tries);
502
503 ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie,
504 wk->ie_len, wk->filter_ta, NULL, 0, 0);
505 wk->probe_auth.transaction = 2;
506
507 wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
508 run_again(local, wk->timeout);
509
510 return WORK_ACT_NONE;
511}
512
513static enum work_action __must_check
514ieee80211_associate(struct ieee80211_work *wk)
515{
516 struct ieee80211_sub_if_data *sdata = wk->sdata;
517 struct ieee80211_local *local = sdata->local;
518
519 if (!wk->assoc.synced) {
520 int ret = drv_tx_sync(local, sdata, wk->filter_ta,
521 IEEE80211_TX_SYNC_ASSOC);
522 if (ret)
523 return WORK_ACT_TIMEOUT;
524 }
525 wk->assoc.synced = true;
526
527 wk->assoc.tries++;
528 if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) {
529 printk(KERN_DEBUG "%s: association with %pM"
530 " timed out\n",
531 sdata->name, wk->filter_ta);
532
533 /*
534 * Most likely AP is not in the range so remove the
535 * bss struct for that AP.
536 */
537 if (wk->assoc.bss)
538 cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss);
539
540 return WORK_ACT_TIMEOUT;
541 }
542
543 printk(KERN_DEBUG "%s: associate with %pM (try %d)\n",
544 sdata->name, wk->filter_ta, wk->assoc.tries);
545 ieee80211_send_assoc(sdata, wk);
546
547 wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
548 run_again(local, wk->timeout);
549
550 return WORK_ACT_NONE;
551}
552
553static enum work_action __must_check
554ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
555{
556 /*
557 * First time we run, do nothing -- the generic code will
558 * have switched to the right channel etc.
559 */
560 if (!wk->started) {
561 wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration);
562
563 cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk,
564 wk->chan, wk->chan_type,
565 wk->remain.duration, GFP_KERNEL);
566
567 return WORK_ACT_NONE;
568 }
569
570 return WORK_ACT_TIMEOUT;
571}
572
573static enum work_action __must_check
574ieee80211_offchannel_tx(struct ieee80211_work *wk)
575{
576 if (!wk->started) {
577 wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait);
578
579 /*
580 * After this, offchan_tx.frame remains but now is no
581 * longer a valid pointer -- we still need it as the
582 * cookie for canceling this work/status matching.
583 */
584 ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame);
585
586 return WORK_ACT_NONE;
587 }
588
589 return WORK_ACT_TIMEOUT;
590}
591
592static enum work_action __must_check
593ieee80211_assoc_beacon_wait(struct ieee80211_work *wk)
594{
595 if (wk->started)
596 return WORK_ACT_TIMEOUT;
597
598 /*
599 * Wait up to one beacon interval ...
600 * should this be more if we miss one?
601 */
602 printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
603 wk->sdata->name, wk->filter_ta);
604 wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval);
605 return WORK_ACT_NONE;
606}
607
608static void ieee80211_auth_challenge(struct ieee80211_work *wk,
609 struct ieee80211_mgmt *mgmt,
610 size_t len)
611{
612 struct ieee80211_sub_if_data *sdata = wk->sdata;
613 u8 *pos;
614 struct ieee802_11_elems elems;
615
616 pos = mgmt->u.auth.variable;
617 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
618 if (!elems.challenge)
619 return;
620 ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm,
621 elems.challenge - 2, elems.challenge_len + 2,
622 wk->filter_ta, wk->probe_auth.key,
623 wk->probe_auth.key_len, wk->probe_auth.key_idx);
624 wk->probe_auth.transaction = 4;
625}
626
627static enum work_action __must_check
628ieee80211_rx_mgmt_auth(struct ieee80211_work *wk,
629 struct ieee80211_mgmt *mgmt, size_t len)
630{
631 u16 auth_alg, auth_transaction, status_code;
632
633 if (wk->type != IEEE80211_WORK_AUTH)
634 return WORK_ACT_MISMATCH;
635
636 if (len < 24 + 6)
637 return WORK_ACT_NONE;
638
639 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
640 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
641 status_code = le16_to_cpu(mgmt->u.auth.status_code);
642
643 if (auth_alg != wk->probe_auth.algorithm ||
644 auth_transaction != wk->probe_auth.transaction)
645 return WORK_ACT_NONE;
646
647 if (status_code != WLAN_STATUS_SUCCESS) {
648 printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n",
649 wk->sdata->name, mgmt->sa, status_code);
650 return WORK_ACT_DONE;
651 }
652
653 switch (wk->probe_auth.algorithm) {
654 case WLAN_AUTH_OPEN:
655 case WLAN_AUTH_LEAP:
656 case WLAN_AUTH_FT:
657 break;
658 case WLAN_AUTH_SHARED_KEY:
659 if (wk->probe_auth.transaction != 4) {
660 ieee80211_auth_challenge(wk, mgmt, len);
661 /* need another frame */
662 return WORK_ACT_NONE;
663 }
664 break;
665 default:
666 WARN_ON(1);
667 return WORK_ACT_NONE;
668 }
669
670 printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name);
671 return WORK_ACT_DONE;
672}
673
674static enum work_action __must_check
675ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk,
676 struct ieee80211_mgmt *mgmt, size_t len,
677 bool reassoc)
678{
679 struct ieee80211_sub_if_data *sdata = wk->sdata;
680 struct ieee80211_local *local = sdata->local;
681 u16 capab_info, status_code, aid;
682 struct ieee802_11_elems elems;
683 u8 *pos;
684
685 if (wk->type != IEEE80211_WORK_ASSOC)
686 return WORK_ACT_MISMATCH;
687
688 /*
689 * AssocResp and ReassocResp have identical structure, so process both
690 * of them in this function.
691 */
692
693 if (len < 24 + 6)
694 return WORK_ACT_NONE;
695
696 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
697 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
698 aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
699
700 printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x "
701 "status=%d aid=%d)\n",
702 sdata->name, reassoc ? "Rea" : "A", mgmt->sa,
703 capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
704
705 pos = mgmt->u.assoc_resp.variable;
706 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
707
708 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
709 elems.timeout_int && elems.timeout_int_len == 5 &&
710 elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
711 u32 tu, ms;
712 tu = get_unaligned_le32(elems.timeout_int + 1);
713 ms = tu * 1024 / 1000;
714 printk(KERN_DEBUG "%s: %pM rejected association temporarily; "
715 "comeback duration %u TU (%u ms)\n",
716 sdata->name, mgmt->sa, tu, ms);
717 wk->timeout = jiffies + msecs_to_jiffies(ms);
718 if (ms > IEEE80211_ASSOC_TIMEOUT)
719 run_again(local, wk->timeout);
720 return WORK_ACT_NONE;
721 }
722
723 if (status_code != WLAN_STATUS_SUCCESS)
724 printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n",
725 sdata->name, mgmt->sa, status_code);
726 else
727 printk(KERN_DEBUG "%s: associated\n", sdata->name);
728
729 return WORK_ACT_DONE;
730}
731
732static enum work_action __must_check
733ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk,
734 struct ieee80211_mgmt *mgmt, size_t len,
735 struct ieee80211_rx_status *rx_status)
736{
737 struct ieee80211_sub_if_data *sdata = wk->sdata;
738 struct ieee80211_local *local = sdata->local;
739 size_t baselen;
740
741 ASSERT_WORK_MTX(local);
742
743 if (wk->type != IEEE80211_WORK_DIRECT_PROBE)
744 return WORK_ACT_MISMATCH;
745
746 if (len < 24 + 12)
747 return WORK_ACT_NONE;
748
749 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
750 if (baselen > len)
751 return WORK_ACT_NONE;
752
753 printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name);
754 return WORK_ACT_DONE;
755}
756
757static enum work_action __must_check
758ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk,
759 struct ieee80211_mgmt *mgmt, size_t len)
760{
761 struct ieee80211_sub_if_data *sdata = wk->sdata;
762 struct ieee80211_local *local = sdata->local;
763
764 ASSERT_WORK_MTX(local);
765
766 if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
767 return WORK_ACT_MISMATCH;
768
769 if (len < 24 + 12)
770 return WORK_ACT_NONE;
771
772 printk(KERN_DEBUG "%s: beacon received\n", sdata->name);
773 return WORK_ACT_DONE;
774}
775
776static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
777 struct sk_buff *skb)
778{
779 struct ieee80211_rx_status *rx_status;
780 struct ieee80211_mgmt *mgmt;
781 struct ieee80211_work *wk;
782 enum work_action rma = WORK_ACT_NONE;
783 u16 fc;
784
785 rx_status = (struct ieee80211_rx_status *) skb->cb;
786 mgmt = (struct ieee80211_mgmt *) skb->data;
787 fc = le16_to_cpu(mgmt->frame_control);
788
789 mutex_lock(&local->mtx);
790
791 list_for_each_entry(wk, &local->work_list, list) {
792 const u8 *bssid = NULL;
793
794 switch (wk->type) {
795 case IEEE80211_WORK_DIRECT_PROBE:
796 case IEEE80211_WORK_AUTH:
797 case IEEE80211_WORK_ASSOC:
798 case IEEE80211_WORK_ASSOC_BEACON_WAIT:
799 bssid = wk->filter_ta;
800 break;
801 default:
802 continue;
803 }
804
805 /*
806 * Before queuing, we already verified mgmt->sa,
807 * so this is needed just for matching.
808 */
809 if (compare_ether_addr(bssid, mgmt->bssid))
810 continue;
811
812 switch (fc & IEEE80211_FCTL_STYPE) {
813 case IEEE80211_STYPE_BEACON:
814 rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len);
815 break;
816 case IEEE80211_STYPE_PROBE_RESP:
817 rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len,
818 rx_status);
819 break;
820 case IEEE80211_STYPE_AUTH:
821 rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len);
822 break;
823 case IEEE80211_STYPE_ASSOC_RESP:
824 rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt,
825 skb->len, false);
826 break;
827 case IEEE80211_STYPE_REASSOC_RESP:
828 rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt,
829 skb->len, true);
830 break;
831 default:
832 WARN_ON(1);
833 rma = WORK_ACT_NONE;
834 }
835
836 /*
837 * We've either received an unexpected frame, or we have
838 * multiple work items and need to match the frame to the
839 * right one.
840 */
841 if (rma == WORK_ACT_MISMATCH)
842 continue;
843
844 /*
845 * We've processed this frame for that work, so it can't
846 * belong to another work struct.
847 * NB: this is also required for correctness for 'rma'!
848 */
849 break;
850 }
851
852 switch (rma) {
853 case WORK_ACT_MISMATCH:
854 /* ignore this unmatched frame */
855 break;
856 case WORK_ACT_NONE:
857 break;
858 case WORK_ACT_DONE:
859 list_del_rcu(&wk->list);
860 break;
861 default:
862 WARN(1, "unexpected: %d", rma);
863 }
864
865 mutex_unlock(&local->mtx);
866
867 if (rma != WORK_ACT_DONE)
868 goto out;
869
870 switch (wk->done(wk, skb)) {
871 case WORK_DONE_DESTROY:
872 free_work(wk);
873 break;
874 case WORK_DONE_REQUEUE:
875 synchronize_rcu();
876 wk->started = false; /* restart */
877 mutex_lock(&local->mtx);
878 list_add_tail(&wk->list, &local->work_list);
879 mutex_unlock(&local->mtx);
880 }
881
882 out:
883 kfree_skb(skb);
884}
885
886static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
887 enum nl80211_channel_type oper_ct)
888{
889 switch (wk_ct) {
890 case NL80211_CHAN_NO_HT:
891 return true;
892 case NL80211_CHAN_HT20:
893 if (oper_ct != NL80211_CHAN_NO_HT)
894 return true;
895 return false;
896 case NL80211_CHAN_HT40MINUS:
897 case NL80211_CHAN_HT40PLUS:
898 return (wk_ct == oper_ct);
899 }
900 WARN_ON(1); /* shouldn't get here */
901 return false;
902}
903
904static enum nl80211_channel_type
905ieee80211_calc_ct(enum nl80211_channel_type wk_ct,
906 enum nl80211_channel_type oper_ct)
907{
908 switch (wk_ct) {
909 case NL80211_CHAN_NO_HT:
910 return oper_ct;
911 case NL80211_CHAN_HT20:
912 if (oper_ct != NL80211_CHAN_NO_HT)
913 return oper_ct;
914 return wk_ct;
915 case NL80211_CHAN_HT40MINUS:
916 case NL80211_CHAN_HT40PLUS:
917 return wk_ct;
918 }
919 WARN_ON(1); /* shouldn't get here */
920 return wk_ct;
921}
922
923
924static void ieee80211_work_timer(unsigned long data)
925{
926 struct ieee80211_local *local = (void *) data;
927
928 if (local->quiescing)
929 return;
930
931 ieee80211_queue_work(&local->hw, &local->work_work);
932}
933
934static void ieee80211_work_work(struct work_struct *work)
935{
936 struct ieee80211_local *local =
937 container_of(work, struct ieee80211_local, work_work);
938 struct sk_buff *skb;
939 struct ieee80211_work *wk, *tmp;
940 LIST_HEAD(free_work);
941 enum work_action rma;
942 bool remain_off_channel = false;
943
944 if (local->scanning)
945 return;
946
947 /*
948 * ieee80211_queue_work() should have picked up most cases,
949 * here we'll pick the rest.
950 */
951 if (WARN(local->suspended, "work scheduled while going to suspend\n"))
952 return;
953
954 /* first process frames to avoid timing out while a frame is pending */
955 while ((skb = skb_dequeue(&local->work_skb_queue)))
956 ieee80211_work_rx_queued_mgmt(local, skb);
957
958 mutex_lock(&local->mtx);
959
960 ieee80211_recalc_idle(local);
961
962 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
963 bool started = wk->started;
964
965 /* mark work as started if it's on the current off-channel */
966 if (!started && local->tmp_channel &&
967 wk->chan == local->tmp_channel &&
968 wk->chan_type == local->tmp_channel_type) {
969 started = true;
970 wk->timeout = jiffies;
971 }
972
973 if (!started && !local->tmp_channel) {
974 bool on_oper_chan;
975 bool tmp_chan_changed = false;
976 bool on_oper_chan2;
977 enum nl80211_channel_type wk_ct;
978 on_oper_chan = ieee80211_cfg_on_oper_channel(local);
979
980 /* Work with existing channel type if possible. */
981 wk_ct = wk->chan_type;
982 if (wk->chan == local->hw.conf.channel)
983 wk_ct = ieee80211_calc_ct(wk->chan_type,
984 local->hw.conf.channel_type);
985
986 if (local->tmp_channel)
987 if ((local->tmp_channel != wk->chan) ||
988 (local->tmp_channel_type != wk_ct))
989 tmp_chan_changed = true;
990
991 local->tmp_channel = wk->chan;
992 local->tmp_channel_type = wk_ct;
993 /*
994 * Leave the station vifs in awake mode if they
995 * happen to be on the same channel as
996 * the requested channel.
997 */
998 on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
999 if (on_oper_chan != on_oper_chan2) {
1000 if (on_oper_chan2) {
1001 /* going off oper channel, PS too */
1002 ieee80211_offchannel_stop_vifs(local,
1003 true);
1004 ieee80211_hw_config(local, 0);
1005 } else {
1006 /* going on channel, but leave PS
1007 * off-channel. */
1008 ieee80211_hw_config(local, 0);
1009 ieee80211_offchannel_return(local,
1010 true,
1011 false);
1012 }
1013 } else if (tmp_chan_changed)
1014 /* Still off-channel, but on some other
1015 * channel, so update hardware.
1016 * PS should already be off-channel.
1017 */
1018 ieee80211_hw_config(local, 0);
1019
1020 started = true;
1021 wk->timeout = jiffies;
1022 }
1023
1024 /* don't try to work with items that aren't started */
1025 if (!started)
1026 continue;
1027
1028 if (time_is_after_jiffies(wk->timeout)) {
1029 /*
1030 * This work item isn't supposed to be worked on
1031 * right now, but take care to adjust the timer
1032 * properly.
1033 */
1034 run_again(local, wk->timeout);
1035 continue;
1036 }
1037
1038 switch (wk->type) {
1039 default:
1040 WARN_ON(1);
1041 /* nothing */
1042 rma = WORK_ACT_NONE;
1043 break;
1044 case IEEE80211_WORK_ABORT:
1045 rma = WORK_ACT_TIMEOUT;
1046 break;
1047 case IEEE80211_WORK_DIRECT_PROBE:
1048 rma = ieee80211_direct_probe(wk);
1049 break;
1050 case IEEE80211_WORK_AUTH:
1051 rma = ieee80211_authenticate(wk);
1052 break;
1053 case IEEE80211_WORK_ASSOC:
1054 rma = ieee80211_associate(wk);
1055 break;
1056 case IEEE80211_WORK_REMAIN_ON_CHANNEL:
1057 rma = ieee80211_remain_on_channel_timeout(wk);
1058 break;
1059 case IEEE80211_WORK_OFFCHANNEL_TX:
1060 rma = ieee80211_offchannel_tx(wk);
1061 break;
1062 case IEEE80211_WORK_ASSOC_BEACON_WAIT:
1063 rma = ieee80211_assoc_beacon_wait(wk);
1064 break;
1065 }
1066
1067 wk->started = started;
1068
1069 switch (rma) {
1070 case WORK_ACT_NONE:
1071 /* might have changed the timeout */
1072 run_again(local, wk->timeout);
1073 break;
1074 case WORK_ACT_TIMEOUT:
1075 list_del_rcu(&wk->list);
1076 synchronize_rcu();
1077 list_add(&wk->list, &free_work);
1078 break;
1079 default:
1080 WARN(1, "unexpected: %d", rma);
1081 }
1082 }
1083
1084 list_for_each_entry(wk, &local->work_list, list) {
1085 if (!wk->started)
1086 continue;
1087 if (wk->chan != local->tmp_channel)
1088 continue;
1089 if (!ieee80211_work_ct_coexists(wk->chan_type,
1090 local->tmp_channel_type))
1091 continue;
1092 remain_off_channel = true;
1093 }
1094
1095 if (!remain_off_channel && local->tmp_channel) {
1096 local->tmp_channel = NULL;
1097 /* If tmp_channel wasn't operating channel, then
1098 * we need to go back on-channel.
1099 * NOTE: If we can ever be here while scannning,
1100 * or if the hw_config() channel config logic changes,
1101 * then we may need to do a more thorough check to see if
1102 * we still need to do a hardware config. Currently,
1103 * we cannot be here while scanning, however.
1104 */
1105 if (!ieee80211_cfg_on_oper_channel(local))
1106 ieee80211_hw_config(local, 0);
1107
1108 /* At the least, we need to disable offchannel_ps,
1109 * so just go ahead and run the entire offchannel
1110 * return logic here. We *could* skip enabling
1111 * beaconing if we were already on-oper-channel
1112 * as a future optimization.
1113 */
1114 ieee80211_offchannel_return(local, true, true);
1115
1116 /* give connection some time to breathe */
1117 run_again(local, jiffies + HZ/2);
1118 }
1119
1120 if (list_empty(&local->work_list) && local->scan_req &&
1121 !local->scanning)
1122 ieee80211_queue_delayed_work(&local->hw,
1123 &local->scan_work,
1124 round_jiffies_relative(0));
1125
1126 ieee80211_recalc_idle(local);
1127
1128 mutex_unlock(&local->mtx);
1129
1130 list_for_each_entry_safe(wk, tmp, &free_work, list) {
1131 wk->done(wk, NULL);
1132 list_del(&wk->list);
1133 kfree(wk);
1134 }
1135}
1136
1137void ieee80211_add_work(struct ieee80211_work *wk)
1138{
1139 struct ieee80211_local *local;
1140
1141 if (WARN_ON(!wk->chan))
1142 return;
1143
1144 if (WARN_ON(!wk->sdata))
1145 return;
1146
1147 if (WARN_ON(!wk->done))
1148 return;
1149
1150 if (WARN_ON(!ieee80211_sdata_running(wk->sdata)))
1151 return;
1152
1153 wk->started = false;
1154
1155 local = wk->sdata->local;
1156 mutex_lock(&local->mtx);
1157 list_add_tail(&wk->list, &local->work_list);
1158 mutex_unlock(&local->mtx);
1159
1160 ieee80211_queue_work(&local->hw, &local->work_work);
1161}
1162
1163void ieee80211_work_init(struct ieee80211_local *local)
1164{
1165 INIT_LIST_HEAD(&local->work_list);
1166 setup_timer(&local->work_timer, ieee80211_work_timer,
1167 (unsigned long)local);
1168 INIT_WORK(&local->work_work, ieee80211_work_work);
1169 skb_queue_head_init(&local->work_skb_queue);
1170}
1171
1172void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
1173{
1174 struct ieee80211_local *local = sdata->local;
1175 struct ieee80211_work *wk;
1176 bool cleanup = false;
1177
1178 mutex_lock(&local->mtx);
1179 list_for_each_entry(wk, &local->work_list, list) {
1180 if (wk->sdata != sdata)
1181 continue;
1182 cleanup = true;
1183 wk->type = IEEE80211_WORK_ABORT;
1184 wk->started = true;
1185 wk->timeout = jiffies;
1186 }
1187 mutex_unlock(&local->mtx);
1188
1189 /* run cleanups etc. */
1190 if (cleanup)
1191 ieee80211_work_work(&local->work_work);
1192
1193 mutex_lock(&local->mtx);
1194 list_for_each_entry(wk, &local->work_list, list) {
1195 if (wk->sdata != sdata)
1196 continue;
1197 WARN_ON(1);
1198 break;
1199 }
1200 mutex_unlock(&local->mtx);
1201}
1202
1203ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
1204 struct sk_buff *skb)
1205{
1206 struct ieee80211_local *local = sdata->local;
1207 struct ieee80211_mgmt *mgmt;
1208 struct ieee80211_work *wk;
1209 u16 fc;
1210
1211 if (skb->len < 24)
1212 return RX_DROP_MONITOR;
1213
1214 mgmt = (struct ieee80211_mgmt *) skb->data;
1215 fc = le16_to_cpu(mgmt->frame_control);
1216
1217 list_for_each_entry_rcu(wk, &local->work_list, list) {
1218 if (sdata != wk->sdata)
1219 continue;
1220 if (compare_ether_addr(wk->filter_ta, mgmt->sa))
1221 continue;
1222 if (compare_ether_addr(wk->filter_ta, mgmt->bssid))
1223 continue;
1224
1225 switch (fc & IEEE80211_FCTL_STYPE) {
1226 case IEEE80211_STYPE_AUTH:
1227 case IEEE80211_STYPE_PROBE_RESP:
1228 case IEEE80211_STYPE_ASSOC_RESP:
1229 case IEEE80211_STYPE_REASSOC_RESP:
1230 case IEEE80211_STYPE_BEACON:
1231 skb_queue_tail(&local->work_skb_queue, skb);
1232 ieee80211_queue_work(&local->hw, &local->work_work);
1233 return RX_QUEUED;
1234 }
1235 }
1236
1237 return RX_CONTINUE;
1238}
1239
1240static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk,
1241 struct sk_buff *skb)
1242{
1243 /*
1244 * We are done serving the remain-on-channel command.
1245 */
1246 cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk,
1247 wk->chan, wk->chan_type,
1248 GFP_KERNEL);
1249
1250 return WORK_DONE_DESTROY;
1251}
1252
1253int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
1254 struct ieee80211_channel *chan,
1255 enum nl80211_channel_type channel_type,
1256 unsigned int duration, u64 *cookie)
1257{
1258 struct ieee80211_work *wk;
1259
1260 wk = kzalloc(sizeof(*wk), GFP_KERNEL);
1261 if (!wk)
1262 return -ENOMEM;
1263
1264 wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL;
1265 wk->chan = chan;
1266 wk->chan_type = channel_type;
1267 wk->sdata = sdata;
1268 wk->done = ieee80211_remain_done;
1269
1270 wk->remain.duration = duration;
1271
1272 *cookie = (unsigned long) wk;
1273
1274 ieee80211_add_work(wk);
1275
1276 return 0;
1277}
1278
1279int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
1280 u64 cookie)
1281{
1282 struct ieee80211_local *local = sdata->local;
1283 struct ieee80211_work *wk, *tmp;
1284 bool found = false;
1285
1286 mutex_lock(&local->mtx);
1287 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
1288 if ((unsigned long) wk == cookie) {
1289 wk->timeout = jiffies;
1290 found = true;
1291 break;
1292 }
1293 }
1294 mutex_unlock(&local->mtx);
1295
1296 if (!found)
1297 return -ENOENT;
1298
1299 ieee80211_queue_work(&local->hw, &local->work_work);
1300
1301 return 0;
1302}