driver-ops.h 34 KB
Newer Older
1
2
3
4
5
#ifndef __MAC80211_DRIVER_OPS
#define __MAC80211_DRIVER_OPS

#include <net/mac80211.h>
#include "ieee80211_i.h"
6
#include "trace.h"
7

8
static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
9
{
10
11
12
	return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER),
		     "%s:  Failed check-sdata-in-driver check, flags: 0x%x\n",
		     sdata->dev ? sdata->dev->name : sdata->name, sdata->flags);
13
14
}

15
16
17
18
19
20
21
22
23
24
static inline struct ieee80211_sub_if_data *
get_bss_sdata(struct ieee80211_sub_if_data *sdata)
{
	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
		sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
				     u.ap);

	return sdata;
}

25
26
27
static inline void drv_tx(struct ieee80211_local *local,
			  struct ieee80211_tx_control *control,
			  struct sk_buff *skb)
28
{
29
	local->ops->tx(&local->hw, control, skb);
30
31
}

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata,
				      u32 sset, u8 *data)
{
	struct ieee80211_local *local = sdata->local;
	if (local->ops->get_et_strings) {
		trace_drv_get_et_strings(local, sset);
		local->ops->get_et_strings(&local->hw, &sdata->vif, sset, data);
		trace_drv_return_void(local);
	}
}

static inline void drv_get_et_stats(struct ieee80211_sub_if_data *sdata,
				    struct ethtool_stats *stats,
				    u64 *data)
{
	struct ieee80211_local *local = sdata->local;
	if (local->ops->get_et_stats) {
		trace_drv_get_et_stats(local);
		local->ops->get_et_stats(&local->hw, &sdata->vif, stats, data);
		trace_drv_return_void(local);
	}
}

static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata,
					int sset)
{
	struct ieee80211_local *local = sdata->local;
	int rv = 0;
	if (local->ops->get_et_sset_count) {
		trace_drv_get_et_sset_count(local, sset);
		rv = local->ops->get_et_sset_count(&local->hw, &sdata->vif,
						   sset);
		trace_drv_return_int(local, rv);
	}
	return rv;
}

69
70
static inline int drv_start(struct ieee80211_local *local)
{
71
72
	int ret;

73
74
	might_sleep();

75
	trace_drv_start(local);
76
77
78
	local->started = true;
	smp_mb();
	ret = local->ops->start(&local->hw);
79
	trace_drv_return_int(local, ret);
80
	return ret;
81
82
83
84
}

static inline void drv_stop(struct ieee80211_local *local)
{
85
86
	might_sleep();

87
	trace_drv_stop(local);
88
89
	local->ops->stop(&local->hw);
	trace_drv_return_void(local);
90
91
92
93
94
95
96
97

	/* sync away all work on the tasklet before clearing started */
	tasklet_disable(&local->tasklet);
	tasklet_enable(&local->tasklet);

	barrier();

	local->started = false;
98
99
}

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#ifdef CONFIG_PM
static inline int drv_suspend(struct ieee80211_local *local,
			      struct cfg80211_wowlan *wowlan)
{
	int ret;

	might_sleep();

	trace_drv_suspend(local);
	ret = local->ops->suspend(&local->hw, wowlan);
	trace_drv_return_int(local, ret);
	return ret;
}

static inline int drv_resume(struct ieee80211_local *local)
{
	int ret;

	might_sleep();

	trace_drv_resume(local);
	ret = local->ops->resume(&local->hw);
	trace_drv_return_int(local, ret);
	return ret;
}
125
126
127
128
129
130
131
132
133
134
135
136
137

static inline void drv_set_wakeup(struct ieee80211_local *local,
				  bool enabled)
{
	might_sleep();

	if (!local->ops->set_wakeup)
		return;

	trace_drv_set_wakeup(local, enabled);
	local->ops->set_wakeup(&local->hw, enabled);
	trace_drv_return_void(local);
}
138
139
#endif

140
static inline int drv_add_interface(struct ieee80211_local *local,
141
				    struct ieee80211_sub_if_data *sdata)
142
{
143
144
145
146
	int ret;

	might_sleep();

147
	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
148
		    (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
149
		     !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
150
		     !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))))
151
152
153
154
		return -EINVAL;

	trace_drv_add_interface(local, sdata);
	ret = local->ops->add_interface(&local->hw, &sdata->vif);
155
	trace_drv_return_int(local, ret);
156
157
158
159

	if (ret == 0)
		sdata->flags |= IEEE80211_SDATA_IN_DRIVER;

160
	return ret;
161
162
}

163
164
static inline int drv_change_interface(struct ieee80211_local *local,
				       struct ieee80211_sub_if_data *sdata,
165
				       enum nl80211_iftype type, bool p2p)
