16c92544dSBjoern A. Zeeb /*-
26c92544dSBjoern A. Zeeb * SPDX-License-Identifier: BSD-2-Clause
36c92544dSBjoern A. Zeeb *
4*cbb3ec25SBjoern A. Zeeb * Copyright (c) 2020,2022-2023 Bjoern A. Zeeb <bz@FreeBSD.org>
56c92544dSBjoern A. Zeeb *
66c92544dSBjoern A. Zeeb * Redistribution and use in source and binary forms, with or without
76c92544dSBjoern A. Zeeb * modification, are permitted provided that the following conditions
86c92544dSBjoern A. Zeeb * are met:
96c92544dSBjoern A. Zeeb * 1. Redistributions of source code must retain the above copyright
106c92544dSBjoern A. Zeeb * notice, this list of conditions and the following disclaimer.
116c92544dSBjoern A. Zeeb * 2. Redistributions in binary form must reproduce the above copyright
126c92544dSBjoern A. Zeeb * notice, this list of conditions and the following disclaimer in the
136c92544dSBjoern A. Zeeb * documentation and/or other materials provided with the distribution.
146c92544dSBjoern A. Zeeb *
156c92544dSBjoern A. Zeeb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
166c92544dSBjoern A. Zeeb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
176c92544dSBjoern A. Zeeb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
186c92544dSBjoern A. Zeeb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
196c92544dSBjoern A. Zeeb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
206c92544dSBjoern A. Zeeb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
216c92544dSBjoern A. Zeeb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
226c92544dSBjoern A. Zeeb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
236c92544dSBjoern A. Zeeb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
246c92544dSBjoern A. Zeeb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
256c92544dSBjoern A. Zeeb * SUCH DAMAGE.
266c92544dSBjoern A. Zeeb *
276c92544dSBjoern A. Zeeb * $FreeBSD$
286c92544dSBjoern A. Zeeb */
296c92544dSBjoern A. Zeeb
306c92544dSBjoern A. Zeeb #ifndef _MT76_UTIL_H
316c92544dSBjoern A. Zeeb #define _MT76_UTIL_H
326c92544dSBjoern A. Zeeb
336c92544dSBjoern A. Zeeb #include <linux/kthread.h>
346c92544dSBjoern A. Zeeb
356c92544dSBjoern A. Zeeb struct mt76_worker
366c92544dSBjoern A. Zeeb {
376c92544dSBjoern A. Zeeb void(*fn)(struct mt76_worker *);
386c92544dSBjoern A. Zeeb struct task_struct *task;
396c92544dSBjoern A. Zeeb unsigned long state;
406c92544dSBjoern A. Zeeb };
416c92544dSBjoern A. Zeeb
426c92544dSBjoern A. Zeeb enum mt76_worker_state {
436c92544dSBjoern A. Zeeb MT76_WORKER_SCHEDULED,
446c92544dSBjoern A. Zeeb MT76_WORKER_RUNNING,
456c92544dSBjoern A. Zeeb };
466c92544dSBjoern A. Zeeb
476c92544dSBjoern A. Zeeb #if 0
486c92544dSBjoern A. Zeeb bool __mt76_poll(struct mt76_dev *, u32, u32, u32, int);
496c92544dSBjoern A. Zeeb bool __mt76_poll_msec(struct mt76_dev *, u32, u32, u32, int);
506c92544dSBjoern A. Zeeb int mt76_get_min_avg_rssi(struct mt76_dev *, bool);
516c92544dSBjoern A. Zeeb #endif
526c92544dSBjoern A. Zeeb int mt76_wcid_alloc(u32 *, int);
536c92544dSBjoern A. Zeeb int __mt76_worker_fn(void *);
546c92544dSBjoern A. Zeeb
556c92544dSBjoern A. Zeeb /* wcid_phy_mask is [32] */
566c92544dSBjoern A. Zeeb static inline void
mt76_wcid_mask_set(u32 * mask,u16 bit)576c92544dSBjoern A. Zeeb mt76_wcid_mask_set(u32 *mask, u16 bit)
586c92544dSBjoern A. Zeeb {
596c92544dSBjoern A. Zeeb
606c92544dSBjoern A. Zeeb mask[bit / 32] |= BIT(bit % 32);
616c92544dSBjoern A. Zeeb }
626c92544dSBjoern A. Zeeb
636c92544dSBjoern A. Zeeb static inline void
mt76_wcid_mask_clear(u32 * mask,u16 bit)646c92544dSBjoern A. Zeeb mt76_wcid_mask_clear(u32 *mask, u16 bit)
656c92544dSBjoern A. Zeeb {
666c92544dSBjoern A. Zeeb
676c92544dSBjoern A. Zeeb mask[bit / 32] &= ~BIT(bit % 32);
686c92544dSBjoern A. Zeeb }
696c92544dSBjoern A. Zeeb
706c92544dSBjoern A. Zeeb /* See, e.g., __mt76_worker_fn for some details. */
716c92544dSBjoern A. Zeeb static inline int
mt76_worker_setup(struct ieee80211_hw * hw,struct mt76_worker * w,void (* wfunc)(struct mt76_worker *),const char * name)726c92544dSBjoern A. Zeeb mt76_worker_setup(struct ieee80211_hw *hw, struct mt76_worker *w,
736c92544dSBjoern A. Zeeb void (*wfunc)(struct mt76_worker *), const char *name)
746c92544dSBjoern A. Zeeb {
756c92544dSBjoern A. Zeeb int rc;
766c92544dSBjoern A. Zeeb
776c92544dSBjoern A. Zeeb if (wfunc)
786c92544dSBjoern A. Zeeb w->fn = wfunc;
796c92544dSBjoern A. Zeeb
806c92544dSBjoern A. Zeeb w->task = kthread_run(__mt76_worker_fn, w,
816c92544dSBjoern A. Zeeb "mt76-worker");
826c92544dSBjoern A. Zeeb
836c92544dSBjoern A. Zeeb if (!IS_ERR(w->task))
846c92544dSBjoern A. Zeeb return (0);
856c92544dSBjoern A. Zeeb
866c92544dSBjoern A. Zeeb rc = PTR_ERR(w->task);
876c92544dSBjoern A. Zeeb w->task = NULL;
886c92544dSBjoern A. Zeeb return (rc);
896c92544dSBjoern A. Zeeb }
906c92544dSBjoern A. Zeeb
916c92544dSBjoern A. Zeeb static inline void
mt76_worker_schedule(struct mt76_worker * w)926c92544dSBjoern A. Zeeb mt76_worker_schedule(struct mt76_worker *w)
936c92544dSBjoern A. Zeeb {
946c92544dSBjoern A. Zeeb
956c92544dSBjoern A. Zeeb if (w->task == NULL)
966c92544dSBjoern A. Zeeb return;
976c92544dSBjoern A. Zeeb
986c92544dSBjoern A. Zeeb if (!test_and_set_bit(MT76_WORKER_SCHEDULED, &w->state) ||
996c92544dSBjoern A. Zeeb !test_bit(MT76_WORKER_RUNNING, &w->state))
1006c92544dSBjoern A. Zeeb wake_up_process(w->task);
1016c92544dSBjoern A. Zeeb }
1026c92544dSBjoern A. Zeeb
1036c92544dSBjoern A. Zeeb static inline void
mt76_worker_enable(struct mt76_worker * w)1046c92544dSBjoern A. Zeeb mt76_worker_enable(struct mt76_worker *w)
1056c92544dSBjoern A. Zeeb {
1066c92544dSBjoern A. Zeeb
1076c92544dSBjoern A. Zeeb if (w->task == NULL)
1086c92544dSBjoern A. Zeeb return;
1096c92544dSBjoern A. Zeeb
1106c92544dSBjoern A. Zeeb kthread_unpark(w->task);
1116c92544dSBjoern A. Zeeb mt76_worker_schedule(w);
1126c92544dSBjoern A. Zeeb }
1136c92544dSBjoern A. Zeeb
1146c92544dSBjoern A. Zeeb static inline void
mt76_worker_disable(struct mt76_worker * w)1156c92544dSBjoern A. Zeeb mt76_worker_disable(struct mt76_worker *w)
1166c92544dSBjoern A. Zeeb {
1176c92544dSBjoern A. Zeeb
1186c92544dSBjoern A. Zeeb if (w->task == NULL)
1196c92544dSBjoern A. Zeeb return;
1206c92544dSBjoern A. Zeeb
1216c92544dSBjoern A. Zeeb kthread_park(w->task);
1226c92544dSBjoern A. Zeeb WRITE_ONCE(w->state, 0);
1236c92544dSBjoern A. Zeeb }
1246c92544dSBjoern A. Zeeb
1256c92544dSBjoern A. Zeeb static inline void
mt76_worker_teardown(struct mt76_worker * w)1266c92544dSBjoern A. Zeeb mt76_worker_teardown(struct mt76_worker *w)
1276c92544dSBjoern A. Zeeb {
1286c92544dSBjoern A. Zeeb
1296c92544dSBjoern A. Zeeb if (w->task == NULL)
1306c92544dSBjoern A. Zeeb return;
1316c92544dSBjoern A. Zeeb
1326c92544dSBjoern A. Zeeb kthread_stop(w->task);
1336c92544dSBjoern A. Zeeb w->task = NULL;
1346c92544dSBjoern A. Zeeb }
1356c92544dSBjoern A. Zeeb
1366c92544dSBjoern A. Zeeb static inline void
mt76_skb_set_moredata(struct sk_buff * skb,bool moredata)1376c92544dSBjoern A. Zeeb mt76_skb_set_moredata(struct sk_buff *skb, bool moredata)
1386c92544dSBjoern A. Zeeb {
1396c92544dSBjoern A. Zeeb /*
1406c92544dSBjoern A. Zeeb * This would be net80211::IEEE80211_FC1_MORE_DATA
1416c92544dSBjoern A. Zeeb * Implement it as mostly LinuxKPI 802.11 to avoid
1426c92544dSBjoern A. Zeeb * further header pollution and possible conflicts.
1436c92544dSBjoern A. Zeeb */
1446c92544dSBjoern A. Zeeb struct ieee80211_hdr *hdr;
1456c92544dSBjoern A. Zeeb uint16_t val;
1466c92544dSBjoern A. Zeeb
1476c92544dSBjoern A. Zeeb hdr = (struct ieee80211_hdr *)skb->data;
1486c92544dSBjoern A. Zeeb val = cpu_to_le16(IEEE80211_FC1_MORE_DATA << 8);
1496c92544dSBjoern A. Zeeb if (!moredata)
1506c92544dSBjoern A. Zeeb hdr->frame_control &= ~val;
1516c92544dSBjoern A. Zeeb else
1526c92544dSBjoern A. Zeeb hdr->frame_control |= val;
1536c92544dSBjoern A. Zeeb }
1546c92544dSBjoern A. Zeeb
1556c92544dSBjoern A. Zeeb #endif /* _MT76_UTIL_H */
156