xref: /linux/drivers/net/wireless/mediatek/mt76/util.h (revision 30bdd69246ea9726a7688ef02c60b1ec0ae66d38)
11802d0beSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
217f1de56SFelix Fietkau /*
317f1de56SFelix Fietkau  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
417f1de56SFelix Fietkau  * Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
517f1de56SFelix Fietkau  */
617f1de56SFelix Fietkau 
717f1de56SFelix Fietkau #ifndef __MT76_UTIL_H
817f1de56SFelix Fietkau #define __MT76_UTIL_H
917f1de56SFelix Fietkau 
1017f1de56SFelix Fietkau #include <linux/skbuff.h>
1117f1de56SFelix Fietkau #include <linux/bitops.h>
1217f1de56SFelix Fietkau #include <linux/bitfield.h>
13*30bdd692SFelix Fietkau #include <net/mac80211.h>
14*30bdd692SFelix Fietkau 
15*30bdd692SFelix Fietkau struct mt76_worker
16*30bdd692SFelix Fietkau {
17*30bdd692SFelix Fietkau 	struct task_struct *task;
18*30bdd692SFelix Fietkau 	void (*fn)(struct mt76_worker *);
19*30bdd692SFelix Fietkau 	unsigned long state;
20*30bdd692SFelix Fietkau };
21*30bdd692SFelix Fietkau 
22*30bdd692SFelix Fietkau enum {
23*30bdd692SFelix Fietkau 	MT76_WORKER_SCHEDULED,
24*30bdd692SFelix Fietkau 	MT76_WORKER_RUNNING,
25*30bdd692SFelix Fietkau };
2617f1de56SFelix Fietkau 
2717f1de56SFelix Fietkau #define MT76_INCR(_var, _size) \
2813381dcdSRyder Lee 	(_var = (((_var) + 1) % (_size)))
2917f1de56SFelix Fietkau 
305e616ad2SFelix Fietkau int mt76_wcid_alloc(u32 *mask, int size);
3117f1de56SFelix Fietkau 
32426e8e41SFelix Fietkau static inline bool
335e616ad2SFelix Fietkau mt76_wcid_mask_test(u32 *mask, int idx)
34426e8e41SFelix Fietkau {
355e616ad2SFelix Fietkau 	return mask[idx / 32] & BIT(idx % 32);
36426e8e41SFelix Fietkau }
37426e8e41SFelix Fietkau 
3817f1de56SFelix Fietkau static inline void
395e616ad2SFelix Fietkau mt76_wcid_mask_set(u32 *mask, int idx)
40426e8e41SFelix Fietkau {
415e616ad2SFelix Fietkau 	mask[idx / 32] |= BIT(idx % 32);
42426e8e41SFelix Fietkau }
43426e8e41SFelix Fietkau 
44426e8e41SFelix Fietkau static inline void
455e616ad2SFelix Fietkau mt76_wcid_mask_clear(u32 *mask, int idx)
4617f1de56SFelix Fietkau {
475e616ad2SFelix Fietkau 	mask[idx / 32] &= ~BIT(idx % 32);
4817f1de56SFelix Fietkau }
4917f1de56SFelix Fietkau 
5017f1de56SFelix Fietkau static inline void
5117f1de56SFelix Fietkau mt76_skb_set_moredata(struct sk_buff *skb, bool enable)
5217f1de56SFelix Fietkau {
5317f1de56SFelix Fietkau 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
5417f1de56SFelix Fietkau 
5517f1de56SFelix Fietkau 	if (enable)
5617f1de56SFelix Fietkau 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
5717f1de56SFelix Fietkau 	else
5817f1de56SFelix Fietkau 		hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
5917f1de56SFelix Fietkau }
6017f1de56SFelix Fietkau 
61*30bdd692SFelix Fietkau int __mt76_worker_fn(void *ptr);
62*30bdd692SFelix Fietkau 
63*30bdd692SFelix Fietkau static inline int
64*30bdd692SFelix Fietkau mt76_worker_setup(struct ieee80211_hw *hw, struct mt76_worker *w,
65*30bdd692SFelix Fietkau 		  void (*fn)(struct mt76_worker *),
66*30bdd692SFelix Fietkau 		  const char *name)
67*30bdd692SFelix Fietkau {
68*30bdd692SFelix Fietkau 	const char *dev_name = wiphy_name(hw->wiphy);
69*30bdd692SFelix Fietkau 	int ret;
70*30bdd692SFelix Fietkau 
71*30bdd692SFelix Fietkau 	if (fn)
72*30bdd692SFelix Fietkau 		w->fn = fn;
73*30bdd692SFelix Fietkau 	w->task = kthread_create(__mt76_worker_fn, w, "mt76-%s %s",
74*30bdd692SFelix Fietkau 				 name, dev_name);
75*30bdd692SFelix Fietkau 
76*30bdd692SFelix Fietkau 	ret = PTR_ERR_OR_ZERO(w->task);
77*30bdd692SFelix Fietkau 	if (ret) {
78*30bdd692SFelix Fietkau 		w->task = NULL;
79*30bdd692SFelix Fietkau 		return ret;
80*30bdd692SFelix Fietkau 	}
81*30bdd692SFelix Fietkau 
82*30bdd692SFelix Fietkau 	wake_up_process(w->task);
83*30bdd692SFelix Fietkau 
84*30bdd692SFelix Fietkau 	return 0;
85*30bdd692SFelix Fietkau }
86*30bdd692SFelix Fietkau 
87*30bdd692SFelix Fietkau static inline void mt76_worker_schedule(struct mt76_worker *w)
88*30bdd692SFelix Fietkau {
89*30bdd692SFelix Fietkau 	if (!w->task)
90*30bdd692SFelix Fietkau 		return;
91*30bdd692SFelix Fietkau 
92*30bdd692SFelix Fietkau 	if (!test_and_set_bit(MT76_WORKER_SCHEDULED, &w->state) &&
93*30bdd692SFelix Fietkau 	    !test_bit(MT76_WORKER_RUNNING, &w->state))
94*30bdd692SFelix Fietkau 		wake_up_process(w->task);
95*30bdd692SFelix Fietkau }
96*30bdd692SFelix Fietkau 
97*30bdd692SFelix Fietkau static inline void mt76_worker_disable(struct mt76_worker *w)
98*30bdd692SFelix Fietkau {
99*30bdd692SFelix Fietkau 	if (!w->task)
100*30bdd692SFelix Fietkau 		return;
101*30bdd692SFelix Fietkau 
102*30bdd692SFelix Fietkau 	kthread_park(w->task);
103*30bdd692SFelix Fietkau 	WRITE_ONCE(w->state, 0);
104*30bdd692SFelix Fietkau }
105*30bdd692SFelix Fietkau 
106*30bdd692SFelix Fietkau static inline void mt76_worker_enable(struct mt76_worker *w)
107*30bdd692SFelix Fietkau {
108*30bdd692SFelix Fietkau 	if (!w->task)
109*30bdd692SFelix Fietkau 		return;
110*30bdd692SFelix Fietkau 
111*30bdd692SFelix Fietkau 	kthread_unpark(w->task);
112*30bdd692SFelix Fietkau 	mt76_worker_schedule(w);
113*30bdd692SFelix Fietkau }
114*30bdd692SFelix Fietkau 
115*30bdd692SFelix Fietkau static inline void mt76_worker_teardown(struct mt76_worker *w)
116*30bdd692SFelix Fietkau {
117*30bdd692SFelix Fietkau 	if (!w->task)
118*30bdd692SFelix Fietkau 		return;
119*30bdd692SFelix Fietkau 
120*30bdd692SFelix Fietkau 	kthread_stop(w->task);
121*30bdd692SFelix Fietkau 	w->task = NULL;
122*30bdd692SFelix Fietkau }
123*30bdd692SFelix Fietkau 
12417f1de56SFelix Fietkau #endif
125