166
167
168
169
170
{
	int ret;

	might_sleep();

171
172
	if (!check_sdata_in_driver(sdata))
		return -EIO;
173

174
175
	trace_drv_change_interface(local, sdata, type, p2p);
	ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
176
177
178
179
	trace_drv_return_int(local, ret);
	return ret;
}

180
static inline void drv_remove_interface(struct ieee80211_local *local,
181
					struct ieee80211_sub_if_data *sdata)
182
{
183
184
	might_sleep();

185
186
	if (!check_sdata_in_driver(sdata))
		return;
187
188
189
190

	trace_drv_remove_interface(local, sdata);
	local->ops->remove_interface(&local->hw, &sdata->vif);
	sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
191
	trace_drv_return_void(local);
192
193
194
195
}

static inline int drv_config(struct ieee80211_local *local, u32 changed)
{
196
197
198
199
	int ret;

	might_sleep();

200
	trace_drv_config(local, changed);
201
	ret = local->ops->config(&local->hw, changed);
202
	trace_drv_return_int(local, ret);
203
	return ret;
204
205
206
}

static inline void drv_bss_info_changed(struct ieee80211_local *local,
Johannes Berg's avatar
Johannes Berg committed
207
					struct ieee80211_sub_if_data *sdata,
208
209
210
					struct ieee80211_bss_conf *info,
					u32 changed)
{
211
212
	might_sleep();

213
214
215
216
	if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON |
				    BSS_CHANGED_BEACON_ENABLED) &&
			 sdata->vif.type != NL80211_IFTYPE_AP &&
			 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
217
218
			 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
			 sdata->vif.type != NL80211_IFTYPE_OCB))
219
220
221
222
223
		return;

	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
			 sdata->vif.type == NL80211_IFTYPE_MONITOR))
		return;
224

225
226
	if (!check_sdata_in_driver(sdata))
		return;
227

228
	trace_drv_bss_info_changed(local, sdata, info, changed);
229
	if (local->ops->bss_info_changed)
Johannes Berg's avatar
Johannes Berg committed
230
		local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
231
	trace_drv_return_void(local);
232
233
}

234
static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
235
					struct netdev_hw_addr_list *mc_list)
236
237
238
{
	u64 ret = 0;

239
240
	trace_drv_prepare_multicast(local, mc_list->count);

241
	if (local->ops->prepare_multicast)
242
		ret = local->ops->prepare_multicast(&local->hw, mc_list);
243

244
	trace_drv_return_u64(local, ret);
245
246
247
248

	return ret;
}

249
250
251
static inline void drv_configure_filter(struct ieee80211_local *local,
					unsigned int changed_flags,
					unsigned int *total_flags,
252
					u64 multicast)
253
{
254
255
	might_sleep();

256
	trace_drv_configure_filter(local, changed_flags, total_flags,
257
				   multicast);
258
259
260
	local->ops->configure_filter(&local->hw, changed_flags, total_flags,
				     multicast);
	trace_drv_return_void(local);
261
262
}

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
static inline void drv_config_iface_filter(struct ieee80211_local *local,
					   struct ieee80211_sub_if_data *sdata,
					   unsigned int filter_flags,
					   unsigned int changed_flags)
{
	might_sleep();

	trace_drv_config_iface_filter(local, sdata, filter_flags,
				      changed_flags);
	if (local->ops->config_iface_filter)
		local->ops->config_iface_filter(&local->hw, &sdata->vif,
						filter_flags,
						changed_flags);
	trace_drv_return_void(local);
}

279
280
281
static inline int drv_set_tim(struct ieee80211_local *local,
			      struct ieee80211_sta *sta, bool set)
{
282
	int ret = 0;
283
	trace_drv_set_tim(local, sta, set);
284
	if (local->ops->set_tim)
285
		ret = local->ops->set_tim(&local->hw, sta, set);
286
	trace_drv_return_int(local, ret);
287
	return ret;
288
289
290
}

static inline int drv_set_key(struct ieee80211_local *local,
Johannes Berg's avatar
Johannes Berg committed
291
292
			      enum set_key_cmd cmd,
			      struct ieee80211_sub_if_data *sdata,
293
294
295
			      struct ieee80211_sta *sta,
			      struct ieee80211_key_conf *key)
{
296
297
298
299
	int ret;

	might_sleep();

300
	sdata = get_bss_sdata(sdata);
301
302
	if (!check_sdata_in_driver(sdata))
		return -EIO;
303

304
	trace_drv_set_key(local, cmd, sdata, sta, key);
305
	ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
306
	trace_drv_return_int(local, ret);
307
	return ret;
308
309
310
}

