Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
0004  * Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
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