1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __MAC802154_DRIVER_OPS
3#define __MAC802154_DRIVER_OPS
4
5#include <linux/types.h>
6#include <linux/rtnetlink.h>
7
8#include <net/mac802154.h>
9
10#include "ieee802154_i.h"
11#include "trace.h"
12
13static inline int
14drv_xmit_async(struct ieee802154_local *local, struct sk_buff *skb)
15{
16	return local->ops->xmit_async(&local->hw, skb);
17}
18
19static inline int
20drv_xmit_sync(struct ieee802154_local *local, struct sk_buff *skb)
21{
22	might_sleep();
23
24	return local->ops->xmit_sync(&local->hw, skb);
25}
26
27static inline int drv_start(struct ieee802154_local *local)
28{
29	int ret;
30
31	might_sleep();
32
33	trace_802154_drv_start(local);
34	local->started = true;
35	smp_mb();
36	ret = local->ops->start(&local->hw);
37	trace_802154_drv_return_int(local, ret);
38	return ret;
39}
40
41static inline void drv_stop(struct ieee802154_local *local)
42{
43	might_sleep();
44
45	trace_802154_drv_stop(local);
46	local->ops->stop(&local->hw);
47	trace_802154_drv_return_void(local);
48
49	/* sync away all work on the tasklet before clearing started */
50	tasklet_disable(&local->tasklet);
51	tasklet_enable(&local->tasklet);
52
53	barrier();
54
55	local->started = false;
56}
57
58static inline int
59drv_set_channel(struct ieee802154_local *local, u8 page, u8 channel)
60{
61	int ret;
62
63	might_sleep();
64
65	trace_802154_drv_set_channel(local, page, channel);
66	ret = local->ops->set_channel(&local->hw, page, channel);
67	trace_802154_drv_return_int(local, ret);
68	return ret;
69}
70
71static inline int drv_set_tx_power(struct ieee802154_local *local, s32 mbm)
72{
73	int ret;
74
75	might_sleep();
76
77	if (!local->ops->set_txpower) {
78		WARN_ON(1);
79		return -EOPNOTSUPP;
80	}
81
82	trace_802154_drv_set_tx_power(local, mbm);
83	ret = local->ops->set_txpower(&local->hw, mbm);
84	trace_802154_drv_return_int(local, ret);
85	return ret;
86}
87
88static inline int drv_set_cca_mode(struct ieee802154_local *local,
89				   const struct wpan_phy_cca *cca)
90{
91	int ret;
92
93	might_sleep();
94
95	if (!local->ops->set_cca_mode) {
96		WARN_ON(1);
97		return -EOPNOTSUPP;
98	}
99
100	trace_802154_drv_set_cca_mode(local, cca);
101	ret = local->ops->set_cca_mode(&local->hw, cca);
102	trace_802154_drv_return_int(local, ret);
103	return ret;
104}
105
106static inline int drv_set_lbt_mode(struct ieee802154_local *local, bool mode)
107{
108	int ret;
109
110	might_sleep();
111
112	if (!local->ops->set_lbt) {
113		WARN_ON(1);
114		return -EOPNOTSUPP;
115	}
116
117	trace_802154_drv_set_lbt_mode(local, mode);
118	ret = local->ops->set_lbt(&local->hw, mode);
119	trace_802154_drv_return_int(local, ret);
120	return ret;
121}
122
123static inline int
124drv_set_cca_ed_level(struct ieee802154_local *local, s32 mbm)
125{
126	int ret;
127
128	might_sleep();
129
130	if (!local->ops->set_cca_ed_level) {
131		WARN_ON(1);
132		return -EOPNOTSUPP;
133	}
134
135	trace_802154_drv_set_cca_ed_level(local, mbm);
136	ret = local->ops->set_cca_ed_level(&local->hw, mbm);
137	trace_802154_drv_return_int(local, ret);
138	return ret;
139}
140
141static inline int drv_set_pan_id(struct ieee802154_local *local, __le16 pan_id)
142{
143	struct ieee802154_hw_addr_filt filt;
144	int ret;
145
146	might_sleep();
147
148	if (!local->ops->set_hw_addr_filt) {
149		WARN_ON(1);
150		return -EOPNOTSUPP;
151	}
152
153	filt.pan_id = pan_id;
154
155	trace_802154_drv_set_pan_id(local, pan_id);
156	ret = local->ops->set_hw_addr_filt(&local->hw, &filt,
157					    IEEE802154_AFILT_PANID_CHANGED);
158	trace_802154_drv_return_int(local, ret);
159	return ret;
160}
161
162static inline int
163drv_set_extended_addr(struct ieee802154_local *local, __le64 extended_addr)
164{
165	struct ieee802154_hw_addr_filt filt;
166	int ret;
167
168	might_sleep();
169
170	if (!local->ops->set_hw_addr_filt) {
171		WARN_ON(1);
172		return -EOPNOTSUPP;
173	}
174
175	filt.ieee_addr = extended_addr;
176
177	trace_802154_drv_set_extended_addr(local, extended_addr);
178	ret = local->ops->set_hw_addr_filt(&local->hw, &filt,
179					    IEEE802154_AFILT_IEEEADDR_CHANGED);
180	trace_802154_drv_return_int(local, ret);
181	return ret;
182}
183
184static inline int
185drv_set_short_addr(struct ieee802154_local *local, __le16 short_addr)
186{
187	struct ieee802154_hw_addr_filt filt;
188	int ret;
189
190	might_sleep();
191
192	if (!local->ops->set_hw_addr_filt) {
193		WARN_ON(1);
194		return -EOPNOTSUPP;
195	}
196
197	filt.short_addr = short_addr;
198
199	trace_802154_drv_set_short_addr(local, short_addr);
200	ret = local->ops->set_hw_addr_filt(&local->hw, &filt,
201					    IEEE802154_AFILT_SADDR_CHANGED);
202	trace_802154_drv_return_int(local, ret);
203	return ret;
204}
205
206static inline int
207drv_set_pan_coord(struct ieee802154_local *local, bool is_coord)
208{
209	struct ieee802154_hw_addr_filt filt;
210	int ret;
211
212	might_sleep();
213
214	if (!local->ops->set_hw_addr_filt) {
215		WARN_ON(1);
216		return -EOPNOTSUPP;
217	}
218
219	filt.pan_coord = is_coord;
220
221	trace_802154_drv_set_pan_coord(local, is_coord);
222	ret = local->ops->set_hw_addr_filt(&local->hw, &filt,
223					    IEEE802154_AFILT_PANC_CHANGED);
224	trace_802154_drv_return_int(local, ret);
225	return ret;
226}
227
228static inline int
229drv_set_csma_params(struct ieee802154_local *local, u8 min_be, u8 max_be,
230		    u8 max_csma_backoffs)
231{
232	int ret;
233
234	might_sleep();
235
236	if (!local->ops->set_csma_params) {
237		WARN_ON(1);
238		return -EOPNOTSUPP;
239	}
240
241	trace_802154_drv_set_csma_params(local, min_be, max_be,
242					 max_csma_backoffs);
243	ret = local->ops->set_csma_params(&local->hw, min_be, max_be,
244					   max_csma_backoffs);
245	trace_802154_drv_return_int(local, ret);
246	return ret;
247}
248
249static inline int
250drv_set_max_frame_retries(struct ieee802154_local *local, s8 max_frame_retries)
251{
252	int ret;
253
254	might_sleep();
255
256	if (!local->ops->set_frame_retries) {
257		WARN_ON(1);
258		return -EOPNOTSUPP;
259	}
260
261	trace_802154_drv_set_max_frame_retries(local, max_frame_retries);
262	ret = local->ops->set_frame_retries(&local->hw, max_frame_retries);
263	trace_802154_drv_return_int(local, ret);
264	return ret;
265}
266
267static inline int
268drv_set_promiscuous_mode(struct ieee802154_local *local, bool on)
269{
270	int ret;
271
272	might_sleep();
273
274	if (!local->ops->set_promiscuous_mode) {
275		WARN_ON(1);
276		return -EOPNOTSUPP;
277	}
278
279	trace_802154_drv_set_promiscuous_mode(local, on);
280	ret = local->ops->set_promiscuous_mode(&local->hw, on);
281	trace_802154_drv_return_int(local, ret);
282	return ret;
283}
284
285#endif /* __MAC802154_DRIVER_OPS */
286