static inline void drv_update_tkip_key(struct ieee80211_local *local,
311
				       struct ieee80211_sub_if_data *sdata,
312
				       struct ieee80211_key_conf *conf,
313
				       struct sta_info *sta, u32 iv32,
314
315
				       u16 *phase1key)
{
316
317
318
319
320
	struct ieee80211_sta *ista = NULL;

	if (sta)
		ista = &sta->sta;

321
	sdata = get_bss_sdata(sdata);
322
323
	if (!check_sdata_in_driver(sdata))
		return;
324

325
	trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
326
	if (local->ops->update_tkip_key)
327
328
		local->ops->update_tkip_key(&local->hw, &sdata->vif, conf,
					    ista, iv32, phase1key);
329
	trace_drv_return_void(local);
330
331
332
}

static inline int drv_hw_scan(struct ieee80211_local *local,
333
			      struct ieee80211_sub_if_data *sdata,
334
			      struct ieee80211_scan_request *req)
335
{
336
337
338
339
	int ret;

	might_sleep();

340
341
	if (!check_sdata_in_driver(sdata))
		return -EIO;
342

343
	trace_drv_hw_scan(local, sdata);
344
	ret = local->ops->hw_scan(&local->hw, &sdata->vif, req);
345
	trace_drv_return_int(local, ret);
346
	return ret;
347
348
}

349
350
351
352
353
static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
				      struct ieee80211_sub_if_data *sdata)
{
	might_sleep();

354
355
	if (!check_sdata_in_driver(sdata))
		return;
356

357
358
359
360
361
	trace_drv_cancel_hw_scan(local, sdata);
	local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
	trace_drv_return_void(local);
}

362
363
364
365
static inline int
drv_sched_scan_start(struct ieee80211_local *local,
		     struct ieee80211_sub_if_data *sdata,
		     struct cfg80211_sched_scan_request *req,
366
		     struct ieee80211_scan_ies *ies)
367
368
369
370
371
{
	int ret;

	might_sleep();

372
373
	if (!check_sdata_in_driver(sdata))
		return -EIO;
374

375
376
377
378
379
380
381
	trace_drv_sched_scan_start(local, sdata);
	ret = local->ops->sched_scan_start(&local->hw, &sdata->vif,
					      req, ies);
	trace_drv_return_int(local, ret);
	return ret;
}

382
383
static inline int drv_sched_scan_stop(struct ieee80211_local *local,
				      struct ieee80211_sub_if_data *sdata)
384
{
385
386
	int ret;

387
388
	might_sleep();

389
390
	if (!check_sdata_in_driver(sdata))
		return -EIO;
391

392
	trace_drv_sched_scan_stop(local, sdata);
393
394
395
396
	ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif);
	trace_drv_return_int(local, ret);

	return ret;
397
398
}

399
400
401
static inline void drv_sw_scan_start(struct ieee80211_local *local,
				     struct ieee80211_sub_if_data *sdata,
				     const u8 *mac_addr)
402
{
403
404
	might_sleep();

405
	trace_drv_sw_scan_start(local, sdata, mac_addr);
406
	if (local->ops->sw_scan_start)
407
		local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr);
408
	trace_drv_return_void(local);
409
410
}

411
412
static inline void drv_sw_scan_complete(struct ieee80211_local *local,
					struct ieee80211_sub_if_data *sdata)
413
{
414
415
	might_sleep();

416
	trace_drv_sw_scan_complete(local, sdata);
417
	if (local->ops->sw_scan_complete)
418
		local->ops->sw_scan_complete(&local->hw, &sdata->vif);
419
	trace_drv_return_void(local);
420
421
422
423
424
}

static inline int drv_get_stats(struct ieee80211_local *local,
				struct ieee80211_low_level_stats *stats)
{
425
426
	int ret = -EOPNOTSUPP;

427
428
	might_sleep();

429
430
431
432
433
	if (local->ops->get_stats)
		ret = local->ops->get_stats(&local->hw, stats);
	trace_drv_get_stats(local, stats, ret);

	return ret;
434
435
}

436
437
438
static inline void drv_get_key_seq(struct ieee80211_local *local,
				   struct ieee80211_key *key,
				   struct ieee80211_key_seq *seq)
439
{
440
441
442
	if (local->ops->get_key_seq)
		local->ops->get_key_seq(&local->hw, &key->conf, seq);
	trace_drv_get_key_seq(local, &key->conf);
443
444
}

445
446
447
448
449
450
451
452
453
454
455
456
457
458
static inline int drv_set_frag_threshold(struct ieee80211_local *local,
					u32 value)
{
	int ret = 0;

	might_sleep();

	trace_drv_set_frag_threshold(local, value);
	if (local->ops->set_frag_threshold)
		ret = local->ops->set_frag_threshold(&local->hw, value);
	trace_drv_return_int(local, ret);
	return ret;
}

459
460
461
static inline int drv_set_rts_threshold(struct ieee80211_local *local,
					u32 value)
{
462
	int ret = 0;
463
464
465

	might_sleep();

466
	trace_drv_set_rts_threshold(local, value);
467
	if (local->ops->set_rts_threshold)
468
		ret = local->ops->set_rts_threshold(&local->hw, value);
469
	trace_drv_return_int(local, ret);
470
	return ret;
471
472
}

