Linux Audio

Check our new training course

Loading...
v5.4
  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 */
v6.8
  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_set_pan_id(struct ieee802154_local *local, __le16 pan_id)
 28{
 29	struct ieee802154_hw_addr_filt filt;
 30	int ret;
 31
 32	might_sleep();
 33
 34	if (!local->ops->set_hw_addr_filt) {
 35		WARN_ON(1);
 36		return -EOPNOTSUPP;
 37	}
 38
 39	filt.pan_id = pan_id;
 40
 41	trace_802154_drv_set_pan_id(local, pan_id);
 42	ret = local->ops->set_hw_addr_filt(&local->hw, &filt,
 43					    IEEE802154_AFILT_PANID_CHANGED);
 44	trace_802154_drv_return_int(local, ret);
 45	return ret;
 46}
 47
 48static inline int
 49drv_set_extended_addr(struct ieee802154_local *local, __le64 extended_addr)
 50{
 51	struct ieee802154_hw_addr_filt filt;
 52	int ret;
 53
 54	might_sleep();
 
 
 55
 56	if (!local->ops->set_hw_addr_filt) {
 57		WARN_ON(1);
 58		return -EOPNOTSUPP;
 59	}
 60
 61	filt.ieee_addr = extended_addr;
 62
 63	trace_802154_drv_set_extended_addr(local, extended_addr);
 64	ret = local->ops->set_hw_addr_filt(&local->hw, &filt,
 65					    IEEE802154_AFILT_IEEEADDR_CHANGED);
 66	trace_802154_drv_return_int(local, ret);
 67	return ret;
 68}
 69
 70static inline int
 71drv_set_short_addr(struct ieee802154_local *local, __le16 short_addr)
 72{
 73	struct ieee802154_hw_addr_filt filt;
 74	int ret;
 75
 76	might_sleep();
 77
 78	if (!local->ops->set_hw_addr_filt) {
 79		WARN_ON(1);
 80		return -EOPNOTSUPP;
 81	}
 82
 83	filt.short_addr = short_addr;
 84
 85	trace_802154_drv_set_short_addr(local, short_addr);
 86	ret = local->ops->set_hw_addr_filt(&local->hw, &filt,
 87					    IEEE802154_AFILT_SADDR_CHANGED);
 88	trace_802154_drv_return_int(local, ret);
 89	return ret;
 90}
 91
 92static inline int
 93drv_set_pan_coord(struct ieee802154_local *local, bool is_coord)
 94{
 95	struct ieee802154_hw_addr_filt filt;
 96	int ret;
 97
 98	might_sleep();
 99
100	if (!local->ops->set_hw_addr_filt) {
101		WARN_ON(1);
102		return -EOPNOTSUPP;
103	}
104
105	filt.pan_coord = is_coord;
106
107	trace_802154_drv_set_pan_coord(local, is_coord);
108	ret = local->ops->set_hw_addr_filt(&local->hw, &filt,
109					    IEEE802154_AFILT_PANC_CHANGED);
110	trace_802154_drv_return_int(local, ret);
111	return ret;
112}
113
114static inline int
115drv_set_promiscuous_mode(struct ieee802154_local *local, bool on)
116{
117	int ret;
118
119	might_sleep();
120
121	if (!local->ops->set_promiscuous_mode) {
122		WARN_ON(1);
123		return -EOPNOTSUPP;
124	}
125
126	trace_802154_drv_set_promiscuous_mode(local, on);
127	ret = local->ops->set_promiscuous_mode(&local->hw, on);
128	trace_802154_drv_return_int(local, ret);
129	return ret;
130}
131
132static inline int drv_start(struct ieee802154_local *local,
133			    enum ieee802154_filtering_level level,
134			    const struct ieee802154_hw_addr_filt *addr_filt)
135{
136	int ret;
137
138	might_sleep();
139
140	/* setup receive mode parameters e.g. address mode */
141	if (local->hw.flags & IEEE802154_HW_AFILT) {
142		ret = drv_set_pan_id(local, addr_filt->pan_id);
143		if (ret < 0)
144			return ret;
145
146		ret = drv_set_short_addr(local, addr_filt->short_addr);
147		if (ret < 0)
148			return ret;
149
150		ret = drv_set_extended_addr(local, addr_filt->ieee_addr);
151		if (ret < 0)
152			return ret;
153	}
154
155	switch (level) {
156	case IEEE802154_FILTERING_NONE:
157		fallthrough;
158	case IEEE802154_FILTERING_1_FCS:
159		fallthrough;
160	case IEEE802154_FILTERING_2_PROMISCUOUS:
161		/* TODO: Requires a different receive mode setup e.g.
162		 * at86rf233 hardware.
163		 */
164		fallthrough;
165	case IEEE802154_FILTERING_3_SCAN:
166		if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) {
167			ret = drv_set_promiscuous_mode(local, true);
168			if (ret < 0)
169				return ret;
170		} else {
171			return -EOPNOTSUPP;
172		}
173
174		/* In practice other filtering levels can be requested, but as
175		 * for now most hardware/drivers only support
176		 * IEEE802154_FILTERING_NONE, we fallback to this actual
177		 * filtering level in hardware and make our own additional
178		 * filtering in mac802154 receive path.
179		 *
180		 * TODO: Move this logic to the device drivers as hardware may
181		 * support more higher level filters. Hardware may also require
182		 * a different order how register are set, which could currently
183		 * be buggy, so all received parameters need to be moved to the
184		 * start() callback and let the driver go into the mode before
185		 * it will turn on receive handling.
186		 */
187		local->phy->filtering = IEEE802154_FILTERING_NONE;
188		break;
189	case IEEE802154_FILTERING_4_FRAME_FIELDS:
190		/* Do not error out if IEEE802154_HW_PROMISCUOUS because we
191		 * expect the hardware to operate at the level
192		 * IEEE802154_FILTERING_4_FRAME_FIELDS anyway.
193		 */
194		if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) {
195			ret = drv_set_promiscuous_mode(local, false);
196			if (ret < 0)
197				return ret;
198		}
199
200		local->phy->filtering = IEEE802154_FILTERING_4_FRAME_FIELDS;
201		break;
202	default:
203		WARN_ON(1);
204		return -EINVAL;
205	}
206
207	trace_802154_drv_start(local);
208	local->started = true;
209	smp_mb();
210	ret = local->ops->start(&local->hw);
211	trace_802154_drv_return_int(local, ret);
212	return ret;
213}
214
215static inline void drv_stop(struct ieee802154_local *local)
216{
217	might_sleep();
218
219	trace_802154_drv_stop(local);
220	local->ops->stop(&local->hw);
221	trace_802154_drv_return_void(local);
222
223	/* sync away all work on the tasklet before clearing started */
224	tasklet_disable(&local->tasklet);
225	tasklet_enable(&local->tasklet);
226
227	barrier();
228
229	local->started = false;
230}
231
232static inline int
233drv_set_channel(struct ieee802154_local *local, u8 page, u8 channel)
234{
235	int ret;
236
237	might_sleep();
238
239	trace_802154_drv_set_channel(local, page, channel);
240	ret = local->ops->set_channel(&local->hw, page, channel);
 
 
 
 
 
241	trace_802154_drv_return_int(local, ret);
242	return ret;
243}
244
245static inline int drv_set_tx_power(struct ieee802154_local *local, s32 mbm)
246{
 
247	int ret;
248
249	might_sleep();
250
251	if (!local->ops->set_txpower) {
252		WARN_ON(1);
253		return -EOPNOTSUPP;
254	}
255
256	trace_802154_drv_set_tx_power(local, mbm);
257	ret = local->ops->set_txpower(&local->hw, mbm);
 
 
 
258	trace_802154_drv_return_int(local, ret);
259	return ret;
260}
261
262static inline int drv_set_cca_mode(struct ieee802154_local *local,
263				   const struct wpan_phy_cca *cca)
264{
 
265	int ret;
266
267	might_sleep();
268
269	if (!local->ops->set_cca_mode) {
270		WARN_ON(1);
271		return -EOPNOTSUPP;
272	}
273
274	trace_802154_drv_set_cca_mode(local, cca);
275	ret = local->ops->set_cca_mode(&local->hw, cca);
 
 
 
276	trace_802154_drv_return_int(local, ret);
277	return ret;
278}
279
280static inline int drv_set_lbt_mode(struct ieee802154_local *local, bool mode)
 
