0001
0002
0003
0004
0005
0006
0007 #ifndef __MT76_UTIL_H
0008 #define __MT76_UTIL_H
0009
0010 #include <linux/skbuff.h>
0011 #include <linux/bitops.h>
0012 #include <linux/bitfield.h>
0013 #include <net/mac80211.h>
0014
0015 struct mt76_worker
0016 {
0017 struct task_struct *task;
0018 void (*fn)(struct mt76_worker *);
0019 unsigned long state;
0020 };
0021
0022 enum {
0023 MT76_WORKER_SCHEDULED,
0024 MT76_WORKER_RUNNING,
0025 };
0026
0027 #define MT76_INCR(_var, _size) \
0028 (_var = (((_var) + 1) % (_size)))
0029
0030 int mt76_wcid_alloc(u32 *mask, int size);
0031
0032 static inline bool
0033 mt76_wcid_mask_test(u32 *mask, int idx)
0034 {
0035 return mask[idx / 32] & BIT(idx % 32);
0036 }
0037
0038 static inline void
0039 mt76_wcid_mask_set(u32 *mask, int idx)
0040 {
0041 mask[idx / 32] |= BIT(idx % 32);
0042 }
0043
0044 static inline void
0045 mt76_wcid_mask_clear(u32 *mask, int idx)
0046 {
0047 mask[idx / 32] &= ~BIT(idx % 32);
0048 }
0049
0050 static inline void
0051 mt76_skb_set_moredata(struct sk_buff *skb, bool enable)
0052 {
0053 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
0054
0055 if (enable)
0056 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
0057 else
0058 hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
0059 }
0060
0061 int __mt76_worker_fn(void *ptr);
0062
0063 static inline int
0064 mt76_worker_setup(struct ieee80211_hw *hw, struct mt76_worker *w,
0065 void (*fn)(struct mt76_worker *),
0066 const char *name)
0067 {
0068 const char *dev_name = wiphy_name(hw->wiphy);
0069 int ret;
0070
0071 if (fn)
0072 w->fn = fn;
0073 w->task = kthread_run(__mt76_worker_fn, w,
0074 "mt76-%s %s", name, dev_name);
0075
0076 if (IS_ERR(w->task)) {
0077 ret = PTR_ERR(w->task);
0078 w->task = NULL;
0079 return ret;
0080 }
0081
0082 return 0;
0083 }
0084
0085 static inline void mt76_worker_schedule(struct mt76_worker *w)
0086 {
0087 if (!w->task)
0088 return;
0089
0090 if (!test_and_set_bit(MT76_WORKER_SCHEDULED, &w->state) &&
0091 !test_bit(MT76_WORKER_RUNNING, &w->state))
0092 wake_up_process(w->task);
0093 }
0094
0095 static inline void mt76_worker_disable(struct mt76_worker *w)
0096 {
0097 if (!w->task)
0098 return;
0099
0100 kthread_park(w->task);
0101 WRITE_ONCE(w->state, 0);
0102 }
0103
0104 static inline void mt76_worker_enable(struct mt76_worker *w)
0105 {
0106 if (!w->task)
0107 return;
0108
0109 kthread_unpark(w->task);
0110 mt76_worker_schedule(w);
0111 }
0112
0113 static inline void mt76_worker_teardown(struct mt76_worker *w)
0114 {
0115 if (!w->task)
0116 return;
0117
0118 kthread_stop(w->task);
0119 w->task = NULL;
0120 }
0121
0122 #endif