473
static inline int drv_set_coverage_class(struct ieee80211_local *local,
474
					 s16 value)
475
476
477
478
{
	int ret = 0;
	might_sleep();

479
	trace_drv_set_coverage_class(local, value);
480
481
482
483
484
	if (local->ops->set_coverage_class)
		local->ops->set_coverage_class(&local->hw, value);
	else
		ret = -EOPNOTSUPP;

485
	trace_drv_return_int(local, ret);
486
487
488
	return ret;
}

489
static inline void drv_sta_notify(struct ieee80211_local *local,
Johannes Berg's avatar
Johannes Berg committed
490
				  struct ieee80211_sub_if_data *sdata,
491
492
493
				  enum sta_notify_cmd cmd,
				  struct ieee80211_sta *sta)
{
494
	sdata = get_bss_sdata(sdata);
495
496
	if (!check_sdata_in_driver(sdata))
		return;
497

498
	trace_drv_sta_notify(local, sdata, cmd, sta);
499
	if (local->ops->sta_notify)
Johannes Berg's avatar
Johannes Berg committed
500
		local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta);
501
	trace_drv_return_void(local);
502
503
}

504
505
506
507
508
509
510
511
static inline int drv_sta_add(struct ieee80211_local *local,
			      struct ieee80211_sub_if_data *sdata,
			      struct ieee80211_sta *sta)
{
	int ret = 0;

	might_sleep();

512
	sdata = get_bss_sdata(sdata);
513
514
	if (!check_sdata_in_driver(sdata))
		return -EIO;
515

516
	trace_drv_sta_add(local, sdata, sta);
517
518
519
	if (local->ops->sta_add)
		ret = local->ops->sta_add(&local->hw, &sdata->vif, sta);

520
	trace_drv_return_int(local, ret);
521
522
523
524
525
526
527
528
529
530

	return ret;
}

static inline void drv_sta_remove(struct ieee80211_local *local,
				  struct ieee80211_sub_if_data *sdata,
				  struct ieee80211_sta *sta)
{
	might_sleep();

531
	sdata = get_bss_sdata(sdata);
532
533
	if (!check_sdata_in_driver(sdata))
		return;
534

535
	trace_drv_sta_remove(local, sdata, sta);
536
537
538
	if (local->ops->sta_remove)
		local->ops->sta_remove(&local->hw, &sdata->vif, sta);

539
	trace_drv_return_void(local);
540
541
}

542
543
544
545
546
547
548
549
550
#ifdef CONFIG_MAC80211_DEBUGFS
static inline void drv_sta_add_debugfs(struct ieee80211_local *local,
				       struct ieee80211_sub_if_data *sdata,
				       struct ieee80211_sta *sta,
				       struct dentry *dir)
{
	might_sleep();

	sdata = get_bss_sdata(sdata);
551
552
	if (!check_sdata_in_driver(sdata))
		return;
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574

	if (local->ops->sta_add_debugfs)
		local->ops->sta_add_debugfs(&local->hw, &sdata->vif,
					    sta, dir);
}

static inline void drv_sta_remove_debugfs(struct ieee80211_local *local,
					  struct ieee80211_sub_if_data *sdata,
					  struct ieee80211_sta *sta,
					  struct dentry *dir)
{
	might_sleep();

	sdata = get_bss_sdata(sdata);
	check_sdata_in_driver(sdata);

	if (local->ops->sta_remove_debugfs)
		local->ops->sta_remove_debugfs(&local->hw, &sdata->vif,
					       sta, dir);
}
#endif

575
576
577
578
579
580
581
static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local,
					  struct ieee80211_sub_if_data *sdata,
					  struct sta_info *sta)
{
	might_sleep();

	sdata = get_bss_sdata(sdata);
582
583
	if (!check_sdata_in_driver(sdata))
		return;
584
585
586
587
588
589
590
591

	trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta);
	if (local->ops->sta_pre_rcu_remove)
		local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif,
					       &sta->sta);
	trace_drv_return_void(local);
}

592
__must_check
593
594
595
596
int drv_sta_state(struct ieee80211_local *local,
		  struct ieee80211_sub_if_data *sdata,
		  struct sta_info *sta,
		  enum ieee80211_sta_state old_state,
597
		  enum ieee80211_sta_state new_state);
598

599
600
601
602
603
static inline void drv_sta_rc_update(struct ieee80211_local *local,
				     struct ieee80211_sub_if_data *sdata,
				     struct ieee80211_sta *sta, u32 changed)
{
	sdata = get_bss_sdata(sdata);
604
605
	if (!check_sdata_in_driver(sdata))
		return;
606

607
	WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED &&
608
609
		(sdata->vif.type != NL80211_IFTYPE_ADHOC &&
		 sdata->vif.type != NL80211_IFTYPE_MESH_POINT));
610

