xref: /linux/drivers/net/wireless/mediatek/mt76/util.h (revision 8f7aa3d3c7323f4ca2768a9e74ebbe359c4f8f88)
1 /* SPDX-License-Identifier: BSD-3-Clause-Clear */
2 /*
3  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
4  */
5 
6 #ifndef __MT76_UTIL_H
7 #define __MT76_UTIL_H
8 
9 #include <linux/skbuff.h>
10 #include <linux/bitops.h>
11 #include <linux/bitfield.h>
12 #include <net/mac80211.h>
13 
14 struct mt76_worker
15 {
16 	struct task_struct *task;
17 	void (*fn)(struct mt76_worker *);
18 	unsigned long state;
19 };
20 
21 enum {
22 	MT76_WORKER_SCHEDULED,
23 	MT76_WORKER_RUNNING,
24 };
25 
26 #define MT76_INCR(_var, _size) \
27 	(_var = (((_var) + 1) % (_size)))
28 
29 int mt76_wcid_alloc(u32 *mask, int size);
30 
31 static inline void
32 mt76_wcid_mask_set(u32 *mask, int idx)
33 {
34 	mask[idx / 32] |= BIT(idx % 32);
35 }
36 
37 static inline void
38 mt76_wcid_mask_clear(u32 *mask, int idx)
39 {
40 	mask[idx / 32] &= ~BIT(idx % 32);
41 }
42 
43 static inline void
44 mt76_skb_set_moredata(struct sk_buff *skb, bool enable)
45 {
46 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
47 
48 	if (enable)
49 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
50 	else
51 		hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
52 }
53 
54 int __mt76_worker_fn(void *ptr);
55 
56 static inline int
57 mt76_worker_setup(struct ieee80211_hw *hw, struct mt76_worker *w,
58 		  void (*fn)(struct mt76_worker *),
59 		  const char *name)
60 {
61 	const char *dev_name = wiphy_name(hw->wiphy);
62 	int ret;
63 
64 	if (fn)
65 		w->fn = fn;
66 	w->task = kthread_run(__mt76_worker_fn, w,
67 			      "mt76-%s %s", name, dev_name);
68 
69 	if (IS_ERR(w->task)) {
70 		ret = PTR_ERR(w->task);
71 		w->task = NULL;
72 		return ret;
73 	}
74 
75 	return 0;
76 }
77 
78 static inline void mt76_worker_schedule(struct mt76_worker *w)
79 {
80 	if (!w->task)
81 		return;
82 
83 	if (!test_and_set_bit(MT76_WORKER_SCHEDULED, &w->state) &&
84 	    !test_bit(MT76_WORKER_RUNNING, &w->state))
85 		wake_up_process(w->task);
86 }
87 
88 static inline void mt76_worker_disable(struct mt76_worker *w)
89 {
90 	if (!w->task)
91 		return;
92 
93 	kthread_park(w->task);
94 	WRITE_ONCE(w->state, 0);
95 }
96 
97 static inline void mt76_worker_enable(struct mt76_worker *w)
98 {
99 	if (!w->task)
100 		return;
101 
102 	kthread_unpark(w->task);
103 	mt76_worker_schedule(w);
104 }
105 
106 static inline void mt76_worker_teardown(struct mt76_worker *w)
107 {
108 	if (!w->task)
109 		return;
110 
111 	kthread_stop(w->task);
112 	w->task = NULL;
113 }
114 
115 #endif
116