16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC 26c92544dSBjoern A. Zeeb /* Copyright (C) 2020 MediaTek Inc. */ 36c92544dSBjoern A. Zeeb 46c92544dSBjoern A. Zeeb #include <linux/etherdevice.h> 56c92544dSBjoern A. Zeeb #include <linux/platform_device.h> 66c92544dSBjoern A. Zeeb #include <linux/pci.h> 76c92544dSBjoern A. Zeeb #include <linux/module.h> 86c92544dSBjoern A. Zeeb #include "mt7915.h" 96c92544dSBjoern A. Zeeb #include "mcu.h" 106c92544dSBjoern A. Zeeb 116c92544dSBjoern A. Zeeb static bool mt7915_dev_running(struct mt7915_dev *dev) 126c92544dSBjoern A. Zeeb { 136c92544dSBjoern A. Zeeb struct mt7915_phy *phy; 146c92544dSBjoern A. Zeeb 156c92544dSBjoern A. Zeeb if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) 166c92544dSBjoern A. Zeeb return true; 176c92544dSBjoern A. Zeeb 186c92544dSBjoern A. Zeeb phy = mt7915_ext_phy(dev); 196c92544dSBjoern A. Zeeb 206c92544dSBjoern A. Zeeb return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state); 216c92544dSBjoern A. Zeeb } 226c92544dSBjoern A. Zeeb 23*cbb3ec25SBjoern A. Zeeb int mt7915_run(struct ieee80211_hw *hw) 246c92544dSBjoern A. Zeeb { 256c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 266c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 276c92544dSBjoern A. Zeeb bool running; 286c92544dSBjoern A. Zeeb int ret; 296c92544dSBjoern A. Zeeb 306c92544dSBjoern A. Zeeb running = mt7915_dev_running(dev); 316c92544dSBjoern A. Zeeb 326c92544dSBjoern A. Zeeb if (!running) { 33*cbb3ec25SBjoern A. Zeeb ret = mt76_connac_mcu_set_pm(&dev->mt76, 34*cbb3ec25SBjoern A. Zeeb dev->phy.mt76->band_idx, 0); 356c92544dSBjoern A. Zeeb if (ret) 366c92544dSBjoern A. Zeeb goto out; 376c92544dSBjoern A. Zeeb 38*cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_mac(dev, dev->phy.mt76->band_idx, 39*cbb3ec25SBjoern A. Zeeb true, true); 406c92544dSBjoern A. Zeeb if (ret) 416c92544dSBjoern A. Zeeb goto out; 426c92544dSBjoern A. Zeeb 43*cbb3ec25SBjoern A. Zeeb mt7915_mac_enable_nf(dev, dev->phy.mt76->band_idx); 446c92544dSBjoern A. Zeeb } 456c92544dSBjoern A. Zeeb 46*cbb3ec25SBjoern A. Zeeb if (phy != &dev->phy) { 47*cbb3ec25SBjoern A. Zeeb ret = mt76_connac_mcu_set_pm(&dev->mt76, 48*cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx, 0); 496c92544dSBjoern A. Zeeb if (ret) 506c92544dSBjoern A. Zeeb goto out; 516c92544dSBjoern A. Zeeb 52*cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_mac(dev, phy->mt76->band_idx, 53*cbb3ec25SBjoern A. Zeeb true, true); 546c92544dSBjoern A. Zeeb if (ret) 556c92544dSBjoern A. Zeeb goto out; 566c92544dSBjoern A. Zeeb 57*cbb3ec25SBjoern A. Zeeb mt7915_mac_enable_nf(dev, phy->mt76->band_idx); 586c92544dSBjoern A. Zeeb } 596c92544dSBjoern A. Zeeb 60*cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_thermal_throttling(phy, 61*cbb3ec25SBjoern A. Zeeb MT7915_THERMAL_THROTTLE_MAX); 62*cbb3ec25SBjoern A. Zeeb 63*cbb3ec25SBjoern A. Zeeb if (ret) 64*cbb3ec25SBjoern A. Zeeb goto out; 65*cbb3ec25SBjoern A. Zeeb 66*cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_thermal_protect(phy); 67*cbb3ec25SBjoern A. Zeeb 68*cbb3ec25SBjoern A. Zeeb if (ret) 69*cbb3ec25SBjoern A. Zeeb goto out; 70*cbb3ec25SBjoern A. Zeeb 716c92544dSBjoern A. Zeeb ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 72*cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx); 736c92544dSBjoern A. Zeeb if (ret) 746c92544dSBjoern A. Zeeb goto out; 756c92544dSBjoern A. Zeeb 766c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_sku_en(phy, true); 776c92544dSBjoern A. Zeeb if (ret) 786c92544dSBjoern A. Zeeb goto out; 796c92544dSBjoern A. Zeeb 806c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH)); 816c92544dSBjoern A. Zeeb if (ret) 826c92544dSBjoern A. Zeeb goto out; 836c92544dSBjoern A. Zeeb 846c92544dSBjoern A. Zeeb set_bit(MT76_STATE_RUNNING, &phy->mt76->state); 856c92544dSBjoern A. Zeeb 866c92544dSBjoern A. Zeeb if (!mt76_testmode_enabled(phy->mt76)) 876c92544dSBjoern A. Zeeb ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, 886c92544dSBjoern A. Zeeb MT7915_WATCHDOG_TIME); 896c92544dSBjoern A. Zeeb 906c92544dSBjoern A. Zeeb if (!running) 916c92544dSBjoern A. Zeeb mt7915_mac_reset_counters(phy); 926c92544dSBjoern A. Zeeb 936c92544dSBjoern A. Zeeb out: 94*cbb3ec25SBjoern A. Zeeb return ret; 95*cbb3ec25SBjoern A. Zeeb } 96*cbb3ec25SBjoern A. Zeeb 97*cbb3ec25SBjoern A. Zeeb static int mt7915_start(struct ieee80211_hw *hw) 98*cbb3ec25SBjoern A. Zeeb { 99*cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 100*cbb3ec25SBjoern A. Zeeb int ret; 101*cbb3ec25SBjoern A. Zeeb 102*cbb3ec25SBjoern A. Zeeb flush_work(&dev->init_work); 103*cbb3ec25SBjoern A. Zeeb 104*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 105*cbb3ec25SBjoern A. Zeeb ret = mt7915_run(hw); 1066c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 1076c92544dSBjoern A. Zeeb 1086c92544dSBjoern A. Zeeb return ret; 1096c92544dSBjoern A. Zeeb } 1106c92544dSBjoern A. Zeeb 1116c92544dSBjoern A. Zeeb static void mt7915_stop(struct ieee80211_hw *hw) 1126c92544dSBjoern A. Zeeb { 1136c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 1146c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 1156c92544dSBjoern A. Zeeb 1166c92544dSBjoern A. Zeeb cancel_delayed_work_sync(&phy->mt76->mac_work); 1176c92544dSBjoern A. Zeeb 1186c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 1196c92544dSBjoern A. Zeeb 1206c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, true); 1216c92544dSBjoern A. Zeeb 1226c92544dSBjoern A. Zeeb clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); 1236c92544dSBjoern A. Zeeb 1246c92544dSBjoern A. Zeeb if (phy != &dev->phy) { 125*cbb3ec25SBjoern A. Zeeb mt76_connac_mcu_set_pm(&dev->mt76, phy->mt76->band_idx, 1); 126*cbb3ec25SBjoern A. Zeeb mt7915_mcu_set_mac(dev, phy->mt76->band_idx, false, false); 1276c92544dSBjoern A. Zeeb } 1286c92544dSBjoern A. Zeeb 1296c92544dSBjoern A. Zeeb if (!mt7915_dev_running(dev)) { 130*cbb3ec25SBjoern A. Zeeb mt76_connac_mcu_set_pm(&dev->mt76, dev->phy.mt76->band_idx, 1); 131*cbb3ec25SBjoern A. Zeeb mt7915_mcu_set_mac(dev, dev->phy.mt76->band_idx, false, false); 1326c92544dSBjoern A. Zeeb } 1336c92544dSBjoern A. Zeeb 1346c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 1356c92544dSBjoern A. Zeeb } 1366c92544dSBjoern A. Zeeb 1376c92544dSBjoern A. Zeeb static inline int get_free_idx(u32 mask, u8 start, u8 end) 1386c92544dSBjoern A. Zeeb { 1396c92544dSBjoern A. Zeeb return ffs(~mask & GENMASK(end, start)); 1406c92544dSBjoern A. Zeeb } 1416c92544dSBjoern A. Zeeb 1426c92544dSBjoern A. Zeeb static int get_omac_idx(enum nl80211_iftype type, u64 mask) 1436c92544dSBjoern A. Zeeb { 1446c92544dSBjoern A. Zeeb int i; 1456c92544dSBjoern A. Zeeb 1466c92544dSBjoern A. Zeeb switch (type) { 1476c92544dSBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT: 1486c92544dSBjoern A. Zeeb case NL80211_IFTYPE_ADHOC: 1496c92544dSBjoern A. Zeeb case NL80211_IFTYPE_STATION: 1506c92544dSBjoern A. Zeeb /* prefer hw bssid slot 1-3 */ 1516c92544dSBjoern A. Zeeb i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3); 1526c92544dSBjoern A. Zeeb if (i) 1536c92544dSBjoern A. Zeeb return i - 1; 1546c92544dSBjoern A. Zeeb 1556c92544dSBjoern A. Zeeb if (type != NL80211_IFTYPE_STATION) 1566c92544dSBjoern A. Zeeb break; 1576c92544dSBjoern A. Zeeb 1586c92544dSBjoern A. Zeeb i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); 1596c92544dSBjoern A. Zeeb if (i) 1606c92544dSBjoern A. Zeeb return i - 1; 1616c92544dSBjoern A. Zeeb 1626c92544dSBjoern A. Zeeb if (~mask & BIT(HW_BSSID_0)) 1636c92544dSBjoern A. Zeeb return HW_BSSID_0; 1646c92544dSBjoern A. Zeeb 1656c92544dSBjoern A. Zeeb break; 1666c92544dSBjoern A. Zeeb case NL80211_IFTYPE_MONITOR: 1676c92544dSBjoern A. Zeeb case NL80211_IFTYPE_AP: 1686c92544dSBjoern A. Zeeb /* ap uses hw bssid 0 and ext bssid */ 1696c92544dSBjoern A. Zeeb if (~mask & BIT(HW_BSSID_0)) 1706c92544dSBjoern A. Zeeb return HW_BSSID_0; 1716c92544dSBjoern A. Zeeb 1726c92544dSBjoern A. Zeeb i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); 1736c92544dSBjoern A. Zeeb if (i) 1746c92544dSBjoern A. Zeeb return i - 1; 1756c92544dSBjoern A. Zeeb 1766c92544dSBjoern A. Zeeb break; 1776c92544dSBjoern A. Zeeb default: 1786c92544dSBjoern A. Zeeb WARN_ON(1); 1796c92544dSBjoern A. Zeeb break; 1806c92544dSBjoern A. Zeeb } 1816c92544dSBjoern A. Zeeb 1826c92544dSBjoern A. Zeeb return -1; 1836c92544dSBjoern A. Zeeb } 1846c92544dSBjoern A. Zeeb 1856c92544dSBjoern A. Zeeb static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif) 1866c92544dSBjoern A. Zeeb { 1876c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 1886c92544dSBjoern A. Zeeb int i; 1896c92544dSBjoern A. Zeeb 1906c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) { 1916c92544dSBjoern A. Zeeb mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI; 1926c92544dSBjoern A. Zeeb mvif->bitrate_mask.control[i].he_gi = 0xff; 1936c92544dSBjoern A. Zeeb mvif->bitrate_mask.control[i].he_ltf = 0xff; 1946c92544dSBjoern A. Zeeb mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0); 1956c92544dSBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff, 1966c92544dSBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].ht_mcs)); 1976c92544dSBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff, 1986c92544dSBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].vht_mcs)); 1996c92544dSBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].he_mcs, 0xff, 2006c92544dSBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].he_mcs)); 2016c92544dSBjoern A. Zeeb } 2026c92544dSBjoern A. Zeeb } 2036c92544dSBjoern A. Zeeb 2046c92544dSBjoern A. Zeeb static int mt7915_add_interface(struct ieee80211_hw *hw, 2056c92544dSBjoern A. Zeeb struct ieee80211_vif *vif) 2066c92544dSBjoern A. Zeeb { 2076c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 2086c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 2096c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 2106c92544dSBjoern A. Zeeb struct mt76_txq *mtxq; 2116c92544dSBjoern A. Zeeb bool ext_phy = phy != &dev->phy; 2126c92544dSBjoern A. Zeeb int idx, ret = 0; 2136c92544dSBjoern A. Zeeb 2146c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 2156c92544dSBjoern A. Zeeb 2166c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, true); 2176c92544dSBjoern A. Zeeb 2186c92544dSBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_MONITOR && 2196c92544dSBjoern A. Zeeb is_zero_ether_addr(vif->addr)) 2206c92544dSBjoern A. Zeeb phy->monitor_vif = vif; 2216c92544dSBjoern A. Zeeb 2226c92544dSBjoern A. Zeeb mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); 2236c92544dSBjoern A. Zeeb if (mvif->mt76.idx >= (MT7915_MAX_INTERFACES << dev->dbdc_support)) { 2246c92544dSBjoern A. Zeeb ret = -ENOSPC; 2256c92544dSBjoern A. Zeeb goto out; 2266c92544dSBjoern A. Zeeb } 2276c92544dSBjoern A. Zeeb 2286c92544dSBjoern A. Zeeb idx = get_omac_idx(vif->type, phy->omac_mask); 2296c92544dSBjoern A. Zeeb if (idx < 0) { 2306c92544dSBjoern A. Zeeb ret = -ENOSPC; 2316c92544dSBjoern A. Zeeb goto out; 2326c92544dSBjoern A. Zeeb } 2336c92544dSBjoern A. Zeeb mvif->mt76.omac_idx = idx; 2346c92544dSBjoern A. Zeeb mvif->phy = phy; 235*cbb3ec25SBjoern A. Zeeb mvif->mt76.band_idx = phy->mt76->band_idx; 2366c92544dSBjoern A. Zeeb 2376c92544dSBjoern A. Zeeb mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; 2386c92544dSBjoern A. Zeeb if (ext_phy) 2396c92544dSBjoern A. Zeeb mvif->mt76.wmm_idx += 2; 2406c92544dSBjoern A. Zeeb 2416c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_dev_info(phy, vif, true); 2426c92544dSBjoern A. Zeeb if (ret) 2436c92544dSBjoern A. Zeeb goto out; 2446c92544dSBjoern A. Zeeb 2456c92544dSBjoern A. Zeeb dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); 2466c92544dSBjoern A. Zeeb phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); 2476c92544dSBjoern A. Zeeb 2486c92544dSBjoern A. Zeeb idx = MT7915_WTBL_RESERVED - mvif->mt76.idx; 2496c92544dSBjoern A. Zeeb 2506c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&mvif->sta.rc_list); 251*cbb3ec25SBjoern A. Zeeb INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); 2526c92544dSBjoern A. Zeeb mvif->sta.wcid.idx = idx; 2536c92544dSBjoern A. Zeeb mvif->sta.wcid.phy_idx = ext_phy; 2546c92544dSBjoern A. Zeeb mvif->sta.wcid.hw_key_idx = -1; 2556c92544dSBjoern A. Zeeb mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; 2566c92544dSBjoern A. Zeeb mt76_packet_id_init(&mvif->sta.wcid); 2576c92544dSBjoern A. Zeeb 2586c92544dSBjoern A. Zeeb mt7915_mac_wtbl_update(dev, idx, 2596c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 2606c92544dSBjoern A. Zeeb 2616c92544dSBjoern A. Zeeb if (vif->txq) { 2626c92544dSBjoern A. Zeeb mtxq = (struct mt76_txq *)vif->txq->drv_priv; 2636c92544dSBjoern A. Zeeb mtxq->wcid = idx; 2646c92544dSBjoern A. Zeeb } 2656c92544dSBjoern A. Zeeb 2666c92544dSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_AP && 2676c92544dSBjoern A. Zeeb (!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3)) 2686c92544dSBjoern A. Zeeb vif->offload_flags = 0; 2696c92544dSBjoern A. Zeeb vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; 2706c92544dSBjoern A. Zeeb 2716c92544dSBjoern A. Zeeb mt7915_init_bitrate_mask(vif); 2726c92544dSBjoern A. Zeeb memset(&mvif->cap, -1, sizeof(mvif->cap)); 2736c92544dSBjoern A. Zeeb 2746c92544dSBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, true); 2756c92544dSBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, true); 2766c92544dSBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); 2776c92544dSBjoern A. Zeeb 2786c92544dSBjoern A. Zeeb out: 2796c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 2806c92544dSBjoern A. Zeeb 2816c92544dSBjoern A. Zeeb return ret; 2826c92544dSBjoern A. Zeeb } 2836c92544dSBjoern A. Zeeb 2846c92544dSBjoern A. Zeeb static void mt7915_remove_interface(struct ieee80211_hw *hw, 2856c92544dSBjoern A. Zeeb struct ieee80211_vif *vif) 2866c92544dSBjoern A. Zeeb { 2876c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 2886c92544dSBjoern A. Zeeb struct mt7915_sta *msta = &mvif->sta; 2896c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 2906c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 2916c92544dSBjoern A. Zeeb int idx = msta->wcid.idx; 2926c92544dSBjoern A. Zeeb 2936c92544dSBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, false); 2946c92544dSBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, false); 2956c92544dSBjoern A. Zeeb 2966c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 2976c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, true); 2986c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 2996c92544dSBjoern A. Zeeb 3006c92544dSBjoern A. Zeeb if (vif == phy->monitor_vif) 3016c92544dSBjoern A. Zeeb phy->monitor_vif = NULL; 3026c92544dSBjoern A. Zeeb 3036c92544dSBjoern A. Zeeb mt7915_mcu_add_dev_info(phy, vif, false); 3046c92544dSBjoern A. Zeeb 3056c92544dSBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], NULL); 3066c92544dSBjoern A. Zeeb 3076c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 3086c92544dSBjoern A. Zeeb dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); 3096c92544dSBjoern A. Zeeb phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); 3106c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 3116c92544dSBjoern A. Zeeb 312*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 313*cbb3ec25SBjoern A. Zeeb if (!list_empty(&msta->wcid.poll_list)) 314*cbb3ec25SBjoern A. Zeeb list_del_init(&msta->wcid.poll_list); 315*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 3166c92544dSBjoern A. Zeeb 3176c92544dSBjoern A. Zeeb mt76_packet_id_flush(&dev->mt76, &msta->wcid); 3186c92544dSBjoern A. Zeeb } 3196c92544dSBjoern A. Zeeb 3206c92544dSBjoern A. Zeeb int mt7915_set_channel(struct mt7915_phy *phy) 3216c92544dSBjoern A. Zeeb { 3226c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 3236c92544dSBjoern A. Zeeb int ret; 3246c92544dSBjoern A. Zeeb 3256c92544dSBjoern A. Zeeb cancel_delayed_work_sync(&phy->mt76->mac_work); 3266c92544dSBjoern A. Zeeb 3276c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 3286c92544dSBjoern A. Zeeb set_bit(MT76_RESET, &phy->mt76->state); 3296c92544dSBjoern A. Zeeb 3306c92544dSBjoern A. Zeeb mt76_set_channel(phy->mt76); 3316c92544dSBjoern A. Zeeb 3326c92544dSBjoern A. Zeeb if (dev->flash_mode) { 3336c92544dSBjoern A. Zeeb ret = mt7915_mcu_apply_tx_dpd(phy); 3346c92544dSBjoern A. Zeeb if (ret) 3356c92544dSBjoern A. Zeeb goto out; 3366c92544dSBjoern A. Zeeb } 3376c92544dSBjoern A. Zeeb 3386c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH)); 3396c92544dSBjoern A. Zeeb if (ret) 3406c92544dSBjoern A. Zeeb goto out; 3416c92544dSBjoern A. Zeeb 3426c92544dSBjoern A. Zeeb mt7915_mac_set_timing(phy); 3436c92544dSBjoern A. Zeeb ret = mt7915_dfs_init_radar_detector(phy); 3446c92544dSBjoern A. Zeeb mt7915_mac_cca_stats_reset(phy); 3456c92544dSBjoern A. Zeeb 3466c92544dSBjoern A. Zeeb mt7915_mac_reset_counters(phy); 3476c92544dSBjoern A. Zeeb phy->noise = 0; 3486c92544dSBjoern A. Zeeb 3496c92544dSBjoern A. Zeeb out: 3506c92544dSBjoern A. Zeeb clear_bit(MT76_RESET, &phy->mt76->state); 3516c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 3526c92544dSBjoern A. Zeeb 3536c92544dSBjoern A. Zeeb mt76_txq_schedule_all(phy->mt76); 3546c92544dSBjoern A. Zeeb 3556c92544dSBjoern A. Zeeb if (!mt76_testmode_enabled(phy->mt76)) 3566c92544dSBjoern A. Zeeb ieee80211_queue_delayed_work(phy->mt76->hw, 3576c92544dSBjoern A. Zeeb &phy->mt76->mac_work, 3586c92544dSBjoern A. Zeeb MT7915_WATCHDOG_TIME); 3596c92544dSBjoern A. Zeeb 3606c92544dSBjoern A. Zeeb return ret; 3616c92544dSBjoern A. Zeeb } 3626c92544dSBjoern A. Zeeb 3636c92544dSBjoern A. Zeeb static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 3646c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta, 3656c92544dSBjoern A. Zeeb struct ieee80211_key_conf *key) 3666c92544dSBjoern A. Zeeb { 3676c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 3686c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 3696c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 3706c92544dSBjoern A. Zeeb struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv : 3716c92544dSBjoern A. Zeeb &mvif->sta; 3726c92544dSBjoern A. Zeeb struct mt76_wcid *wcid = &msta->wcid; 3736c92544dSBjoern A. Zeeb u8 *wcid_keyidx = &wcid->hw_key_idx; 3746c92544dSBjoern A. Zeeb int idx = key->keyidx; 3756c92544dSBjoern A. Zeeb int err = 0; 3766c92544dSBjoern A. Zeeb 3776c92544dSBjoern A. Zeeb /* The hardware does not support per-STA RX GTK, fallback 3786c92544dSBjoern A. Zeeb * to software mode for these. 3796c92544dSBjoern A. Zeeb */ 3806c92544dSBjoern A. Zeeb if ((vif->type == NL80211_IFTYPE_ADHOC || 3816c92544dSBjoern A. Zeeb vif->type == NL80211_IFTYPE_MESH_POINT) && 3826c92544dSBjoern A. Zeeb (key->cipher == WLAN_CIPHER_SUITE_TKIP || 3836c92544dSBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_CCMP) && 3846c92544dSBjoern A. Zeeb !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) 3856c92544dSBjoern A. Zeeb return -EOPNOTSUPP; 3866c92544dSBjoern A. Zeeb 3876c92544dSBjoern A. Zeeb /* fall back to sw encryption for unsupported ciphers */ 3886c92544dSBjoern A. Zeeb switch (key->cipher) { 3896c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_AES_CMAC: 3906c92544dSBjoern A. Zeeb wcid_keyidx = &wcid->hw_key_idx2; 3916c92544dSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; 3926c92544dSBjoern A. Zeeb break; 3936c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_TKIP: 3946c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP: 3956c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP_256: 3966c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP: 3976c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP_256: 3986c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_SMS4: 3996c92544dSBjoern A. Zeeb break; 4006c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_WEP40: 4016c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_WEP104: 4026c92544dSBjoern A. Zeeb default: 4036c92544dSBjoern A. Zeeb return -EOPNOTSUPP; 4046c92544dSBjoern A. Zeeb } 4056c92544dSBjoern A. Zeeb 4066c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 4076c92544dSBjoern A. Zeeb 4086c92544dSBjoern A. Zeeb if (cmd == SET_KEY && !sta && !mvif->mt76.cipher) { 4096c92544dSBjoern A. Zeeb mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher); 4106c92544dSBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, true); 4116c92544dSBjoern A. Zeeb } 4126c92544dSBjoern A. Zeeb 413*cbb3ec25SBjoern A. Zeeb if (cmd == SET_KEY) { 4146c92544dSBjoern A. Zeeb *wcid_keyidx = idx; 415*cbb3ec25SBjoern A. Zeeb } else { 416*cbb3ec25SBjoern A. Zeeb if (idx == *wcid_keyidx) 4176c92544dSBjoern A. Zeeb *wcid_keyidx = -1; 4186c92544dSBjoern A. Zeeb goto out; 419*cbb3ec25SBjoern A. Zeeb } 4206c92544dSBjoern A. Zeeb 421*cbb3ec25SBjoern A. Zeeb mt76_wcid_key_setup(&dev->mt76, wcid, key); 4226c92544dSBjoern A. Zeeb err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip, 4236c92544dSBjoern A. Zeeb key, MCU_EXT_CMD(STA_REC_UPDATE), 4246c92544dSBjoern A. Zeeb &msta->wcid, cmd); 4256c92544dSBjoern A. Zeeb out: 4266c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 4276c92544dSBjoern A. Zeeb 4286c92544dSBjoern A. Zeeb return err; 4296c92544dSBjoern A. Zeeb } 4306c92544dSBjoern A. Zeeb 4316c92544dSBjoern A. Zeeb static int mt7915_set_sar_specs(struct ieee80211_hw *hw, 4326c92544dSBjoern A. Zeeb const struct cfg80211_sar_specs *sar) 4336c92544dSBjoern A. Zeeb { 4346c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 4356c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 4366c92544dSBjoern A. Zeeb int err = -EINVAL; 4376c92544dSBjoern A. Zeeb 4386c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 4396c92544dSBjoern A. Zeeb if (!cfg80211_chandef_valid(&phy->mt76->chandef)) 4406c92544dSBjoern A. Zeeb goto out; 4416c92544dSBjoern A. Zeeb 4426c92544dSBjoern A. Zeeb err = mt76_init_sar_power(hw, sar); 4436c92544dSBjoern A. Zeeb if (err) 4446c92544dSBjoern A. Zeeb goto out; 4456c92544dSBjoern A. Zeeb 4466c92544dSBjoern A. Zeeb err = mt7915_mcu_set_txpower_sku(phy); 4476c92544dSBjoern A. Zeeb out: 4486c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 4496c92544dSBjoern A. Zeeb 4506c92544dSBjoern A. Zeeb return err; 4516c92544dSBjoern A. Zeeb } 4526c92544dSBjoern A. Zeeb 4536c92544dSBjoern A. Zeeb static int mt7915_config(struct ieee80211_hw *hw, u32 changed) 4546c92544dSBjoern A. Zeeb { 4556c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 4566c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 4576c92544dSBjoern A. Zeeb int ret; 4586c92544dSBjoern A. Zeeb 4596c92544dSBjoern A. Zeeb if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 4606c92544dSBjoern A. Zeeb #ifdef CONFIG_NL80211_TESTMODE 4616c92544dSBjoern A. Zeeb if (phy->mt76->test.state != MT76_TM_STATE_OFF) { 4626c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 4636c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, false); 4646c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 4656c92544dSBjoern A. Zeeb } 4666c92544dSBjoern A. Zeeb #endif 4676c92544dSBjoern A. Zeeb ieee80211_stop_queues(hw); 4686c92544dSBjoern A. Zeeb ret = mt7915_set_channel(phy); 4696c92544dSBjoern A. Zeeb if (ret) 4706c92544dSBjoern A. Zeeb return ret; 4716c92544dSBjoern A. Zeeb ieee80211_wake_queues(hw); 4726c92544dSBjoern A. Zeeb } 4736c92544dSBjoern A. Zeeb 474*cbb3ec25SBjoern A. Zeeb if (changed & (IEEE80211_CONF_CHANGE_POWER | 475*cbb3ec25SBjoern A. Zeeb IEEE80211_CONF_CHANGE_CHANNEL)) { 4766c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_txpower_sku(phy); 4776c92544dSBjoern A. Zeeb if (ret) 4786c92544dSBjoern A. Zeeb return ret; 4796c92544dSBjoern A. Zeeb } 4806c92544dSBjoern A. Zeeb 4816c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 4826c92544dSBjoern A. Zeeb 4836c92544dSBjoern A. Zeeb if (changed & IEEE80211_CONF_CHANGE_MONITOR) { 4846c92544dSBjoern A. Zeeb bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); 485*cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx; 4866c92544dSBjoern A. Zeeb 4876c92544dSBjoern A. Zeeb if (!enabled) 4886c92544dSBjoern A. Zeeb phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; 4896c92544dSBjoern A. Zeeb else 4906c92544dSBjoern A. Zeeb phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; 4916c92544dSBjoern A. Zeeb 4926c92544dSBjoern A. Zeeb mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN, 4936c92544dSBjoern A. Zeeb enabled); 4946c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, true); 4956c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); 4966c92544dSBjoern A. Zeeb } 4976c92544dSBjoern A. Zeeb 4986c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 4996c92544dSBjoern A. Zeeb 5006c92544dSBjoern A. Zeeb return 0; 5016c92544dSBjoern A. Zeeb } 5026c92544dSBjoern A. Zeeb 5036c92544dSBjoern A. Zeeb static int 5046c92544dSBjoern A. Zeeb mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 5056c92544dSBjoern A. Zeeb unsigned int link_id, u16 queue, 5066c92544dSBjoern A. Zeeb const struct ieee80211_tx_queue_params *params) 5076c92544dSBjoern A. Zeeb { 5086c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 5096c92544dSBjoern A. Zeeb 5106c92544dSBjoern A. Zeeb /* no need to update right away, we'll get BSS_CHANGED_QOS */ 5116c92544dSBjoern A. Zeeb queue = mt76_connac_lmac_mapping(queue); 5126c92544dSBjoern A. Zeeb mvif->queue_params[queue] = *params; 5136c92544dSBjoern A. Zeeb 5146c92544dSBjoern A. Zeeb return 0; 5156c92544dSBjoern A. Zeeb } 5166c92544dSBjoern A. Zeeb 5176c92544dSBjoern A. Zeeb static void mt7915_configure_filter(struct ieee80211_hw *hw, 5186c92544dSBjoern A. Zeeb unsigned int changed_flags, 5196c92544dSBjoern A. Zeeb unsigned int *total_flags, 5206c92544dSBjoern A. Zeeb u64 multicast) 5216c92544dSBjoern A. Zeeb { 5226c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 5236c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 524*cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx; 5256c92544dSBjoern A. Zeeb u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | 5266c92544dSBjoern A. Zeeb MT_WF_RFCR1_DROP_BF_POLL | 5276c92544dSBjoern A. Zeeb MT_WF_RFCR1_DROP_BA | 5286c92544dSBjoern A. Zeeb MT_WF_RFCR1_DROP_CFEND | 5296c92544dSBjoern A. Zeeb MT_WF_RFCR1_DROP_CFACK; 5306c92544dSBjoern A. Zeeb u32 flags = 0; 5316c92544dSBjoern A. Zeeb 5326c92544dSBjoern A. Zeeb #define MT76_FILTER(_flag, _hw) do { \ 5336c92544dSBjoern A. Zeeb flags |= *total_flags & FIF_##_flag; \ 5346c92544dSBjoern A. Zeeb phy->rxfilter &= ~(_hw); \ 5356c92544dSBjoern A. Zeeb phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ 5366c92544dSBjoern A. Zeeb } while (0) 5376c92544dSBjoern A. Zeeb 5386c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 5396c92544dSBjoern A. Zeeb 5406c92544dSBjoern A. Zeeb phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | 5416c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_OTHER_BEACON | 5426c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_FRAME_REPORT | 5436c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_PROBEREQ | 5446c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_MCAST_FILTERED | 5456c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_MCAST | 5466c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_BCAST | 5476c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_DUPLICATE | 5486c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_A2_BSSID | 5496c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_UNWANTED_CTL | 5506c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_STBC_MULTI); 5516c92544dSBjoern A. Zeeb 5526c92544dSBjoern A. Zeeb MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | 5536c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_A3_MAC | 5546c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_A3_BSSID); 5556c92544dSBjoern A. Zeeb 5566c92544dSBjoern A. Zeeb MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL); 5576c92544dSBjoern A. Zeeb 5586c92544dSBjoern A. Zeeb MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | 5596c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_RTS | 5606c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_CTL_RSV | 5616c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_NDPA); 5626c92544dSBjoern A. Zeeb 5636c92544dSBjoern A. Zeeb *total_flags = flags; 5646c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); 5656c92544dSBjoern A. Zeeb 5666c92544dSBjoern A. Zeeb if (*total_flags & FIF_CONTROL) 5676c92544dSBjoern A. Zeeb mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags); 5686c92544dSBjoern A. Zeeb else 5696c92544dSBjoern A. Zeeb mt76_set(dev, MT_WF_RFCR1(band), ctl_flags); 5706c92544dSBjoern A. Zeeb 5716c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 5726c92544dSBjoern A. Zeeb } 5736c92544dSBjoern A. Zeeb 5746c92544dSBjoern A. Zeeb static void 5756c92544dSBjoern A. Zeeb mt7915_update_bss_color(struct ieee80211_hw *hw, 5766c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 5776c92544dSBjoern A. Zeeb struct cfg80211_he_bss_color *bss_color) 5786c92544dSBjoern A. Zeeb { 5796c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 5806c92544dSBjoern A. Zeeb 5816c92544dSBjoern A. Zeeb switch (vif->type) { 5826c92544dSBjoern A. Zeeb case NL80211_IFTYPE_AP: { 5836c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 5846c92544dSBjoern A. Zeeb 5856c92544dSBjoern A. Zeeb if (mvif->mt76.omac_idx > HW_BSSID_MAX) 5866c92544dSBjoern A. Zeeb return; 5876c92544dSBjoern A. Zeeb fallthrough; 5886c92544dSBjoern A. Zeeb } 5896c92544dSBjoern A. Zeeb case NL80211_IFTYPE_STATION: 5906c92544dSBjoern A. Zeeb mt7915_mcu_update_bss_color(dev, vif, bss_color); 5916c92544dSBjoern A. Zeeb break; 5926c92544dSBjoern A. Zeeb default: 5936c92544dSBjoern A. Zeeb break; 5946c92544dSBjoern A. Zeeb } 5956c92544dSBjoern A. Zeeb } 5966c92544dSBjoern A. Zeeb 5976c92544dSBjoern A. Zeeb static void mt7915_bss_info_changed(struct ieee80211_hw *hw, 5986c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 5996c92544dSBjoern A. Zeeb struct ieee80211_bss_conf *info, 6006c92544dSBjoern A. Zeeb u64 changed) 6016c92544dSBjoern A. Zeeb { 6026c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 6036c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 604*cbb3ec25SBjoern A. Zeeb int set_bss_info = -1, set_sta = -1; 6056c92544dSBjoern A. Zeeb 6066c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 6076c92544dSBjoern A. Zeeb 6086c92544dSBjoern A. Zeeb /* 6096c92544dSBjoern A. Zeeb * station mode uses BSSID to map the wlan entry to a peer, 6106c92544dSBjoern A. Zeeb * and then peer references bss_info_rfch to set bandwidth cap. 6116c92544dSBjoern A. Zeeb */ 6126c92544dSBjoern A. Zeeb if (changed & BSS_CHANGED_BSSID && 613*cbb3ec25SBjoern A. Zeeb vif->type == NL80211_IFTYPE_STATION) 614*cbb3ec25SBjoern A. Zeeb set_bss_info = set_sta = !is_zero_ether_addr(info->bssid); 615*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_ASSOC) 616*cbb3ec25SBjoern A. Zeeb set_bss_info = vif->cfg.assoc; 617*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON_ENABLED && 618*cbb3ec25SBjoern A. Zeeb vif->type != NL80211_IFTYPE_AP) 619*cbb3ec25SBjoern A. Zeeb set_bss_info = set_sta = info->enable_beacon; 6206c92544dSBjoern A. Zeeb 621*cbb3ec25SBjoern A. Zeeb if (set_bss_info == 1) 622*cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, true); 623*cbb3ec25SBjoern A. Zeeb if (set_sta == 1) 624*cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, true); 6256c92544dSBjoern A. Zeeb 626*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_CTS_PROT) 627*cbb3ec25SBjoern A. Zeeb mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot); 6286c92544dSBjoern A. Zeeb 6296c92544dSBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_SLOT) { 6306c92544dSBjoern A. Zeeb int slottime = info->use_short_slot ? 9 : 20; 6316c92544dSBjoern A. Zeeb 6326c92544dSBjoern A. Zeeb if (slottime != phy->slottime) { 6336c92544dSBjoern A. Zeeb phy->slottime = slottime; 6346c92544dSBjoern A. Zeeb mt7915_mac_set_timing(phy); 6356c92544dSBjoern A. Zeeb } 6366c92544dSBjoern A. Zeeb } 6376c92544dSBjoern A. Zeeb 6386c92544dSBjoern A. Zeeb /* ensure that enable txcmd_mode after bss_info */ 6396c92544dSBjoern A. Zeeb if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) 6406c92544dSBjoern A. Zeeb mt7915_mcu_set_tx(dev, vif); 6416c92544dSBjoern A. Zeeb 6426c92544dSBjoern A. Zeeb if (changed & BSS_CHANGED_HE_OBSS_PD) 643*cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_obss_spr(phy, vif, &info->he_obss_pd); 6446c92544dSBjoern A. Zeeb 6456c92544dSBjoern A. Zeeb if (changed & BSS_CHANGED_HE_BSS_COLOR) 6466c92544dSBjoern A. Zeeb mt7915_update_bss_color(hw, vif, &info->he_bss_color); 6476c92544dSBjoern A. Zeeb 6486c92544dSBjoern A. Zeeb if (changed & (BSS_CHANGED_BEACON | 6496c92544dSBjoern A. Zeeb BSS_CHANGED_BEACON_ENABLED | 6506c92544dSBjoern A. Zeeb BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | 6516c92544dSBjoern A. Zeeb BSS_CHANGED_FILS_DISCOVERY)) 6526c92544dSBjoern A. Zeeb mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); 6536c92544dSBjoern A. Zeeb 654*cbb3ec25SBjoern A. Zeeb if (set_bss_info == 0) 655*cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, false); 656*cbb3ec25SBjoern A. Zeeb if (set_sta == 0) 657*cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, false); 658*cbb3ec25SBjoern A. Zeeb 659*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 660*cbb3ec25SBjoern A. Zeeb } 661*cbb3ec25SBjoern A. Zeeb 662*cbb3ec25SBjoern A. Zeeb static void 663*cbb3ec25SBjoern A. Zeeb mt7915_vif_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif) 664*cbb3ec25SBjoern A. Zeeb { 665*cbb3ec25SBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 666*cbb3ec25SBjoern A. Zeeb struct mt7915_vif_cap *vc = &mvif->cap; 667*cbb3ec25SBjoern A. Zeeb 668*cbb3ec25SBjoern A. Zeeb vc->ht_ldpc = vif->bss_conf.ht_ldpc; 669*cbb3ec25SBjoern A. Zeeb vc->vht_ldpc = vif->bss_conf.vht_ldpc; 670*cbb3ec25SBjoern A. Zeeb vc->vht_su_ebfer = vif->bss_conf.vht_su_beamformer; 671*cbb3ec25SBjoern A. Zeeb vc->vht_su_ebfee = vif->bss_conf.vht_su_beamformee; 672*cbb3ec25SBjoern A. Zeeb vc->vht_mu_ebfer = vif->bss_conf.vht_mu_beamformer; 673*cbb3ec25SBjoern A. Zeeb vc->vht_mu_ebfee = vif->bss_conf.vht_mu_beamformee; 674*cbb3ec25SBjoern A. Zeeb vc->he_ldpc = vif->bss_conf.he_ldpc; 675*cbb3ec25SBjoern A. Zeeb vc->he_su_ebfer = vif->bss_conf.he_su_beamformer; 676*cbb3ec25SBjoern A. Zeeb vc->he_su_ebfee = vif->bss_conf.he_su_beamformee; 677*cbb3ec25SBjoern A. Zeeb vc->he_mu_ebfer = vif->bss_conf.he_mu_beamformer; 678*cbb3ec25SBjoern A. Zeeb } 679*cbb3ec25SBjoern A. Zeeb 680*cbb3ec25SBjoern A. Zeeb static int 681*cbb3ec25SBjoern A. Zeeb mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 682*cbb3ec25SBjoern A. Zeeb struct ieee80211_bss_conf *link_conf) 683*cbb3ec25SBjoern A. Zeeb { 684*cbb3ec25SBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 685*cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 686*cbb3ec25SBjoern A. Zeeb int err; 687*cbb3ec25SBjoern A. Zeeb 688*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 689*cbb3ec25SBjoern A. Zeeb 690*cbb3ec25SBjoern A. Zeeb mt7915_vif_check_caps(phy, vif); 691*cbb3ec25SBjoern A. Zeeb 692*cbb3ec25SBjoern A. Zeeb err = mt7915_mcu_add_bss_info(phy, vif, true); 693*cbb3ec25SBjoern A. Zeeb if (err) 694*cbb3ec25SBjoern A. Zeeb goto out; 695*cbb3ec25SBjoern A. Zeeb err = mt7915_mcu_add_sta(dev, vif, NULL, true); 696*cbb3ec25SBjoern A. Zeeb out: 697*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 698*cbb3ec25SBjoern A. Zeeb 699*cbb3ec25SBjoern A. Zeeb return err; 700*cbb3ec25SBjoern A. Zeeb } 701*cbb3ec25SBjoern A. Zeeb 702*cbb3ec25SBjoern A. Zeeb static void 703*cbb3ec25SBjoern A. Zeeb mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 704*cbb3ec25SBjoern A. Zeeb struct ieee80211_bss_conf *link_conf) 705*cbb3ec25SBjoern A. Zeeb { 706*cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 707*cbb3ec25SBjoern A. Zeeb 708*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 709*cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, false); 7106c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 7116c92544dSBjoern A. Zeeb } 7126c92544dSBjoern A. Zeeb 7136c92544dSBjoern A. Zeeb static void 7146c92544dSBjoern A. Zeeb mt7915_channel_switch_beacon(struct ieee80211_hw *hw, 7156c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 7166c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef) 7176c92544dSBjoern A. Zeeb { 7186c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 7196c92544dSBjoern A. Zeeb 7206c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 7216c92544dSBjoern A. Zeeb mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON); 7226c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 7236c92544dSBjoern A. Zeeb } 7246c92544dSBjoern A. Zeeb 7256c92544dSBjoern A. Zeeb int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, 7266c92544dSBjoern A. Zeeb struct ieee80211_sta *sta) 7276c92544dSBjoern A. Zeeb { 7286c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); 7296c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 7306c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 7316c92544dSBjoern A. Zeeb bool ext_phy = mvif->phy != &dev->phy; 7326c92544dSBjoern A. Zeeb int ret, idx; 7336c92544dSBjoern A. Zeeb 7346c92544dSBjoern A. Zeeb idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); 7356c92544dSBjoern A. Zeeb if (idx < 0) 7366c92544dSBjoern A. Zeeb return -ENOSPC; 7376c92544dSBjoern A. Zeeb 7386c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&msta->rc_list); 739*cbb3ec25SBjoern A. Zeeb INIT_LIST_HEAD(&msta->wcid.poll_list); 7406c92544dSBjoern A. Zeeb msta->vif = mvif; 7416c92544dSBjoern A. Zeeb msta->wcid.sta = 1; 7426c92544dSBjoern A. Zeeb msta->wcid.idx = idx; 7436c92544dSBjoern A. Zeeb msta->wcid.phy_idx = ext_phy; 7446c92544dSBjoern A. Zeeb msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; 7456c92544dSBjoern A. Zeeb msta->jiffies = jiffies; 7466c92544dSBjoern A. Zeeb 747*cbb3ec25SBjoern A. Zeeb ewma_avg_signal_init(&msta->avg_ack_signal); 748*cbb3ec25SBjoern A. Zeeb 7496c92544dSBjoern A. Zeeb mt7915_mac_wtbl_update(dev, idx, 7506c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 7516c92544dSBjoern A. Zeeb 7526c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_sta(dev, vif, sta, true); 7536c92544dSBjoern A. Zeeb if (ret) 7546c92544dSBjoern A. Zeeb return ret; 7556c92544dSBjoern A. Zeeb 7566c92544dSBjoern A. Zeeb return mt7915_mcu_add_rate_ctrl(dev, vif, sta, false); 7576c92544dSBjoern A. Zeeb } 7586c92544dSBjoern A. Zeeb 7596c92544dSBjoern A. Zeeb void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, 7606c92544dSBjoern A. Zeeb struct ieee80211_sta *sta) 7616c92544dSBjoern A. Zeeb { 7626c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); 7636c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 7646c92544dSBjoern A. Zeeb int i; 7656c92544dSBjoern A. Zeeb 7666c92544dSBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, sta, false); 7676c92544dSBjoern A. Zeeb 7686c92544dSBjoern A. Zeeb mt7915_mac_wtbl_update(dev, msta->wcid.idx, 7696c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 7706c92544dSBjoern A. Zeeb 7716c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) 7726c92544dSBjoern A. Zeeb mt7915_mac_twt_teardown_flow(dev, msta, i); 7736c92544dSBjoern A. Zeeb 774*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&mdev->sta_poll_lock); 775*cbb3ec25SBjoern A. Zeeb if (!list_empty(&msta->wcid.poll_list)) 776*cbb3ec25SBjoern A. Zeeb list_del_init(&msta->wcid.poll_list); 7776c92544dSBjoern A. Zeeb if (!list_empty(&msta->rc_list)) 7786c92544dSBjoern A. Zeeb list_del_init(&msta->rc_list); 779*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&mdev->sta_poll_lock); 7806c92544dSBjoern A. Zeeb } 7816c92544dSBjoern A. Zeeb 7826c92544dSBjoern A. Zeeb static void mt7915_tx(struct ieee80211_hw *hw, 7836c92544dSBjoern A. Zeeb struct ieee80211_tx_control *control, 7846c92544dSBjoern A. Zeeb struct sk_buff *skb) 7856c92544dSBjoern A. Zeeb { 7866c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 7876c92544dSBjoern A. Zeeb struct mt76_phy *mphy = hw->priv; 7886c92544dSBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 7896c92544dSBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif; 7906c92544dSBjoern A. Zeeb struct mt76_wcid *wcid = &dev->mt76.global_wcid; 7916c92544dSBjoern A. Zeeb 7926c92544dSBjoern A. Zeeb if (control->sta) { 7936c92544dSBjoern A. Zeeb struct mt7915_sta *sta; 7946c92544dSBjoern A. Zeeb 7956c92544dSBjoern A. Zeeb sta = (struct mt7915_sta *)control->sta->drv_priv; 7966c92544dSBjoern A. Zeeb wcid = &sta->wcid; 7976c92544dSBjoern A. Zeeb } 7986c92544dSBjoern A. Zeeb 7996c92544dSBjoern A. Zeeb if (vif && !control->sta) { 8006c92544dSBjoern A. Zeeb struct mt7915_vif *mvif; 8016c92544dSBjoern A. Zeeb 8026c92544dSBjoern A. Zeeb mvif = (struct mt7915_vif *)vif->drv_priv; 8036c92544dSBjoern A. Zeeb wcid = &mvif->sta.wcid; 8046c92544dSBjoern A. Zeeb } 8056c92544dSBjoern A. Zeeb 8066c92544dSBjoern A. Zeeb mt76_tx(mphy, control->sta, wcid, skb); 8076c92544dSBjoern A. Zeeb } 8086c92544dSBjoern A. Zeeb 8096c92544dSBjoern A. Zeeb static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, u32 val) 8106c92544dSBjoern A. Zeeb { 8116c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 8126c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 8136c92544dSBjoern A. Zeeb int ret; 8146c92544dSBjoern A. Zeeb 8156c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 816*cbb3ec25SBjoern A. Zeeb ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, 817*cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx); 8186c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 8196c92544dSBjoern A. Zeeb 8206c92544dSBjoern A. Zeeb return ret; 8216c92544dSBjoern A. Zeeb } 8226c92544dSBjoern A. Zeeb 8236c92544dSBjoern A. Zeeb static int 8246c92544dSBjoern A. Zeeb mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 8256c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params) 8266c92544dSBjoern A. Zeeb { 8276c92544dSBjoern A. Zeeb enum ieee80211_ampdu_mlme_action action = params->action; 8286c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 8296c92544dSBjoern A. Zeeb struct ieee80211_sta *sta = params->sta; 8306c92544dSBjoern A. Zeeb struct ieee80211_txq *txq = sta->txq[params->tid]; 8316c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 8326c92544dSBjoern A. Zeeb u16 tid = params->tid; 8336c92544dSBjoern A. Zeeb u16 ssn = params->ssn; 8346c92544dSBjoern A. Zeeb struct mt76_txq *mtxq; 8356c92544dSBjoern A. Zeeb int ret = 0; 8366c92544dSBjoern A. Zeeb 8376c92544dSBjoern A. Zeeb if (!txq) 8386c92544dSBjoern A. Zeeb return -EINVAL; 8396c92544dSBjoern A. Zeeb 8406c92544dSBjoern A. Zeeb mtxq = (struct mt76_txq *)txq->drv_priv; 8416c92544dSBjoern A. Zeeb 8426c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 8436c92544dSBjoern A. Zeeb switch (action) { 8446c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_RX_START: 8456c92544dSBjoern A. Zeeb mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, 8466c92544dSBjoern A. Zeeb params->buf_size); 8476c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_rx_ba(dev, params, true); 8486c92544dSBjoern A. Zeeb break; 8496c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_RX_STOP: 8506c92544dSBjoern A. Zeeb mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); 8516c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_rx_ba(dev, params, false); 8526c92544dSBjoern A. Zeeb break; 8536c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_OPERATIONAL: 8546c92544dSBjoern A. Zeeb mtxq->aggr = true; 8556c92544dSBjoern A. Zeeb mtxq->send_bar = false; 8566c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_tx_ba(dev, params, true); 8576c92544dSBjoern A. Zeeb break; 8586c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH: 8596c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 8606c92544dSBjoern A. Zeeb mtxq->aggr = false; 861*cbb3ec25SBjoern A. Zeeb clear_bit(tid, &msta->wcid.ampdu_state); 8626c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_tx_ba(dev, params, false); 8636c92544dSBjoern A. Zeeb break; 8646c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_START: 865*cbb3ec25SBjoern A. Zeeb set_bit(tid, &msta->wcid.ampdu_state); 8666c92544dSBjoern A. Zeeb ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; 8676c92544dSBjoern A. Zeeb break; 8686c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_CONT: 8696c92544dSBjoern A. Zeeb mtxq->aggr = false; 870*cbb3ec25SBjoern A. Zeeb clear_bit(tid, &msta->wcid.ampdu_state); 8716c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_tx_ba(dev, params, false); 8726c92544dSBjoern A. Zeeb ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 8736c92544dSBjoern A. Zeeb break; 8746c92544dSBjoern A. Zeeb } 8756c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 8766c92544dSBjoern A. Zeeb 8776c92544dSBjoern A. Zeeb return ret; 8786c92544dSBjoern A. Zeeb } 8796c92544dSBjoern A. Zeeb 8806c92544dSBjoern A. Zeeb static int 8816c92544dSBjoern A. Zeeb mt7915_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 8826c92544dSBjoern A. Zeeb struct ieee80211_sta *sta) 8836c92544dSBjoern A. Zeeb { 8846c92544dSBjoern A. Zeeb return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST, 8856c92544dSBjoern A. Zeeb IEEE80211_STA_NONE); 8866c92544dSBjoern A. Zeeb } 8876c92544dSBjoern A. Zeeb 8886c92544dSBjoern A. Zeeb static int 8896c92544dSBjoern A. Zeeb mt7915_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 8906c92544dSBjoern A. Zeeb struct ieee80211_sta *sta) 8916c92544dSBjoern A. Zeeb { 8926c92544dSBjoern A. Zeeb return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE, 8936c92544dSBjoern A. Zeeb IEEE80211_STA_NOTEXIST); 8946c92544dSBjoern A. Zeeb } 8956c92544dSBjoern A. Zeeb 8966c92544dSBjoern A. Zeeb static int 8976c92544dSBjoern A. Zeeb mt7915_get_stats(struct ieee80211_hw *hw, 8986c92544dSBjoern A. Zeeb struct ieee80211_low_level_stats *stats) 8996c92544dSBjoern A. Zeeb { 9006c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 9016c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 902*cbb3ec25SBjoern A. Zeeb struct mt76_mib_stats *mib = &phy->mib; 9036c92544dSBjoern A. Zeeb 9046c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 9056c92544dSBjoern A. Zeeb 9066c92544dSBjoern A. Zeeb stats->dot11RTSSuccessCount = mib->rts_cnt; 9076c92544dSBjoern A. Zeeb stats->dot11RTSFailureCount = mib->rts_retries_cnt; 9086c92544dSBjoern A. Zeeb stats->dot11FCSErrorCount = mib->fcs_err_cnt; 9096c92544dSBjoern A. Zeeb stats->dot11ACKFailureCount = mib->ack_fail_cnt; 9106c92544dSBjoern A. Zeeb 9116c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 9126c92544dSBjoern A. Zeeb 9136c92544dSBjoern A. Zeeb return 0; 9146c92544dSBjoern A. Zeeb } 9156c92544dSBjoern A. Zeeb 9166c92544dSBjoern A. Zeeb u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif) 9176c92544dSBjoern A. Zeeb { 9186c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 9196c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 920*cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx; 9216c92544dSBjoern A. Zeeb union { 9226c92544dSBjoern A. Zeeb u64 t64; 9236c92544dSBjoern A. Zeeb u32 t32[2]; 9246c92544dSBjoern A. Zeeb } tsf; 9256c92544dSBjoern A. Zeeb u16 n; 9266c92544dSBjoern A. Zeeb 9276c92544dSBjoern A. Zeeb lockdep_assert_held(&dev->mt76.mutex); 9286c92544dSBjoern A. Zeeb 9296c92544dSBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 9306c92544dSBjoern A. Zeeb : mvif->mt76.omac_idx; 9316c92544dSBjoern A. Zeeb /* TSF software read */ 9326c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76)) 9336c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, 9346c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_READ); 9356c92544dSBjoern A. Zeeb else 9366c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE, 9376c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_READ); 9386c92544dSBjoern A. Zeeb tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band)); 9396c92544dSBjoern A. Zeeb tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band)); 9406c92544dSBjoern A. Zeeb 9416c92544dSBjoern A. Zeeb return tsf.t64; 9426c92544dSBjoern A. Zeeb } 9436c92544dSBjoern A. Zeeb 9446c92544dSBjoern A. Zeeb static u64 9456c92544dSBjoern A. Zeeb mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 9466c92544dSBjoern A. Zeeb { 9476c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 9486c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 9496c92544dSBjoern A. Zeeb u64 ret; 9506c92544dSBjoern A. Zeeb 9516c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 9526c92544dSBjoern A. Zeeb ret = __mt7915_get_tsf(hw, mvif); 9536c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 9546c92544dSBjoern A. Zeeb 9556c92544dSBjoern A. Zeeb return ret; 9566c92544dSBjoern A. Zeeb } 9576c92544dSBjoern A. Zeeb 9586c92544dSBjoern A. Zeeb static void 9596c92544dSBjoern A. Zeeb mt7915_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 9606c92544dSBjoern A. Zeeb u64 timestamp) 9616c92544dSBjoern A. Zeeb { 9626c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 9636c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 9646c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 965*cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx; 9666c92544dSBjoern A. Zeeb union { 9676c92544dSBjoern A. Zeeb u64 t64; 9686c92544dSBjoern A. Zeeb u32 t32[2]; 9696c92544dSBjoern A. Zeeb } tsf = { .t64 = timestamp, }; 9706c92544dSBjoern A. Zeeb u16 n; 9716c92544dSBjoern A. Zeeb 9726c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 9736c92544dSBjoern A. Zeeb 9746c92544dSBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 9756c92544dSBjoern A. Zeeb : mvif->mt76.omac_idx; 9766c92544dSBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]); 9776c92544dSBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]); 9786c92544dSBjoern A. Zeeb /* TSF software overwrite */ 9796c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76)) 9806c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, 9816c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_WRITE); 9826c92544dSBjoern A. Zeeb else 9836c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE, 9846c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_WRITE); 9856c92544dSBjoern A. Zeeb 9866c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 9876c92544dSBjoern A. Zeeb } 9886c92544dSBjoern A. Zeeb 9896c92544dSBjoern A. Zeeb static void 9906c92544dSBjoern A. Zeeb mt7915_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 9916c92544dSBjoern A. Zeeb s64 timestamp) 9926c92544dSBjoern A. Zeeb { 9936c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 9946c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 9956c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 996*cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx; 9976c92544dSBjoern A. Zeeb union { 9986c92544dSBjoern A. Zeeb u64 t64; 9996c92544dSBjoern A. Zeeb u32 t32[2]; 10006c92544dSBjoern A. Zeeb } tsf = { .t64 = timestamp, }; 10016c92544dSBjoern A. Zeeb u16 n; 10026c92544dSBjoern A. Zeeb 10036c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 10046c92544dSBjoern A. Zeeb 10056c92544dSBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 10066c92544dSBjoern A. Zeeb : mvif->mt76.omac_idx; 10076c92544dSBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]); 10086c92544dSBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]); 10096c92544dSBjoern A. Zeeb /* TSF software adjust*/ 10106c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76)) 10116c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE, 10126c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_ADJUST); 10136c92544dSBjoern A. Zeeb else 10146c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE, 10156c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_ADJUST); 10166c92544dSBjoern A. Zeeb 10176c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 10186c92544dSBjoern A. Zeeb } 10196c92544dSBjoern A. Zeeb 10206c92544dSBjoern A. Zeeb static void 10216c92544dSBjoern A. Zeeb mt7915_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) 10226c92544dSBjoern A. Zeeb { 10236c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 10246c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 10256c92544dSBjoern A. Zeeb 10266c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 10276c92544dSBjoern A. Zeeb phy->coverage_class = max_t(s16, coverage_class, 0); 10286c92544dSBjoern A. Zeeb mt7915_mac_set_timing(phy); 10296c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 10306c92544dSBjoern A. Zeeb } 10316c92544dSBjoern A. Zeeb 10326c92544dSBjoern A. Zeeb static int 10336c92544dSBjoern A. Zeeb mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) 10346c92544dSBjoern A. Zeeb { 10356c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 10366c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 10376c92544dSBjoern A. Zeeb int max_nss = hweight8(hw->wiphy->available_antennas_tx); 1038*cbb3ec25SBjoern A. Zeeb u8 chainshift = dev->chainshift; 1039*cbb3ec25SBjoern A. Zeeb u8 band = phy->mt76->band_idx; 10406c92544dSBjoern A. Zeeb 10416c92544dSBjoern A. Zeeb if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) 10426c92544dSBjoern A. Zeeb return -EINVAL; 10436c92544dSBjoern A. Zeeb 10446c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 10456c92544dSBjoern A. Zeeb 10466c92544dSBjoern A. Zeeb phy->mt76->antenna_mask = tx_ant; 10476c92544dSBjoern A. Zeeb 1048*cbb3ec25SBjoern A. Zeeb /* handle a variant of mt7916 which has 3T3R but nss2 on 5 GHz band */ 1049*cbb3ec25SBjoern A. Zeeb if (is_mt7916(&dev->mt76) && band && hweight8(tx_ant) == max_nss) 1050*cbb3ec25SBjoern A. Zeeb phy->mt76->chainmask = (dev->chainmask >> chainshift) << chainshift; 1051*cbb3ec25SBjoern A. Zeeb else 1052*cbb3ec25SBjoern A. Zeeb phy->mt76->chainmask = tx_ant << (chainshift * band); 10536c92544dSBjoern A. Zeeb 10546c92544dSBjoern A. Zeeb mt76_set_stream_caps(phy->mt76, true); 10556c92544dSBjoern A. Zeeb mt7915_set_stream_vht_txbf_caps(phy); 10566c92544dSBjoern A. Zeeb mt7915_set_stream_he_caps(phy); 10576c92544dSBjoern A. Zeeb 10586c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 10596c92544dSBjoern A. Zeeb 10606c92544dSBjoern A. Zeeb return 0; 10616c92544dSBjoern A. Zeeb } 10626c92544dSBjoern A. Zeeb 10636c92544dSBjoern A. Zeeb static void mt7915_sta_statistics(struct ieee80211_hw *hw, 10646c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 10656c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, 10666c92544dSBjoern A. Zeeb struct station_info *sinfo) 10676c92544dSBjoern A. Zeeb { 10686c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 10696c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 10706c92544dSBjoern A. Zeeb struct rate_info *txrate = &msta->wcid.rate; 10716c92544dSBjoern A. Zeeb struct rate_info rxrate = {}; 10726c92544dSBjoern A. Zeeb 10736c92544dSBjoern A. Zeeb if (is_mt7915(&phy->dev->mt76) && 10746c92544dSBjoern A. Zeeb !mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) { 10756c92544dSBjoern A. Zeeb sinfo->rxrate = rxrate; 10766c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); 10776c92544dSBjoern A. Zeeb } 10786c92544dSBjoern A. Zeeb 1079*cbb3ec25SBjoern A. Zeeb if (txrate->legacy || txrate->flags) { 10806c92544dSBjoern A. Zeeb if (txrate->legacy) { 10816c92544dSBjoern A. Zeeb sinfo->txrate.legacy = txrate->legacy; 10826c92544dSBjoern A. Zeeb } else { 10836c92544dSBjoern A. Zeeb sinfo->txrate.mcs = txrate->mcs; 10846c92544dSBjoern A. Zeeb sinfo->txrate.nss = txrate->nss; 10856c92544dSBjoern A. Zeeb sinfo->txrate.bw = txrate->bw; 10866c92544dSBjoern A. Zeeb sinfo->txrate.he_gi = txrate->he_gi; 10876c92544dSBjoern A. Zeeb sinfo->txrate.he_dcm = txrate->he_dcm; 10886c92544dSBjoern A. Zeeb sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; 10896c92544dSBjoern A. Zeeb } 10906c92544dSBjoern A. Zeeb sinfo->txrate.flags = txrate->flags; 10916c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); 1092*cbb3ec25SBjoern A. Zeeb } 10936c92544dSBjoern A. Zeeb 10946c92544dSBjoern A. Zeeb /* offloading flows bypass networking stack, so driver counts and 10956c92544dSBjoern A. Zeeb * reports sta statistics via NL80211_STA_INFO when WED is active. 10966c92544dSBjoern A. Zeeb */ 10976c92544dSBjoern A. Zeeb if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { 10986c92544dSBjoern A. Zeeb sinfo->tx_bytes = msta->wcid.stats.tx_bytes; 10996c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); 11006c92544dSBjoern A. Zeeb 1101*cbb3ec25SBjoern A. Zeeb if (!mt7915_mcu_wed_wa_tx_stats(phy->dev, msta->wcid.idx)) { 11026c92544dSBjoern A. Zeeb sinfo->tx_packets = msta->wcid.stats.tx_packets; 11036c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); 1104*cbb3ec25SBjoern A. Zeeb } 1105*cbb3ec25SBjoern A. Zeeb 1106*cbb3ec25SBjoern A. Zeeb if (mtk_wed_get_rx_capa(&phy->dev->mt76.mmio.wed)) { 1107*cbb3ec25SBjoern A. Zeeb sinfo->rx_bytes = msta->wcid.stats.rx_bytes; 1108*cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64); 1109*cbb3ec25SBjoern A. Zeeb 1110*cbb3ec25SBjoern A. Zeeb sinfo->rx_packets = msta->wcid.stats.rx_packets; 1111*cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS); 1112*cbb3ec25SBjoern A. Zeeb } 1113*cbb3ec25SBjoern A. Zeeb } 11146c92544dSBjoern A. Zeeb 11156c92544dSBjoern A. Zeeb sinfo->tx_failed = msta->wcid.stats.tx_failed; 11166c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); 11176c92544dSBjoern A. Zeeb 11186c92544dSBjoern A. Zeeb sinfo->tx_retries = msta->wcid.stats.tx_retries; 11196c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); 1120*cbb3ec25SBjoern A. Zeeb 1121*cbb3ec25SBjoern A. Zeeb sinfo->ack_signal = (s8)msta->ack_signal; 1122*cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); 1123*cbb3ec25SBjoern A. Zeeb 1124*cbb3ec25SBjoern A. Zeeb sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal); 1125*cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); 11266c92544dSBjoern A. Zeeb } 11276c92544dSBjoern A. Zeeb 11286c92544dSBjoern A. Zeeb static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) 11296c92544dSBjoern A. Zeeb { 11306c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 11316c92544dSBjoern A. Zeeb struct mt7915_dev *dev = msta->vif->phy->dev; 11326c92544dSBjoern A. Zeeb u32 *changed = data; 11336c92544dSBjoern A. Zeeb 1134*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 11356c92544dSBjoern A. Zeeb msta->changed |= *changed; 11366c92544dSBjoern A. Zeeb if (list_empty(&msta->rc_list)) 11376c92544dSBjoern A. Zeeb list_add_tail(&msta->rc_list, &dev->sta_rc_list); 1138*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 11396c92544dSBjoern A. Zeeb } 11406c92544dSBjoern A. Zeeb 11416c92544dSBjoern A. Zeeb static void mt7915_sta_rc_update(struct ieee80211_hw *hw, 11426c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 11436c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, 11446c92544dSBjoern A. Zeeb u32 changed) 11456c92544dSBjoern A. Zeeb { 11466c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 11476c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 11486c92544dSBjoern A. Zeeb 11496c92544dSBjoern A. Zeeb mt7915_sta_rc_work(&changed, sta); 11506c92544dSBjoern A. Zeeb ieee80211_queue_work(hw, &dev->rc_work); 11516c92544dSBjoern A. Zeeb } 11526c92544dSBjoern A. Zeeb 11536c92544dSBjoern A. Zeeb static int 11546c92544dSBjoern A. Zeeb mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 11556c92544dSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask) 11566c92544dSBjoern A. Zeeb { 11576c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 11586c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 11596c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 11606c92544dSBjoern A. Zeeb u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED; 11616c92544dSBjoern A. Zeeb 11626c92544dSBjoern A. Zeeb mvif->bitrate_mask = *mask; 11636c92544dSBjoern A. Zeeb 11646c92544dSBjoern A. Zeeb /* if multiple rates across different preambles are given we can 11656c92544dSBjoern A. Zeeb * reconfigure this info with all peers using sta_rec command with 11666c92544dSBjoern A. Zeeb * the below exception cases. 11676c92544dSBjoern A. Zeeb * - single rate : if a rate is passed along with different preambles, 11686c92544dSBjoern A. Zeeb * we select the highest one as fixed rate. i.e VHT MCS for VHT peers. 11696c92544dSBjoern A. Zeeb * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT 11706c92544dSBjoern A. Zeeb * then multiple MCS setting (MCS 4,5,6) is not supported. 11716c92544dSBjoern A. Zeeb */ 11726c92544dSBjoern A. Zeeb ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed); 11736c92544dSBjoern A. Zeeb ieee80211_queue_work(hw, &dev->rc_work); 11746c92544dSBjoern A. Zeeb 11756c92544dSBjoern A. Zeeb return 0; 11766c92544dSBjoern A. Zeeb } 11776c92544dSBjoern A. Zeeb 11786c92544dSBjoern A. Zeeb static void mt7915_sta_set_4addr(struct ieee80211_hw *hw, 11796c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 11806c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, 11816c92544dSBjoern A. Zeeb bool enabled) 11826c92544dSBjoern A. Zeeb { 11836c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 11846c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 11856c92544dSBjoern A. Zeeb 11866c92544dSBjoern A. Zeeb if (enabled) 11876c92544dSBjoern A. Zeeb set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); 11886c92544dSBjoern A. Zeeb else 11896c92544dSBjoern A. Zeeb clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); 11906c92544dSBjoern A. Zeeb 11916c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); 11926c92544dSBjoern A. Zeeb } 11936c92544dSBjoern A. Zeeb 11946c92544dSBjoern A. Zeeb static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw, 11956c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 11966c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, 11976c92544dSBjoern A. Zeeb bool enabled) 11986c92544dSBjoern A. Zeeb { 11996c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 12006c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 12016c92544dSBjoern A. Zeeb 12026c92544dSBjoern A. Zeeb if (enabled) 12036c92544dSBjoern A. Zeeb set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); 12046c92544dSBjoern A. Zeeb else 12056c92544dSBjoern A. Zeeb clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); 12066c92544dSBjoern A. Zeeb 12076c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta); 12086c92544dSBjoern A. Zeeb } 12096c92544dSBjoern A. Zeeb 1210*cbb3ec25SBjoern A. Zeeb static int mt7915_sta_set_txpwr(struct ieee80211_hw *hw, 1211*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 1212*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta) 1213*cbb3ec25SBjoern A. Zeeb { 1214*cbb3ec25SBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 1215*cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 1216*cbb3ec25SBjoern A. Zeeb s16 txpower = sta->deflink.txpwr.power; 1217*cbb3ec25SBjoern A. Zeeb int ret; 1218*cbb3ec25SBjoern A. Zeeb 1219*cbb3ec25SBjoern A. Zeeb if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) 1220*cbb3ec25SBjoern A. Zeeb txpower = 0; 1221*cbb3ec25SBjoern A. Zeeb 1222*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 1223*cbb3ec25SBjoern A. Zeeb 1224*cbb3ec25SBjoern A. Zeeb /* NOTE: temporarily use 0 as minimum limit, which is a 1225*cbb3ec25SBjoern A. Zeeb * global setting and will be applied to all stations. 1226*cbb3ec25SBjoern A. Zeeb */ 1227*cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_txpower_frame_min(phy, 0); 1228*cbb3ec25SBjoern A. Zeeb if (ret) 1229*cbb3ec25SBjoern A. Zeeb goto out; 1230*cbb3ec25SBjoern A. Zeeb 1231*cbb3ec25SBjoern A. Zeeb /* This only applies to data frames while pushing traffic, 1232*cbb3ec25SBjoern A. Zeeb * whereas the management frames or other packets that are 1233*cbb3ec25SBjoern A. Zeeb * using fixed rate can be configured via TxD. 1234*cbb3ec25SBjoern A. Zeeb */ 1235*cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_txpower_frame(phy, vif, sta, txpower); 1236*cbb3ec25SBjoern A. Zeeb 1237*cbb3ec25SBjoern A. Zeeb out: 1238*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 1239*cbb3ec25SBjoern A. Zeeb 1240*cbb3ec25SBjoern A. Zeeb return ret; 1241*cbb3ec25SBjoern A. Zeeb } 1242*cbb3ec25SBjoern A. Zeeb 12436c92544dSBjoern A. Zeeb static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = { 12446c92544dSBjoern A. Zeeb "tx_ampdu_cnt", 12456c92544dSBjoern A. Zeeb "tx_stop_q_empty_cnt", 12466c92544dSBjoern A. Zeeb "tx_mpdu_attempts", 12476c92544dSBjoern A. Zeeb "tx_mpdu_success", 12486c92544dSBjoern A. Zeeb "tx_rwp_fail_cnt", 12496c92544dSBjoern A. Zeeb "tx_rwp_need_cnt", 12506c92544dSBjoern A. Zeeb "tx_pkt_ebf_cnt", 12516c92544dSBjoern A. Zeeb "tx_pkt_ibf_cnt", 12526c92544dSBjoern A. Zeeb "tx_ampdu_len:0-1", 12536c92544dSBjoern A. Zeeb "tx_ampdu_len:2-10", 12546c92544dSBjoern A. Zeeb "tx_ampdu_len:11-19", 12556c92544dSBjoern A. Zeeb "tx_ampdu_len:20-28", 12566c92544dSBjoern A. Zeeb "tx_ampdu_len:29-37", 12576c92544dSBjoern A. Zeeb "tx_ampdu_len:38-46", 12586c92544dSBjoern A. Zeeb "tx_ampdu_len:47-55", 12596c92544dSBjoern A. Zeeb "tx_ampdu_len:56-79", 12606c92544dSBjoern A. Zeeb "tx_ampdu_len:80-103", 12616c92544dSBjoern A. Zeeb "tx_ampdu_len:104-127", 12626c92544dSBjoern A. Zeeb "tx_ampdu_len:128-151", 12636c92544dSBjoern A. Zeeb "tx_ampdu_len:152-175", 12646c92544dSBjoern A. Zeeb "tx_ampdu_len:176-199", 12656c92544dSBjoern A. Zeeb "tx_ampdu_len:200-223", 12666c92544dSBjoern A. Zeeb "tx_ampdu_len:224-247", 12676c92544dSBjoern A. Zeeb "ba_miss_count", 12686c92544dSBjoern A. Zeeb "tx_beamformer_ppdu_iBF", 12696c92544dSBjoern A. Zeeb "tx_beamformer_ppdu_eBF", 12706c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_all", 12716c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_he", 12726c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_vht", 12736c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_ht", 12746c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_bw", /* zero based idx: 20, 40, 80, 160 */ 12756c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_nc", 12766c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_nr", 12776c92544dSBjoern A. Zeeb "tx_beamformee_ok_feedback_pkts", 12786c92544dSBjoern A. Zeeb "tx_beamformee_feedback_trig", 12796c92544dSBjoern A. Zeeb "tx_mu_beamforming", 12806c92544dSBjoern A. Zeeb "tx_mu_mpdu", 12816c92544dSBjoern A. Zeeb "tx_mu_successful_mpdu", 12826c92544dSBjoern A. Zeeb "tx_su_successful_mpdu", 12836c92544dSBjoern A. Zeeb "tx_msdu_pack_1", 12846c92544dSBjoern A. Zeeb "tx_msdu_pack_2", 12856c92544dSBjoern A. Zeeb "tx_msdu_pack_3", 12866c92544dSBjoern A. Zeeb "tx_msdu_pack_4", 12876c92544dSBjoern A. Zeeb "tx_msdu_pack_5", 12886c92544dSBjoern A. Zeeb "tx_msdu_pack_6", 12896c92544dSBjoern A. Zeeb "tx_msdu_pack_7", 12906c92544dSBjoern A. Zeeb "tx_msdu_pack_8", 12916c92544dSBjoern A. Zeeb 12926c92544dSBjoern A. Zeeb /* rx counters */ 12936c92544dSBjoern A. Zeeb "rx_fifo_full_cnt", 12946c92544dSBjoern A. Zeeb "rx_mpdu_cnt", 12956c92544dSBjoern A. Zeeb "channel_idle_cnt", 12966c92544dSBjoern A. Zeeb "primary_cca_busy_time", 12976c92544dSBjoern A. Zeeb "secondary_cca_busy_time", 12986c92544dSBjoern A. Zeeb "primary_energy_detect_time", 12996c92544dSBjoern A. Zeeb "cck_mdrdy_time", 13006c92544dSBjoern A. Zeeb "ofdm_mdrdy_time", 13016c92544dSBjoern A. Zeeb "green_mdrdy_time", 13026c92544dSBjoern A. Zeeb "rx_vector_mismatch_cnt", 13036c92544dSBjoern A. Zeeb "rx_delimiter_fail_cnt", 13046c92544dSBjoern A. Zeeb "rx_mrdy_cnt", 13056c92544dSBjoern A. Zeeb "rx_len_mismatch_cnt", 13066c92544dSBjoern A. Zeeb "rx_ampdu_cnt", 13076c92544dSBjoern A. Zeeb "rx_ampdu_bytes_cnt", 13086c92544dSBjoern A. Zeeb "rx_ampdu_valid_subframe_cnt", 13096c92544dSBjoern A. Zeeb "rx_ampdu_valid_subframe_b_cnt", 13106c92544dSBjoern A. Zeeb "rx_pfdrop_cnt", 13116c92544dSBjoern A. Zeeb "rx_vec_queue_overflow_drop_cnt", 13126c92544dSBjoern A. Zeeb "rx_ba_cnt", 13136c92544dSBjoern A. Zeeb 1314*cbb3ec25SBjoern A. Zeeb /* muru mu-mimo and ofdma related stats */ 1315*cbb3ec25SBjoern A. Zeeb "dl_cck_cnt", 1316*cbb3ec25SBjoern A. Zeeb "dl_ofdm_cnt", 1317*cbb3ec25SBjoern A. Zeeb "dl_htmix_cnt", 1318*cbb3ec25SBjoern A. Zeeb "dl_htgf_cnt", 1319*cbb3ec25SBjoern A. Zeeb "dl_vht_su_cnt", 1320*cbb3ec25SBjoern A. Zeeb "dl_vht_2mu_cnt", 1321*cbb3ec25SBjoern A. Zeeb "dl_vht_3mu_cnt", 1322*cbb3ec25SBjoern A. Zeeb "dl_vht_4mu_cnt", 1323*cbb3ec25SBjoern A. Zeeb "dl_he_su_cnt", 1324*cbb3ec25SBjoern A. Zeeb "dl_he_ext_su_cnt", 1325*cbb3ec25SBjoern A. Zeeb "dl_he_2ru_cnt", 1326*cbb3ec25SBjoern A. Zeeb "dl_he_2mu_cnt", 1327*cbb3ec25SBjoern A. Zeeb "dl_he_3ru_cnt", 1328*cbb3ec25SBjoern A. Zeeb "dl_he_3mu_cnt", 1329*cbb3ec25SBjoern A. Zeeb "dl_he_4ru_cnt", 1330*cbb3ec25SBjoern A. Zeeb "dl_he_4mu_cnt", 1331*cbb3ec25SBjoern A. Zeeb "dl_he_5to8ru_cnt", 1332*cbb3ec25SBjoern A. Zeeb "dl_he_9to16ru_cnt", 1333*cbb3ec25SBjoern A. Zeeb "dl_he_gtr16ru_cnt", 1334*cbb3ec25SBjoern A. Zeeb 1335*cbb3ec25SBjoern A. Zeeb "ul_hetrig_su_cnt", 1336*cbb3ec25SBjoern A. Zeeb "ul_hetrig_2ru_cnt", 1337*cbb3ec25SBjoern A. Zeeb "ul_hetrig_3ru_cnt", 1338*cbb3ec25SBjoern A. Zeeb "ul_hetrig_4ru_cnt", 1339*cbb3ec25SBjoern A. Zeeb "ul_hetrig_5to8ru_cnt", 1340*cbb3ec25SBjoern A. Zeeb "ul_hetrig_9to16ru_cnt", 1341*cbb3ec25SBjoern A. Zeeb "ul_hetrig_gtr16ru_cnt", 1342*cbb3ec25SBjoern A. Zeeb "ul_hetrig_2mu_cnt", 1343*cbb3ec25SBjoern A. Zeeb "ul_hetrig_3mu_cnt", 1344*cbb3ec25SBjoern A. Zeeb "ul_hetrig_4mu_cnt", 1345*cbb3ec25SBjoern A. Zeeb 13466c92544dSBjoern A. Zeeb /* per vif counters */ 13476c92544dSBjoern A. Zeeb "v_tx_mode_cck", 13486c92544dSBjoern A. Zeeb "v_tx_mode_ofdm", 13496c92544dSBjoern A. Zeeb "v_tx_mode_ht", 13506c92544dSBjoern A. Zeeb "v_tx_mode_ht_gf", 13516c92544dSBjoern A. Zeeb "v_tx_mode_vht", 13526c92544dSBjoern A. Zeeb "v_tx_mode_he_su", 13536c92544dSBjoern A. Zeeb "v_tx_mode_he_ext_su", 13546c92544dSBjoern A. Zeeb "v_tx_mode_he_tb", 13556c92544dSBjoern A. Zeeb "v_tx_mode_he_mu", 13566c92544dSBjoern A. Zeeb "v_tx_bw_20", 13576c92544dSBjoern A. Zeeb "v_tx_bw_40", 13586c92544dSBjoern A. Zeeb "v_tx_bw_80", 13596c92544dSBjoern A. Zeeb "v_tx_bw_160", 13606c92544dSBjoern A. Zeeb "v_tx_mcs_0", 13616c92544dSBjoern A. Zeeb "v_tx_mcs_1", 13626c92544dSBjoern A. Zeeb "v_tx_mcs_2", 13636c92544dSBjoern A. Zeeb "v_tx_mcs_3", 13646c92544dSBjoern A. Zeeb "v_tx_mcs_4", 13656c92544dSBjoern A. Zeeb "v_tx_mcs_5", 13666c92544dSBjoern A. Zeeb "v_tx_mcs_6", 13676c92544dSBjoern A. Zeeb "v_tx_mcs_7", 13686c92544dSBjoern A. Zeeb "v_tx_mcs_8", 13696c92544dSBjoern A. Zeeb "v_tx_mcs_9", 13706c92544dSBjoern A. Zeeb "v_tx_mcs_10", 13716c92544dSBjoern A. Zeeb "v_tx_mcs_11", 1372*cbb3ec25SBjoern A. Zeeb "v_tx_nss_1", 1373*cbb3ec25SBjoern A. Zeeb "v_tx_nss_2", 1374*cbb3ec25SBjoern A. Zeeb "v_tx_nss_3", 1375*cbb3ec25SBjoern A. Zeeb "v_tx_nss_4", 13766c92544dSBjoern A. Zeeb }; 13776c92544dSBjoern A. Zeeb 13786c92544dSBjoern A. Zeeb #define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats) 13796c92544dSBjoern A. Zeeb 13806c92544dSBjoern A. Zeeb /* Ethtool related API */ 13816c92544dSBjoern A. Zeeb static 13826c92544dSBjoern A. Zeeb void mt7915_get_et_strings(struct ieee80211_hw *hw, 13836c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 13846c92544dSBjoern A. Zeeb u32 sset, u8 *data) 13856c92544dSBjoern A. Zeeb { 1386*cbb3ec25SBjoern A. Zeeb if (sset != ETH_SS_STATS) 1387*cbb3ec25SBjoern A. Zeeb return; 1388*cbb3ec25SBjoern A. Zeeb 1389*cbb3ec25SBjoern A. Zeeb memcpy(data, *mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats)); 1390*cbb3ec25SBjoern A. Zeeb data += sizeof(mt7915_gstrings_stats); 1391*cbb3ec25SBjoern A. Zeeb page_pool_ethtool_stats_get_strings(data); 13926c92544dSBjoern A. Zeeb } 13936c92544dSBjoern A. Zeeb 13946c92544dSBjoern A. Zeeb static 13956c92544dSBjoern A. Zeeb int mt7915_get_et_sset_count(struct ieee80211_hw *hw, 13966c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, int sset) 13976c92544dSBjoern A. Zeeb { 1398*cbb3ec25SBjoern A. Zeeb if (sset != ETH_SS_STATS) 13996c92544dSBjoern A. Zeeb return 0; 1400*cbb3ec25SBjoern A. Zeeb 1401*cbb3ec25SBjoern A. Zeeb return MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count(); 14026c92544dSBjoern A. Zeeb } 14036c92544dSBjoern A. Zeeb 14046c92544dSBjoern A. Zeeb static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) 14056c92544dSBjoern A. Zeeb { 14066c92544dSBjoern A. Zeeb struct mt76_ethtool_worker_info *wi = wi_data; 14076c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 14086c92544dSBjoern A. Zeeb 14096c92544dSBjoern A. Zeeb if (msta->vif->mt76.idx != wi->idx) 14106c92544dSBjoern A. Zeeb return; 14116c92544dSBjoern A. Zeeb 1412*cbb3ec25SBjoern A. Zeeb mt76_ethtool_worker(wi, &msta->wcid.stats, false); 14136c92544dSBjoern A. Zeeb } 14146c92544dSBjoern A. Zeeb 14156c92544dSBjoern A. Zeeb static 14166c92544dSBjoern A. Zeeb void mt7915_get_et_stats(struct ieee80211_hw *hw, 14176c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 14186c92544dSBjoern A. Zeeb struct ethtool_stats *stats, u64 *data) 14196c92544dSBjoern A. Zeeb { 14206c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 14216c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 14226c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 1423*cbb3ec25SBjoern A. Zeeb struct mt76_mib_stats *mib = &phy->mib; 14246c92544dSBjoern A. Zeeb struct mt76_ethtool_worker_info wi = { 14256c92544dSBjoern A. Zeeb .data = data, 14266c92544dSBjoern A. Zeeb .idx = mvif->mt76.idx, 14276c92544dSBjoern A. Zeeb }; 14286c92544dSBjoern A. Zeeb /* See mt7915_ampdu_stat_read_phy, etc */ 1429*cbb3ec25SBjoern A. Zeeb int i, ei = 0, stats_size; 14306c92544dSBjoern A. Zeeb 14316c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 14326c92544dSBjoern A. Zeeb 14336c92544dSBjoern A. Zeeb mt7915_mac_update_stats(phy); 14346c92544dSBjoern A. Zeeb 14356c92544dSBjoern A. Zeeb data[ei++] = mib->tx_ampdu_cnt; 14366c92544dSBjoern A. Zeeb data[ei++] = mib->tx_stop_q_empty_cnt; 14376c92544dSBjoern A. Zeeb data[ei++] = mib->tx_mpdu_attempts_cnt; 14386c92544dSBjoern A. Zeeb data[ei++] = mib->tx_mpdu_success_cnt; 14396c92544dSBjoern A. Zeeb data[ei++] = mib->tx_rwp_fail_cnt; 14406c92544dSBjoern A. Zeeb data[ei++] = mib->tx_rwp_need_cnt; 14416c92544dSBjoern A. Zeeb data[ei++] = mib->tx_pkt_ebf_cnt; 14426c92544dSBjoern A. Zeeb data[ei++] = mib->tx_pkt_ibf_cnt; 14436c92544dSBjoern A. Zeeb 14446c92544dSBjoern A. Zeeb /* Tx ampdu stat */ 14456c92544dSBjoern A. Zeeb for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++) 1446*cbb3ec25SBjoern A. Zeeb data[ei++] = phy->mt76->aggr_stats[i]; 14476c92544dSBjoern A. Zeeb 14486c92544dSBjoern A. Zeeb data[ei++] = phy->mib.ba_miss_cnt; 14496c92544dSBjoern A. Zeeb 14506c92544dSBjoern A. Zeeb /* Tx Beamformer monitor */ 14516c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_ibf_ppdu_cnt; 14526c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_ebf_ppdu_cnt; 14536c92544dSBjoern A. Zeeb 14546c92544dSBjoern A. Zeeb /* Tx Beamformer Rx feedback monitor */ 14556c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_all_cnt; 14566c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_he_cnt; 14576c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_vht_cnt; 14586c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_ht_cnt; 14596c92544dSBjoern A. Zeeb 14606c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_bw; 14616c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_nc_cnt; 14626c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_nr_cnt; 14636c92544dSBjoern A. Zeeb 14646c92544dSBjoern A. Zeeb /* Tx Beamformee Rx NDPA & Tx feedback report */ 14656c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_fb_cpl_cnt; 14666c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_fb_trig_cnt; 14676c92544dSBjoern A. Zeeb 14686c92544dSBjoern A. Zeeb /* Tx SU & MU counters */ 14696c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_cnt; 14706c92544dSBjoern A. Zeeb data[ei++] = mib->tx_mu_mpdu_cnt; 14716c92544dSBjoern A. Zeeb data[ei++] = mib->tx_mu_acked_mpdu_cnt; 14726c92544dSBjoern A. Zeeb data[ei++] = mib->tx_su_acked_mpdu_cnt; 14736c92544dSBjoern A. Zeeb 14746c92544dSBjoern A. Zeeb /* Tx amsdu info (pack-count histogram) */ 14756c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) 14766c92544dSBjoern A. Zeeb data[ei++] = mib->tx_amsdu[i]; 14776c92544dSBjoern A. Zeeb 14786c92544dSBjoern A. Zeeb /* rx counters */ 14796c92544dSBjoern A. Zeeb data[ei++] = mib->rx_fifo_full_cnt; 14806c92544dSBjoern A. Zeeb data[ei++] = mib->rx_mpdu_cnt; 14816c92544dSBjoern A. Zeeb data[ei++] = mib->channel_idle_cnt; 14826c92544dSBjoern A. Zeeb data[ei++] = mib->primary_cca_busy_time; 14836c92544dSBjoern A. Zeeb data[ei++] = mib->secondary_cca_busy_time; 14846c92544dSBjoern A. Zeeb data[ei++] = mib->primary_energy_detect_time; 14856c92544dSBjoern A. Zeeb data[ei++] = mib->cck_mdrdy_time; 14866c92544dSBjoern A. Zeeb data[ei++] = mib->ofdm_mdrdy_time; 14876c92544dSBjoern A. Zeeb data[ei++] = mib->green_mdrdy_time; 14886c92544dSBjoern A. Zeeb data[ei++] = mib->rx_vector_mismatch_cnt; 14896c92544dSBjoern A. Zeeb data[ei++] = mib->rx_delimiter_fail_cnt; 14906c92544dSBjoern A. Zeeb data[ei++] = mib->rx_mrdy_cnt; 14916c92544dSBjoern A. Zeeb data[ei++] = mib->rx_len_mismatch_cnt; 14926c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ampdu_cnt; 14936c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ampdu_bytes_cnt; 14946c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ampdu_valid_subframe_cnt; 14956c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ampdu_valid_subframe_bytes_cnt; 14966c92544dSBjoern A. Zeeb data[ei++] = mib->rx_pfdrop_cnt; 14976c92544dSBjoern A. Zeeb data[ei++] = mib->rx_vec_queue_overflow_drop_cnt; 14986c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ba_cnt; 14996c92544dSBjoern A. Zeeb 1500*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_cck_cnt; 1501*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_ofdm_cnt; 1502*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_htmix_cnt; 1503*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_htgf_cnt; 1504*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_vht_su_cnt; 1505*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_vht_2mu_cnt; 1506*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_vht_3mu_cnt; 1507*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_vht_4mu_cnt; 1508*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_su_cnt; 1509*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_ext_su_cnt; 1510*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_2ru_cnt; 1511*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_2mu_cnt; 1512*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_3ru_cnt; 1513*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_3mu_cnt; 1514*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_4ru_cnt; 1515*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_4mu_cnt; 1516*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_5to8ru_cnt; 1517*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_9to16ru_cnt; 1518*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_gtr16ru_cnt; 1519*cbb3ec25SBjoern A. Zeeb 1520*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_su_cnt; 1521*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_2ru_cnt; 1522*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_3ru_cnt; 1523*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_4ru_cnt; 1524*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_5to8ru_cnt; 1525*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_9to16ru_cnt; 1526*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_gtr16ru_cnt; 1527*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_2mu_cnt; 1528*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_3mu_cnt; 1529*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_4mu_cnt; 1530*cbb3ec25SBjoern A. Zeeb 15316c92544dSBjoern A. Zeeb /* Add values for all stations owned by this vif */ 15326c92544dSBjoern A. Zeeb wi.initial_stat_idx = ei; 15336c92544dSBjoern A. Zeeb ieee80211_iterate_stations_atomic(hw, mt7915_ethtool_worker, &wi); 15346c92544dSBjoern A. Zeeb 15356c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 15366c92544dSBjoern A. Zeeb 15376c92544dSBjoern A. Zeeb if (wi.sta_count == 0) 15386c92544dSBjoern A. Zeeb return; 15396c92544dSBjoern A. Zeeb 15406c92544dSBjoern A. Zeeb ei += wi.worker_stat_count; 1541*cbb3ec25SBjoern A. Zeeb 1542*cbb3ec25SBjoern A. Zeeb mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei); 1543*cbb3ec25SBjoern A. Zeeb 1544*cbb3ec25SBjoern A. Zeeb stats_size = MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count(); 1545*cbb3ec25SBjoern A. Zeeb if (ei != stats_size) 1546*cbb3ec25SBjoern A. Zeeb dev_err(dev->mt76.dev, "ei: %d size: %d", ei, stats_size); 15476c92544dSBjoern A. Zeeb } 15486c92544dSBjoern A. Zeeb 15496c92544dSBjoern A. Zeeb static void 15506c92544dSBjoern A. Zeeb mt7915_twt_teardown_request(struct ieee80211_hw *hw, 15516c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, 15526c92544dSBjoern A. Zeeb u8 flowid) 15536c92544dSBjoern A. Zeeb { 15546c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 15556c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 15566c92544dSBjoern A. Zeeb 15576c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 15586c92544dSBjoern A. Zeeb mt7915_mac_twt_teardown_flow(dev, msta, flowid); 15596c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 15606c92544dSBjoern A. Zeeb } 15616c92544dSBjoern A. Zeeb 15626c92544dSBjoern A. Zeeb static int 15636c92544dSBjoern A. Zeeb mt7915_set_radar_background(struct ieee80211_hw *hw, 15646c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef) 15656c92544dSBjoern A. Zeeb { 15666c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 15676c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 15686c92544dSBjoern A. Zeeb int ret = -EINVAL; 15696c92544dSBjoern A. Zeeb bool running; 15706c92544dSBjoern A. Zeeb 15716c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 15726c92544dSBjoern A. Zeeb 15736c92544dSBjoern A. Zeeb if (dev->mt76.region == NL80211_DFS_UNSET) 15746c92544dSBjoern A. Zeeb goto out; 15756c92544dSBjoern A. Zeeb 15766c92544dSBjoern A. Zeeb if (dev->rdd2_phy && dev->rdd2_phy != phy) { 15776c92544dSBjoern A. Zeeb /* rdd2 is already locked */ 15786c92544dSBjoern A. Zeeb ret = -EBUSY; 15796c92544dSBjoern A. Zeeb goto out; 15806c92544dSBjoern A. Zeeb } 15816c92544dSBjoern A. Zeeb 15826c92544dSBjoern A. Zeeb /* rdd2 already configured on a radar channel */ 15836c92544dSBjoern A. Zeeb running = dev->rdd2_phy && 15846c92544dSBjoern A. Zeeb cfg80211_chandef_valid(&dev->rdd2_chandef) && 15856c92544dSBjoern A. Zeeb !!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR); 15866c92544dSBjoern A. Zeeb 15876c92544dSBjoern A. Zeeb if (!chandef || running || 15886c92544dSBjoern A. Zeeb !(chandef->chan->flags & IEEE80211_CHAN_RADAR)) { 15896c92544dSBjoern A. Zeeb ret = mt7915_mcu_rdd_background_enable(phy, NULL); 15906c92544dSBjoern A. Zeeb if (ret) 15916c92544dSBjoern A. Zeeb goto out; 15926c92544dSBjoern A. Zeeb 15936c92544dSBjoern A. Zeeb if (!running) 15946c92544dSBjoern A. Zeeb goto update_phy; 15956c92544dSBjoern A. Zeeb } 15966c92544dSBjoern A. Zeeb 15976c92544dSBjoern A. Zeeb ret = mt7915_mcu_rdd_background_enable(phy, chandef); 15986c92544dSBjoern A. Zeeb if (ret) 15996c92544dSBjoern A. Zeeb goto out; 16006c92544dSBjoern A. Zeeb 16016c92544dSBjoern A. Zeeb update_phy: 16026c92544dSBjoern A. Zeeb dev->rdd2_phy = chandef ? phy : NULL; 16036c92544dSBjoern A. Zeeb if (chandef) 16046c92544dSBjoern A. Zeeb dev->rdd2_chandef = *chandef; 16056c92544dSBjoern A. Zeeb out: 16066c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 16076c92544dSBjoern A. Zeeb 16086c92544dSBjoern A. Zeeb return ret; 16096c92544dSBjoern A. Zeeb } 16106c92544dSBjoern A. Zeeb 16116c92544dSBjoern A. Zeeb #ifdef CONFIG_NET_MEDIATEK_SOC_WED 16126c92544dSBjoern A. Zeeb static int 16136c92544dSBjoern A. Zeeb mt7915_net_fill_forward_path(struct ieee80211_hw *hw, 16146c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, 16156c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, 16166c92544dSBjoern A. Zeeb struct net_device_path_ctx *ctx, 16176c92544dSBjoern A. Zeeb struct net_device_path *path) 16186c92544dSBjoern A. Zeeb { 16196c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 16206c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 16216c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 16226c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw); 16236c92544dSBjoern A. Zeeb struct mtk_wed_device *wed = &dev->mt76.mmio.wed; 16246c92544dSBjoern A. Zeeb 16256c92544dSBjoern A. Zeeb if (!mtk_wed_device_active(wed)) 16266c92544dSBjoern A. Zeeb return -ENODEV; 16276c92544dSBjoern A. Zeeb 16286c92544dSBjoern A. Zeeb if (msta->wcid.idx > 0xff) 16296c92544dSBjoern A. Zeeb return -EIO; 16306c92544dSBjoern A. Zeeb 16316c92544dSBjoern A. Zeeb path->type = DEV_PATH_MTK_WDMA; 16326c92544dSBjoern A. Zeeb path->dev = ctx->dev; 16336c92544dSBjoern A. Zeeb path->mtk_wdma.wdma_idx = wed->wdma_idx; 16346c92544dSBjoern A. Zeeb path->mtk_wdma.bss = mvif->mt76.idx; 1635*cbb3ec25SBjoern A. Zeeb path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff; 16366c92544dSBjoern A. Zeeb path->mtk_wdma.queue = phy != &dev->phy; 16376c92544dSBjoern A. Zeeb 16386c92544dSBjoern A. Zeeb ctx->dev = NULL; 16396c92544dSBjoern A. Zeeb 16406c92544dSBjoern A. Zeeb return 0; 16416c92544dSBjoern A. Zeeb } 16426c92544dSBjoern A. Zeeb #endif 16436c92544dSBjoern A. Zeeb 16446c92544dSBjoern A. Zeeb const struct ieee80211_ops mt7915_ops = { 16456c92544dSBjoern A. Zeeb .tx = mt7915_tx, 16466c92544dSBjoern A. Zeeb .start = mt7915_start, 16476c92544dSBjoern A. Zeeb .stop = mt7915_stop, 16486c92544dSBjoern A. Zeeb .add_interface = mt7915_add_interface, 16496c92544dSBjoern A. Zeeb .remove_interface = mt7915_remove_interface, 16506c92544dSBjoern A. Zeeb .config = mt7915_config, 16516c92544dSBjoern A. Zeeb .conf_tx = mt7915_conf_tx, 16526c92544dSBjoern A. Zeeb .configure_filter = mt7915_configure_filter, 16536c92544dSBjoern A. Zeeb .bss_info_changed = mt7915_bss_info_changed, 1654*cbb3ec25SBjoern A. Zeeb .start_ap = mt7915_start_ap, 1655*cbb3ec25SBjoern A. Zeeb .stop_ap = mt7915_stop_ap, 16566c92544dSBjoern A. Zeeb .sta_add = mt7915_sta_add, 16576c92544dSBjoern A. Zeeb .sta_remove = mt7915_sta_remove, 16586c92544dSBjoern A. Zeeb .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, 16596c92544dSBjoern A. Zeeb .sta_rc_update = mt7915_sta_rc_update, 16606c92544dSBjoern A. Zeeb .set_key = mt7915_set_key, 16616c92544dSBjoern A. Zeeb .ampdu_action = mt7915_ampdu_action, 16626c92544dSBjoern A. Zeeb .set_rts_threshold = mt7915_set_rts_threshold, 16636c92544dSBjoern A. Zeeb .wake_tx_queue = mt76_wake_tx_queue, 16646c92544dSBjoern A. Zeeb .sw_scan_start = mt76_sw_scan, 16656c92544dSBjoern A. Zeeb .sw_scan_complete = mt76_sw_scan_complete, 16666c92544dSBjoern A. Zeeb .release_buffered_frames = mt76_release_buffered_frames, 16676c92544dSBjoern A. Zeeb .get_txpower = mt76_get_txpower, 16686c92544dSBjoern A. Zeeb .set_sar_specs = mt7915_set_sar_specs, 16696c92544dSBjoern A. Zeeb .channel_switch_beacon = mt7915_channel_switch_beacon, 16706c92544dSBjoern A. Zeeb .get_stats = mt7915_get_stats, 16716c92544dSBjoern A. Zeeb .get_et_sset_count = mt7915_get_et_sset_count, 16726c92544dSBjoern A. Zeeb .get_et_stats = mt7915_get_et_stats, 16736c92544dSBjoern A. Zeeb .get_et_strings = mt7915_get_et_strings, 16746c92544dSBjoern A. Zeeb .get_tsf = mt7915_get_tsf, 16756c92544dSBjoern A. Zeeb .set_tsf = mt7915_set_tsf, 16766c92544dSBjoern A. Zeeb .offset_tsf = mt7915_offset_tsf, 16776c92544dSBjoern A. Zeeb .get_survey = mt76_get_survey, 16786c92544dSBjoern A. Zeeb .get_antenna = mt76_get_antenna, 16796c92544dSBjoern A. Zeeb .set_antenna = mt7915_set_antenna, 16806c92544dSBjoern A. Zeeb .set_bitrate_mask = mt7915_set_bitrate_mask, 16816c92544dSBjoern A. Zeeb .set_coverage_class = mt7915_set_coverage_class, 16826c92544dSBjoern A. Zeeb .sta_statistics = mt7915_sta_statistics, 1683*cbb3ec25SBjoern A. Zeeb .sta_set_txpwr = mt7915_sta_set_txpwr, 16846c92544dSBjoern A. Zeeb .sta_set_4addr = mt7915_sta_set_4addr, 16856c92544dSBjoern A. Zeeb .sta_set_decap_offload = mt7915_sta_set_decap_offload, 16866c92544dSBjoern A. Zeeb .add_twt_setup = mt7915_mac_add_twt_setup, 16876c92544dSBjoern A. Zeeb .twt_teardown_request = mt7915_twt_teardown_request, 16886c92544dSBjoern A. Zeeb CFG80211_TESTMODE_CMD(mt76_testmode_cmd) 16896c92544dSBjoern A. Zeeb CFG80211_TESTMODE_DUMP(mt76_testmode_dump) 16906c92544dSBjoern A. Zeeb #ifdef CONFIG_MAC80211_DEBUGFS 16916c92544dSBjoern A. Zeeb .sta_add_debugfs = mt7915_sta_add_debugfs, 16926c92544dSBjoern A. Zeeb #endif 16936c92544dSBjoern A. Zeeb .set_radar_background = mt7915_set_radar_background, 16946c92544dSBjoern A. Zeeb #ifdef CONFIG_NET_MEDIATEK_SOC_WED 16956c92544dSBjoern A. Zeeb .net_fill_forward_path = mt7915_net_fill_forward_path, 16966c92544dSBjoern A. Zeeb #endif 16976c92544dSBjoern A. Zeeb }; 1698