611
612
613
614
615
616
617
618
	trace_drv_sta_rc_update(local, sdata, sta, changed);
	if (local->ops->sta_rc_update)
		local->ops->sta_rc_update(&local->hw, &sdata->vif,
					  sta, changed);

	trace_drv_return_void(local);
}

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local,
					   struct ieee80211_sub_if_data *sdata,
					   struct ieee80211_sta *sta)
{
	sdata = get_bss_sdata(sdata);
	if (!check_sdata_in_driver(sdata))
		return;

	trace_drv_sta_rate_tbl_update(local, sdata, sta);
	if (local->ops->sta_rate_tbl_update)
		local->ops->sta_rate_tbl_update(&local->hw, &sdata->vif, sta);

	trace_drv_return_void(local);
}

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
static inline void drv_sta_statistics(struct ieee80211_local *local,
				      struct ieee80211_sub_if_data *sdata,
				      struct ieee80211_sta *sta,
				      struct station_info *sinfo)
{
	sdata = get_bss_sdata(sdata);
	if (!check_sdata_in_driver(sdata))
		return;

	trace_drv_sta_statistics(local, sdata, sta);
	if (local->ops->sta_statistics)
		local->ops->sta_statistics(&local->hw, &sdata->vif, sta, sinfo);
	trace_drv_return_void(local);
}

649
static inline int drv_conf_tx(struct ieee80211_local *local,
650
			      struct ieee80211_sub_if_data *sdata, u16 ac,
651
652
			      const struct ieee80211_tx_queue_params *params)
{
653
	int ret = -EOPNOTSUPP;
654
655
656

	might_sleep();

657
658
	if (!check_sdata_in_driver(sdata))
		return -EIO;
659

660
661
662
663
664
665
	if (WARN_ONCE(params->cw_min == 0 ||
		      params->cw_min > params->cw_max,
		      "%s: invalid CW_min/CW_max: %d/%d\n",
		      sdata->name, params->cw_min, params->cw_max))
		return -EINVAL;

666
	trace_drv_conf_tx(local, sdata, ac, params);
667
	if (local->ops->conf_tx)
668
		ret = local->ops->conf_tx(&local->hw, &sdata->vif,
669
					  ac, params);
670
	trace_drv_return_int(local, ret);
671
	return ret;
672
673
}

674
675
static inline u64 drv_get_tsf(struct ieee80211_local *local,
			      struct ieee80211_sub_if_data *sdata)
676
{
677
	u64 ret = -1ULL;
678
679
680

	might_sleep();

681
682
	if (!check_sdata_in_driver(sdata))
		return ret;
683

684
	trace_drv_get_tsf(local, sdata);
685
	if (local->ops->get_tsf)
686
		ret = local->ops->get_tsf(&local->hw, &sdata->vif);
687
	trace_drv_return_u64(local, ret);
688
	return ret;
689
690
}

691
692
693
static inline void drv_set_tsf(struct ieee80211_local *local,
			       struct ieee80211_sub_if_data *sdata,
			       u64 tsf)
694
{
695
696
	might_sleep();

697
698
	if (!check_sdata_in_driver(sdata))
		return;
699

700
	trace_drv_set_tsf(local, sdata, tsf);
701
	if (local->ops->set_tsf)
702
		local->ops->set_tsf(&local->hw, &sdata->vif, tsf);
703
	trace_drv_return_void(local);
704
705
}

706
707
static inline void drv_reset_tsf(struct ieee80211_local *local,
				 struct ieee80211_sub_if_data *sdata)
708
{
709
710
	might_sleep();

711
712
	if (!check_sdata_in_driver(sdata))
		return;
713

714
	trace_drv_reset_tsf(local, sdata);
715
	if (local->ops->reset_tsf)
716
		local->ops->reset_tsf(&local->hw, &sdata->vif);
717
	trace_drv_return_void(local);
718
719
720
721
}

static inline int drv_tx_last_beacon(struct ieee80211_local *local)
{
722
	int ret = 0; /* default unsupported op for less congestion */
723
724
725

	might_sleep();

726
	trace_drv_tx_last_beacon(local);
727
	if (local->ops->tx_last_beacon)
728
		ret = local->ops->tx_last_beacon(&local->hw);
729
	trace_drv_return_int(local, ret);
730
	return ret;
731
732
733
}

static inline int drv_ampdu_action(struct ieee80211_local *local,
Johannes Berg's avatar
Johannes Berg committed
734
				   struct ieee80211_sub_if_data *sdata,
735
736
				   enum ieee80211_ampdu_mlme_action action,
				   struct ieee80211_sta *sta, u16 tid,
737
				   u16 *ssn, u8 buf_size)
738
{
739
	int ret = -EOPNOTSUPP;
740
741
742

	might_sleep();

743
	sdata = get_bss_sdata(sdata);
744
745
	if (!check_sdata_in_driver(sdata))
		return -EIO;
746

747
	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
748

749
	if (local->ops->ampdu_action)
Johannes Berg's avatar
Johannes Berg committed
750
		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
751
					       sta, tid, ssn, buf_size);
