1#ifndef __MAC80211_DRIVER_OPS
2#define __MAC80211_DRIVER_OPS
3
4#include <net/mac80211.h>
5#include "ieee80211_i.h"
6#include "trace.h"
7
8static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata)
9{
10	return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER),
11		     "%s:  Failed check-sdata-in-driver check, flags: 0x%x\n",
12		     sdata->dev ? sdata->dev->name : sdata->name, sdata->flags);
13}
14
15static inline struct ieee80211_sub_if_data *
16get_bss_sdata(struct ieee80211_sub_if_data *sdata)
17{
18	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
19		sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
20				     u.ap);
21
22	return sdata;
23}
24
25static inline void drv_tx(struct ieee80211_local *local,
26			  struct ieee80211_tx_control *control,
27			  struct sk_buff *skb)
28{
29	local->ops->tx(&local->hw, control, skb);
30}
31
32static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata,
33				      u32 sset, u8 *data)
34{
35	struct ieee80211_local *local = sdata->local;
36	if (local->ops->get_et_strings) {
37		trace_drv_get_et_strings(local, sset);
38		local->ops->get_et_strings(&local->hw, &sdata->vif, sset, data);
39		trace_drv_return_void(local);
40	}
41}
42
43static inline void drv_get_et_stats(struct ieee80211_sub_if_data *sdata,
44				    struct ethtool_stats *stats,
45				    u64 *data)
46{
47	struct ieee80211_local *local = sdata->local;
48	if (local->ops->get_et_stats) {
49		trace_drv_get_et_stats(local);
50		local->ops->get_et_stats(&local->hw, &sdata->vif, stats, data);
51		trace_drv_return_void(local);
52	}
53}
54
55static inline int drv_get_et_sset_count(struct ieee80211_sub_if_data *sdata,
56					int sset)
57{
58	struct ieee80211_local *local = sdata->local;
59	int rv = 0;
60	if (local->ops->get_et_sset_count) {
61		trace_drv_get_et_sset_count(local, sset);
62		rv = local->ops->get_et_sset_count(&local->hw, &sdata->vif,
63						   sset);
64		trace_drv_return_int(local, rv);
65	}
66	return rv;
67}
68
69static inline int drv_start(struct ieee80211_local *local)
70{
71	int ret;
72
73	might_sleep();
74
75	trace_drv_start(local);
76	local->started = true;
77	smp_mb();
78	ret = local->ops->start(&local->hw);
79	trace_drv_return_int(local, ret);
80	return ret;
81}
82
83static inline void drv_stop(struct ieee80211_local *local)
84{
85	might_sleep();
86
87	trace_drv_stop(local);
88	local->ops->stop(&local->hw);
89	trace_drv_return_void(local);
90
91	/* sync away all work on the tasklet before clearing started */
92	tasklet_disable(&local->tasklet);
93	tasklet_enable(&local->tasklet);
94
95	barrier();
96
97	local->started = false;
98}
99
100#ifdef CONFIG_PM
101static inline int drv_suspend(struct ieee80211_local *local,
102			      struct cfg80211_wowlan *wowlan)
103{
104	int ret;
105
106	might_sleep();
107
108	trace_drv_suspend(local);
109	ret = local->ops->suspend(&local->hw, wowlan);
110	trace_drv_return_int(local, ret);
111	return ret;
112}
113
114static inline int drv_resume(struct ieee80211_local *local)
115{
116	int ret;
117
118	might_sleep();
119
120	trace_drv_resume(local);
121	ret = local->ops->resume(&local->hw);
122	trace_drv_return_int(local, ret);
123	return ret;
124}
125
126static inline void drv_set_wakeup(struct ieee80211_local *local,
127				  bool enabled)
128{
129	might_sleep();
130
131	if (!local->ops->set_wakeup)
132		return;
133
134	trace_drv_set_wakeup(local, enabled);
135	local->ops->set_wakeup(&local->hw, enabled);
136	trace_drv_return_void(local);
137}
138#endif
139
140static inline int drv_add_interface(struct ieee80211_local *local,
141				    struct ieee80211_sub_if_data *sdata)
142{
143	int ret;
144
145	might_sleep();
146
147	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
148		    (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
149		     !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF) &&
150		     !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))))
151		return -EINVAL;
152
153	trace_drv_add_interface(local, sdata);
154	ret = local->ops->add_interface(&local->hw, &sdata->vif);
155	trace_drv_return_int(local, ret);
156
157	if (ret == 0)
158		sdata->flags |= IEEE80211_SDATA_IN_DRIVER;
159
160	return ret;
161}
162
163static inline int drv_change_interface(struct ieee80211_local *local,
164				       struct ieee80211_sub_if_data *sdata,
165				       enum nl80211_iftype type, bool p2p)
166{
167	int ret;
168
169	might_sleep();
170
171	if (!check_sdata_in_driver(sdata))
172		return -EIO;
173
174	trace_drv_change_interface(local, sdata, type, p2p);
175	ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p);
176	trace_drv_return_int(local, ret);
177	return ret;
178}
179
180static inline void drv_remove_interface(struct ieee80211_local *local,
181					struct ieee80211_sub_if_data *sdata)
182{
183	might_sleep();
184
185	if (!check_sdata_in_driver(sdata))
186		return;
187
188	trace_drv_remove_interface(local, sdata);
189	local->ops->remove_interface(&local->hw, &sdata->vif);
190	sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
191	trace_drv_return_void(local);
192}
193
194static inline int drv_config(struct ieee80211_local *local, u32 changed)
195{
196	int ret;
197
198	might_sleep();
199
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
206static inline void drv_bss_info_changed(struct ieee80211_local *local,
207					struct ieee80211_sub_if_data *sdata,
208					struct ieee80211_bss_conf *info,
209					u32 changed)
210{
211	might_sleep();
212
213	if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON |
214				    BSS_CHANGED_BEACON_ENABLED) &&
215			 sdata->vif.type != NL80211_IFTYPE_AP &&
216			 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
217			 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
218			 sdata->vif.type != NL80211_IFTYPE_OCB))
219		return;
220
221	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
222			 sdata->vif.type == NL80211_IFTYPE_MONITOR))
223		return;
224
225	if (!check_sdata_in_driver(sdata))
226		return;
227
228	trace_drv_bss_info_changed(local, sdata, info, changed);
229	if (local->ops->bss_info_changed)
230		local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
231	trace_drv_return_void(local);
232}
233
234static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
235					struct netdev_hw_addr_list *mc_list)
236{
237	u64 ret = 0;
238
239	trace_drv_prepare_multicast(local, mc_list->count);
240
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	return ret;
247}
248
249static inline void drv_configure_filter(struct ieee80211_local *local,
250					unsigned int changed_flags,
251					unsigned int *total_flags,
252					u64 multicast)
253{
254	might_sleep();
255
256	trace_drv_configure_filter(local, changed_flags, total_flags,
257				   multicast);
258	local->ops->configure_filter(&local->hw, changed_flags, total_flags,
259				     multicast);
260	trace_drv_return_void(local);
261}
262
263static inline int drv_set_tim(struct ieee80211_local *local,
264			      struct ieee80211_sta *sta, bool set)
265{
266	int ret = 0;
267	trace_drv_set_tim(local, sta, set);
268	if (local->ops->set_tim)
269		ret = local->ops->set_tim(&local->hw, sta, set);
270	trace_drv_return_int(local, ret);
271	return ret;
272}
273
274static inline int drv_set_key(struct ieee80211_local *local,
275			      enum set_key_cmd cmd,
276			      struct ieee80211_sub_if_data *sdata,
277			      struct ieee80211_sta *sta,
278			      struct ieee80211_key_conf *key)
279{
280	int ret;
281
282	might_sleep();
283
284	sdata = get_bss_sdata(sdata);
285	if (!check_sdata_in_driver(sdata))
286		return -EIO;
287
288	trace_drv_set_key(local, cmd, sdata, sta, key);
289	ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key);
290	trace_drv_return_int(local, ret);
291	return ret;
292}
293
294static inline void drv_update_tkip_key(struct ieee80211_local *local,
295				       struct ieee80211_sub_if_data *sdata,
296				       struct ieee80211_key_conf *conf,
297				       struct sta_info *sta, u32 iv32,
298				       u16 *phase1key)
299{
300	struct ieee80211_sta *ista = NULL;
301
302	if (sta)
303		ista = &sta->sta;
304
305	sdata = get_bss_sdata(sdata);
306	if (!check_sdata_in_driver(sdata))
307		return;
308
309	trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
310	if (local->ops->update_tkip_key)
311		local->ops->update_tkip_key(&local->hw, &sdata->vif, conf,
312					    ista, iv32, phase1key);
313	trace_drv_return_void(local);
314}
315
316static inline int drv_hw_scan(struct ieee80211_local *local,
317			      struct ieee80211_sub_if_data *sdata,
318			      struct ieee80211_scan_request *req)
319{
320	int ret;
321
322	might_sleep();
323
324	if (!check_sdata_in_driver(sdata))
325		return -EIO;
326
327	trace_drv_hw_scan(local, sdata);
328	ret = local->ops->hw_scan(&local->hw, &sdata->vif, req);
329	trace_drv_return_int(local, ret);
330	return ret;
331}
332
333static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
334				      struct ieee80211_sub_if_data *sdata)
335{
336	might_sleep();
337
338	if (!check_sdata_in_driver(sdata))
339		return;
340
341	trace_drv_cancel_hw_scan(local, sdata);
342	local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
343	trace_drv_return_void(local);
344}
345
346static inline int
347drv_sched_scan_start(struct ieee80211_local *local,
348		     struct ieee80211_sub_if_data *sdata,
349		     struct cfg80211_sched_scan_request *req,
350		     struct ieee80211_scan_ies *ies)
351{
352	int ret;
353
354	might_sleep();
355
356	if (!check_sdata_in_driver(sdata))
357		return -EIO;
358
359	trace_drv_sched_scan_start(local, sdata);
360	ret = local->ops->sched_scan_start(&local->hw, &sdata->vif,
361					      req, ies);
362	trace_drv_return_int(local, ret);
363	return ret;
364}
365
366static inline int drv_sched_scan_stop(struct ieee80211_local *local,
367				      struct ieee80211_sub_if_data *sdata)
368{
369	int ret;
370
371	might_sleep();
372
373	if (!check_sdata_in_driver(sdata))
374		return -EIO;
375
376	trace_drv_sched_scan_stop(local, sdata);
377	ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif);
378	trace_drv_return_int(local, ret);
379
380	return ret;
381}
382
383static inline void drv_sw_scan_start(struct ieee80211_local *local,
384				     struct ieee80211_sub_if_data *sdata,
385				     const u8 *mac_addr)
386{
387	might_sleep();
388
389	trace_drv_sw_scan_start(local, sdata, mac_addr);
390	if (local->ops->sw_scan_start)
391		local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr);
392	trace_drv_return_void(local);
393}
394
395static inline void drv_sw_scan_complete(struct ieee80211_local *local,
396					struct ieee80211_sub_if_data *sdata)
397{
398	might_sleep();
399
400	trace_drv_sw_scan_complete(local, sdata);
401	if (local->ops->sw_scan_complete)
402		local->ops->sw_scan_complete(&local->hw, &sdata->vif);
403	trace_drv_return_void(local);
404}
405
406static inline int drv_get_stats(struct ieee80211_local *local,
407				struct ieee80211_low_level_stats *stats)
408{
409	int ret = -EOPNOTSUPP;
410
411	might_sleep();
412
413	if (local->ops->get_stats)
414		ret = local->ops->get_stats(&local->hw, stats);
415	trace_drv_get_stats(local, stats, ret);
416
417	return ret;
418}
419
420static inline void drv_get_tkip_seq(struct ieee80211_local *local,
421				    u8 hw_key_idx, u32 *iv32, u16 *iv16)
422{
423	if (local->ops->get_tkip_seq)
424		local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16);
425	trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16);
426}
427
428static inline int drv_set_frag_threshold(struct ieee80211_local *local,
429					u32 value)
430{
431	int ret = 0;
432
433	might_sleep();
434
435	trace_drv_set_frag_threshold(local, value);
436	if (local->ops->set_frag_threshold)
437		ret = local->ops->set_frag_threshold(&local->hw, value);
438	trace_drv_return_int(local, ret);
439	return ret;
440}
441
442static inline int drv_set_rts_threshold(struct ieee80211_local *local,
443					u32 value)
444{
445	int ret = 0;
446
447	might_sleep();
448
449	trace_drv_set_rts_threshold(local, value);
450	if (local->ops->set_rts_threshold)
451		ret = local->ops->set_rts_threshold(&local->hw, value);
452	trace_drv_return_int(local, ret);
453	return ret;
454}
455
456static inline int drv_set_coverage_class(struct ieee80211_local *local,
457					 s16 value)
458{
459	int ret = 0;
460	might_sleep();
461
462	trace_drv_set_coverage_class(local, value);
463	if (local->ops->set_coverage_class)
464		local->ops->set_coverage_class(&local->hw, value);
465	else
466		ret = -EOPNOTSUPP;
467
468	trace_drv_return_int(local, ret);
469	return ret;
470}
471
472static inline void drv_sta_notify(struct ieee80211_local *local,
473				  struct ieee80211_sub_if_data *sdata,
474				  enum sta_notify_cmd cmd,
475				  struct ieee80211_sta *sta)
476{
477	sdata = get_bss_sdata(sdata);
478	if (!check_sdata_in_driver(sdata))
479		return;
480
481	trace_drv_sta_notify(local, sdata, cmd, sta);
482	if (local->ops->sta_notify)
483		local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta);
484	trace_drv_return_void(local);
485}
486
487static inline int drv_sta_add(struct ieee80211_local *local,
488			      struct ieee80211_sub_if_data *sdata,
489			      struct ieee80211_sta *sta)
490{
491	int ret = 0;
492
493	might_sleep();
494
495	sdata = get_bss_sdata(sdata);
496	if (!check_sdata_in_driver(sdata))
497		return -EIO;
498
499	trace_drv_sta_add(local, sdata, sta);
500	if (local->ops->sta_add)
501		ret = local->ops->sta_add(&local->hw, &sdata->vif, sta);
502
503	trace_drv_return_int(local, ret);
504
505	return ret;
506}
507
508static inline void drv_sta_remove(struct ieee80211_local *local,
509				  struct ieee80211_sub_if_data *sdata,
510				  struct ieee80211_sta *sta)
511{
512	might_sleep();
513
514	sdata = get_bss_sdata(sdata);
515	if (!check_sdata_in_driver(sdata))
516		return;
517
518	trace_drv_sta_remove(local, sdata, sta);
519	if (local->ops->sta_remove)
520		local->ops->sta_remove(&local->hw, &sdata->vif, sta);
521
522	trace_drv_return_void(local);
523}
524
525#ifdef CONFIG_MAC80211_DEBUGFS
526static inline void drv_sta_add_debugfs(struct ieee80211_local *local,
527				       struct ieee80211_sub_if_data *sdata,
528				       struct ieee80211_sta *sta,
529				       struct dentry *dir)
530{
531	might_sleep();
532
533	sdata = get_bss_sdata(sdata);
534	if (!check_sdata_in_driver(sdata))
535		return;
536
537	if (local->ops->sta_add_debugfs)
538		local->ops->sta_add_debugfs(&local->hw, &sdata->vif,
539					    sta, dir);
540}
541
542static inline void drv_sta_remove_debugfs(struct ieee80211_local *local,
543					  struct ieee80211_sub_if_data *sdata,
544					  struct ieee80211_sta *sta,
545					  struct dentry *dir)
546{
547	might_sleep();
548
549	sdata = get_bss_sdata(sdata);
550	check_sdata_in_driver(sdata);
551
552	if (local->ops->sta_remove_debugfs)
553		local->ops->sta_remove_debugfs(&local->hw, &sdata->vif,
554					       sta, dir);
555}
556#endif
557
558static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local,
559					  struct ieee80211_sub_if_data *sdata,
560					  struct sta_info *sta)
561{
562	might_sleep();
563
564	sdata = get_bss_sdata(sdata);
565	if (!check_sdata_in_driver(sdata))
566		return;
567
568	trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta);
569	if (local->ops->sta_pre_rcu_remove)
570		local->ops->sta_pre_rcu_remove(&local->hw, &sdata->vif,
571					       &sta->sta);
572	trace_drv_return_void(local);
573}
574
575static inline __must_check
576int drv_sta_state(struct ieee80211_local *local,
577		  struct ieee80211_sub_if_data *sdata,
578		  struct sta_info *sta,
579		  enum ieee80211_sta_state old_state,
580		  enum ieee80211_sta_state new_state)
581{
582	int ret = 0;
583
584	might_sleep();
585
586	sdata = get_bss_sdata(sdata);
587	if (!check_sdata_in_driver(sdata))
588		return -EIO;
589
590	trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
591	if (local->ops->sta_state) {
592		ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
593					    old_state, new_state);
594	} else if (old_state == IEEE80211_STA_AUTH &&
595		   new_state == IEEE80211_STA_ASSOC) {
596		ret = drv_sta_add(local, sdata, &sta->sta);
597		if (ret == 0)
598			sta->uploaded = true;
599	} else if (old_state == IEEE80211_STA_ASSOC &&
600		   new_state == IEEE80211_STA_AUTH) {
601		drv_sta_remove(local, sdata, &sta->sta);
602	}
603	trace_drv_return_int(local, ret);
604	return ret;
605}
606
607static inline void drv_sta_rc_update(struct ieee80211_local *local,
608				     struct ieee80211_sub_if_data *sdata,
609				     struct ieee80211_sta *sta, u32 changed)
610{
611	sdata = get_bss_sdata(sdata);
612	if (!check_sdata_in_driver(sdata))
613		return;
614
615	WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED &&
616		(sdata->vif.type != NL80211_IFTYPE_ADHOC &&
617		 sdata->vif.type != NL80211_IFTYPE_MESH_POINT));
618
619	trace_drv_sta_rc_update(local, sdata, sta, changed);
620	if (local->ops->sta_rc_update)
621		local->ops->sta_rc_update(&local->hw, &sdata->vif,
622					  sta, changed);
623
624	trace_drv_return_void(local);
625}
626
627static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local,
628					   struct ieee80211_sub_if_data *sdata,
629					   struct ieee80211_sta *sta)
630{
631	sdata = get_bss_sdata(sdata);
632	if (!check_sdata_in_driver(sdata))
633		return;
634
635	trace_drv_sta_rate_tbl_update(local, sdata, sta);
636	if (local->ops->sta_rate_tbl_update)
637		local->ops->sta_rate_tbl_update(&local->hw, &sdata->vif, sta);
638
639	trace_drv_return_void(local);
640}
641
642static inline void drv_sta_statistics(struct ieee80211_local *local,
643				      struct ieee80211_sub_if_data *sdata,
644				      struct ieee80211_sta *sta,
645				      struct station_info *sinfo)
646{
647	sdata = get_bss_sdata(sdata);
648	if (!check_sdata_in_driver(sdata))
649		return;
650
651	trace_drv_sta_statistics(local, sdata, sta);
652	if (local->ops->sta_statistics)
653		local->ops->sta_statistics(&local->hw, &sdata->vif, sta, sinfo);
654	trace_drv_return_void(local);
655}
656
657static inline int drv_conf_tx(struct ieee80211_local *local,
658			      struct ieee80211_sub_if_data *sdata, u16 ac,
659			      const struct ieee80211_tx_queue_params *params)
660{
661	int ret = -EOPNOTSUPP;
662
663	might_sleep();
664
665	if (!check_sdata_in_driver(sdata))
666		return -EIO;
667
668	if (WARN_ONCE(params->cw_min == 0 ||
669		      params->cw_min > params->cw_max,
670		      "%s: invalid CW_min/CW_max: %d/%d\n",
671		      sdata->name, params->cw_min, params->cw_max))
672		return -EINVAL;
673
674	trace_drv_conf_tx(local, sdata, ac, params);
675	if (local->ops->conf_tx)
676		ret = local->ops->conf_tx(&local->hw, &sdata->vif,
677					  ac, params);
678	trace_drv_return_int(local, ret);
679	return ret;
680}
681
682static inline u64 drv_get_tsf(struct ieee80211_local *local,
683			      struct ieee80211_sub_if_data *sdata)
684{
685	u64 ret = -1ULL;
686
687	might_sleep();
688
689	if (!check_sdata_in_driver(sdata))
690		return ret;
691
692	trace_drv_get_tsf(local, sdata);
693	if (local->ops->get_tsf)
694		ret = local->ops->get_tsf(&local->hw, &sdata->vif);
695	trace_drv_return_u64(local, ret);
696	return ret;
697}
698
699static inline void drv_set_tsf(struct ieee80211_local *local,
700			       struct ieee80211_sub_if_data *sdata,
701			       u64 tsf)
702{
703	might_sleep();
704
705	if (!check_sdata_in_driver(sdata))
706		return;
707
708	trace_drv_set_tsf(local, sdata, tsf);
709	if (local->ops->set_tsf)
710		local->ops->set_tsf(&local->hw, &sdata->vif, tsf);
711	trace_drv_return_void(local);
712}
713
714static inline void drv_reset_tsf(struct ieee80211_local *local,
715				 struct ieee80211_sub_if_data *sdata)
716{
717	might_sleep();
718
719	if (!check_sdata_in_driver(sdata))
720		return;
721
722	trace_drv_reset_tsf(local, sdata);
723	if (local->ops->reset_tsf)
724		local->ops->reset_tsf(&local->hw, &sdata->vif);
725	trace_drv_return_void(local);
726}
727
728static inline int drv_tx_last_beacon(struct ieee80211_local *local)
729{
730	int ret = 0; /* default unsupported op for less congestion */
731
732	might_sleep();
733
734	trace_drv_tx_last_beacon(local);
735	if (local->ops->tx_last_beacon)
736		ret = local->ops->tx_last_beacon(&local->hw);
737	trace_drv_return_int(local, ret);
738	return ret;
739}
740
741static inline int drv_ampdu_action(struct ieee80211_local *local,
742				   struct ieee80211_sub_if_data *sdata,
743				   enum ieee80211_ampdu_mlme_action action,
744				   struct ieee80211_sta *sta, u16 tid,
745				   u16 *ssn, u8 buf_size)
746{
747	int ret = -EOPNOTSUPP;
748
749	might_sleep();
750
751	sdata = get_bss_sdata(sdata);
752	if (!check_sdata_in_driver(sdata))
753		return -EIO;
754
755	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
756
757	if (local->ops->ampdu_action)
758		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
759					       sta, tid, ssn, buf_size);
760
761	trace_drv_return_int(local, ret);
762
763	return ret;
764}
765
766static inline int drv_get_survey(struct ieee80211_local *local, int idx,
767				struct survey_info *survey)
768{
769	int ret = -EOPNOTSUPP;
770
771	trace_drv_get_survey(local, idx, survey);
772
773	if (local->ops->get_survey)
774		ret = local->ops->get_survey(&local->hw, idx, survey);
775
776	trace_drv_return_int(local, ret);
777
778	return ret;
779}
780
781static inline void drv_rfkill_poll(struct ieee80211_local *local)
782{
783	might_sleep();
784
785	if (local->ops->rfkill_poll)
786		local->ops->rfkill_poll(&local->hw);
787}
788
789static inline void drv_flush(struct ieee80211_local *local,
790			     struct ieee80211_sub_if_data *sdata,
791			     u32 queues, bool drop)
792{
793	struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL;
794
795	might_sleep();
796
797	if (sdata && !check_sdata_in_driver(sdata))
798		return;
799
800	trace_drv_flush(local, queues, drop);
801	if (local->ops->flush)
802		local->ops->flush(&local->hw, vif, queues, drop);
803	trace_drv_return_void(local);
804}
805
806static inline void drv_channel_switch(struct ieee80211_local *local,
807				      struct ieee80211_sub_if_data *sdata,
808				      struct ieee80211_channel_switch *ch_switch)
809{
810	might_sleep();
811
812	trace_drv_channel_switch(local, sdata, ch_switch);
813	local->ops->channel_switch(&local->hw, &sdata->vif, ch_switch);
814	trace_drv_return_void(local);
815}
816
817
818static inline int drv_set_antenna(struct ieee80211_local *local,
819				  u32 tx_ant, u32 rx_ant)
820{
821	int ret = -EOPNOTSUPP;
822	might_sleep();
823	if (local->ops->set_antenna)
824		ret = local->ops->set_antenna(&local->hw, tx_ant, rx_ant);
825	trace_drv_set_antenna(local, tx_ant, rx_ant, ret);
826	return ret;
827}
828
829static inline int drv_get_antenna(struct ieee80211_local *local,
830				  u32 *tx_ant, u32 *rx_ant)
831{
832	int ret = -EOPNOTSUPP;
833	might_sleep();
834	if (local->ops->get_antenna)
835		ret = local->ops->get_antenna(&local->hw, tx_ant, rx_ant);
836	trace_drv_get_antenna(local, *tx_ant, *rx_ant, ret);
837	return ret;
838}
839
840static inline int drv_remain_on_channel(struct ieee80211_local *local,
841					struct ieee80211_sub_if_data *sdata,
842					struct ieee80211_channel *chan,
843					unsigned int duration,
844					enum ieee80211_roc_type type)
845{
846	int ret;
847
848	might_sleep();
849
850	trace_drv_remain_on_channel(local, sdata, chan, duration, type);
851	ret = local->ops->remain_on_channel(&local->hw, &sdata->vif,
852					    chan, duration, type);
853	trace_drv_return_int(local, ret);
854
855	return ret;
856}
857
858static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local)
859{
860	int ret;
861
862	might_sleep();
863
864	trace_drv_cancel_remain_on_channel(local);
865	ret = local->ops->cancel_remain_on_channel(&local->hw);
866	trace_drv_return_int(local, ret);
867
868	return ret;
869}
870
871static inline int drv_set_ringparam(struct ieee80211_local *local,
872				    u32 tx, u32 rx)
873{
874	int ret = -ENOTSUPP;
875
876	might_sleep();
877
878	trace_drv_set_ringparam(local, tx, rx);
879	if (local->ops->set_ringparam)
880		ret = local->ops->set_ringparam(&local->hw, tx, rx);
881	trace_drv_return_int(local, ret);
882
883	return ret;
884}
885
886static inline void drv_get_ringparam(struct ieee80211_local *local,
887				     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
888{
889	might_sleep();
890
891	trace_drv_get_ringparam(local, tx, tx_max, rx, rx_max);
892	if (local->ops->get_ringparam)
893		local->ops->get_ringparam(&local->hw, tx, tx_max, rx, rx_max);
894	trace_drv_return_void(local);
895}
896
897static inline bool drv_tx_frames_pending(struct ieee80211_local *local)
898{
899	bool ret = false;
900
901	might_sleep();
902
903	trace_drv_tx_frames_pending(local);
904	if (local->ops->tx_frames_pending)
905		ret = local->ops->tx_frames_pending(&local->hw);
906	trace_drv_return_bool(local, ret);
907
908	return ret;
909}
910
911static inline int drv_set_bitrate_mask(struct ieee80211_local *local,
912				       struct ieee80211_sub_if_data *sdata,
913				       const struct cfg80211_bitrate_mask *mask)
914{
915	int ret = -EOPNOTSUPP;
916
917	might_sleep();
918
919	if (!check_sdata_in_driver(sdata))
920		return -EIO;
921
922	trace_drv_set_bitrate_mask(local, sdata, mask);
923	if (local->ops->set_bitrate_mask)
924		ret = local->ops->set_bitrate_mask(&local->hw,
925						   &sdata->vif, mask);
926	trace_drv_return_int(local, ret);
927
928	return ret;
929}
930
931static inline void drv_set_rekey_data(struct ieee80211_local *local,
932				      struct ieee80211_sub_if_data *sdata,
933				      struct cfg80211_gtk_rekey_data *data)
934{
935	if (!check_sdata_in_driver(sdata))
936		return;
937
938	trace_drv_set_rekey_data(local, sdata, data);
939	if (local->ops->set_rekey_data)
940		local->ops->set_rekey_data(&local->hw, &sdata->vif, data);
941	trace_drv_return_void(local);
942}
943
944static inline void drv_event_callback(struct ieee80211_local *local,
945				      struct ieee80211_sub_if_data *sdata,
946				      const struct ieee80211_event *event)
947{
948	trace_drv_event_callback(local, sdata, event);
949	if (local->ops->event_callback)
950		local->ops->event_callback(&local->hw, &sdata->vif, event);
951	trace_drv_return_void(local);
952}
953
954static inline void
955drv_release_buffered_frames(struct ieee80211_local *local,
956			    struct sta_info *sta, u16 tids, int num_frames,
957			    enum ieee80211_frame_release_type reason,
958			    bool more_data)
959{
960	trace_drv_release_buffered_frames(local, &sta->sta, tids, num_frames,
961					  reason, more_data);
962	if (local->ops->release_buffered_frames)
963		local->ops->release_buffered_frames(&local->hw, &sta->sta, tids,
964						    num_frames, reason,
965						    more_data);
966	trace_drv_return_void(local);
967}
968
969static inline void
970drv_allow_buffered_frames(struct ieee80211_local *local,
971			  struct sta_info *sta, u16 tids, int num_frames,
972			  enum ieee80211_frame_release_type reason,
973			  bool more_data)
974{
975	trace_drv_allow_buffered_frames(local, &sta->sta, tids, num_frames,
976					reason, more_data);
977	if (local->ops->allow_buffered_frames)
978		local->ops->allow_buffered_frames(&local->hw, &sta->sta,
979						  tids, num_frames, reason,
980						  more_data);
981	trace_drv_return_void(local);
982}
983
984static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
985				      struct ieee80211_sub_if_data *sdata)
986{
987	might_sleep();
988
989	if (!check_sdata_in_driver(sdata))
990		return;
991	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
992
993	trace_drv_mgd_prepare_tx(local, sdata);
994	if (local->ops->mgd_prepare_tx)
995		local->ops->mgd_prepare_tx(&local->hw, &sdata->vif);
996	trace_drv_return_void(local);
997}
998
999static inline void
1000drv_mgd_protect_tdls_discover(struct ieee80211_local *local,
1001			      struct ieee80211_sub_if_data *sdata)
1002{
1003	might_sleep();
1004
1005	if (!check_sdata_in_driver(sdata))
1006		return;
1007	WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
1008
1009	trace_drv_mgd_protect_tdls_discover(local, sdata);
1010	if (local->ops->mgd_protect_tdls_discover)
1011		local->ops->mgd_protect_tdls_discover(&local->hw, &sdata->vif);
1012	trace_drv_return_void(local);
1013}
1014
1015static inline int drv_add_chanctx(struct ieee80211_local *local,
1016				  struct ieee80211_chanctx *ctx)
1017{
1018	int ret = -EOPNOTSUPP;
1019
1020	trace_drv_add_chanctx(local, ctx);
1021	if (local->ops->add_chanctx)
1022		ret = local->ops->add_chanctx(&local->hw, &ctx->conf);
1023	trace_drv_return_int(local, ret);
1024	if (!ret)
1025		ctx->driver_present = true;
1026
1027	return ret;
1028}
1029
1030static inline void drv_remove_chanctx(struct ieee80211_local *local,
1031				      struct ieee80211_chanctx *ctx)
1032{
1033	if (WARN_ON(!ctx->driver_present))
1034		return;
1035
1036	trace_drv_remove_chanctx(local, ctx);
1037	if (local->ops->remove_chanctx)
1038		local->ops->remove_chanctx(&local->hw, &ctx->conf);
1039	trace_drv_return_void(local);
1040	ctx->driver_present = false;
1041}
1042
1043static inline void drv_change_chanctx(struct ieee80211_local *local,
1044				      struct ieee80211_chanctx *ctx,
1045				      u32 changed)
1046{
1047	trace_drv_change_chanctx(local, ctx, changed);
1048	if (local->ops->change_chanctx) {
1049		WARN_ON_ONCE(!ctx->driver_present);
1050		local->ops->change_chanctx(&local->hw, &ctx->conf, changed);
1051	}
1052	trace_drv_return_void(local);
1053}
1054
1055static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
1056					 struct ieee80211_sub_if_data *sdata,
1057					 struct ieee80211_chanctx *ctx)
1058{
1059	int ret = 0;
1060
1061	if (!check_sdata_in_driver(sdata))
1062		return -EIO;
1063
1064	trace_drv_assign_vif_chanctx(local, sdata, ctx);
1065	if (local->ops->assign_vif_chanctx) {
1066		WARN_ON_ONCE(!ctx->driver_present);
1067		ret = local->ops->assign_vif_chanctx(&local->hw,
1068						     &sdata->vif,
1069						     &ctx->conf);
1070	}
1071	trace_drv_return_int(local, ret);
1072
1073	return ret;
1074}
1075
1076static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
1077					    struct ieee80211_sub_if_data *sdata,
1078					    struct ieee80211_chanctx *ctx)
1079{
1080	if (!check_sdata_in_driver(sdata))
1081		return;
1082
1083	trace_drv_unassign_vif_chanctx(local, sdata, ctx);
1084	if (local->ops->unassign_vif_chanctx) {
1085		WARN_ON_ONCE(!ctx->driver_present);
1086		local->ops->unassign_vif_chanctx(&local->hw,
1087						 &sdata->vif,
1088						 &ctx->conf);
1089	}
1090	trace_drv_return_void(local);
1091}
1092
1093static inline int
1094drv_switch_vif_chanctx(struct ieee80211_local *local,
1095		       struct ieee80211_vif_chanctx_switch *vifs,
1096		       int n_vifs,
1097		       enum ieee80211_chanctx_switch_mode mode)
1098{
1099	int ret = 0;
1100	int i;
1101
1102	if (!local->ops->switch_vif_chanctx)
1103		return -EOPNOTSUPP;
1104
1105	for (i = 0; i < n_vifs; i++) {
1106		struct ieee80211_chanctx *new_ctx =
1107			container_of(vifs[i].new_ctx,
1108				     struct ieee80211_chanctx,
1109				     conf);
1110		struct ieee80211_chanctx *old_ctx =
1111			container_of(vifs[i].old_ctx,
1112				     struct ieee80211_chanctx,
1113				     conf);
1114
1115		WARN_ON_ONCE(!old_ctx->driver_present);
1116		WARN_ON_ONCE((mode == CHANCTX_SWMODE_SWAP_CONTEXTS &&
1117			      new_ctx->driver_present) ||
1118			     (mode == CHANCTX_SWMODE_REASSIGN_VIF &&
1119			      !new_ctx->driver_present));
1120	}
1121
1122	trace_drv_switch_vif_chanctx(local, vifs, n_vifs, mode);
1123	ret = local->ops->switch_vif_chanctx(&local->hw,
1124					     vifs, n_vifs, mode);
1125	trace_drv_return_int(local, ret);
1126
1127	if (!ret && mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
1128		for (i = 0; i < n_vifs; i++) {
1129			struct ieee80211_chanctx *new_ctx =
1130				container_of(vifs[i].new_ctx,
1131					     struct ieee80211_chanctx,
1132					     conf);
1133			struct ieee80211_chanctx *old_ctx =
1134				container_of(vifs[i].old_ctx,
1135					     struct ieee80211_chanctx,
1136					     conf);
1137
1138			new_ctx->driver_present = true;
1139			old_ctx->driver_present = false;
1140		}
1141	}
1142
1143	return ret;
1144}
1145
1146static inline int drv_start_ap(struct ieee80211_local *local,
1147			       struct ieee80211_sub_if_data *sdata)
1148{
1149	int ret = 0;
1150
1151	if (!check_sdata_in_driver(sdata))
1152		return -EIO;
1153
1154	trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf);
1155	if (local->ops->start_ap)
1156		ret = local->ops->start_ap(&local->hw, &sdata->vif);
1157	trace_drv_return_int(local, ret);
1158	return ret;
1159}
1160
1161static inline void drv_stop_ap(struct ieee80211_local *local,
1162			       struct ieee80211_sub_if_data *sdata)
1163{
1164	if (!check_sdata_in_driver(sdata))
1165		return;
1166
1167	trace_drv_stop_ap(local, sdata);
1168	if (local->ops->stop_ap)
1169		local->ops->stop_ap(&local->hw, &sdata->vif);
1170	trace_drv_return_void(local);
1171}
1172
1173static inline void
1174drv_reconfig_complete(struct ieee80211_local *local,
1175		      enum ieee80211_reconfig_type reconfig_type)
1176{
1177	might_sleep();
1178
1179	trace_drv_reconfig_complete(local, reconfig_type);
1180	if (local->ops->reconfig_complete)
1181		local->ops->reconfig_complete(&local->hw, reconfig_type);
1182	trace_drv_return_void(local);
1183}
1184
1185static inline void
1186drv_set_default_unicast_key(struct ieee80211_local *local,
1187			    struct ieee80211_sub_if_data *sdata,
1188			    int key_idx)
1189{
1190	if (!check_sdata_in_driver(sdata))
1191		return;
1192
1193	WARN_ON_ONCE(key_idx < -1 || key_idx > 3);
1194
1195	trace_drv_set_default_unicast_key(local, sdata, key_idx);
1196	if (local->ops->set_default_unicast_key)
1197		local->ops->set_default_unicast_key(&local->hw, &sdata->vif,
1198						    key_idx);
1199	trace_drv_return_void(local);
1200}
1201
1202#if IS_ENABLED(CONFIG_IPV6)
1203static inline void drv_ipv6_addr_change(struct ieee80211_local *local,
1204					struct ieee80211_sub_if_data *sdata,
1205					struct inet6_dev *idev)
1206{
1207	trace_drv_ipv6_addr_change(local, sdata);
1208	if (local->ops->ipv6_addr_change)
1209		local->ops->ipv6_addr_change(&local->hw, &sdata->vif, idev);
1210	trace_drv_return_void(local);
1211}
1212#endif
1213
1214static inline void
1215drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata,
1216			  struct cfg80211_chan_def *chandef)
1217{
1218	struct ieee80211_local *local = sdata->local;
1219
1220	if (local->ops->channel_switch_beacon) {
1221		trace_drv_channel_switch_beacon(local, sdata, chandef);
1222		local->ops->channel_switch_beacon(&local->hw, &sdata->vif,
1223						  chandef);
1224	}
1225}
1226
1227static inline int
1228drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata,
1229		       struct ieee80211_channel_switch *ch_switch)
1230{
1231	struct ieee80211_local *local = sdata->local;
1232	int ret = 0;
1233
1234	if (!check_sdata_in_driver(sdata))
1235		return -EIO;
1236
1237	trace_drv_pre_channel_switch(local, sdata, ch_switch);
1238	if (local->ops->pre_channel_switch)
1239		ret = local->ops->pre_channel_switch(&local->hw, &sdata->vif,
1240						     ch_switch);
1241	trace_drv_return_int(local, ret);
1242	return ret;
1243}
1244
1245static inline int
1246drv_post_channel_switch(struct ieee80211_sub_if_data *sdata)
1247{
1248	struct ieee80211_local *local = sdata->local;
1249	int ret = 0;
1250
1251	if (!check_sdata_in_driver(sdata))
1252		return -EIO;
1253
1254	trace_drv_post_channel_switch(local, sdata);
1255	if (local->ops->post_channel_switch)
1256		ret = local->ops->post_channel_switch(&local->hw, &sdata->vif);
1257	trace_drv_return_int(local, ret);
1258	return ret;
1259}
1260
1261static inline int drv_join_ibss(struct ieee80211_local *local,
1262				struct ieee80211_sub_if_data *sdata)
1263{
1264	int ret = 0;
1265
1266	might_sleep();
1267	if (!check_sdata_in_driver(sdata))
1268		return -EIO;
1269
1270	trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf);
1271	if (local->ops->join_ibss)
1272		ret = local->ops->join_ibss(&local->hw, &sdata->vif);
1273	trace_drv_return_int(local, ret);
1274	return ret;
1275}
1276
1277static inline void drv_leave_ibss(struct ieee80211_local *local,
1278				  struct ieee80211_sub_if_data *sdata)
1279{
1280	might_sleep();
1281	if (!check_sdata_in_driver(sdata))
1282		return;
1283
1284	trace_drv_leave_ibss(local, sdata);
1285	if (local->ops->leave_ibss)
1286		local->ops->leave_ibss(&local->hw, &sdata->vif);
1287	trace_drv_return_void(local);
1288}
1289
1290static inline u32 drv_get_expected_throughput(struct ieee80211_local *local,
1291					      struct ieee80211_sta *sta)
1292{
1293	u32 ret = 0;
1294
1295	trace_drv_get_expected_throughput(sta);
1296	if (local->ops->get_expected_throughput)
1297		ret = local->ops->get_expected_throughput(sta);
1298	trace_drv_return_u32(local, ret);
1299
1300	return ret;
1301}
1302
1303static inline int drv_get_txpower(struct ieee80211_local *local,
1304				  struct ieee80211_sub_if_data *sdata, int *dbm)
1305{
1306	int ret;
1307
1308	if (!local->ops->get_txpower)
1309		return -EOPNOTSUPP;
1310
1311	ret = local->ops->get_txpower(&local->hw, &sdata->vif, dbm);
1312	trace_drv_get_txpower(local, sdata, *dbm, ret);
1313
1314	return ret;
1315}
1316
1317static inline int
1318drv_tdls_channel_switch(struct ieee80211_local *local,
1319			struct ieee80211_sub_if_data *sdata,
1320			struct ieee80211_sta *sta, u8 oper_class,
1321			struct cfg80211_chan_def *chandef,
1322			struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie)
1323{
1324	int ret;
1325
1326	might_sleep();
1327	if (!check_sdata_in_driver(sdata))
1328		return -EIO;
1329
1330	if (!local->ops->tdls_channel_switch)
1331		return -EOPNOTSUPP;
1332
1333	trace_drv_tdls_channel_switch(local, sdata, sta, oper_class, chandef);
1334	ret = local->ops->tdls_channel_switch(&local->hw, &sdata->vif, sta,
1335					      oper_class, chandef, tmpl_skb,
1336					      ch_sw_tm_ie);
1337	trace_drv_return_int(local, ret);
1338	return ret;
1339}
1340
1341static inline void
1342drv_tdls_cancel_channel_switch(struct ieee80211_local *local,
1343			       struct ieee80211_sub_if_data *sdata,
1344			       struct ieee80211_sta *sta)
1345{
1346	might_sleep();
1347	if (!check_sdata_in_driver(sdata))
1348		return;
1349
1350	if (!local->ops->tdls_cancel_channel_switch)
1351		return;
1352
1353	trace_drv_tdls_cancel_channel_switch(local, sdata, sta);
1354	local->ops->tdls_cancel_channel_switch(&local->hw, &sdata->vif, sta);
1355	trace_drv_return_void(local);
1356}
1357
1358static inline void
1359drv_tdls_recv_channel_switch(struct ieee80211_local *local,
1360			     struct ieee80211_sub_if_data *sdata,
1361			     struct ieee80211_tdls_ch_sw_params *params)
1362{
1363	trace_drv_tdls_recv_channel_switch(local, sdata, params);
1364	if (local->ops->tdls_recv_channel_switch)
1365		local->ops->tdls_recv_channel_switch(&local->hw, &sdata->vif,
1366						     params);
1367	trace_drv_return_void(local);
1368}
1369
1370static inline void drv_wake_tx_queue(struct ieee80211_local *local,
1371				     struct txq_info *txq)
1372{
1373	struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif);
1374
1375	if (!check_sdata_in_driver(sdata))
1376		return;
1377
1378	trace_drv_wake_tx_queue(local, sdata, txq);
1379	local->ops->wake_tx_queue(&local->hw, &txq->txq);
1380}
1381
1382#endif /* __MAC80211_DRIVER_OPS */
1383