xref: /freebsd/sys/compat/linuxkpi/common/src/linux_80211_macops.c (revision 7b43f4d064195bcf66816cb9fe350a1392fe24ce)
16b4cac81SBjoern A. Zeeb /*-
2d9f59799SBjoern A. Zeeb  * Copyright (c) 2021-2022 The FreeBSD Foundation
36b4cac81SBjoern A. Zeeb  *
46b4cac81SBjoern A. Zeeb  * This software was developed by Björn Zeeb under sponsorship from
56b4cac81SBjoern A. Zeeb  * the FreeBSD Foundation.
66b4cac81SBjoern A. Zeeb  *
76b4cac81SBjoern A. Zeeb  * Redistribution and use in source and binary forms, with or without
86b4cac81SBjoern A. Zeeb  * modification, are permitted provided that the following conditions
96b4cac81SBjoern A. Zeeb  * are met:
106b4cac81SBjoern A. Zeeb  * 1. Redistributions of source code must retain the above copyright
116b4cac81SBjoern A. Zeeb  *    notice, this list of conditions and the following disclaimer.
126b4cac81SBjoern A. Zeeb  * 2. Redistributions in binary form must reproduce the above copyright
136b4cac81SBjoern A. Zeeb  *    notice, this list of conditions and the following disclaimer in the
146b4cac81SBjoern A. Zeeb  *    documentation and/or other materials provided with the distribution.
156b4cac81SBjoern A. Zeeb  *
166b4cac81SBjoern A. Zeeb  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
176b4cac81SBjoern A. Zeeb  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
186b4cac81SBjoern A. Zeeb  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
196b4cac81SBjoern A. Zeeb  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
206b4cac81SBjoern A. Zeeb  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
216b4cac81SBjoern A. Zeeb  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
226b4cac81SBjoern A. Zeeb  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
236b4cac81SBjoern A. Zeeb  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
246b4cac81SBjoern A. Zeeb  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
256b4cac81SBjoern A. Zeeb  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
266b4cac81SBjoern A. Zeeb  * SUCH DAMAGE.
276b4cac81SBjoern A. Zeeb  */
286b4cac81SBjoern A. Zeeb 
296b4cac81SBjoern A. Zeeb #include <sys/param.h>
306b4cac81SBjoern A. Zeeb #include <sys/types.h>
316b4cac81SBjoern A. Zeeb #include <sys/kernel.h>
326b4cac81SBjoern A. Zeeb #include <sys/errno.h>
336b4cac81SBjoern A. Zeeb 
346b4cac81SBjoern A. Zeeb #define	LINUXKPI_NET80211
356b4cac81SBjoern A. Zeeb #include <net/mac80211.h>
366b4cac81SBjoern A. Zeeb 
376b4cac81SBjoern A. Zeeb #include "linux_80211.h"
386b4cac81SBjoern A. Zeeb 
3964d3da00SBjoern A. Zeeb /* Could be a different tracing framework later. */
4064d3da00SBjoern A. Zeeb #ifdef LINUXKPI_DEBUG_80211
4164d3da00SBjoern A. Zeeb #define	LKPI_80211_TRACE_MO(fmt, ...)					\
4264d3da00SBjoern A. Zeeb     if (linuxkpi_debug_80211 & D80211_TRACE_MO)				\
433206587aSBjoern A. Zeeb 	printf("LKPI_80211_TRACE_MO %s:%d: %d %d %u_" fmt "\n",		\
443206587aSBjoern A. Zeeb 	    __func__, __LINE__, curcpu, curthread->td_tid,		\
453206587aSBjoern A. Zeeb 	    (unsigned int)ticks, __VA_ARGS__)
4664d3da00SBjoern A. Zeeb #else
4764d3da00SBjoern A. Zeeb #define	LKPI_80211_TRACE_MO(...)	do { } while(0)
4864d3da00SBjoern A. Zeeb #endif
4964d3da00SBjoern A. Zeeb 
506b4cac81SBjoern A. Zeeb int
516b4cac81SBjoern A. Zeeb lkpi_80211_mo_start(struct ieee80211_hw *hw)
526b4cac81SBjoern A. Zeeb {
536b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
546b4cac81SBjoern A. Zeeb 	int error;
556b4cac81SBjoern A. Zeeb 
566b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
576b4cac81SBjoern A. Zeeb 	if (lhw->ops->start == NULL) {
586b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
596b4cac81SBjoern A. Zeeb 		goto out;
606b4cac81SBjoern A. Zeeb 	}
616b4cac81SBjoern A. Zeeb 
626b4cac81SBjoern A. Zeeb 	if ((lhw->sc_flags & LKPI_MAC80211_DRV_STARTED)) {
636b4cac81SBjoern A. Zeeb 		/* Trying to start twice is an error. */
646b4cac81SBjoern A. Zeeb 		error = EEXIST;
656b4cac81SBjoern A. Zeeb 		goto out;
666b4cac81SBjoern A. Zeeb 	}
6764d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p", hw);
686b4cac81SBjoern A. Zeeb 	error = lhw->ops->start(hw);
696b4cac81SBjoern A. Zeeb 	if (error == 0)
706b4cac81SBjoern A. Zeeb 		lhw->sc_flags |= LKPI_MAC80211_DRV_STARTED;
716b4cac81SBjoern A. Zeeb 
726b4cac81SBjoern A. Zeeb out:
736b4cac81SBjoern A. Zeeb 	return (error);
746b4cac81SBjoern A. Zeeb }
756b4cac81SBjoern A. Zeeb 
766b4cac81SBjoern A. Zeeb void
77*7b43f4d0SBjoern A. Zeeb lkpi_80211_mo_stop(struct ieee80211_hw *hw, bool suspend)
786b4cac81SBjoern A. Zeeb {
796b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
806b4cac81SBjoern A. Zeeb 
816b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
826b4cac81SBjoern A. Zeeb 	if (lhw->ops->stop == NULL)
836b4cac81SBjoern A. Zeeb 		return;
846b4cac81SBjoern A. Zeeb 
85*7b43f4d0SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p suspend %d", hw, suspend);
86*7b43f4d0SBjoern A. Zeeb 	lhw->ops->stop(hw, suspend);
876b4cac81SBjoern A. Zeeb 	lhw->sc_flags &= ~LKPI_MAC80211_DRV_STARTED;
886b4cac81SBjoern A. Zeeb }
896b4cac81SBjoern A. Zeeb 
906b4cac81SBjoern A. Zeeb int
91527687a9SBjoern A. Zeeb lkpi_80211_mo_get_antenna(struct ieee80211_hw *hw, u32 *txs, u32 *rxs)
92527687a9SBjoern A. Zeeb {
93527687a9SBjoern A. Zeeb 	struct lkpi_hw *lhw;
94527687a9SBjoern A. Zeeb 	int error;
95527687a9SBjoern A. Zeeb 
96527687a9SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
97527687a9SBjoern A. Zeeb 	if (lhw->ops->get_antenna == NULL) {
98527687a9SBjoern A. Zeeb 		error = EOPNOTSUPP;
99527687a9SBjoern A. Zeeb 		goto out;
100527687a9SBjoern A. Zeeb 	}
101527687a9SBjoern A. Zeeb 
10264d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p", hw);
103527687a9SBjoern A. Zeeb 	error = lhw->ops->get_antenna(hw, txs, rxs);
104527687a9SBjoern A. Zeeb 
105527687a9SBjoern A. Zeeb out:
106527687a9SBjoern A. Zeeb 	return (error);
107527687a9SBjoern A. Zeeb }
108527687a9SBjoern A. Zeeb 
109527687a9SBjoern A. Zeeb int
1106b4cac81SBjoern A. Zeeb lkpi_80211_mo_set_frag_threshold(struct ieee80211_hw *hw, uint32_t frag_th)
1116b4cac81SBjoern A. Zeeb {
1126b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
1136b4cac81SBjoern A. Zeeb 	int error;
1146b4cac81SBjoern A. Zeeb 
1156b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
1166b4cac81SBjoern A. Zeeb 	if (lhw->ops->set_frag_threshold == NULL) {
1176b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
1186b4cac81SBjoern A. Zeeb 		goto out;
1196b4cac81SBjoern A. Zeeb 	}
1206b4cac81SBjoern A. Zeeb 
12164d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p frag_th %u", hw, frag_th);
1226b4cac81SBjoern A. Zeeb 	error = lhw->ops->set_frag_threshold(hw, frag_th);
1236b4cac81SBjoern A. Zeeb 
1246b4cac81SBjoern A. Zeeb out:
1256b4cac81SBjoern A. Zeeb 	return (error);
1266b4cac81SBjoern A. Zeeb }
1276b4cac81SBjoern A. Zeeb 
1286b4cac81SBjoern A. Zeeb int
1296b4cac81SBjoern A. Zeeb lkpi_80211_mo_set_rts_threshold(struct ieee80211_hw *hw, uint32_t rts_th)
1306b4cac81SBjoern A. Zeeb {
1316b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
1326b4cac81SBjoern A. Zeeb 	int error;
1336b4cac81SBjoern A. Zeeb 
1346b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
1356b4cac81SBjoern A. Zeeb 	if (lhw->ops->set_rts_threshold == NULL) {
1366b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
1376b4cac81SBjoern A. Zeeb 		goto out;
1386b4cac81SBjoern A. Zeeb 	}
1396b4cac81SBjoern A. Zeeb 
14064d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p rts_th %u", hw, rts_th);
1416b4cac81SBjoern A. Zeeb 	error = lhw->ops->set_rts_threshold(hw, rts_th);
1426b4cac81SBjoern A. Zeeb 
1436b4cac81SBjoern A. Zeeb out:
1446b4cac81SBjoern A. Zeeb 	return (error);
1456b4cac81SBjoern A. Zeeb }
1466b4cac81SBjoern A. Zeeb 
1476b4cac81SBjoern A. Zeeb 
1486b4cac81SBjoern A. Zeeb int
1496b4cac81SBjoern A. Zeeb lkpi_80211_mo_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1506b4cac81SBjoern A. Zeeb {
1516b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
1526b4cac81SBjoern A. Zeeb 	struct lkpi_vif *lvif;
1536b4cac81SBjoern A. Zeeb 	int error;
1546b4cac81SBjoern A. Zeeb 
1556b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
1566b4cac81SBjoern A. Zeeb 	if (lhw->ops->add_interface == NULL) {
1576b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
1586b4cac81SBjoern A. Zeeb 		goto out;
1596b4cac81SBjoern A. Zeeb 	}
1606b4cac81SBjoern A. Zeeb 
1616b4cac81SBjoern A. Zeeb 	lvif = VIF_TO_LVIF(vif);
1626b4cac81SBjoern A. Zeeb 	LKPI_80211_LVIF_LOCK(lvif);
1636b4cac81SBjoern A. Zeeb 	if (lvif->added_to_drv) {
1646b4cac81SBjoern A. Zeeb 		LKPI_80211_LVIF_UNLOCK(lvif);
1656b4cac81SBjoern A. Zeeb 		/* Trying to add twice is an error. */
1666b4cac81SBjoern A. Zeeb 		error = EEXIST;
1676b4cac81SBjoern A. Zeeb 		goto out;
1686b4cac81SBjoern A. Zeeb 	}
1696b4cac81SBjoern A. Zeeb 	LKPI_80211_LVIF_UNLOCK(lvif);
1706b4cac81SBjoern A. Zeeb 
17164d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p", hw, vif);
1726b4cac81SBjoern A. Zeeb 	error = lhw->ops->add_interface(hw, vif);
1736b4cac81SBjoern A. Zeeb 	if (error == 0) {
1746b4cac81SBjoern A. Zeeb 		LKPI_80211_LVIF_LOCK(lvif);
1756b4cac81SBjoern A. Zeeb 		lvif->added_to_drv = true;
1766b4cac81SBjoern A. Zeeb 		LKPI_80211_LVIF_UNLOCK(lvif);
1776b4cac81SBjoern A. Zeeb 	}
1786b4cac81SBjoern A. Zeeb 
1796b4cac81SBjoern A. Zeeb out:
1806b4cac81SBjoern A. Zeeb 	return (error);
1816b4cac81SBjoern A. Zeeb }
1826b4cac81SBjoern A. Zeeb 
1836b4cac81SBjoern A. Zeeb void
1846b4cac81SBjoern A. Zeeb lkpi_80211_mo_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1856b4cac81SBjoern A. Zeeb {
1866b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
1876b4cac81SBjoern A. Zeeb 	struct lkpi_vif *lvif;
1886b4cac81SBjoern A. Zeeb 
1896b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
1906b4cac81SBjoern A. Zeeb 	if (lhw->ops->remove_interface == NULL)
1916b4cac81SBjoern A. Zeeb 		return;
1926b4cac81SBjoern A. Zeeb 
1936b4cac81SBjoern A. Zeeb 	lvif = VIF_TO_LVIF(vif);
1946b4cac81SBjoern A. Zeeb 	LKPI_80211_LVIF_LOCK(lvif);
1956b4cac81SBjoern A. Zeeb 	if (!lvif->added_to_drv) {
1966b4cac81SBjoern A. Zeeb 		LKPI_80211_LVIF_UNLOCK(lvif);
1976b4cac81SBjoern A. Zeeb 		return;
1986b4cac81SBjoern A. Zeeb 	}
1996b4cac81SBjoern A. Zeeb 	LKPI_80211_LVIF_UNLOCK(lvif);
2006b4cac81SBjoern A. Zeeb 
20164d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p", hw, vif);
2026b4cac81SBjoern A. Zeeb 	lhw->ops->remove_interface(hw, vif);
2036b4cac81SBjoern A. Zeeb 	LKPI_80211_LVIF_LOCK(lvif);
2046b4cac81SBjoern A. Zeeb 	lvif->added_to_drv = false;
2056b4cac81SBjoern A. Zeeb 	LKPI_80211_LVIF_UNLOCK(lvif);
2066b4cac81SBjoern A. Zeeb }
2076b4cac81SBjoern A. Zeeb 
2086b4cac81SBjoern A. Zeeb 
2096b4cac81SBjoern A. Zeeb int
2106b4cac81SBjoern A. Zeeb lkpi_80211_mo_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2116b4cac81SBjoern A. Zeeb     struct ieee80211_scan_request *sr)
2126b4cac81SBjoern A. Zeeb {
2136b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
2146b4cac81SBjoern A. Zeeb 	int error;
2156b4cac81SBjoern A. Zeeb 
2163206587aSBjoern A. Zeeb 	/*
2173206587aSBjoern A. Zeeb 	 * MUST NOT return EPERM as that is a "magic number 1" based on rtw88
2183206587aSBjoern A. Zeeb 	 * driver indicating hw_scan is not supported despite the ops call
2193206587aSBjoern A. Zeeb 	 * being available.
2203206587aSBjoern A. Zeeb 	 */
2213206587aSBjoern A. Zeeb 
2226b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
2236b4cac81SBjoern A. Zeeb 	if (lhw->ops->hw_scan == NULL) {
2243206587aSBjoern A. Zeeb 		/* Return magic number to use sw scan. */
2253206587aSBjoern A. Zeeb 		error = 1;
2266b4cac81SBjoern A. Zeeb 		goto out;
2276b4cac81SBjoern A. Zeeb 	}
2286b4cac81SBjoern A. Zeeb 
2293206587aSBjoern A. Zeeb 	LKPI_80211_TRACE_MO("CALLING hw %p vif %p sr %p", hw, vif, sr);
2306b4cac81SBjoern A. Zeeb 	error = lhw->ops->hw_scan(hw, vif, sr);
2313206587aSBjoern A. Zeeb 	LKPI_80211_TRACE_MO("RETURNING hw %p vif %p sr %p error %d", hw, vif, sr, error);
2326b4cac81SBjoern A. Zeeb 
2336b4cac81SBjoern A. Zeeb out:
2346b4cac81SBjoern A. Zeeb 	return (error);
2356b4cac81SBjoern A. Zeeb }
2366b4cac81SBjoern A. Zeeb 
2376b4cac81SBjoern A. Zeeb void
2386b4cac81SBjoern A. Zeeb lkpi_80211_mo_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
2396b4cac81SBjoern A. Zeeb {
2406b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
2416b4cac81SBjoern A. Zeeb 
2426b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
2436b4cac81SBjoern A. Zeeb 	if (lhw->ops->cancel_hw_scan == NULL)
2446b4cac81SBjoern A. Zeeb 		return;
2456b4cac81SBjoern A. Zeeb 
24664d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p", hw, vif);
2476b4cac81SBjoern A. Zeeb 	lhw->ops->cancel_hw_scan(hw, vif);
2486b4cac81SBjoern A. Zeeb }
2496b4cac81SBjoern A. Zeeb 
2506b4cac81SBjoern A. Zeeb void
2516b4cac81SBjoern A. Zeeb lkpi_80211_mo_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
2526b4cac81SBjoern A. Zeeb {
2536b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
2546b4cac81SBjoern A. Zeeb 
2556b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
2566b4cac81SBjoern A. Zeeb 	if (lhw->ops->sw_scan_complete == NULL)
2576b4cac81SBjoern A. Zeeb 		return;
2586b4cac81SBjoern A. Zeeb 
25964d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p", hw, vif);
2606b4cac81SBjoern A. Zeeb 	lhw->ops->sw_scan_complete(hw, vif);
261a486fbbdSBjoern A. Zeeb 	lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING;
2626b4cac81SBjoern A. Zeeb }
2636b4cac81SBjoern A. Zeeb 
2646b4cac81SBjoern A. Zeeb void
2656b4cac81SBjoern A. Zeeb lkpi_80211_mo_sw_scan_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2666b4cac81SBjoern A. Zeeb     const u8 *addr)
2676b4cac81SBjoern A. Zeeb {
2686b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
2696b4cac81SBjoern A. Zeeb 
2706b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
2716b4cac81SBjoern A. Zeeb 	if (lhw->ops->sw_scan_start == NULL)
2726b4cac81SBjoern A. Zeeb 		return;
2736b4cac81SBjoern A. Zeeb 
27464d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p", hw, vif);
2756b4cac81SBjoern A. Zeeb 	lhw->ops->sw_scan_start(hw, vif, addr);
2766b4cac81SBjoern A. Zeeb }
2776b4cac81SBjoern A. Zeeb 
2786b4cac81SBjoern A. Zeeb 
2796b4cac81SBjoern A. Zeeb /*
2806b4cac81SBjoern A. Zeeb  * We keep the Linux type here;  it really is an uintptr_t.
2816b4cac81SBjoern A. Zeeb  */
2826b4cac81SBjoern A. Zeeb u64
2836b4cac81SBjoern A. Zeeb lkpi_80211_mo_prepare_multicast(struct ieee80211_hw *hw,
2846b4cac81SBjoern A. Zeeb     struct netdev_hw_addr_list *mc_list)
2856b4cac81SBjoern A. Zeeb {
2866b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
2876b4cac81SBjoern A. Zeeb 	u64 ptr;
2886b4cac81SBjoern A. Zeeb 
2896b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
2906b4cac81SBjoern A. Zeeb 	if (lhw->ops->prepare_multicast == NULL)
2916b4cac81SBjoern A. Zeeb 		return (0);
2926b4cac81SBjoern A. Zeeb 
29364d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p mc_list %p", hw, mc_list);
2946b4cac81SBjoern A. Zeeb 	ptr = lhw->ops->prepare_multicast(hw, mc_list);
2956b4cac81SBjoern A. Zeeb 	return (ptr);
2966b4cac81SBjoern A. Zeeb }
2976b4cac81SBjoern A. Zeeb 
2986b4cac81SBjoern A. Zeeb void
2996b4cac81SBjoern A. Zeeb lkpi_80211_mo_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
3006b4cac81SBjoern A. Zeeb     unsigned int *total_flags, u64 mc_ptr)
3016b4cac81SBjoern A. Zeeb {
3026b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
3036b4cac81SBjoern A. Zeeb 
3046b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
3056b4cac81SBjoern A. Zeeb 	if (lhw->ops->configure_filter == NULL)
3066b4cac81SBjoern A. Zeeb 		return;
3076b4cac81SBjoern A. Zeeb 
3086b4cac81SBjoern A. Zeeb 	if (mc_ptr == 0)
3096b4cac81SBjoern A. Zeeb 		return;
3106b4cac81SBjoern A. Zeeb 
31164d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p changed_flags %#x total_flags %p mc_ptr %ju", hw, changed_flags, total_flags, (uintmax_t)mc_ptr);
3126b4cac81SBjoern A. Zeeb 	lhw->ops->configure_filter(hw, changed_flags, total_flags, mc_ptr);
3136b4cac81SBjoern A. Zeeb }
3146b4cac81SBjoern A. Zeeb 
3156b4cac81SBjoern A. Zeeb 
3166b4cac81SBjoern A. Zeeb /*
3176b4cac81SBjoern A. Zeeb  * So far we only called sta_{add,remove} as an alternative to sta_state.
318d9f59799SBjoern A. Zeeb  * Let's keep the implementation simpler and hide sta_{add,remove} under the
3196b4cac81SBjoern A. Zeeb  * hood here calling them if state_state is not available from mo_sta_state.
3206b4cac81SBjoern A. Zeeb  */
3216b4cac81SBjoern A. Zeeb static int
3226b4cac81SBjoern A. Zeeb lkpi_80211_mo_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
3236b4cac81SBjoern A. Zeeb     struct ieee80211_sta *sta)
3246b4cac81SBjoern A. Zeeb {
3256b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
3266b4cac81SBjoern A. Zeeb 	struct lkpi_sta *lsta;
3276b4cac81SBjoern A. Zeeb 	int error;
3286b4cac81SBjoern A. Zeeb 
3296b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
3306b4cac81SBjoern A. Zeeb 	if (lhw->ops->sta_add == NULL) {
3316b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
3326b4cac81SBjoern A. Zeeb 		goto out;
3336b4cac81SBjoern A. Zeeb 	}
3346b4cac81SBjoern A. Zeeb 
3356b4cac81SBjoern A. Zeeb 	lsta = STA_TO_LSTA(sta);
3366b4cac81SBjoern A. Zeeb 	if (lsta->added_to_drv) {
3376b4cac81SBjoern A. Zeeb 		error = EEXIST;
3386b4cac81SBjoern A. Zeeb 		goto out;
3396b4cac81SBjoern A. Zeeb 	}
3406b4cac81SBjoern A. Zeeb 
34164d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p sta %p", hw, vif, sta);
3426b4cac81SBjoern A. Zeeb 	error = lhw->ops->sta_add(hw, vif, sta);
3436b4cac81SBjoern A. Zeeb 	if (error == 0)
3446b4cac81SBjoern A. Zeeb 		lsta->added_to_drv = true;
3456b4cac81SBjoern A. Zeeb 
3466b4cac81SBjoern A. Zeeb out:
3476b4cac81SBjoern A. Zeeb 	return error;
3486b4cac81SBjoern A. Zeeb }
3496b4cac81SBjoern A. Zeeb 
3506b4cac81SBjoern A. Zeeb static int
3516b4cac81SBjoern A. Zeeb lkpi_80211_mo_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
3526b4cac81SBjoern A. Zeeb     struct ieee80211_sta *sta)
3536b4cac81SBjoern A. Zeeb {
3546b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
3556b4cac81SBjoern A. Zeeb 	struct lkpi_sta *lsta;
3566b4cac81SBjoern A. Zeeb 	int error;
3576b4cac81SBjoern A. Zeeb 
3586b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
3596b4cac81SBjoern A. Zeeb 	if (lhw->ops->sta_remove == NULL) {
3606b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
3616b4cac81SBjoern A. Zeeb 		goto out;
3626b4cac81SBjoern A. Zeeb 	}
3636b4cac81SBjoern A. Zeeb 
3646b4cac81SBjoern A. Zeeb 	lsta = STA_TO_LSTA(sta);
3656b4cac81SBjoern A. Zeeb 	if (!lsta->added_to_drv) {
3666b4cac81SBjoern A. Zeeb 		/* If we never added the sta, do not complain on cleanup. */
3676b4cac81SBjoern A. Zeeb 		error = 0;
3686b4cac81SBjoern A. Zeeb 		goto out;
3696b4cac81SBjoern A. Zeeb 	}
3706b4cac81SBjoern A. Zeeb 
37164d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p sta %p", hw, vif, sta);
3726b4cac81SBjoern A. Zeeb 	error = lhw->ops->sta_remove(hw, vif, sta);
3736b4cac81SBjoern A. Zeeb 	if (error == 0)
3746b4cac81SBjoern A. Zeeb 		lsta->added_to_drv = false;
3756b4cac81SBjoern A. Zeeb 
3766b4cac81SBjoern A. Zeeb out:
3776b4cac81SBjoern A. Zeeb 	return error;
3786b4cac81SBjoern A. Zeeb }
3796b4cac81SBjoern A. Zeeb 
3806b4cac81SBjoern A. Zeeb int
3816b4cac81SBjoern A. Zeeb lkpi_80211_mo_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
382e7fe0373SBjoern A. Zeeb     struct lkpi_sta *lsta, enum ieee80211_sta_state nstate)
3836b4cac81SBjoern A. Zeeb {
3846b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
385e7fe0373SBjoern A. Zeeb 	struct ieee80211_sta *sta;
3866b4cac81SBjoern A. Zeeb 	int error;
3876b4cac81SBjoern A. Zeeb 
3886b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
389e7fe0373SBjoern A. Zeeb 	sta = LSTA_TO_STA(lsta);
3906b4cac81SBjoern A. Zeeb 	if (lhw->ops->sta_state != NULL) {
39164d3da00SBjoern A. Zeeb 		LKPI_80211_TRACE_MO("hw %p vif %p sta %p nstate %d", hw, vif, sta, nstate);
3926b4cac81SBjoern A. Zeeb 		error = lhw->ops->sta_state(hw, vif, sta, lsta->state, nstate);
3936b4cac81SBjoern A. Zeeb 		if (error == 0) {
3946b4cac81SBjoern A. Zeeb 			if (nstate == IEEE80211_STA_NOTEXIST)
3956b4cac81SBjoern A. Zeeb 				lsta->added_to_drv = false;
3966b4cac81SBjoern A. Zeeb 			else
3976b4cac81SBjoern A. Zeeb 				lsta->added_to_drv = true;
3986b4cac81SBjoern A. Zeeb 			lsta->state = nstate;
3996b4cac81SBjoern A. Zeeb 		}
4006b4cac81SBjoern A. Zeeb 		goto out;
4016b4cac81SBjoern A. Zeeb 	}
4026b4cac81SBjoern A. Zeeb 
4036b4cac81SBjoern A. Zeeb 	/* XXX-BZ is the change state AUTH or ASSOC here? */
404878fb1e5SBjoern A. Zeeb 	if (lsta->state < IEEE80211_STA_ASSOC && nstate == IEEE80211_STA_ASSOC) {
4056b4cac81SBjoern A. Zeeb 		error = lkpi_80211_mo_sta_add(hw, vif, sta);
406878fb1e5SBjoern A. Zeeb 		if (error == 0)
407878fb1e5SBjoern A. Zeeb 			lsta->added_to_drv = true;
408878fb1e5SBjoern A. Zeeb 	} else if (lsta->state >= IEEE80211_STA_ASSOC &&
409878fb1e5SBjoern A. Zeeb 	    nstate < IEEE80211_STA_ASSOC) {
4106b4cac81SBjoern A. Zeeb 		error = lkpi_80211_mo_sta_remove(hw, vif, sta);
411878fb1e5SBjoern A. Zeeb 		if (error == 0)
412878fb1e5SBjoern A. Zeeb 			lsta->added_to_drv = false;
413878fb1e5SBjoern A. Zeeb 	} else
4146b4cac81SBjoern A. Zeeb 		/* Nothing to do. */
4156b4cac81SBjoern A. Zeeb 		error = 0;
416878fb1e5SBjoern A. Zeeb 	if (error == 0)
417878fb1e5SBjoern A. Zeeb 		lsta->state = nstate;
4186b4cac81SBjoern A. Zeeb 
4196b4cac81SBjoern A. Zeeb out:
4206b4cac81SBjoern A. Zeeb 	/* XXX-BZ should we manage state in here? */
4216b4cac81SBjoern A. Zeeb 	return (error);
4226b4cac81SBjoern A. Zeeb }
4236b4cac81SBjoern A. Zeeb 
4246b4cac81SBjoern A. Zeeb int
4256b4cac81SBjoern A. Zeeb lkpi_80211_mo_config(struct ieee80211_hw *hw, uint32_t changed)
4266b4cac81SBjoern A. Zeeb {
4276b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
4286b4cac81SBjoern A. Zeeb 	int error;
4296b4cac81SBjoern A. Zeeb 
4306b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
4316b4cac81SBjoern A. Zeeb 	if (lhw->ops->config == NULL) {
4326b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
4336b4cac81SBjoern A. Zeeb 		goto out;
4346b4cac81SBjoern A. Zeeb 	}
4356b4cac81SBjoern A. Zeeb 
43664d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p changed %u", hw, changed);
4376b4cac81SBjoern A. Zeeb 	error = lhw->ops->config(hw, changed);
4386b4cac81SBjoern A. Zeeb 
4396b4cac81SBjoern A. Zeeb out:
4406b4cac81SBjoern A. Zeeb 	return (error);
4416b4cac81SBjoern A. Zeeb }
4426b4cac81SBjoern A. Zeeb 
4436b4cac81SBjoern A. Zeeb 
4446b4cac81SBjoern A. Zeeb int
4456b4cac81SBjoern A. Zeeb lkpi_80211_mo_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
44668541546SBjoern A. Zeeb     struct ieee80211_bss_conf *conf, struct ieee80211_chanctx_conf *chanctx_conf)
4476b4cac81SBjoern A. Zeeb {
4486b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
4496b4cac81SBjoern A. Zeeb 	int error;
4506b4cac81SBjoern A. Zeeb 
4516b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
4526b4cac81SBjoern A. Zeeb 	if (lhw->ops->assign_vif_chanctx == NULL) {
4536b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
4546b4cac81SBjoern A. Zeeb 		goto out;
4556b4cac81SBjoern A. Zeeb 	}
4566b4cac81SBjoern A. Zeeb 
45768541546SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p bss_conf %p chanctx_conf %p",
45868541546SBjoern A. Zeeb 	    hw, vif, conf, chanctx_conf);
45968541546SBjoern A. Zeeb 	error = lhw->ops->assign_vif_chanctx(hw, vif, conf, chanctx_conf);
4606b4cac81SBjoern A. Zeeb 	if (error == 0)
4616b4cac81SBjoern A. Zeeb 		vif->chanctx_conf = chanctx_conf;
4626b4cac81SBjoern A. Zeeb 
4636b4cac81SBjoern A. Zeeb out:
4646b4cac81SBjoern A. Zeeb 	return (error);
4656b4cac81SBjoern A. Zeeb }
4666b4cac81SBjoern A. Zeeb 
4676b4cac81SBjoern A. Zeeb void
4686b4cac81SBjoern A. Zeeb lkpi_80211_mo_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
46968541546SBjoern A. Zeeb     struct ieee80211_bss_conf *conf, struct ieee80211_chanctx_conf **chanctx_conf)
4706b4cac81SBjoern A. Zeeb {
4716b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
4726b4cac81SBjoern A. Zeeb 
4736b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
4746b4cac81SBjoern A. Zeeb 	if (lhw->ops->unassign_vif_chanctx == NULL)
4756b4cac81SBjoern A. Zeeb 		return;
4766b4cac81SBjoern A. Zeeb 
4776b4cac81SBjoern A. Zeeb 	if (*chanctx_conf == NULL)
4786b4cac81SBjoern A. Zeeb 		return;
4796b4cac81SBjoern A. Zeeb 
48068541546SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p bss_conf %p chanctx_conf %p",
48168541546SBjoern A. Zeeb 	    hw, vif, conf, *chanctx_conf);
48268541546SBjoern A. Zeeb 	lhw->ops->unassign_vif_chanctx(hw, vif, conf, *chanctx_conf);
4836b4cac81SBjoern A. Zeeb 	*chanctx_conf = NULL;
4846b4cac81SBjoern A. Zeeb }
4856b4cac81SBjoern A. Zeeb 
4866b4cac81SBjoern A. Zeeb 
4876b4cac81SBjoern A. Zeeb int
4886b4cac81SBjoern A. Zeeb lkpi_80211_mo_add_chanctx(struct ieee80211_hw *hw,
4896b4cac81SBjoern A. Zeeb     struct ieee80211_chanctx_conf *chanctx_conf)
4906b4cac81SBjoern A. Zeeb {
4916b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
492c5e25798SBjoern A. Zeeb 	struct lkpi_chanctx *lchanctx;
4936b4cac81SBjoern A. Zeeb 	int error;
4946b4cac81SBjoern A. Zeeb 
4956b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
4966b4cac81SBjoern A. Zeeb 	if (lhw->ops->add_chanctx == NULL) {
4976b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
4986b4cac81SBjoern A. Zeeb 		goto out;
4996b4cac81SBjoern A. Zeeb 	}
5006b4cac81SBjoern A. Zeeb 
50164d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p chanctx_conf %p", hw, chanctx_conf);
5026b4cac81SBjoern A. Zeeb 	error = lhw->ops->add_chanctx(hw, chanctx_conf);
503c5e25798SBjoern A. Zeeb 	if (error == 0) {
504c5e25798SBjoern A. Zeeb 		lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
505c5e25798SBjoern A. Zeeb 		lchanctx->added_to_drv = true;
506c5e25798SBjoern A. Zeeb 	}
5076b4cac81SBjoern A. Zeeb 
5086b4cac81SBjoern A. Zeeb out:
5096b4cac81SBjoern A. Zeeb 	return (error);
5106b4cac81SBjoern A. Zeeb }
5116b4cac81SBjoern A. Zeeb 
5126b4cac81SBjoern A. Zeeb void
5136b4cac81SBjoern A. Zeeb lkpi_80211_mo_change_chanctx(struct ieee80211_hw *hw,
5146b4cac81SBjoern A. Zeeb     struct ieee80211_chanctx_conf *chanctx_conf, uint32_t changed)
5156b4cac81SBjoern A. Zeeb {
5166b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
5176b4cac81SBjoern A. Zeeb 
5186b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
5196b4cac81SBjoern A. Zeeb 	if (lhw->ops->change_chanctx == NULL)
5206b4cac81SBjoern A. Zeeb 		return;
5216b4cac81SBjoern A. Zeeb 
52264d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p chanctx_conf %p changed %u", hw, chanctx_conf, changed);
5236b4cac81SBjoern A. Zeeb 	lhw->ops->change_chanctx(hw, chanctx_conf, changed);
5246b4cac81SBjoern A. Zeeb }
5256b4cac81SBjoern A. Zeeb 
5266b4cac81SBjoern A. Zeeb void
5276b4cac81SBjoern A. Zeeb lkpi_80211_mo_remove_chanctx(struct ieee80211_hw *hw,
5286b4cac81SBjoern A. Zeeb     struct ieee80211_chanctx_conf *chanctx_conf)
5296b4cac81SBjoern A. Zeeb {
5306b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
531c5e25798SBjoern A. Zeeb 	struct lkpi_chanctx *lchanctx;
5326b4cac81SBjoern A. Zeeb 
5336b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
5346b4cac81SBjoern A. Zeeb 	if (lhw->ops->remove_chanctx == NULL)
5356b4cac81SBjoern A. Zeeb 		return;
5366b4cac81SBjoern A. Zeeb 
53764d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p chanctx_conf %p", hw, chanctx_conf);
5386b4cac81SBjoern A. Zeeb 	lhw->ops->remove_chanctx(hw, chanctx_conf);
539c5e25798SBjoern A. Zeeb 	lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
540c5e25798SBjoern A. Zeeb 	lchanctx->added_to_drv = false;
5416b4cac81SBjoern A. Zeeb }
5426b4cac81SBjoern A. Zeeb 
5436b4cac81SBjoern A. Zeeb void
5446b4cac81SBjoern A. Zeeb lkpi_80211_mo_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
545467d3e2eSBjoern A. Zeeb     struct ieee80211_bss_conf *conf, uint64_t changed)
5466b4cac81SBjoern A. Zeeb {
5476b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
5486b4cac81SBjoern A. Zeeb 
5496b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
550727f88f2SBjoern A. Zeeb 	if (lhw->ops->link_info_changed == NULL &&
551727f88f2SBjoern A. Zeeb 	    lhw->ops->bss_info_changed == NULL)
5526b4cac81SBjoern A. Zeeb 		return;
5536b4cac81SBjoern A. Zeeb 
55464d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p conf %p changed %#jx", hw, vif, conf, (uintmax_t)changed);
555727f88f2SBjoern A. Zeeb 	if (lhw->ops->link_info_changed != NULL)
556727f88f2SBjoern A. Zeeb 		lhw->ops->link_info_changed(hw, vif, conf, changed);
557727f88f2SBjoern A. Zeeb 	else
5586b4cac81SBjoern A. Zeeb 		lhw->ops->bss_info_changed(hw, vif, conf, changed);
5596b4cac81SBjoern A. Zeeb }
5606b4cac81SBjoern A. Zeeb 
5616b4cac81SBjoern A. Zeeb int
5626b4cac81SBjoern A. Zeeb lkpi_80211_mo_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
56368541546SBjoern A. Zeeb     uint32_t link_id, uint16_t ac, const struct ieee80211_tx_queue_params *txqp)
5646b4cac81SBjoern A. Zeeb {
5656b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
5666b4cac81SBjoern A. Zeeb 	int error;
5676b4cac81SBjoern A. Zeeb 
5686b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
5696b4cac81SBjoern A. Zeeb 	if (lhw->ops->conf_tx == NULL) {
5706b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
5716b4cac81SBjoern A. Zeeb 		goto out;
5726b4cac81SBjoern A. Zeeb 	}
5736b4cac81SBjoern A. Zeeb 
57468541546SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p link_id %u ac %u txpq %p",
57568541546SBjoern A. Zeeb 	    hw, vif, link_id, ac, txqp);
57668541546SBjoern A. Zeeb 	error = lhw->ops->conf_tx(hw, vif, link_id, ac, txqp);
5776b4cac81SBjoern A. Zeeb 
5786b4cac81SBjoern A. Zeeb out:
5796b4cac81SBjoern A. Zeeb 	return (error);
5806b4cac81SBjoern A. Zeeb }
5816b4cac81SBjoern A. Zeeb 
5826b4cac81SBjoern A. Zeeb void
5836b4cac81SBjoern A. Zeeb lkpi_80211_mo_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5846b4cac81SBjoern A. Zeeb     uint32_t nqueues, bool drop)
5856b4cac81SBjoern A. Zeeb {
5866b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
5876b4cac81SBjoern A. Zeeb 
5886b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
5896b4cac81SBjoern A. Zeeb 	if (lhw->ops->flush == NULL)
5906b4cac81SBjoern A. Zeeb 		return;
5916b4cac81SBjoern A. Zeeb 
59264d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p nqueues %u drop %d", hw, vif, nqueues, drop);
5936b4cac81SBjoern A. Zeeb 	lhw->ops->flush(hw, vif, nqueues, drop);
5946b4cac81SBjoern A. Zeeb }
5956b4cac81SBjoern A. Zeeb 
5966b4cac81SBjoern A. Zeeb void
5976b4cac81SBjoern A. Zeeb lkpi_80211_mo_mgd_prepare_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5986b4cac81SBjoern A. Zeeb     struct ieee80211_prep_tx_info *txinfo)
5996b4cac81SBjoern A. Zeeb {
6006b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
6016b4cac81SBjoern A. Zeeb 
6026b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
6036b4cac81SBjoern A. Zeeb 	if (lhw->ops->mgd_prepare_tx == NULL)
6046b4cac81SBjoern A. Zeeb 		return;
6056b4cac81SBjoern A. Zeeb 
60664d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p txinfo %p", hw, vif, txinfo);
6076b4cac81SBjoern A. Zeeb 	lhw->ops->mgd_prepare_tx(hw, vif, txinfo);
6086b4cac81SBjoern A. Zeeb }
6096b4cac81SBjoern A. Zeeb 
6106b4cac81SBjoern A. Zeeb void
6116b4cac81SBjoern A. Zeeb lkpi_80211_mo_mgd_complete_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
6126b4cac81SBjoern A. Zeeb     struct ieee80211_prep_tx_info *txinfo)
6136b4cac81SBjoern A. Zeeb {
6146b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
6156b4cac81SBjoern A. Zeeb 
6166b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
6176b4cac81SBjoern A. Zeeb 	if (lhw->ops->mgd_complete_tx == NULL)
6186b4cac81SBjoern A. Zeeb 		return;
6196b4cac81SBjoern A. Zeeb 
62064d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p txinfo %p", hw, vif, txinfo);
6216b4cac81SBjoern A. Zeeb 	lhw->ops->mgd_complete_tx(hw, vif, txinfo);
6226b4cac81SBjoern A. Zeeb }
6236b4cac81SBjoern A. Zeeb 
6246b4cac81SBjoern A. Zeeb void
6256b4cac81SBjoern A. Zeeb lkpi_80211_mo_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *txctrl,
6266b4cac81SBjoern A. Zeeb     struct sk_buff *skb)
6276b4cac81SBjoern A. Zeeb {
6286b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
6296b4cac81SBjoern A. Zeeb 
6306b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
6316b4cac81SBjoern A. Zeeb 	if (lhw->ops->tx == NULL)
6326b4cac81SBjoern A. Zeeb 		return;
6336b4cac81SBjoern A. Zeeb 
63464d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p txctrl %p skb %p", hw, txctrl, skb);
6356b4cac81SBjoern A. Zeeb 	lhw->ops->tx(hw, txctrl, skb);
6366b4cac81SBjoern A. Zeeb }
6376b4cac81SBjoern A. Zeeb 
6386b4cac81SBjoern A. Zeeb void
6396b4cac81SBjoern A. Zeeb lkpi_80211_mo_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
6406b4cac81SBjoern A. Zeeb {
6416b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
6426b4cac81SBjoern A. Zeeb 
6436b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
6446b4cac81SBjoern A. Zeeb 	if (lhw->ops->wake_tx_queue == NULL)
6456b4cac81SBjoern A. Zeeb 		return;
6466b4cac81SBjoern A. Zeeb 
64764d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p txq %p", hw, txq);
6486b4cac81SBjoern A. Zeeb 	lhw->ops->wake_tx_queue(hw, txq);
6496b4cac81SBjoern A. Zeeb }
6506b4cac81SBjoern A. Zeeb 
6516b4cac81SBjoern A. Zeeb void
6526b4cac81SBjoern A. Zeeb lkpi_80211_mo_sync_rx_queues(struct ieee80211_hw *hw)
6536b4cac81SBjoern A. Zeeb {
6546b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
6556b4cac81SBjoern A. Zeeb 
6566b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
6576b4cac81SBjoern A. Zeeb 	if (lhw->ops->sync_rx_queues == NULL)
6586b4cac81SBjoern A. Zeeb 		return;
6596b4cac81SBjoern A. Zeeb 
66064d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p", hw);
6616b4cac81SBjoern A. Zeeb 	lhw->ops->sync_rx_queues(hw);
6626b4cac81SBjoern A. Zeeb }
6636b4cac81SBjoern A. Zeeb 
6646b4cac81SBjoern A. Zeeb void
6656b4cac81SBjoern A. Zeeb lkpi_80211_mo_sta_pre_rcu_remove(struct ieee80211_hw *hw,
6666b4cac81SBjoern A. Zeeb     struct ieee80211_vif *vif, struct ieee80211_sta *sta)
6676b4cac81SBjoern A. Zeeb {
6686b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
6696b4cac81SBjoern A. Zeeb 
6706b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
6716b4cac81SBjoern A. Zeeb 	if (lhw->ops->sta_pre_rcu_remove == NULL)
6726b4cac81SBjoern A. Zeeb 		return;
6736b4cac81SBjoern A. Zeeb 
67464d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p sta %p", hw, vif, sta);
6756b4cac81SBjoern A. Zeeb 	lhw->ops->sta_pre_rcu_remove(hw, vif, sta);
6766b4cac81SBjoern A. Zeeb }
6776b4cac81SBjoern A. Zeeb 
6786b4cac81SBjoern A. Zeeb int
6796b4cac81SBjoern A. Zeeb lkpi_80211_mo_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
6806b4cac81SBjoern A. Zeeb     struct ieee80211_vif *vif, struct ieee80211_sta *sta,
6816b4cac81SBjoern A. Zeeb     struct ieee80211_key_conf *kc)
6826b4cac81SBjoern A. Zeeb {
6836b4cac81SBjoern A. Zeeb 	struct lkpi_hw *lhw;
6846b4cac81SBjoern A. Zeeb 	int error;
6856b4cac81SBjoern A. Zeeb 
6866b4cac81SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
6876b4cac81SBjoern A. Zeeb 	if (lhw->ops->set_key == NULL) {
6886b4cac81SBjoern A. Zeeb 		error = EOPNOTSUPP;
6896b4cac81SBjoern A. Zeeb 		goto out;
6906b4cac81SBjoern A. Zeeb 	}
6916b4cac81SBjoern A. Zeeb 
69264d3da00SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p cmd %d vif %p sta %p kc %p", hw, cmd, vif, sta, kc);
6936b4cac81SBjoern A. Zeeb 	error = lhw->ops->set_key(hw, cmd, vif, sta, kc);
6946b4cac81SBjoern A. Zeeb 
6956b4cac81SBjoern A. Zeeb out:
6966b4cac81SBjoern A. Zeeb 	return (error);
6976b4cac81SBjoern A. Zeeb }
6989fb91463SBjoern A. Zeeb 
6999fb91463SBjoern A. Zeeb int
7009fb91463SBjoern A. Zeeb lkpi_80211_mo_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
7019fb91463SBjoern A. Zeeb     struct ieee80211_ampdu_params *params)
7029fb91463SBjoern A. Zeeb {
7039fb91463SBjoern A. Zeeb 	struct lkpi_hw *lhw;
7049fb91463SBjoern A. Zeeb 	int error;
7059fb91463SBjoern A. Zeeb 
7069fb91463SBjoern A. Zeeb 	lhw = HW_TO_LHW(hw);
7079fb91463SBjoern A. Zeeb 	if (lhw->ops->ampdu_action == NULL) {
7089fb91463SBjoern A. Zeeb 		error = EOPNOTSUPP;
7099fb91463SBjoern A. Zeeb 		goto out;
7109fb91463SBjoern A. Zeeb 	}
7119fb91463SBjoern A. Zeeb 
7129fb91463SBjoern A. Zeeb 	LKPI_80211_TRACE_MO("hw %p vif %p params %p { %p, %d, %u, %u, %u, %u, %d }",
7139fb91463SBjoern A. Zeeb 	    hw, vif, params, params->sta, params->action, params->buf_size,
7149fb91463SBjoern A. Zeeb 	    params->timeout, params->ssn, params->tid, params->amsdu);
7159fb91463SBjoern A. Zeeb 	error = lhw->ops->ampdu_action(hw, vif, params);
7169fb91463SBjoern A. Zeeb 
7179fb91463SBjoern A. Zeeb out:
7189fb91463SBjoern A. Zeeb 	return (error);
7199fb91463SBjoern A. Zeeb }
720