752

753
754
	trace_drv_return_int(local, ret);

755
	return ret;
756
}
Johannes Berg's avatar
Johannes Berg committed
757

758
759
760
761
static inline int drv_get_survey(struct ieee80211_local *local, int idx,
				struct survey_info *survey)
{
	int ret = -EOPNOTSUPP;
762
763
764

	trace_drv_get_survey(local, idx, survey);

765
	if (local->ops->get_survey)
766
		ret = local->ops->get_survey(&local->hw, idx, survey);
767
768
769

	trace_drv_return_int(local, ret);

770
771
	return ret;
}
Johannes Berg's avatar
Johannes Berg committed
772
773
774

static inline void drv_rfkill_poll(struct ieee80211_local *local)
{
775
776
	might_sleep();

Johannes Berg's avatar
Johannes Berg committed
777
778
779
	if (local->ops->rfkill_poll)
		local->ops->rfkill_poll(&local->hw);
}
780

781
static inline void drv_flush(struct ieee80211_local *local,
782
			     struct ieee80211_sub_if_data *sdata,
783
			     u32 queues, bool drop)
784
{
785
786
	struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL;

787
788
	might_sleep();

789
790
	if (sdata && !check_sdata_in_driver(sdata))
		return;
791

792
	trace_drv_flush(local, queues, drop);
793
	if (local->ops->flush)
794
		local->ops->flush(&local->hw, vif, queues, drop);
795
	trace_drv_return_void(local);
796
}
797
798

static inline void drv_channel_switch(struct ieee80211_local *local,
799
800
				      struct ieee80211_sub_if_data *sdata,
				      struct ieee80211_channel_switch *ch_switch)
801
802
803
{
	might_sleep();

804
805
	trace_drv_channel_switch(local, sdata, ch_switch);
	local->ops->channel_switch(&local->hw, &sdata->vif, ch_switch);
806
	trace_drv_return_void(local);
807
808
}

809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831

static inline int drv_set_antenna(struct ieee80211_local *local,
				  u32 tx_ant, u32 rx_ant)
{
	int ret = -EOPNOTSUPP;
	might_sleep();
	if (local->ops->set_antenna)
		ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant);
	trace_drv_set_antenna(local, tx_ant, rx_ant, ret);
	return ret;
}

static inline int drv_get_antenna(struct ieee80211_local *local,
				  u32 *tx_ant, u32 *rx_ant)
{
	int ret = -EOPNOTSUPP;
	might_sleep();
	if (local->ops->get_antenna)
		ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant);
	trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret);
	return ret;
}

832
static inline int drv_remain_on_channel(struct ieee80211_local *local,
833
					struct ieee80211_sub_if_data *sdata,
834
					struct ieee80211_channel *chan,
835
836
					unsigned int duration,
					enum ieee80211_roc_type type)
837
838
839
840
841
{
	int ret;

	might_sleep();

842
	trace_drv_remain_on_channel(local, sdata, chan, duration, type);
843
	ret = local->ops->remain_on_channel(&local->hw, &sdata->vif,
844
					    chan, duration, type);
845
846
847
848
849
850
851
852
853
854
855
856
857
858
	trace_drv_return_int(local, ret);

	return ret;
}

static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local)
{
	int ret;

	might_sleep();

	trace_drv_cancel_remain_on_channel(local);
	ret = local->ops->cancel_remain_on_channel(&local->hw);
	trace_drv_return_int(local, ret);
859
860
861
862

	return ret;
}

863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
static inline int drv_set_ringparam(struct ieee80211_local *local,
				    u32 tx, u32 rx)
{
	int ret = -ENOTSUPP;

	might_sleep();

	trace_drv_set_ringparam(local, tx, rx);
	if (local->ops->set_ringparam)
		ret = local->ops->set_ringparam(&local->hw, tx, rx);
	trace_drv_return_int(local, ret);

	return ret;
}