281{
 
282	int ret;
283
284	might_sleep();
285
286	if (!local->ops->set_lbt) {
287		WARN_ON(1);
288		return -EOPNOTSUPP;
289	}
290
291	trace_802154_drv_set_lbt_mode(local, mode);
292	ret = local->ops->set_lbt(&local->hw, mode);
 
 
 
293	trace_802154_drv_return_int(local, ret);
294	return ret;
295}
296
297static inline int
298drv_set_cca_ed_level(struct ieee802154_local *local, s32 mbm)
299{
 
300	int ret;
301
302	might_sleep();
303
304	if (!local->ops->set_cca_ed_level) {
305		WARN_ON(1);
306		return -EOPNOTSUPP;
307	}
308
309	trace_802154_drv_set_cca_ed_level(local, mbm);
310	ret = local->ops->set_cca_ed_level(&local->hw, mbm);
 
 
 
311	trace_802154_drv_return_int(local, ret);
312	return ret;
313}
314
315static inline int
316drv_set_csma_params(struct ieee802154_local *local, u8 min_be, u8 max_be,
317		    u8 max_csma_backoffs)
318{
319	int ret;
320
321	might_sleep();
322
323	if (!local->ops->set_csma_params) {
324		WARN_ON(1);
325		return -EOPNOTSUPP;
326	}
327
328	trace_802154_drv_set_csma_params(local, min_be, max_be,
329					 max_csma_backoffs);
330	ret = local->ops->set_csma_params(&local->hw, min_be, max_be,
331					   max_csma_backoffs);
332	trace_802154_drv_return_int(local, ret);
333	return ret;
334}
335
336static inline int
337drv_set_max_frame_retries(struct ieee802154_local *local, s8 max_frame_retries)
338{
339	int ret;
340
341	might_sleep();
342
343	if (!local->ops->set_frame_retries) {
344		WARN_ON(1);
345		return -EOPNOTSUPP;
346	}
347
348	trace_802154_drv_set_max_frame_retries(local, max_frame_retries);
349	ret = local->ops->set_frame_retries(&local->hw, max_frame_retries);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350	trace_802154_drv_return_int(local, ret);
351	return ret;
352}
353
354#endif /* __MAC802154_DRIVER_OPS */