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