Linux Audio

Check our new training course

Loading...
  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
 15struct mt76_worker
 16{
 17	struct task_struct *task;
 18	void (*fn)(struct mt76_worker *);
 19	unsigned long state;
 20};
 21
 22enum {
 23	MT76_WORKER_SCHEDULED,
 24	MT76_WORKER_RUNNING,
 25};
 26
 27#define MT76_INCR(_var, _size) \
 28	(_var = (((_var) + 1) % (_size)))
 29
 30int mt76_wcid_alloc(u32 *mask, int size);
 31
 32static inline void
 33mt76_wcid_mask_set(u32 *mask, int idx)
 34{
 35	mask[idx / 32] |= BIT(idx % 32);
 36}
 37
 38static inline void
 39mt76_wcid_mask_clear(u32 *mask, int idx)
 40{
 41	mask[idx / 32] &= ~BIT(idx % 32);
 42}
 43
 44static inline void
 45mt76_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
 55int __mt76_worker_fn(void *ptr);
 56
 57static inline int
 58mt76_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
 79static 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
 89static 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
 98static 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
107static 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