xref: /linux/drivers/net/wireless/mediatek/mt76/util.h (revision f31a577ae7365bcdaaedbb2064be78e2c4f2946f)
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 
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 
6130bdd692SFelix Fietkau int __mt76_worker_fn(void *ptr);
6230bdd692SFelix Fietkau 
6330bdd692SFelix Fietkau static inline int
6430bdd692SFelix Fietkau mt76_worker_setup(struct ieee80211_hw *hw, struct mt76_worker *w,
6530bdd692SFelix Fietkau 		  void (*fn)(struct mt76_worker *),
6630bdd692SFelix Fietkau 		  const char *name)
6730bdd692SFelix Fietkau {
6830bdd692SFelix Fietkau 	const char *dev_name = wiphy_name(hw->wiphy);
6930bdd692SFelix Fietkau 	int ret;
7030bdd692SFelix Fietkau 
7130bdd692SFelix Fietkau 	if (fn)
7230bdd692SFelix Fietkau 		w->fn = fn;
73*f31a577aSCai Huoqing 	w->task = kthread_run(__mt76_worker_fn, w,
74*f31a577aSCai Huoqing 			      "mt76-%s %s", name, dev_name);
7530bdd692SFelix Fietkau 
76*f31a577aSCai Huoqing 	if (IS_ERR(w->task)) {
77*f31a577aSCai Huoqing 		ret = PTR_ERR(w->task);
7830bdd692SFelix Fietkau 		w->task = NULL;
7930bdd692SFelix Fietkau 		return ret;
8030bdd692SFelix Fietkau 	}
8130bdd692SFelix Fietkau 
8230bdd692SFelix Fietkau 	return 0;
8330bdd692SFelix Fietkau }
8430bdd692SFelix Fietkau 
8530bdd692SFelix Fietkau static inline void mt76_worker_schedule(struct mt76_worker *w)
8630bdd692SFelix Fietkau {
8730bdd692SFelix Fietkau 	if (!w->task)
8830bdd692SFelix Fietkau 		return;
8930bdd692SFelix Fietkau 
9030bdd692SFelix Fietkau 	if (!test_and_set_bit(MT76_WORKER_SCHEDULED, &w->state) &&
9130bdd692SFelix Fietkau 	    !test_bit(MT76_WORKER_RUNNING, &w->state))
9230bdd692SFelix Fietkau 		wake_up_process(w->task);
9330bdd692SFelix Fietkau }
9430bdd692SFelix Fietkau 
9530bdd692SFelix Fietkau static inline void mt76_worker_disable(struct mt76_worker *w)
9630bdd692SFelix Fietkau {
9730bdd692SFelix Fietkau 	if (!w->task)
9830bdd692SFelix Fietkau 		return;
9930bdd692SFelix Fietkau 
10030bdd692SFelix Fietkau 	kthread_park(w->task);
10130bdd692SFelix Fietkau 	WRITE_ONCE(w->state, 0);
10230bdd692SFelix Fietkau }
10330bdd692SFelix Fietkau 
10430bdd692SFelix Fietkau static inline void mt76_worker_enable(struct mt76_worker *w)
10530bdd692SFelix Fietkau {
10630bdd692SFelix Fietkau 	if (!w->task)
10730bdd692SFelix Fietkau 		return;
10830bdd692SFelix Fietkau 
10930bdd692SFelix Fietkau 	kthread_unpark(w->task);
11030bdd692SFelix Fietkau 	mt76_worker_schedule(w);
11130bdd692SFelix Fietkau }
11230bdd692SFelix Fietkau 
11330bdd692SFelix Fietkau static inline void mt76_worker_teardown(struct mt76_worker *w)
11430bdd692SFelix Fietkau {
11530bdd692SFelix Fietkau 	if (!w->task)
11630bdd692SFelix Fietkau 		return;
11730bdd692SFelix Fietkau 
11830bdd692SFelix Fietkau 	kthread_stop(w->task);
11930bdd692SFelix Fietkau 	w->task = NULL;
12030bdd692SFelix Fietkau }
12130bdd692SFelix Fietkau 
12217f1de56SFelix Fietkau #endif
123