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