static inline void drv_get_ringparam(struct ieee80211_local *local,
				     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
{
	might_sleep();

	trace_drv_get_ringparam(local, tx, tx_max, rx, rx_max);
	if (local->ops->get_ringparam)
		local->ops->get_ringparam(&local->hw, tx, tx_max, rx, rx_max);
	trace_drv_return_void(local);
}

889
890
891
892
893
894
895
896
897
898
899
900
901
static inline bool drv_tx_frames_pending(struct ieee80211_local *local)
{
	bool ret = false;

	might_sleep();

	trace_drv_tx_frames_pending(local);
	if (local->ops->tx_frames_pending)
		ret = local->ops->tx_frames_pending(&local->hw);
	trace_drv_return_bool(local, ret);

	return ret;
}
902
903
904
905
906
907
908
909
910

static inline int drv_set_bitrate_mask(struct ieee80211_local *local,
				       struct ieee80211_sub_if_data *sdata,
				       const struct cfg80211_bitrate_mask *mask)
{
	int ret = -EOPNOTSUPP;

	might_sleep();

911
912
	if (!check_sdata_in_driver(sdata))
		return -EIO;
913

914
915
916
917
918
919
920
921
922
	trace_drv_set_bitrate_mask(local, sdata, mask);
	if (local->ops->set_bitrate_mask)
		ret = local->ops->set_bitrate_mask(&local->hw,
						   &sdata->vif, mask);
	trace_drv_return_int(local, ret);

	return ret;
}

923
924
925
926
static inline void drv_set_rekey_data(struct ieee80211_local *local,
				      struct ieee80211_sub_if_data *sdata,
				      struct cfg80211_gtk_rekey_data *data)
{
927
928
	if (!check_sdata_in_driver(sdata))
		return;
929

930
931
932
933
934
935
	trace_drv_set_rekey_data(local, sdata, data);
	if (local->ops->set_rekey_data)
		local->ops->set_rekey_data(&local->hw, &sdata->vif, data);
	trace_drv_return_void(local);
}

936
937
938
static inline void drv_event_callback(struct ieee80211_local *local,
				      struct ieee80211_sub_if_data *sdata,
				      const struct ieee80211_event *event)
939
{
940
941
942
	trace_drv_event_callback(local, sdata, event);
	if (local->ops->event_callback)
		local->ops->event_callback(&local->hw, &sdata->vif, event);
943
944
	trace_drv_return_void(local);
}
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

static inline void
drv_release_buffered_frames(struct ieee80211_local *local,
			    struct sta_info *sta, u16 tids, int num_frames,
			    enum ieee80211_frame_release_type reason,
			    bool more_data)
{
	trace_drv_release_buffered_frames(local, &sta->sta, tids, num_frames,
					  reason, more_data);
	if (local->ops->release_buffered_frames)
		local->ops->release_buffered_frames(&local->hw, &sta->sta, tids,
						    num_frames, reason,
						    more_data);
	trace_drv_return_void(local);
}
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974

static inline void
drv_allow_buffered_frames(struct ieee80211_local *local,
			  struct sta_info *sta, u16 tids, int num_frames,
			  enum ieee80211_frame_release_type reason,
			  bool more_data)
{
	trace_drv_allow_buffered_frames(local, &sta->sta, tids, num_frames,
					reason, more_data);
	if (local->ops->allow_buffered_frames)
		local->ops->allow_buffered_frames(&local->hw, &sta->sta,
						  tids, num_frames, reason,
						  more_data);
	trace_drv_return_void(local);
}
975

Johannes Berg's avatar
Johannes Berg committed
976
977
978
979
980
static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
				      struct ieee80211_sub_if_data *sdata)
{
	might_sleep();

981
982
	if (!check_sdata_in_driver(sdata))
		return;
Johannes Berg's avatar
Johannes Berg committed
983
984
985
986
987
988
989
	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);

	trace_drv_mgd_prepare_tx(local, sdata);
	if (local->ops->mgd_prepare_tx)
		local->ops->mgd_prepare_tx(&local->hw, &sdata->vif);
	trace_drv_return_void(local);
}
990

991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
static inline void
drv_mgd_protect_tdls_discover(struct ieee80211_local *local,
			      struct ieee80211_sub_if_data *sdata)
{
	might_sleep();

	if (!check_sdata_in_driver(sdata))
		return;
	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);

	trace_drv_mgd_protect_tdls_discover(local, sdata);
	if (local->ops->mgd_protect_tdls_discover)
		local->ops->mgd_protect_tdls_discover(&local->hw, &sdata->vif);
	trace_drv_return_void(local);
}

1007
1008
1009
1010
1011
1012
1013
1014
1015
static inline int drv_add_chanctx(struct ieee80211_local *local,
				  struct ieee80211_chanctx *ctx)
{
	int ret = -EOPNOTSUPP;

	trace_drv_add_chanctx(local, ctx);
	if (local->ops->add_chanctx)
		ret = local->ops->add_chanctx(&local->hw, &ctx->conf);
	trace_drv_return_int(local, ret);
1016
1017
	if (!ret)
		ctx->driver_present = true;
1018
1019
1020
1021
1022
1023
1024

	return ret;
}

static inline void drv_remove_chanctx(struct ieee80211_local *local,
				      struct ieee80211_chanctx *ctx)
{
1025
1026
1027
	if (WARN_ON(!ctx->driver_present))
		return;

1028
1029
1030
1031
	trace_drv_remove_chanctx(local, ctx);
	if (local->ops->remove_chanctx)
		local->ops->remove_chanctx(&local->hw, &ctx->conf);
	trace_drv_return_void(local);
1032
	ctx->driver_present = false;
1033
1034
1035
1036
1037
1038
1039
}

