xref: /linux/drivers/net/wireless/mediatek/mt76/util.h (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
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>
1330bdd692SFelix Fietkau #include <net/mac80211.h>
1430bdd692SFelix Fietkau 
1530bdd692SFelix Fietkau struct mt76_worker
1630bdd692SFelix Fietkau {
1730bdd692SFelix Fietkau 	struct task_struct *task;
1830bdd692SFelix Fietkau 	void (*fn)(struct mt76_worker *);
1930bdd692SFelix Fietkau 	unsigned long state;
2030bdd692SFelix Fietkau };
2130bdd692SFelix Fietkau 
2230bdd692SFelix Fietkau enum {
2330bdd692SFelix Fietkau 	MT76_WORKER_SCHEDULED,
2430bdd692SFelix Fietkau 	MT76_WORKER_RUNNING,
2530bdd692SFelix 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 
3217f1de56SFelix Fietkau static inline void
mt76_wcid_mask_set(u32 * mask,int idx)335e616ad2SFelix Fietkau mt76_wcid_mask_set(u32 *mask, int idx)
34426e8e41SFelix Fietkau {
355e616ad2SFelix Fietkau 	mask[idx / 32] |= BIT(idx % 32);
36426e8e41SFelix Fietkau }
37426e8e41SFelix Fietkau 
38426e8e41SFelix Fietkau static inline void
mt76_wcid_mask_clear(u32 * mask,int idx)395e616ad2SFelix Fietkau mt76_wcid_mask_clear(u32 *mask, int idx)
4017f1de56SFelix Fietkau {
415e616ad2SFelix Fietkau 	mask[idx / 32] &= ~BIT(idx % 32);
4217f1de56SFelix Fietkau }
4317f1de56SFelix Fietkau 
4417f1de56SFelix Fietkau static inline void
mt76_skb_set_moredata(struct sk_buff * skb,bool enable)4517f1de56SFelix Fietkau mt76_skb_set_moredata(struct sk_buff *skb, bool enable)
4617f1de56SFelix Fietkau {
4717f1de56SFelix Fietkau 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
4817f1de56SFelix Fietkau 
4917f1de56SFelix Fietkau 	if (enable)
5017f1de56SFelix Fietkau 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
5117f1de56SFelix Fietkau 	else
5217f1de56SFelix Fietkau 		hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
5317f1de56SFelix Fietkau }
5417f1de56SFelix Fietkau 
5530bdd692SFelix Fietkau int __mt76_worker_fn(void *ptr);
5630bdd692SFelix Fietkau 
5730bdd692SFelix Fietkau static inline int
mt76_worker_setup(struct ieee80211_hw * hw,struct mt76_worker * w,void (* fn)(struct mt76_worker *),const char * name)5830bdd692SFelix Fietkau mt76_worker_setup(struct ieee80211_hw *hw, struct mt76_worker *w,
5930bdd692SFelix Fietkau 		  void (*fn)(struct mt76_worker *),
6030bdd692SFelix Fietkau 		  const char *name)
6130bdd692SFelix Fietkau {
6230bdd692SFelix Fietkau 	const char *dev_name = wiphy_name(hw->wiphy);
6330bdd692SFelix Fietkau 	int ret;
6430bdd692SFelix Fietkau 
6530bdd692SFelix Fietkau 	if (fn)
6630bdd692SFelix Fietkau 		w->fn = fn;
67*f31a577aSCai Huoqing 	w->task = kthread_run(__mt76_worker_fn, w,
68*f31a577aSCai Huoqing 			      "mt76-%s %s", name, dev_name);
6930bdd692SFelix Fietkau 
70*f31a577aSCai Huoqing 	if (IS_ERR(w->task)) {
71*f31a577aSCai Huoqing 		ret = PTR_ERR(w->task);
7230bdd692SFelix Fietkau 		w->task = NULL;
7330bdd692SFelix Fietkau 		return ret;
7430bdd692SFelix Fietkau 	}
7530bdd692SFelix Fietkau 
7630bdd692SFelix Fietkau 	return 0;
7730bdd692SFelix Fietkau }
7830bdd692SFelix Fietkau 
mt76_worker_schedule(struct mt76_worker * w)7930bdd692SFelix Fietkau static inline void mt76_worker_schedule(struct mt76_worker *w)
8030bdd692SFelix Fietkau {
8130bdd692SFelix Fietkau 	if (!w->task)
8230bdd692SFelix Fietkau 		return;
8330bdd692SFelix Fietkau 
8430bdd692SFelix Fietkau 	if (!test_and_set_bit(MT76_WORKER_SCHEDULED, &w->state) &&
8530bdd692SFelix Fietkau 	    !test_bit(MT76_WORKER_RUNNING, &w->state))
8630bdd692SFelix Fietkau 		wake_up_process(w->task);
8730bdd692SFelix Fietkau }
8830bdd692SFelix Fietkau 
mt76_worker_disable(struct mt76_worker * w)8930bdd692SFelix Fietkau static inline void mt76_worker_disable(struct mt76_worker *w)
9030bdd692SFelix Fietkau {
9130bdd692SFelix Fietkau 	if (!w->task)
9230bdd692SFelix Fietkau 		return;
9330bdd692SFelix Fietkau 
9430bdd692SFelix Fietkau 	kthread_park(w->task);
9530bdd692SFelix Fietkau 	WRITE_ONCE(w->state, 0);
9630bdd692SFelix Fietkau }
9730bdd692SFelix Fietkau 
mt76_worker_enable(struct mt76_worker * w)9830bdd692SFelix Fietkau static inline void mt76_worker_enable(struct mt76_worker *w)
9930bdd692SFelix Fietkau {
10030bdd692SFelix Fietkau 	if (!w->task)
10130bdd692SFelix Fietkau 		return;
10230bdd692SFelix Fietkau 
10330bdd692SFelix Fietkau 	kthread_unpark(w->task);
10430bdd692SFelix Fietkau 	mt76_worker_schedule(w);
10530bdd692SFelix Fietkau }
10630bdd692SFelix Fietkau 
mt76_worker_teardown(struct mt76_worker * w)10730bdd692SFelix Fietkau static inline void mt76_worker_teardown(struct mt76_worker *w)
10830bdd692SFelix Fietkau {
10930bdd692SFelix Fietkau 	if (!w->task)
11030bdd692SFelix Fietkau 		return;
11130bdd692SFelix Fietkau 
11230bdd692SFelix Fietkau 	kthread_stop(w->task);
11330bdd692SFelix Fietkau 	w->task = NULL;
11430bdd692SFelix Fietkau }
11530bdd692SFelix Fietkau 
11617f1de56SFelix Fietkau #endif
117