static inline void drv_change_chanctx(struct ieee80211_local *local,
				      struct ieee80211_chanctx *ctx,
				      u32 changed)
{
	trace_drv_change_chanctx(local, ctx, changed);
1040
1041
	if (local->ops->change_chanctx) {
		WARN_ON_ONCE(!ctx->driver_present);
1042
		local->ops->change_chanctx(&local->hw, &ctx->conf, changed);
1043
	}
1044
1045
1046
1047
1048
1049
1050
1051
1052
	trace_drv_return_void(local);
}

static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
					 struct ieee80211_sub_if_data *sdata,
					 struct ieee80211_chanctx *ctx)
{
	int ret = 0;

1053
1054
	if (!check_sdata_in_driver(sdata))
		return -EIO;
1055
1056

	trace_drv_assign_vif_chanctx(local, sdata, ctx);
1057
1058
	if (local->ops->assign_vif_chanctx) {
		WARN_ON_ONCE(!ctx->driver_present);
1059
1060
1061
		ret = local->ops->assign_vif_chanctx(&local->hw,
						     &sdata->vif,
						     &ctx->conf);
1062
	}
1063
1064
1065
1066
1067
1068
1069
1070
1071
	trace_drv_return_int(local, ret);

	return ret;
}

static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
					    struct ieee80211_sub_if_data *sdata,
					    struct ieee80211_chanctx *ctx)
{
1072
1073
	if (!check_sdata_in_driver(sdata))
		return;
1074
1075

	trace_drv_unassign_vif_chanctx(local, sdata, ctx);
1076
1077
	if (local->ops->unassign_vif_chanctx) {
		WARN_ON_ONCE(!ctx->driver_present);
1078
1079
1080
		local->ops->unassign_vif_chanctx(&local->hw,
						 &sdata->vif,
						 &ctx->conf);
1081
	}
1082
1083
1084
	trace_drv_return_void(local);
}

1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
static inline int
drv_switch_vif_chanctx(struct ieee80211_local *local,
		       struct ieee80211_vif_chanctx_switch *vifs,
		       int n_vifs,
		       enum ieee80211_chanctx_switch_mode mode)
{
	int ret = 0;
	int i;

	if (!local->ops->switch_vif_chanctx)
		return -EOPNOTSUPP;

	for (i = 0; i < n_vifs; i++) {
		struct ieee80211_chanctx *new_ctx =
			container_of(vifs[i].new_ctx,
				     struct ieee80211_chanctx,
				     conf);
		struct ieee80211_chanctx *old_ctx =
			container_of(vifs[i].old_ctx,
				     struct ieee80211_chanctx,
				     conf);

		WARN_ON_ONCE(!old_ctx->driver_present);
		WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS &&
			      new_ctx->driver_present) ||
			     (mode == CHANCTX_SWMODE_REASSIGN_VIF &&
			      !new_ctx->driver_present));
	}

	trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode);
	ret = local->ops->switch_vif_chanctx(&local->hw,
					     vifs, n_vifs, mode);
	trace_drv_return_int(local, ret);

	if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
		for (i = 0; i < n_vifs; i++) {
			struct ieee80211_chanctx *new_ctx =
				container_of(vifs[i].new_ctx,
					     struct ieee80211_chanctx,
					     conf);
			struct ieee80211_chanctx *old_ctx =
				container_of(vifs[i].old_ctx,
					     struct ieee80211_chanctx,
					     conf);

			new_ctx->driver_present = true;
			old_ctx->driver_present = false;
		}
	}

	return ret;
}

1138
1139
1140
1141
1142
static inline int drv_start_ap(struct ieee80211_local *local,
			       struct ieee80211_sub_if_data *sdata)
{
	int ret = 0;

1143
1144
	if (!check_sdata_in_driver(sdata))
		return -EIO;
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155

	trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf);
	if (local->ops->start_ap)
		ret = local->ops->start_ap(&local->hw, &sdata->vif);
	trace_drv_return_int(local, ret);
	return ret;
}

static inline void drv_stop_ap(struct ieee80211_local *local,
			       struct ieee80211_sub_if_data *sdata)
{
1156
1157
	if (!check_sdata_in_driver(sdata))
		return;
1158
1159
1160
1161
1162
1163
1164

	trace_drv_stop_ap(local, sdata);
	if (local->ops->stop_ap)
		local->ops->stop_ap(&local->hw, &sdata->vif);
	trace_drv_return_void(local);
}

1165
1166
1167
static inline void
drv_reconfig_complete(struct ieee80211_local *local,
		      enum ieee80211_reconfig_type reconfig_type)
1168
1169
1170
{
	might_sleep();

1171
1172
1173
	trace_drv_reconfig_complete(local, reconfig_type);
	if (local->ops->reconfig_complete)
		local->ops->reconfig_complete(&local->hw, reconfig_type);