1*cbb3ec25SBjoern A. Zeeb // SPDX-License-Identifier: ISC 2*cbb3ec25SBjoern A. Zeeb /* 3*cbb3ec25SBjoern A. Zeeb * Copyright (C) 2022 MediaTek Inc. 4*cbb3ec25SBjoern A. Zeeb */ 5*cbb3ec25SBjoern A. Zeeb 6*cbb3ec25SBjoern A. Zeeb #include "mt7996.h" 7*cbb3ec25SBjoern A. Zeeb #include "mcu.h" 8*cbb3ec25SBjoern A. Zeeb #include "mac.h" 9*cbb3ec25SBjoern A. Zeeb 10*cbb3ec25SBjoern A. Zeeb static bool mt7996_dev_running(struct mt7996_dev *dev) 11*cbb3ec25SBjoern A. Zeeb { 12*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy; 13*cbb3ec25SBjoern A. Zeeb 14*cbb3ec25SBjoern A. Zeeb if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) 15*cbb3ec25SBjoern A. Zeeb return true; 16*cbb3ec25SBjoern A. Zeeb 17*cbb3ec25SBjoern A. Zeeb phy = mt7996_phy2(dev); 18*cbb3ec25SBjoern A. Zeeb if (phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) 19*cbb3ec25SBjoern A. Zeeb return true; 20*cbb3ec25SBjoern A. Zeeb 21*cbb3ec25SBjoern A. Zeeb phy = mt7996_phy3(dev); 22*cbb3ec25SBjoern A. Zeeb 23*cbb3ec25SBjoern A. Zeeb return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state); 24*cbb3ec25SBjoern A. Zeeb } 25*cbb3ec25SBjoern A. Zeeb 26*cbb3ec25SBjoern A. Zeeb int mt7996_run(struct ieee80211_hw *hw) 27*cbb3ec25SBjoern A. Zeeb { 28*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 29*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 30*cbb3ec25SBjoern A. Zeeb bool running; 31*cbb3ec25SBjoern A. Zeeb int ret; 32*cbb3ec25SBjoern A. Zeeb 33*cbb3ec25SBjoern A. Zeeb running = mt7996_dev_running(dev); 34*cbb3ec25SBjoern A. Zeeb if (!running) { 35*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_set_hdr_trans(dev, true); 36*cbb3ec25SBjoern A. Zeeb if (ret) 37*cbb3ec25SBjoern A. Zeeb goto out; 38*cbb3ec25SBjoern A. Zeeb } 39*cbb3ec25SBjoern A. Zeeb 40*cbb3ec25SBjoern A. Zeeb mt7996_mac_enable_nf(dev, phy->mt76->band_idx); 41*cbb3ec25SBjoern A. Zeeb 42*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_set_rts_thresh(phy, 0x92b); 43*cbb3ec25SBjoern A. Zeeb if (ret) 44*cbb3ec25SBjoern A. Zeeb goto out; 45*cbb3ec25SBjoern A. Zeeb 46*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_set_radio_en(phy, true); 47*cbb3ec25SBjoern A. Zeeb if (ret) 48*cbb3ec25SBjoern A. Zeeb goto out; 49*cbb3ec25SBjoern A. Zeeb 50*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH); 51*cbb3ec25SBjoern A. Zeeb if (ret) 52*cbb3ec25SBjoern A. Zeeb goto out; 53*cbb3ec25SBjoern A. Zeeb 54*cbb3ec25SBjoern A. Zeeb set_bit(MT76_STATE_RUNNING, &phy->mt76->state); 55*cbb3ec25SBjoern A. Zeeb 56*cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, 57*cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME); 58*cbb3ec25SBjoern A. Zeeb 59*cbb3ec25SBjoern A. Zeeb if (!running) 60*cbb3ec25SBjoern A. Zeeb mt7996_mac_reset_counters(phy); 61*cbb3ec25SBjoern A. Zeeb 62*cbb3ec25SBjoern A. Zeeb out: 63*cbb3ec25SBjoern A. Zeeb return ret; 64*cbb3ec25SBjoern A. Zeeb } 65*cbb3ec25SBjoern A. Zeeb 66*cbb3ec25SBjoern A. Zeeb static int mt7996_start(struct ieee80211_hw *hw) 67*cbb3ec25SBjoern A. Zeeb { 68*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 69*cbb3ec25SBjoern A. Zeeb int ret; 70*cbb3ec25SBjoern A. Zeeb 71*cbb3ec25SBjoern A. Zeeb flush_work(&dev->init_work); 72*cbb3ec25SBjoern A. Zeeb 73*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 74*cbb3ec25SBjoern A. Zeeb ret = mt7996_run(hw); 75*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 76*cbb3ec25SBjoern A. Zeeb 77*cbb3ec25SBjoern A. Zeeb return ret; 78*cbb3ec25SBjoern A. Zeeb } 79*cbb3ec25SBjoern A. Zeeb 80*cbb3ec25SBjoern A. Zeeb static void mt7996_stop(struct ieee80211_hw *hw) 81*cbb3ec25SBjoern A. Zeeb { 82*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 83*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 84*cbb3ec25SBjoern A. Zeeb 85*cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&phy->mt76->mac_work); 86*cbb3ec25SBjoern A. Zeeb 87*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 88*cbb3ec25SBjoern A. Zeeb 89*cbb3ec25SBjoern A. Zeeb mt7996_mcu_set_radio_en(phy, false); 90*cbb3ec25SBjoern A. Zeeb 91*cbb3ec25SBjoern A. Zeeb clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); 92*cbb3ec25SBjoern A. Zeeb 93*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 94*cbb3ec25SBjoern A. Zeeb } 95*cbb3ec25SBjoern A. Zeeb 96*cbb3ec25SBjoern A. Zeeb static inline int get_free_idx(u32 mask, u8 start, u8 end) 97*cbb3ec25SBjoern A. Zeeb { 98*cbb3ec25SBjoern A. Zeeb return ffs(~mask & GENMASK(end, start)); 99*cbb3ec25SBjoern A. Zeeb } 100*cbb3ec25SBjoern A. Zeeb 101*cbb3ec25SBjoern A. Zeeb static int get_omac_idx(enum nl80211_iftype type, u64 mask) 102*cbb3ec25SBjoern A. Zeeb { 103*cbb3ec25SBjoern A. Zeeb int i; 104*cbb3ec25SBjoern A. Zeeb 105*cbb3ec25SBjoern A. Zeeb switch (type) { 106*cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT: 107*cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_ADHOC: 108*cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_STATION: 109*cbb3ec25SBjoern A. Zeeb /* prefer hw bssid slot 1-3 */ 110*cbb3ec25SBjoern A. Zeeb i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3); 111*cbb3ec25SBjoern A. Zeeb if (i) 112*cbb3ec25SBjoern A. Zeeb return i - 1; 113*cbb3ec25SBjoern A. Zeeb 114*cbb3ec25SBjoern A. Zeeb if (type != NL80211_IFTYPE_STATION) 115*cbb3ec25SBjoern A. Zeeb break; 116*cbb3ec25SBjoern A. Zeeb 117*cbb3ec25SBjoern A. Zeeb i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); 118*cbb3ec25SBjoern A. Zeeb if (i) 119*cbb3ec25SBjoern A. Zeeb return i - 1; 120*cbb3ec25SBjoern A. Zeeb 121*cbb3ec25SBjoern A. Zeeb if (~mask & BIT(HW_BSSID_0)) 122*cbb3ec25SBjoern A. Zeeb return HW_BSSID_0; 123*cbb3ec25SBjoern A. Zeeb 124*cbb3ec25SBjoern A. Zeeb break; 125*cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_MONITOR: 126*cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_AP: 127*cbb3ec25SBjoern A. Zeeb /* ap uses hw bssid 0 and ext bssid */ 128*cbb3ec25SBjoern A. Zeeb if (~mask & BIT(HW_BSSID_0)) 129*cbb3ec25SBjoern A. Zeeb return HW_BSSID_0; 130*cbb3ec25SBjoern A. Zeeb 131*cbb3ec25SBjoern A. Zeeb i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX); 132*cbb3ec25SBjoern A. Zeeb if (i) 133*cbb3ec25SBjoern A. Zeeb return i - 1; 134*cbb3ec25SBjoern A. Zeeb 135*cbb3ec25SBjoern A. Zeeb break; 136*cbb3ec25SBjoern A. Zeeb default: 137*cbb3ec25SBjoern A. Zeeb WARN_ON(1); 138*cbb3ec25SBjoern A. Zeeb break; 139*cbb3ec25SBjoern A. Zeeb } 140*cbb3ec25SBjoern A. Zeeb 141*cbb3ec25SBjoern A. Zeeb return -1; 142*cbb3ec25SBjoern A. Zeeb } 143*cbb3ec25SBjoern A. Zeeb 144*cbb3ec25SBjoern A. Zeeb static void mt7996_init_bitrate_mask(struct ieee80211_vif *vif) 145*cbb3ec25SBjoern A. Zeeb { 146*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 147*cbb3ec25SBjoern A. Zeeb int i; 148*cbb3ec25SBjoern A. Zeeb 149*cbb3ec25SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) { 150*cbb3ec25SBjoern A. Zeeb mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI; 151*cbb3ec25SBjoern A. Zeeb mvif->bitrate_mask.control[i].he_gi = 0xff; 152*cbb3ec25SBjoern A. Zeeb mvif->bitrate_mask.control[i].he_ltf = 0xff; 153*cbb3ec25SBjoern A. Zeeb mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0); 154*cbb3ec25SBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff, 155*cbb3ec25SBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].ht_mcs)); 156*cbb3ec25SBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff, 157*cbb3ec25SBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].vht_mcs)); 158*cbb3ec25SBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].he_mcs, 0xff, 159*cbb3ec25SBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].he_mcs)); 160*cbb3ec25SBjoern A. Zeeb } 161*cbb3ec25SBjoern A. Zeeb } 162*cbb3ec25SBjoern A. Zeeb 163*cbb3ec25SBjoern A. Zeeb static int mt7996_add_interface(struct ieee80211_hw *hw, 164*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif) 165*cbb3ec25SBjoern A. Zeeb { 166*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 167*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 168*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 169*cbb3ec25SBjoern A. Zeeb struct mt76_txq *mtxq; 170*cbb3ec25SBjoern A. Zeeb u8 band_idx = phy->mt76->band_idx; 171*cbb3ec25SBjoern A. Zeeb int idx, ret = 0; 172*cbb3ec25SBjoern A. Zeeb 173*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 174*cbb3ec25SBjoern A. Zeeb 175*cbb3ec25SBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_MONITOR && 176*cbb3ec25SBjoern A. Zeeb is_zero_ether_addr(vif->addr)) 177*cbb3ec25SBjoern A. Zeeb phy->monitor_vif = vif; 178*cbb3ec25SBjoern A. Zeeb 179*cbb3ec25SBjoern A. Zeeb mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); 180*cbb3ec25SBjoern A. Zeeb if (mvif->mt76.idx >= mt7996_max_interface_num(dev)) { 181*cbb3ec25SBjoern A. Zeeb ret = -ENOSPC; 182*cbb3ec25SBjoern A. Zeeb goto out; 183*cbb3ec25SBjoern A. Zeeb } 184*cbb3ec25SBjoern A. Zeeb 185*cbb3ec25SBjoern A. Zeeb idx = get_omac_idx(vif->type, phy->omac_mask); 186*cbb3ec25SBjoern A. Zeeb if (idx < 0) { 187*cbb3ec25SBjoern A. Zeeb ret = -ENOSPC; 188*cbb3ec25SBjoern A. Zeeb goto out; 189*cbb3ec25SBjoern A. Zeeb } 190*cbb3ec25SBjoern A. Zeeb mvif->mt76.omac_idx = idx; 191*cbb3ec25SBjoern A. Zeeb mvif->phy = phy; 192*cbb3ec25SBjoern A. Zeeb mvif->mt76.band_idx = band_idx; 193*cbb3ec25SBjoern A. Zeeb mvif->mt76.wmm_idx = band_idx; 194*cbb3ec25SBjoern A. Zeeb 195*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_add_dev_info(phy, vif, true); 196*cbb3ec25SBjoern A. Zeeb if (ret) 197*cbb3ec25SBjoern A. Zeeb goto out; 198*cbb3ec25SBjoern A. Zeeb 199*cbb3ec25SBjoern A. Zeeb dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); 200*cbb3ec25SBjoern A. Zeeb phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); 201*cbb3ec25SBjoern A. Zeeb 202*cbb3ec25SBjoern A. Zeeb idx = MT7996_WTBL_RESERVED - mvif->mt76.idx; 203*cbb3ec25SBjoern A. Zeeb 204*cbb3ec25SBjoern A. Zeeb INIT_LIST_HEAD(&mvif->sta.rc_list); 205*cbb3ec25SBjoern A. Zeeb INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); 206*cbb3ec25SBjoern A. Zeeb mvif->sta.wcid.idx = idx; 207*cbb3ec25SBjoern A. Zeeb mvif->sta.wcid.phy_idx = band_idx; 208*cbb3ec25SBjoern A. Zeeb mvif->sta.wcid.hw_key_idx = -1; 209*cbb3ec25SBjoern A. Zeeb mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET; 210*cbb3ec25SBjoern A. Zeeb mt76_packet_id_init(&mvif->sta.wcid); 211*cbb3ec25SBjoern A. Zeeb 212*cbb3ec25SBjoern A. Zeeb mt7996_mac_wtbl_update(dev, idx, 213*cbb3ec25SBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 214*cbb3ec25SBjoern A. Zeeb 215*cbb3ec25SBjoern A. Zeeb if (vif->txq) { 216*cbb3ec25SBjoern A. Zeeb mtxq = (struct mt76_txq *)vif->txq->drv_priv; 217*cbb3ec25SBjoern A. Zeeb mtxq->wcid = idx; 218*cbb3ec25SBjoern A. Zeeb } 219*cbb3ec25SBjoern A. Zeeb 220*cbb3ec25SBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_AP && 221*cbb3ec25SBjoern A. Zeeb (!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3)) 222*cbb3ec25SBjoern A. Zeeb vif->offload_flags = 0; 223*cbb3ec25SBjoern A. Zeeb vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; 224*cbb3ec25SBjoern A. Zeeb 225*cbb3ec25SBjoern A. Zeeb if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) 226*cbb3ec25SBjoern A. Zeeb mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; 227*cbb3ec25SBjoern A. Zeeb else 228*cbb3ec25SBjoern A. Zeeb mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL; 229*cbb3ec25SBjoern A. Zeeb 230*cbb3ec25SBjoern A. Zeeb mt7996_init_bitrate_mask(vif); 231*cbb3ec25SBjoern A. Zeeb 232*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_bss_info(phy, vif, true); 233*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_sta(dev, vif, NULL, true); 234*cbb3ec25SBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); 235*cbb3ec25SBjoern A. Zeeb 236*cbb3ec25SBjoern A. Zeeb out: 237*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 238*cbb3ec25SBjoern A. Zeeb 239*cbb3ec25SBjoern A. Zeeb return ret; 240*cbb3ec25SBjoern A. Zeeb } 241*cbb3ec25SBjoern A. Zeeb 242*cbb3ec25SBjoern A. Zeeb static void mt7996_remove_interface(struct ieee80211_hw *hw, 243*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif) 244*cbb3ec25SBjoern A. Zeeb { 245*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 246*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = &mvif->sta; 247*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 248*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 249*cbb3ec25SBjoern A. Zeeb int idx = msta->wcid.idx; 250*cbb3ec25SBjoern A. Zeeb 251*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_bss_info(phy, vif, false); 252*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_sta(dev, vif, NULL, false); 253*cbb3ec25SBjoern A. Zeeb 254*cbb3ec25SBjoern A. Zeeb if (vif == phy->monitor_vif) 255*cbb3ec25SBjoern A. Zeeb phy->monitor_vif = NULL; 256*cbb3ec25SBjoern A. Zeeb 257*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_dev_info(phy, vif, false); 258*cbb3ec25SBjoern A. Zeeb 259*cbb3ec25SBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], NULL); 260*cbb3ec25SBjoern A. Zeeb 261*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 262*cbb3ec25SBjoern A. Zeeb dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); 263*cbb3ec25SBjoern A. Zeeb phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); 264*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 265*cbb3ec25SBjoern A. Zeeb 266*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 267*cbb3ec25SBjoern A. Zeeb if (!list_empty(&msta->wcid.poll_list)) 268*cbb3ec25SBjoern A. Zeeb list_del_init(&msta->wcid.poll_list); 269*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 270*cbb3ec25SBjoern A. Zeeb 271*cbb3ec25SBjoern A. Zeeb mt76_packet_id_flush(&dev->mt76, &msta->wcid); 272*cbb3ec25SBjoern A. Zeeb } 273*cbb3ec25SBjoern A. Zeeb 274*cbb3ec25SBjoern A. Zeeb int mt7996_set_channel(struct mt7996_phy *phy) 275*cbb3ec25SBjoern A. Zeeb { 276*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev; 277*cbb3ec25SBjoern A. Zeeb int ret; 278*cbb3ec25SBjoern A. Zeeb 279*cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&phy->mt76->mac_work); 280*cbb3ec25SBjoern A. Zeeb 281*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 282*cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &phy->mt76->state); 283*cbb3ec25SBjoern A. Zeeb 284*cbb3ec25SBjoern A. Zeeb mt76_set_channel(phy->mt76); 285*cbb3ec25SBjoern A. Zeeb 286*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH); 287*cbb3ec25SBjoern A. Zeeb if (ret) 288*cbb3ec25SBjoern A. Zeeb goto out; 289*cbb3ec25SBjoern A. Zeeb 290*cbb3ec25SBjoern A. Zeeb ret = mt7996_dfs_init_radar_detector(phy); 291*cbb3ec25SBjoern A. Zeeb mt7996_mac_cca_stats_reset(phy); 292*cbb3ec25SBjoern A. Zeeb 293*cbb3ec25SBjoern A. Zeeb mt7996_mac_reset_counters(phy); 294*cbb3ec25SBjoern A. Zeeb phy->noise = 0; 295*cbb3ec25SBjoern A. Zeeb 296*cbb3ec25SBjoern A. Zeeb out: 297*cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &phy->mt76->state); 298*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 299*cbb3ec25SBjoern A. Zeeb 300*cbb3ec25SBjoern A. Zeeb mt76_txq_schedule_all(phy->mt76); 301*cbb3ec25SBjoern A. Zeeb 302*cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(phy->mt76->hw, 303*cbb3ec25SBjoern A. Zeeb &phy->mt76->mac_work, 304*cbb3ec25SBjoern A. Zeeb MT7996_WATCHDOG_TIME); 305*cbb3ec25SBjoern A. Zeeb 306*cbb3ec25SBjoern A. Zeeb return ret; 307*cbb3ec25SBjoern A. Zeeb } 308*cbb3ec25SBjoern A. Zeeb 309*cbb3ec25SBjoern A. Zeeb static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 310*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta, 311*cbb3ec25SBjoern A. Zeeb struct ieee80211_key_conf *key) 312*cbb3ec25SBjoern A. Zeeb { 313*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 314*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 315*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 316*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = sta ? (struct mt7996_sta *)sta->drv_priv : 317*cbb3ec25SBjoern A. Zeeb &mvif->sta; 318*cbb3ec25SBjoern A. Zeeb struct mt76_wcid *wcid = &msta->wcid; 319*cbb3ec25SBjoern A. Zeeb u8 *wcid_keyidx = &wcid->hw_key_idx; 320*cbb3ec25SBjoern A. Zeeb int idx = key->keyidx; 321*cbb3ec25SBjoern A. Zeeb int err = 0; 322*cbb3ec25SBjoern A. Zeeb 323*cbb3ec25SBjoern A. Zeeb /* The hardware does not support per-STA RX GTK, fallback 324*cbb3ec25SBjoern A. Zeeb * to software mode for these. 325*cbb3ec25SBjoern A. Zeeb */ 326*cbb3ec25SBjoern A. Zeeb if ((vif->type == NL80211_IFTYPE_ADHOC || 327*cbb3ec25SBjoern A. Zeeb vif->type == NL80211_IFTYPE_MESH_POINT) && 328*cbb3ec25SBjoern A. Zeeb (key->cipher == WLAN_CIPHER_SUITE_TKIP || 329*cbb3ec25SBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_CCMP) && 330*cbb3ec25SBjoern A. Zeeb !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) 331*cbb3ec25SBjoern A. Zeeb return -EOPNOTSUPP; 332*cbb3ec25SBjoern A. Zeeb 333*cbb3ec25SBjoern A. Zeeb /* fall back to sw encryption for unsupported ciphers */ 334*cbb3ec25SBjoern A. Zeeb switch (key->cipher) { 335*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_AES_CMAC: 336*cbb3ec25SBjoern A. Zeeb wcid_keyidx = &wcid->hw_key_idx2; 337*cbb3ec25SBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; 338*cbb3ec25SBjoern A. Zeeb break; 339*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_TKIP: 340*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP: 341*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP_256: 342*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP: 343*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP_256: 344*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_SMS4: 345*cbb3ec25SBjoern A. Zeeb break; 346*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_WEP40: 347*cbb3ec25SBjoern A. Zeeb case WLAN_CIPHER_SUITE_WEP104: 348*cbb3ec25SBjoern A. Zeeb default: 349*cbb3ec25SBjoern A. Zeeb return -EOPNOTSUPP; 350*cbb3ec25SBjoern A. Zeeb } 351*cbb3ec25SBjoern A. Zeeb 352*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 353*cbb3ec25SBjoern A. Zeeb 354*cbb3ec25SBjoern A. Zeeb if (cmd == SET_KEY && !sta && !mvif->mt76.cipher) { 355*cbb3ec25SBjoern A. Zeeb mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher); 356*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_bss_info(phy, vif, true); 357*cbb3ec25SBjoern A. Zeeb } 358*cbb3ec25SBjoern A. Zeeb 359*cbb3ec25SBjoern A. Zeeb if (cmd == SET_KEY) { 360*cbb3ec25SBjoern A. Zeeb *wcid_keyidx = idx; 361*cbb3ec25SBjoern A. Zeeb } else { 362*cbb3ec25SBjoern A. Zeeb if (idx == *wcid_keyidx) 363*cbb3ec25SBjoern A. Zeeb *wcid_keyidx = -1; 364*cbb3ec25SBjoern A. Zeeb goto out; 365*cbb3ec25SBjoern A. Zeeb } 366*cbb3ec25SBjoern A. Zeeb 367*cbb3ec25SBjoern A. Zeeb mt76_wcid_key_setup(&dev->mt76, wcid, key); 368*cbb3ec25SBjoern A. Zeeb err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip, 369*cbb3ec25SBjoern A. Zeeb key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), 370*cbb3ec25SBjoern A. Zeeb &msta->wcid, cmd); 371*cbb3ec25SBjoern A. Zeeb out: 372*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 373*cbb3ec25SBjoern A. Zeeb 374*cbb3ec25SBjoern A. Zeeb return err; 375*cbb3ec25SBjoern A. Zeeb } 376*cbb3ec25SBjoern A. Zeeb 377*cbb3ec25SBjoern A. Zeeb static int mt7996_config(struct ieee80211_hw *hw, u32 changed) 378*cbb3ec25SBjoern A. Zeeb { 379*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 380*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 381*cbb3ec25SBjoern A. Zeeb int ret; 382*cbb3ec25SBjoern A. Zeeb 383*cbb3ec25SBjoern A. Zeeb if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 384*cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(hw); 385*cbb3ec25SBjoern A. Zeeb ret = mt7996_set_channel(phy); 386*cbb3ec25SBjoern A. Zeeb if (ret) 387*cbb3ec25SBjoern A. Zeeb return ret; 388*cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(hw); 389*cbb3ec25SBjoern A. Zeeb } 390*cbb3ec25SBjoern A. Zeeb 391*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 392*cbb3ec25SBjoern A. Zeeb 393*cbb3ec25SBjoern A. Zeeb if (changed & IEEE80211_CONF_CHANGE_MONITOR) { 394*cbb3ec25SBjoern A. Zeeb bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); 395*cbb3ec25SBjoern A. Zeeb 396*cbb3ec25SBjoern A. Zeeb if (!enabled) 397*cbb3ec25SBjoern A. Zeeb phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; 398*cbb3ec25SBjoern A. Zeeb else 399*cbb3ec25SBjoern A. Zeeb phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; 400*cbb3ec25SBjoern A. Zeeb 401*cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_DMA_DCR0(phy->mt76->band_idx), 402*cbb3ec25SBjoern A. Zeeb MT_DMA_DCR0_RXD_G5_EN, enabled); 403*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), phy->rxfilter); 404*cbb3ec25SBjoern A. Zeeb } 405*cbb3ec25SBjoern A. Zeeb 406*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 407*cbb3ec25SBjoern A. Zeeb 408*cbb3ec25SBjoern A. Zeeb return 0; 409*cbb3ec25SBjoern A. Zeeb } 410*cbb3ec25SBjoern A. Zeeb 411*cbb3ec25SBjoern A. Zeeb static int 412*cbb3ec25SBjoern A. Zeeb mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 413*cbb3ec25SBjoern A. Zeeb unsigned int link_id, u16 queue, 414*cbb3ec25SBjoern A. Zeeb const struct ieee80211_tx_queue_params *params) 415*cbb3ec25SBjoern A. Zeeb { 416*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 417*cbb3ec25SBjoern A. Zeeb 418*cbb3ec25SBjoern A. Zeeb /* no need to update right away, we'll get BSS_CHANGED_QOS */ 419*cbb3ec25SBjoern A. Zeeb queue = mt76_connac_lmac_mapping(queue); 420*cbb3ec25SBjoern A. Zeeb mvif->queue_params[queue] = *params; 421*cbb3ec25SBjoern A. Zeeb 422*cbb3ec25SBjoern A. Zeeb return 0; 423*cbb3ec25SBjoern A. Zeeb } 424*cbb3ec25SBjoern A. Zeeb 425*cbb3ec25SBjoern A. Zeeb static void mt7996_configure_filter(struct ieee80211_hw *hw, 426*cbb3ec25SBjoern A. Zeeb unsigned int changed_flags, 427*cbb3ec25SBjoern A. Zeeb unsigned int *total_flags, 428*cbb3ec25SBjoern A. Zeeb u64 multicast) 429*cbb3ec25SBjoern A. Zeeb { 430*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 431*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 432*cbb3ec25SBjoern A. Zeeb u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | 433*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR1_DROP_BF_POLL | 434*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR1_DROP_BA | 435*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR1_DROP_CFEND | 436*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR1_DROP_CFACK; 437*cbb3ec25SBjoern A. Zeeb u32 flags = 0; 438*cbb3ec25SBjoern A. Zeeb 439*cbb3ec25SBjoern A. Zeeb #define MT76_FILTER(_flag, _hw) do { \ 440*cbb3ec25SBjoern A. Zeeb flags |= *total_flags & FIF_##_flag; \ 441*cbb3ec25SBjoern A. Zeeb phy->rxfilter &= ~(_hw); \ 442*cbb3ec25SBjoern A. Zeeb phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ 443*cbb3ec25SBjoern A. Zeeb } while (0) 444*cbb3ec25SBjoern A. Zeeb 445*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 446*cbb3ec25SBjoern A. Zeeb 447*cbb3ec25SBjoern A. Zeeb phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | 448*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_OTHER_BEACON | 449*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_FRAME_REPORT | 450*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_PROBEREQ | 451*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_MCAST_FILTERED | 452*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_MCAST | 453*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_BCAST | 454*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_DUPLICATE | 455*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_A2_BSSID | 456*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_UNWANTED_CTL | 457*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_STBC_MULTI); 458*cbb3ec25SBjoern A. Zeeb 459*cbb3ec25SBjoern A. Zeeb MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | 460*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_A3_MAC | 461*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_A3_BSSID); 462*cbb3ec25SBjoern A. Zeeb 463*cbb3ec25SBjoern A. Zeeb MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL); 464*cbb3ec25SBjoern A. Zeeb 465*cbb3ec25SBjoern A. Zeeb MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | 466*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_RTS | 467*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_CTL_RSV | 468*cbb3ec25SBjoern A. Zeeb MT_WF_RFCR_DROP_NDPA); 469*cbb3ec25SBjoern A. Zeeb 470*cbb3ec25SBjoern A. Zeeb *total_flags = flags; 471*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_RFCR(phy->mt76->band_idx), phy->rxfilter); 472*cbb3ec25SBjoern A. Zeeb 473*cbb3ec25SBjoern A. Zeeb if (*total_flags & FIF_CONTROL) 474*cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags); 475*cbb3ec25SBjoern A. Zeeb else 476*cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_WF_RFCR1(phy->mt76->band_idx), ctl_flags); 477*cbb3ec25SBjoern A. Zeeb 478*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 479*cbb3ec25SBjoern A. Zeeb } 480*cbb3ec25SBjoern A. Zeeb 481*cbb3ec25SBjoern A. Zeeb static void 482*cbb3ec25SBjoern A. Zeeb mt7996_update_bss_color(struct ieee80211_hw *hw, 483*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 484*cbb3ec25SBjoern A. Zeeb struct cfg80211_he_bss_color *bss_color) 485*cbb3ec25SBjoern A. Zeeb { 486*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 487*cbb3ec25SBjoern A. Zeeb 488*cbb3ec25SBjoern A. Zeeb switch (vif->type) { 489*cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_AP: { 490*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 491*cbb3ec25SBjoern A. Zeeb 492*cbb3ec25SBjoern A. Zeeb if (mvif->mt76.omac_idx > HW_BSSID_MAX) 493*cbb3ec25SBjoern A. Zeeb return; 494*cbb3ec25SBjoern A. Zeeb fallthrough; 495*cbb3ec25SBjoern A. Zeeb } 496*cbb3ec25SBjoern A. Zeeb case NL80211_IFTYPE_STATION: 497*cbb3ec25SBjoern A. Zeeb mt7996_mcu_update_bss_color(dev, vif, bss_color); 498*cbb3ec25SBjoern A. Zeeb break; 499*cbb3ec25SBjoern A. Zeeb default: 500*cbb3ec25SBjoern A. Zeeb break; 501*cbb3ec25SBjoern A. Zeeb } 502*cbb3ec25SBjoern A. Zeeb } 503*cbb3ec25SBjoern A. Zeeb 504*cbb3ec25SBjoern A. Zeeb static u8 505*cbb3ec25SBjoern A. Zeeb mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 506*cbb3ec25SBjoern A. Zeeb bool beacon, bool mcast) 507*cbb3ec25SBjoern A. Zeeb { 508*cbb3ec25SBjoern A. Zeeb struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; 509*cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy = hw->priv; 510*cbb3ec25SBjoern A. Zeeb u16 rate; 511*cbb3ec25SBjoern A. Zeeb u8 i, idx, ht; 512*cbb3ec25SBjoern A. Zeeb 513*cbb3ec25SBjoern A. Zeeb rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast); 514*cbb3ec25SBjoern A. Zeeb ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM; 515*cbb3ec25SBjoern A. Zeeb 516*cbb3ec25SBjoern A. Zeeb if (beacon && ht) { 517*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 518*cbb3ec25SBjoern A. Zeeb 519*cbb3ec25SBjoern A. Zeeb /* must odd index */ 520*cbb3ec25SBjoern A. Zeeb idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20); 521*cbb3ec25SBjoern A. Zeeb mt7996_mac_set_fixed_rate_table(dev, idx, rate); 522*cbb3ec25SBjoern A. Zeeb return idx; 523*cbb3ec25SBjoern A. Zeeb } 524*cbb3ec25SBjoern A. Zeeb 525*cbb3ec25SBjoern A. Zeeb idx = FIELD_GET(MT_TX_RATE_IDX, rate); 526*cbb3ec25SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) 527*cbb3ec25SBjoern A. Zeeb if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx) 528*cbb3ec25SBjoern A. Zeeb return MT7996_BASIC_RATES_TBL + i; 529*cbb3ec25SBjoern A. Zeeb 530*cbb3ec25SBjoern A. Zeeb return mvif->basic_rates_idx; 531*cbb3ec25SBjoern A. Zeeb } 532*cbb3ec25SBjoern A. Zeeb 533*cbb3ec25SBjoern A. Zeeb static void 534*cbb3ec25SBjoern A. Zeeb mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 535*cbb3ec25SBjoern A. Zeeb struct ieee80211_bss_conf *info) 536*cbb3ec25SBjoern A. Zeeb { 537*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 538*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 539*cbb3ec25SBjoern A. Zeeb u8 band = mvif->mt76.band_idx; 540*cbb3ec25SBjoern A. Zeeb u32 *mu; 541*cbb3ec25SBjoern A. Zeeb 542*cbb3ec25SBjoern A. Zeeb mu = (u32 *)info->mu_group.membership; 543*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD0(band), mu[0]); 544*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD1(band), mu[1]); 545*cbb3ec25SBjoern A. Zeeb 546*cbb3ec25SBjoern A. Zeeb mu = (u32 *)info->mu_group.position; 547*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS0(band), mu[0]); 548*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS1(band), mu[1]); 549*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS2(band), mu[2]); 550*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]); 551*cbb3ec25SBjoern A. Zeeb } 552*cbb3ec25SBjoern A. Zeeb 553*cbb3ec25SBjoern A. Zeeb static void mt7996_bss_info_changed(struct ieee80211_hw *hw, 554*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 555*cbb3ec25SBjoern A. Zeeb struct ieee80211_bss_conf *info, 556*cbb3ec25SBjoern A. Zeeb u64 changed) 557*cbb3ec25SBjoern A. Zeeb { 558*cbb3ec25SBjoern A. Zeeb struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; 559*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 560*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 561*cbb3ec25SBjoern A. Zeeb 562*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 563*cbb3ec25SBjoern A. Zeeb 564*cbb3ec25SBjoern A. Zeeb /* station mode uses BSSID to map the wlan entry to a peer, 565*cbb3ec25SBjoern A. Zeeb * and then peer references bss_info_rfch to set bandwidth cap. 566*cbb3ec25SBjoern A. Zeeb */ 567*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_BSSID && 568*cbb3ec25SBjoern A. Zeeb vif->type == NL80211_IFTYPE_STATION) { 569*cbb3ec25SBjoern A. Zeeb bool join = !is_zero_ether_addr(info->bssid); 570*cbb3ec25SBjoern A. Zeeb 571*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_bss_info(phy, vif, join); 572*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_sta(dev, vif, NULL, join); 573*cbb3ec25SBjoern A. Zeeb } 574*cbb3ec25SBjoern A. Zeeb 575*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_ASSOC) 576*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_bss_info(phy, vif, vif->cfg.assoc); 577*cbb3ec25SBjoern A. Zeeb 578*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_CTS_PROT) 579*cbb3ec25SBjoern A. Zeeb mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot); 580*cbb3ec25SBjoern A. Zeeb 581*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_SLOT) { 582*cbb3ec25SBjoern A. Zeeb int slottime = info->use_short_slot ? 9 : 20; 583*cbb3ec25SBjoern A. Zeeb 584*cbb3ec25SBjoern A. Zeeb if (slottime != phy->slottime) { 585*cbb3ec25SBjoern A. Zeeb phy->slottime = slottime; 586*cbb3ec25SBjoern A. Zeeb mt7996_mcu_set_timing(phy, vif); 587*cbb3ec25SBjoern A. Zeeb } 588*cbb3ec25SBjoern A. Zeeb } 589*cbb3ec25SBjoern A. Zeeb 590*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_MCAST_RATE) 591*cbb3ec25SBjoern A. Zeeb mvif->mcast_rates_idx = 592*cbb3ec25SBjoern A. Zeeb mt7996_get_rates_table(hw, vif, false, true); 593*cbb3ec25SBjoern A. Zeeb 594*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_BASIC_RATES) 595*cbb3ec25SBjoern A. Zeeb mvif->basic_rates_idx = 596*cbb3ec25SBjoern A. Zeeb mt7996_get_rates_table(hw, vif, false, false); 597*cbb3ec25SBjoern A. Zeeb 598*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { 599*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_bss_info(phy, vif, true); 600*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_sta(dev, vif, NULL, true); 601*cbb3ec25SBjoern A. Zeeb } 602*cbb3ec25SBjoern A. Zeeb 603*cbb3ec25SBjoern A. Zeeb /* ensure that enable txcmd_mode after bss_info */ 604*cbb3ec25SBjoern A. Zeeb if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) 605*cbb3ec25SBjoern A. Zeeb mt7996_mcu_set_tx(dev, vif); 606*cbb3ec25SBjoern A. Zeeb 607*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_HE_OBSS_PD) 608*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_obss_spr(phy, vif, &info->he_obss_pd); 609*cbb3ec25SBjoern A. Zeeb 610*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_HE_BSS_COLOR) 611*cbb3ec25SBjoern A. Zeeb mt7996_update_bss_color(hw, vif, &info->he_bss_color); 612*cbb3ec25SBjoern A. Zeeb 613*cbb3ec25SBjoern A. Zeeb if (changed & (BSS_CHANGED_BEACON | 614*cbb3ec25SBjoern A. Zeeb BSS_CHANGED_BEACON_ENABLED)) { 615*cbb3ec25SBjoern A. Zeeb mvif->beacon_rates_idx = 616*cbb3ec25SBjoern A. Zeeb mt7996_get_rates_table(hw, vif, true, false); 617*cbb3ec25SBjoern A. Zeeb 618*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_beacon(hw, vif, info->enable_beacon); 619*cbb3ec25SBjoern A. Zeeb } 620*cbb3ec25SBjoern A. Zeeb 621*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP || 622*cbb3ec25SBjoern A. Zeeb changed & BSS_CHANGED_FILS_DISCOVERY) 623*cbb3ec25SBjoern A. Zeeb mt7996_mcu_beacon_inband_discov(dev, vif, changed); 624*cbb3ec25SBjoern A. Zeeb 625*cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_MU_GROUPS) 626*cbb3ec25SBjoern A. Zeeb mt7996_update_mu_group(hw, vif, info); 627*cbb3ec25SBjoern A. Zeeb 628*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 629*cbb3ec25SBjoern A. Zeeb } 630*cbb3ec25SBjoern A. Zeeb 631*cbb3ec25SBjoern A. Zeeb static void 632*cbb3ec25SBjoern A. Zeeb mt7996_channel_switch_beacon(struct ieee80211_hw *hw, 633*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 634*cbb3ec25SBjoern A. Zeeb struct cfg80211_chan_def *chandef) 635*cbb3ec25SBjoern A. Zeeb { 636*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 637*cbb3ec25SBjoern A. Zeeb 638*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 639*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_beacon(hw, vif, true); 640*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 641*cbb3ec25SBjoern A. Zeeb } 642*cbb3ec25SBjoern A. Zeeb 643*cbb3ec25SBjoern A. Zeeb int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, 644*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta) 645*cbb3ec25SBjoern A. Zeeb { 646*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 647*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 648*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 649*cbb3ec25SBjoern A. Zeeb u8 band_idx = mvif->phy->mt76->band_idx; 650*cbb3ec25SBjoern A. Zeeb int ret, idx; 651*cbb3ec25SBjoern A. Zeeb 652*cbb3ec25SBjoern A. Zeeb idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA); 653*cbb3ec25SBjoern A. Zeeb if (idx < 0) 654*cbb3ec25SBjoern A. Zeeb return -ENOSPC; 655*cbb3ec25SBjoern A. Zeeb 656*cbb3ec25SBjoern A. Zeeb INIT_LIST_HEAD(&msta->rc_list); 657*cbb3ec25SBjoern A. Zeeb INIT_LIST_HEAD(&msta->wcid.poll_list); 658*cbb3ec25SBjoern A. Zeeb msta->vif = mvif; 659*cbb3ec25SBjoern A. Zeeb msta->wcid.sta = 1; 660*cbb3ec25SBjoern A. Zeeb msta->wcid.idx = idx; 661*cbb3ec25SBjoern A. Zeeb msta->wcid.phy_idx = band_idx; 662*cbb3ec25SBjoern A. Zeeb msta->wcid.tx_info |= MT_WCID_TX_INFO_SET; 663*cbb3ec25SBjoern A. Zeeb msta->jiffies = jiffies; 664*cbb3ec25SBjoern A. Zeeb 665*cbb3ec25SBjoern A. Zeeb ewma_avg_signal_init(&msta->avg_ack_signal); 666*cbb3ec25SBjoern A. Zeeb 667*cbb3ec25SBjoern A. Zeeb mt7996_mac_wtbl_update(dev, idx, 668*cbb3ec25SBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 669*cbb3ec25SBjoern A. Zeeb 670*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_add_sta(dev, vif, sta, true); 671*cbb3ec25SBjoern A. Zeeb if (ret) 672*cbb3ec25SBjoern A. Zeeb return ret; 673*cbb3ec25SBjoern A. Zeeb 674*cbb3ec25SBjoern A. Zeeb return mt7996_mcu_add_rate_ctrl(dev, vif, sta, false); 675*cbb3ec25SBjoern A. Zeeb } 676*cbb3ec25SBjoern A. Zeeb 677*cbb3ec25SBjoern A. Zeeb void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, 678*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta) 679*cbb3ec25SBjoern A. Zeeb { 680*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 681*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 682*cbb3ec25SBjoern A. Zeeb int i; 683*cbb3ec25SBjoern A. Zeeb 684*cbb3ec25SBjoern A. Zeeb mt7996_mcu_add_sta(dev, vif, sta, false); 685*cbb3ec25SBjoern A. Zeeb 686*cbb3ec25SBjoern A. Zeeb mt7996_mac_wtbl_update(dev, msta->wcid.idx, 687*cbb3ec25SBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 688*cbb3ec25SBjoern A. Zeeb 689*cbb3ec25SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) 690*cbb3ec25SBjoern A. Zeeb mt7996_mac_twt_teardown_flow(dev, msta, i); 691*cbb3ec25SBjoern A. Zeeb 692*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&mdev->sta_poll_lock); 693*cbb3ec25SBjoern A. Zeeb if (!list_empty(&msta->wcid.poll_list)) 694*cbb3ec25SBjoern A. Zeeb list_del_init(&msta->wcid.poll_list); 695*cbb3ec25SBjoern A. Zeeb if (!list_empty(&msta->rc_list)) 696*cbb3ec25SBjoern A. Zeeb list_del_init(&msta->rc_list); 697*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&mdev->sta_poll_lock); 698*cbb3ec25SBjoern A. Zeeb } 699*cbb3ec25SBjoern A. Zeeb 700*cbb3ec25SBjoern A. Zeeb static void mt7996_tx(struct ieee80211_hw *hw, 701*cbb3ec25SBjoern A. Zeeb struct ieee80211_tx_control *control, 702*cbb3ec25SBjoern A. Zeeb struct sk_buff *skb) 703*cbb3ec25SBjoern A. Zeeb { 704*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 705*cbb3ec25SBjoern A. Zeeb struct mt76_phy *mphy = hw->priv; 706*cbb3ec25SBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 707*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif; 708*cbb3ec25SBjoern A. Zeeb struct mt76_wcid *wcid = &dev->mt76.global_wcid; 709*cbb3ec25SBjoern A. Zeeb 710*cbb3ec25SBjoern A. Zeeb if (control->sta) { 711*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *sta; 712*cbb3ec25SBjoern A. Zeeb 713*cbb3ec25SBjoern A. Zeeb sta = (struct mt7996_sta *)control->sta->drv_priv; 714*cbb3ec25SBjoern A. Zeeb wcid = &sta->wcid; 715*cbb3ec25SBjoern A. Zeeb } 716*cbb3ec25SBjoern A. Zeeb 717*cbb3ec25SBjoern A. Zeeb if (vif && !control->sta) { 718*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif; 719*cbb3ec25SBjoern A. Zeeb 720*cbb3ec25SBjoern A. Zeeb mvif = (struct mt7996_vif *)vif->drv_priv; 721*cbb3ec25SBjoern A. Zeeb wcid = &mvif->sta.wcid; 722*cbb3ec25SBjoern A. Zeeb } 723*cbb3ec25SBjoern A. Zeeb 724*cbb3ec25SBjoern A. Zeeb mt76_tx(mphy, control->sta, wcid, skb); 725*cbb3ec25SBjoern A. Zeeb } 726*cbb3ec25SBjoern A. Zeeb 727*cbb3ec25SBjoern A. Zeeb static int mt7996_set_rts_threshold(struct ieee80211_hw *hw, u32 val) 728*cbb3ec25SBjoern A. Zeeb { 729*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 730*cbb3ec25SBjoern A. Zeeb int ret; 731*cbb3ec25SBjoern A. Zeeb 732*cbb3ec25SBjoern A. Zeeb mutex_lock(&phy->dev->mt76.mutex); 733*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_set_rts_thresh(phy, val); 734*cbb3ec25SBjoern A. Zeeb mutex_unlock(&phy->dev->mt76.mutex); 735*cbb3ec25SBjoern A. Zeeb 736*cbb3ec25SBjoern A. Zeeb return ret; 737*cbb3ec25SBjoern A. Zeeb } 738*cbb3ec25SBjoern A. Zeeb 739*cbb3ec25SBjoern A. Zeeb static int 740*cbb3ec25SBjoern A. Zeeb mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 741*cbb3ec25SBjoern A. Zeeb struct ieee80211_ampdu_params *params) 742*cbb3ec25SBjoern A. Zeeb { 743*cbb3ec25SBjoern A. Zeeb enum ieee80211_ampdu_mlme_action action = params->action; 744*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 745*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta = params->sta; 746*cbb3ec25SBjoern A. Zeeb struct ieee80211_txq *txq = sta->txq[params->tid]; 747*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 748*cbb3ec25SBjoern A. Zeeb u16 tid = params->tid; 749*cbb3ec25SBjoern A. Zeeb u16 ssn = params->ssn; 750*cbb3ec25SBjoern A. Zeeb struct mt76_txq *mtxq; 751*cbb3ec25SBjoern A. Zeeb int ret = 0; 752*cbb3ec25SBjoern A. Zeeb 753*cbb3ec25SBjoern A. Zeeb if (!txq) 754*cbb3ec25SBjoern A. Zeeb return -EINVAL; 755*cbb3ec25SBjoern A. Zeeb 756*cbb3ec25SBjoern A. Zeeb mtxq = (struct mt76_txq *)txq->drv_priv; 757*cbb3ec25SBjoern A. Zeeb 758*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 759*cbb3ec25SBjoern A. Zeeb switch (action) { 760*cbb3ec25SBjoern A. Zeeb case IEEE80211_AMPDU_RX_START: 761*cbb3ec25SBjoern A. Zeeb mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, 762*cbb3ec25SBjoern A. Zeeb params->buf_size); 763*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_add_rx_ba(dev, params, true); 764*cbb3ec25SBjoern A. Zeeb break; 765*cbb3ec25SBjoern A. Zeeb case IEEE80211_AMPDU_RX_STOP: 766*cbb3ec25SBjoern A. Zeeb mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); 767*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_add_rx_ba(dev, params, false); 768*cbb3ec25SBjoern A. Zeeb break; 769*cbb3ec25SBjoern A. Zeeb case IEEE80211_AMPDU_TX_OPERATIONAL: 770*cbb3ec25SBjoern A. Zeeb mtxq->aggr = true; 771*cbb3ec25SBjoern A. Zeeb mtxq->send_bar = false; 772*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_add_tx_ba(dev, params, true); 773*cbb3ec25SBjoern A. Zeeb break; 774*cbb3ec25SBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH: 775*cbb3ec25SBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 776*cbb3ec25SBjoern A. Zeeb mtxq->aggr = false; 777*cbb3ec25SBjoern A. Zeeb clear_bit(tid, &msta->wcid.ampdu_state); 778*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_add_tx_ba(dev, params, false); 779*cbb3ec25SBjoern A. Zeeb break; 780*cbb3ec25SBjoern A. Zeeb case IEEE80211_AMPDU_TX_START: 781*cbb3ec25SBjoern A. Zeeb set_bit(tid, &msta->wcid.ampdu_state); 782*cbb3ec25SBjoern A. Zeeb ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; 783*cbb3ec25SBjoern A. Zeeb break; 784*cbb3ec25SBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_CONT: 785*cbb3ec25SBjoern A. Zeeb mtxq->aggr = false; 786*cbb3ec25SBjoern A. Zeeb clear_bit(tid, &msta->wcid.ampdu_state); 787*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_add_tx_ba(dev, params, false); 788*cbb3ec25SBjoern A. Zeeb ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 789*cbb3ec25SBjoern A. Zeeb break; 790*cbb3ec25SBjoern A. Zeeb } 791*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 792*cbb3ec25SBjoern A. Zeeb 793*cbb3ec25SBjoern A. Zeeb return ret; 794*cbb3ec25SBjoern A. Zeeb } 795*cbb3ec25SBjoern A. Zeeb 796*cbb3ec25SBjoern A. Zeeb static int 797*cbb3ec25SBjoern A. Zeeb mt7996_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 798*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta) 799*cbb3ec25SBjoern A. Zeeb { 800*cbb3ec25SBjoern A. Zeeb return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST, 801*cbb3ec25SBjoern A. Zeeb IEEE80211_STA_NONE); 802*cbb3ec25SBjoern A. Zeeb } 803*cbb3ec25SBjoern A. Zeeb 804*cbb3ec25SBjoern A. Zeeb static int 805*cbb3ec25SBjoern A. Zeeb mt7996_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 806*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta) 807*cbb3ec25SBjoern A. Zeeb { 808*cbb3ec25SBjoern A. Zeeb return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE, 809*cbb3ec25SBjoern A. Zeeb IEEE80211_STA_NOTEXIST); 810*cbb3ec25SBjoern A. Zeeb } 811*cbb3ec25SBjoern A. Zeeb 812*cbb3ec25SBjoern A. Zeeb static int 813*cbb3ec25SBjoern A. Zeeb mt7996_get_stats(struct ieee80211_hw *hw, 814*cbb3ec25SBjoern A. Zeeb struct ieee80211_low_level_stats *stats) 815*cbb3ec25SBjoern A. Zeeb { 816*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 817*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 818*cbb3ec25SBjoern A. Zeeb struct mt76_mib_stats *mib = &phy->mib; 819*cbb3ec25SBjoern A. Zeeb 820*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 821*cbb3ec25SBjoern A. Zeeb 822*cbb3ec25SBjoern A. Zeeb stats->dot11RTSSuccessCount = mib->rts_cnt; 823*cbb3ec25SBjoern A. Zeeb stats->dot11RTSFailureCount = mib->rts_retries_cnt; 824*cbb3ec25SBjoern A. Zeeb stats->dot11FCSErrorCount = mib->fcs_err_cnt; 825*cbb3ec25SBjoern A. Zeeb stats->dot11ACKFailureCount = mib->ack_fail_cnt; 826*cbb3ec25SBjoern A. Zeeb 827*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 828*cbb3ec25SBjoern A. Zeeb 829*cbb3ec25SBjoern A. Zeeb return 0; 830*cbb3ec25SBjoern A. Zeeb } 831*cbb3ec25SBjoern A. Zeeb 832*cbb3ec25SBjoern A. Zeeb u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif) 833*cbb3ec25SBjoern A. Zeeb { 834*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 835*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 836*cbb3ec25SBjoern A. Zeeb union { 837*cbb3ec25SBjoern A. Zeeb u64 t64; 838*cbb3ec25SBjoern A. Zeeb u32 t32[2]; 839*cbb3ec25SBjoern A. Zeeb } tsf; 840*cbb3ec25SBjoern A. Zeeb u16 n; 841*cbb3ec25SBjoern A. Zeeb 842*cbb3ec25SBjoern A. Zeeb lockdep_assert_held(&dev->mt76.mutex); 843*cbb3ec25SBjoern A. Zeeb 844*cbb3ec25SBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 845*cbb3ec25SBjoern A. Zeeb : mvif->mt76.omac_idx; 846*cbb3ec25SBjoern A. Zeeb /* TSF software read */ 847*cbb3ec25SBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE, 848*cbb3ec25SBjoern A. Zeeb MT_LPON_TCR_SW_READ); 849*cbb3ec25SBjoern A. Zeeb tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(phy->mt76->band_idx)); 850*cbb3ec25SBjoern A. Zeeb tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(phy->mt76->band_idx)); 851*cbb3ec25SBjoern A. Zeeb 852*cbb3ec25SBjoern A. Zeeb return tsf.t64; 853*cbb3ec25SBjoern A. Zeeb } 854*cbb3ec25SBjoern A. Zeeb 855*cbb3ec25SBjoern A. Zeeb static u64 856*cbb3ec25SBjoern A. Zeeb mt7996_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 857*cbb3ec25SBjoern A. Zeeb { 858*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 859*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 860*cbb3ec25SBjoern A. Zeeb u64 ret; 861*cbb3ec25SBjoern A. Zeeb 862*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 863*cbb3ec25SBjoern A. Zeeb ret = __mt7996_get_tsf(hw, mvif); 864*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 865*cbb3ec25SBjoern A. Zeeb 866*cbb3ec25SBjoern A. Zeeb return ret; 867*cbb3ec25SBjoern A. Zeeb } 868*cbb3ec25SBjoern A. Zeeb 869*cbb3ec25SBjoern A. Zeeb static void 870*cbb3ec25SBjoern A. Zeeb mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 871*cbb3ec25SBjoern A. Zeeb u64 timestamp) 872*cbb3ec25SBjoern A. Zeeb { 873*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 874*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 875*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 876*cbb3ec25SBjoern A. Zeeb union { 877*cbb3ec25SBjoern A. Zeeb u64 t64; 878*cbb3ec25SBjoern A. Zeeb u32 t32[2]; 879*cbb3ec25SBjoern A. Zeeb } tsf = { .t64 = timestamp, }; 880*cbb3ec25SBjoern A. Zeeb u16 n; 881*cbb3ec25SBjoern A. Zeeb 882*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 883*cbb3ec25SBjoern A. Zeeb 884*cbb3ec25SBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 885*cbb3ec25SBjoern A. Zeeb : mvif->mt76.omac_idx; 886*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]); 887*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]); 888*cbb3ec25SBjoern A. Zeeb /* TSF software overwrite */ 889*cbb3ec25SBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE, 890*cbb3ec25SBjoern A. Zeeb MT_LPON_TCR_SW_WRITE); 891*cbb3ec25SBjoern A. Zeeb 892*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 893*cbb3ec25SBjoern A. Zeeb } 894*cbb3ec25SBjoern A. Zeeb 895*cbb3ec25SBjoern A. Zeeb static void 896*cbb3ec25SBjoern A. Zeeb mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 897*cbb3ec25SBjoern A. Zeeb s64 timestamp) 898*cbb3ec25SBjoern A. Zeeb { 899*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 900*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 901*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 902*cbb3ec25SBjoern A. Zeeb union { 903*cbb3ec25SBjoern A. Zeeb u64 t64; 904*cbb3ec25SBjoern A. Zeeb u32 t32[2]; 905*cbb3ec25SBjoern A. Zeeb } tsf = { .t64 = timestamp, }; 906*cbb3ec25SBjoern A. Zeeb u16 n; 907*cbb3ec25SBjoern A. Zeeb 908*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 909*cbb3ec25SBjoern A. Zeeb 910*cbb3ec25SBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0 911*cbb3ec25SBjoern A. Zeeb : mvif->mt76.omac_idx; 912*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]); 913*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR1(phy->mt76->band_idx), tsf.t32[1]); 914*cbb3ec25SBjoern A. Zeeb /* TSF software adjust*/ 915*cbb3ec25SBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(phy->mt76->band_idx, n), MT_LPON_TCR_SW_MODE, 916*cbb3ec25SBjoern A. Zeeb MT_LPON_TCR_SW_ADJUST); 917*cbb3ec25SBjoern A. Zeeb 918*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 919*cbb3ec25SBjoern A. Zeeb } 920*cbb3ec25SBjoern A. Zeeb 921*cbb3ec25SBjoern A. Zeeb static void 922*cbb3ec25SBjoern A. Zeeb mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) 923*cbb3ec25SBjoern A. Zeeb { 924*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 925*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev; 926*cbb3ec25SBjoern A. Zeeb 927*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 928*cbb3ec25SBjoern A. Zeeb phy->coverage_class = max_t(s16, coverage_class, 0); 929*cbb3ec25SBjoern A. Zeeb mt7996_mac_set_coverage_class(phy); 930*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 931*cbb3ec25SBjoern A. Zeeb } 932*cbb3ec25SBjoern A. Zeeb 933*cbb3ec25SBjoern A. Zeeb static int 934*cbb3ec25SBjoern A. Zeeb mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) 935*cbb3ec25SBjoern A. Zeeb { 936*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 937*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 938*cbb3ec25SBjoern A. Zeeb int max_nss = hweight8(hw->wiphy->available_antennas_tx); 939*cbb3ec25SBjoern A. Zeeb u8 band_idx = phy->mt76->band_idx, shift = dev->chainshift[band_idx]; 940*cbb3ec25SBjoern A. Zeeb 941*cbb3ec25SBjoern A. Zeeb if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) 942*cbb3ec25SBjoern A. Zeeb return -EINVAL; 943*cbb3ec25SBjoern A. Zeeb 944*cbb3ec25SBjoern A. Zeeb if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) 945*cbb3ec25SBjoern A. Zeeb tx_ant = BIT(ffs(tx_ant) - 1) - 1; 946*cbb3ec25SBjoern A. Zeeb 947*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 948*cbb3ec25SBjoern A. Zeeb 949*cbb3ec25SBjoern A. Zeeb phy->mt76->antenna_mask = tx_ant; 950*cbb3ec25SBjoern A. Zeeb 951*cbb3ec25SBjoern A. Zeeb /* restore to the origin chainmask which might have auxiliary path */ 952*cbb3ec25SBjoern A. Zeeb if (hweight8(tx_ant) == max_nss && band_idx < MT_BAND2) 953*cbb3ec25SBjoern A. Zeeb phy->mt76->chainmask = ((dev->chainmask >> shift) & 954*cbb3ec25SBjoern A. Zeeb (BIT(dev->chainshift[band_idx + 1] - shift) - 1)) << shift; 955*cbb3ec25SBjoern A. Zeeb else if (hweight8(tx_ant) == max_nss) 956*cbb3ec25SBjoern A. Zeeb phy->mt76->chainmask = (dev->chainmask >> shift) << shift; 957*cbb3ec25SBjoern A. Zeeb else 958*cbb3ec25SBjoern A. Zeeb phy->mt76->chainmask = tx_ant << shift; 959*cbb3ec25SBjoern A. Zeeb 960*cbb3ec25SBjoern A. Zeeb mt76_set_stream_caps(phy->mt76, true); 961*cbb3ec25SBjoern A. Zeeb mt7996_set_stream_vht_txbf_caps(phy); 962*cbb3ec25SBjoern A. Zeeb mt7996_set_stream_he_eht_caps(phy); 963*cbb3ec25SBjoern A. Zeeb 964*cbb3ec25SBjoern A. Zeeb /* TODO: update bmc_wtbl spe_idx when antenna changes */ 965*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 966*cbb3ec25SBjoern A. Zeeb 967*cbb3ec25SBjoern A. Zeeb return 0; 968*cbb3ec25SBjoern A. Zeeb } 969*cbb3ec25SBjoern A. Zeeb 970*cbb3ec25SBjoern A. Zeeb static void mt7996_sta_statistics(struct ieee80211_hw *hw, 971*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 972*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta, 973*cbb3ec25SBjoern A. Zeeb struct station_info *sinfo) 974*cbb3ec25SBjoern A. Zeeb { 975*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 976*cbb3ec25SBjoern A. Zeeb struct rate_info *txrate = &msta->wcid.rate; 977*cbb3ec25SBjoern A. Zeeb 978*cbb3ec25SBjoern A. Zeeb if (txrate->legacy || txrate->flags) { 979*cbb3ec25SBjoern A. Zeeb if (txrate->legacy) { 980*cbb3ec25SBjoern A. Zeeb sinfo->txrate.legacy = txrate->legacy; 981*cbb3ec25SBjoern A. Zeeb } else { 982*cbb3ec25SBjoern A. Zeeb sinfo->txrate.mcs = txrate->mcs; 983*cbb3ec25SBjoern A. Zeeb sinfo->txrate.nss = txrate->nss; 984*cbb3ec25SBjoern A. Zeeb sinfo->txrate.bw = txrate->bw; 985*cbb3ec25SBjoern A. Zeeb sinfo->txrate.he_gi = txrate->he_gi; 986*cbb3ec25SBjoern A. Zeeb sinfo->txrate.he_dcm = txrate->he_dcm; 987*cbb3ec25SBjoern A. Zeeb sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; 988*cbb3ec25SBjoern A. Zeeb } 989*cbb3ec25SBjoern A. Zeeb sinfo->txrate.flags = txrate->flags; 990*cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); 991*cbb3ec25SBjoern A. Zeeb } 992*cbb3ec25SBjoern A. Zeeb sinfo->txrate.flags = txrate->flags; 993*cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); 994*cbb3ec25SBjoern A. Zeeb 995*cbb3ec25SBjoern A. Zeeb sinfo->ack_signal = (s8)msta->ack_signal; 996*cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); 997*cbb3ec25SBjoern A. Zeeb 998*cbb3ec25SBjoern A. Zeeb sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal); 999*cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); 1000*cbb3ec25SBjoern A. Zeeb } 1001*cbb3ec25SBjoern A. Zeeb 1002*cbb3ec25SBjoern A. Zeeb static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta) 1003*cbb3ec25SBjoern A. Zeeb { 1004*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 1005*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = msta->vif->phy->dev; 1006*cbb3ec25SBjoern A. Zeeb u32 *changed = data; 1007*cbb3ec25SBjoern A. Zeeb 1008*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 1009*cbb3ec25SBjoern A. Zeeb msta->changed |= *changed; 1010*cbb3ec25SBjoern A. Zeeb if (list_empty(&msta->rc_list)) 1011*cbb3ec25SBjoern A. Zeeb list_add_tail(&msta->rc_list, &dev->sta_rc_list); 1012*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 1013*cbb3ec25SBjoern A. Zeeb } 1014*cbb3ec25SBjoern A. Zeeb 1015*cbb3ec25SBjoern A. Zeeb static void mt7996_sta_rc_update(struct ieee80211_hw *hw, 1016*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 1017*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta, 1018*cbb3ec25SBjoern A. Zeeb u32 changed) 1019*cbb3ec25SBjoern A. Zeeb { 1020*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 1021*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev; 1022*cbb3ec25SBjoern A. Zeeb 1023*cbb3ec25SBjoern A. Zeeb mt7996_sta_rc_work(&changed, sta); 1024*cbb3ec25SBjoern A. Zeeb ieee80211_queue_work(hw, &dev->rc_work); 1025*cbb3ec25SBjoern A. Zeeb } 1026*cbb3ec25SBjoern A. Zeeb 1027*cbb3ec25SBjoern A. Zeeb static int 1028*cbb3ec25SBjoern A. Zeeb mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1029*cbb3ec25SBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask) 1030*cbb3ec25SBjoern A. Zeeb { 1031*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 1032*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 1033*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev; 1034*cbb3ec25SBjoern A. Zeeb u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED; 1035*cbb3ec25SBjoern A. Zeeb 1036*cbb3ec25SBjoern A. Zeeb mvif->bitrate_mask = *mask; 1037*cbb3ec25SBjoern A. Zeeb 1038*cbb3ec25SBjoern A. Zeeb /* if multiple rates across different preambles are given we can 1039*cbb3ec25SBjoern A. Zeeb * reconfigure this info with all peers using sta_rec command with 1040*cbb3ec25SBjoern A. Zeeb * the below exception cases. 1041*cbb3ec25SBjoern A. Zeeb * - single rate : if a rate is passed along with different preambles, 1042*cbb3ec25SBjoern A. Zeeb * we select the highest one as fixed rate. i.e VHT MCS for VHT peers. 1043*cbb3ec25SBjoern A. Zeeb * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT 1044*cbb3ec25SBjoern A. Zeeb * then multiple MCS setting (MCS 4,5,6) is not supported. 1045*cbb3ec25SBjoern A. Zeeb */ 1046*cbb3ec25SBjoern A. Zeeb ieee80211_iterate_stations_atomic(hw, mt7996_sta_rc_work, &changed); 1047*cbb3ec25SBjoern A. Zeeb ieee80211_queue_work(hw, &dev->rc_work); 1048*cbb3ec25SBjoern A. Zeeb 1049*cbb3ec25SBjoern A. Zeeb return 0; 1050*cbb3ec25SBjoern A. Zeeb } 1051*cbb3ec25SBjoern A. Zeeb 1052*cbb3ec25SBjoern A. Zeeb static void mt7996_sta_set_4addr(struct ieee80211_hw *hw, 1053*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 1054*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta, 1055*cbb3ec25SBjoern A. Zeeb bool enabled) 1056*cbb3ec25SBjoern A. Zeeb { 1057*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 1058*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 1059*cbb3ec25SBjoern A. Zeeb 1060*cbb3ec25SBjoern A. Zeeb if (enabled) 1061*cbb3ec25SBjoern A. Zeeb set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); 1062*cbb3ec25SBjoern A. Zeeb else 1063*cbb3ec25SBjoern A. Zeeb clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags); 1064*cbb3ec25SBjoern A. Zeeb 1065*cbb3ec25SBjoern A. Zeeb mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta); 1066*cbb3ec25SBjoern A. Zeeb } 1067*cbb3ec25SBjoern A. Zeeb 1068*cbb3ec25SBjoern A. Zeeb static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw, 1069*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 1070*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta, 1071*cbb3ec25SBjoern A. Zeeb bool enabled) 1072*cbb3ec25SBjoern A. Zeeb { 1073*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 1074*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 1075*cbb3ec25SBjoern A. Zeeb 1076*cbb3ec25SBjoern A. Zeeb if (enabled) 1077*cbb3ec25SBjoern A. Zeeb set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); 1078*cbb3ec25SBjoern A. Zeeb else 1079*cbb3ec25SBjoern A. Zeeb clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); 1080*cbb3ec25SBjoern A. Zeeb 1081*cbb3ec25SBjoern A. Zeeb mt7996_mcu_wtbl_update_hdr_trans(dev, vif, sta); 1082*cbb3ec25SBjoern A. Zeeb } 1083*cbb3ec25SBjoern A. Zeeb 1084*cbb3ec25SBjoern A. Zeeb static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = { 1085*cbb3ec25SBjoern A. Zeeb "tx_ampdu_cnt", 1086*cbb3ec25SBjoern A. Zeeb "tx_stop_q_empty_cnt", 1087*cbb3ec25SBjoern A. Zeeb "tx_mpdu_attempts", 1088*cbb3ec25SBjoern A. Zeeb "tx_mpdu_success", 1089*cbb3ec25SBjoern A. Zeeb "tx_rwp_fail_cnt", 1090*cbb3ec25SBjoern A. Zeeb "tx_rwp_need_cnt", 1091*cbb3ec25SBjoern A. Zeeb "tx_pkt_ebf_cnt", 1092*cbb3ec25SBjoern A. Zeeb "tx_pkt_ibf_cnt", 1093*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:0-1", 1094*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:2-10", 1095*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:11-19", 1096*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:20-28", 1097*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:29-37", 1098*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:38-46", 1099*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:47-55", 1100*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:56-79", 1101*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:80-103", 1102*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:104-127", 1103*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:128-151", 1104*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:152-175", 1105*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:176-199", 1106*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:200-223", 1107*cbb3ec25SBjoern A. Zeeb "tx_ampdu_len:224-247", 1108*cbb3ec25SBjoern A. Zeeb "ba_miss_count", 1109*cbb3ec25SBjoern A. Zeeb "tx_beamformer_ppdu_iBF", 1110*cbb3ec25SBjoern A. Zeeb "tx_beamformer_ppdu_eBF", 1111*cbb3ec25SBjoern A. Zeeb "tx_beamformer_rx_feedback_all", 1112*cbb3ec25SBjoern A. Zeeb "tx_beamformer_rx_feedback_he", 1113*cbb3ec25SBjoern A. Zeeb "tx_beamformer_rx_feedback_vht", 1114*cbb3ec25SBjoern A. Zeeb "tx_beamformer_rx_feedback_ht", 1115*cbb3ec25SBjoern A. Zeeb "tx_beamformer_rx_feedback_bw", /* zero based idx: 20, 40, 80, 160 */ 1116*cbb3ec25SBjoern A. Zeeb "tx_beamformer_rx_feedback_nc", 1117*cbb3ec25SBjoern A. Zeeb "tx_beamformer_rx_feedback_nr", 1118*cbb3ec25SBjoern A. Zeeb "tx_beamformee_ok_feedback_pkts", 1119*cbb3ec25SBjoern A. Zeeb "tx_beamformee_feedback_trig", 1120*cbb3ec25SBjoern A. Zeeb "tx_mu_beamforming", 1121*cbb3ec25SBjoern A. Zeeb "tx_mu_mpdu", 1122*cbb3ec25SBjoern A. Zeeb "tx_mu_successful_mpdu", 1123*cbb3ec25SBjoern A. Zeeb "tx_su_successful_mpdu", 1124*cbb3ec25SBjoern A. Zeeb "tx_msdu_pack_1", 1125*cbb3ec25SBjoern A. Zeeb "tx_msdu_pack_2", 1126*cbb3ec25SBjoern A. Zeeb "tx_msdu_pack_3", 1127*cbb3ec25SBjoern A. Zeeb "tx_msdu_pack_4", 1128*cbb3ec25SBjoern A. Zeeb "tx_msdu_pack_5", 1129*cbb3ec25SBjoern A. Zeeb "tx_msdu_pack_6", 1130*cbb3ec25SBjoern A. Zeeb "tx_msdu_pack_7", 1131*cbb3ec25SBjoern A. Zeeb "tx_msdu_pack_8", 1132*cbb3ec25SBjoern A. Zeeb 1133*cbb3ec25SBjoern A. Zeeb /* rx counters */ 1134*cbb3ec25SBjoern A. Zeeb "rx_fifo_full_cnt", 1135*cbb3ec25SBjoern A. Zeeb "rx_mpdu_cnt", 1136*cbb3ec25SBjoern A. Zeeb "channel_idle_cnt", 1137*cbb3ec25SBjoern A. Zeeb "rx_vector_mismatch_cnt", 1138*cbb3ec25SBjoern A. Zeeb "rx_delimiter_fail_cnt", 1139*cbb3ec25SBjoern A. Zeeb "rx_len_mismatch_cnt", 1140*cbb3ec25SBjoern A. Zeeb "rx_ampdu_cnt", 1141*cbb3ec25SBjoern A. Zeeb "rx_ampdu_bytes_cnt", 1142*cbb3ec25SBjoern A. Zeeb "rx_ampdu_valid_subframe_cnt", 1143*cbb3ec25SBjoern A. Zeeb "rx_ampdu_valid_subframe_b_cnt", 1144*cbb3ec25SBjoern A. Zeeb "rx_pfdrop_cnt", 1145*cbb3ec25SBjoern A. Zeeb "rx_vec_queue_overflow_drop_cnt", 1146*cbb3ec25SBjoern A. Zeeb "rx_ba_cnt", 1147*cbb3ec25SBjoern A. Zeeb 1148*cbb3ec25SBjoern A. Zeeb /* per vif counters */ 1149*cbb3ec25SBjoern A. Zeeb "v_tx_mode_cck", 1150*cbb3ec25SBjoern A. Zeeb "v_tx_mode_ofdm", 1151*cbb3ec25SBjoern A. Zeeb "v_tx_mode_ht", 1152*cbb3ec25SBjoern A. Zeeb "v_tx_mode_ht_gf", 1153*cbb3ec25SBjoern A. Zeeb "v_tx_mode_vht", 1154*cbb3ec25SBjoern A. Zeeb "v_tx_mode_he_su", 1155*cbb3ec25SBjoern A. Zeeb "v_tx_mode_he_ext_su", 1156*cbb3ec25SBjoern A. Zeeb "v_tx_mode_he_tb", 1157*cbb3ec25SBjoern A. Zeeb "v_tx_mode_he_mu", 1158*cbb3ec25SBjoern A. Zeeb "v_tx_mode_eht_su", 1159*cbb3ec25SBjoern A. Zeeb "v_tx_mode_eht_trig", 1160*cbb3ec25SBjoern A. Zeeb "v_tx_mode_eht_mu", 1161*cbb3ec25SBjoern A. Zeeb "v_tx_bw_20", 1162*cbb3ec25SBjoern A. Zeeb "v_tx_bw_40", 1163*cbb3ec25SBjoern A. Zeeb "v_tx_bw_80", 1164*cbb3ec25SBjoern A. Zeeb "v_tx_bw_160", 1165*cbb3ec25SBjoern A. Zeeb "v_tx_bw_320", 1166*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_0", 1167*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_1", 1168*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_2", 1169*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_3", 1170*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_4", 1171*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_5", 1172*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_6", 1173*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_7", 1174*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_8", 1175*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_9", 1176*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_10", 1177*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_11", 1178*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_12", 1179*cbb3ec25SBjoern A. Zeeb "v_tx_mcs_13", 1180*cbb3ec25SBjoern A. Zeeb "v_tx_nss_1", 1181*cbb3ec25SBjoern A. Zeeb "v_tx_nss_2", 1182*cbb3ec25SBjoern A. Zeeb "v_tx_nss_3", 1183*cbb3ec25SBjoern A. Zeeb "v_tx_nss_4", 1184*cbb3ec25SBjoern A. Zeeb }; 1185*cbb3ec25SBjoern A. Zeeb 1186*cbb3ec25SBjoern A. Zeeb #define MT7996_SSTATS_LEN ARRAY_SIZE(mt7996_gstrings_stats) 1187*cbb3ec25SBjoern A. Zeeb 1188*cbb3ec25SBjoern A. Zeeb /* Ethtool related API */ 1189*cbb3ec25SBjoern A. Zeeb static 1190*cbb3ec25SBjoern A. Zeeb void mt7996_get_et_strings(struct ieee80211_hw *hw, 1191*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 1192*cbb3ec25SBjoern A. Zeeb u32 sset, u8 *data) 1193*cbb3ec25SBjoern A. Zeeb { 1194*cbb3ec25SBjoern A. Zeeb if (sset == ETH_SS_STATS) 1195*cbb3ec25SBjoern A. Zeeb memcpy(data, *mt7996_gstrings_stats, 1196*cbb3ec25SBjoern A. Zeeb sizeof(mt7996_gstrings_stats)); 1197*cbb3ec25SBjoern A. Zeeb } 1198*cbb3ec25SBjoern A. Zeeb 1199*cbb3ec25SBjoern A. Zeeb static 1200*cbb3ec25SBjoern A. Zeeb int mt7996_get_et_sset_count(struct ieee80211_hw *hw, 1201*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, int sset) 1202*cbb3ec25SBjoern A. Zeeb { 1203*cbb3ec25SBjoern A. Zeeb if (sset == ETH_SS_STATS) 1204*cbb3ec25SBjoern A. Zeeb return MT7996_SSTATS_LEN; 1205*cbb3ec25SBjoern A. Zeeb 1206*cbb3ec25SBjoern A. Zeeb return 0; 1207*cbb3ec25SBjoern A. Zeeb } 1208*cbb3ec25SBjoern A. Zeeb 1209*cbb3ec25SBjoern A. Zeeb static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) 1210*cbb3ec25SBjoern A. Zeeb { 1211*cbb3ec25SBjoern A. Zeeb struct mt76_ethtool_worker_info *wi = wi_data; 1212*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 1213*cbb3ec25SBjoern A. Zeeb 1214*cbb3ec25SBjoern A. Zeeb if (msta->vif->mt76.idx != wi->idx) 1215*cbb3ec25SBjoern A. Zeeb return; 1216*cbb3ec25SBjoern A. Zeeb 1217*cbb3ec25SBjoern A. Zeeb mt76_ethtool_worker(wi, &msta->wcid.stats, true); 1218*cbb3ec25SBjoern A. Zeeb } 1219*cbb3ec25SBjoern A. Zeeb 1220*cbb3ec25SBjoern A. Zeeb static 1221*cbb3ec25SBjoern A. Zeeb void mt7996_get_et_stats(struct ieee80211_hw *hw, 1222*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, 1223*cbb3ec25SBjoern A. Zeeb struct ethtool_stats *stats, u64 *data) 1224*cbb3ec25SBjoern A. Zeeb { 1225*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 1226*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 1227*cbb3ec25SBjoern A. Zeeb struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 1228*cbb3ec25SBjoern A. Zeeb struct mt76_mib_stats *mib = &phy->mib; 1229*cbb3ec25SBjoern A. Zeeb struct mt76_ethtool_worker_info wi = { 1230*cbb3ec25SBjoern A. Zeeb .data = data, 1231*cbb3ec25SBjoern A. Zeeb .idx = mvif->mt76.idx, 1232*cbb3ec25SBjoern A. Zeeb }; 1233*cbb3ec25SBjoern A. Zeeb /* See mt7996_ampdu_stat_read_phy, etc */ 1234*cbb3ec25SBjoern A. Zeeb int i, ei = 0; 1235*cbb3ec25SBjoern A. Zeeb 1236*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 1237*cbb3ec25SBjoern A. Zeeb 1238*cbb3ec25SBjoern A. Zeeb mt7996_mac_update_stats(phy); 1239*cbb3ec25SBjoern A. Zeeb 1240*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_ampdu_cnt; 1241*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_stop_q_empty_cnt; 1242*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_mpdu_attempts_cnt; 1243*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_mpdu_success_cnt; 1244*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_rwp_fail_cnt; 1245*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_rwp_need_cnt; 1246*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_ebf_ppdu_cnt; 1247*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_ibf_ppdu_cnt; 1248*cbb3ec25SBjoern A. Zeeb 1249*cbb3ec25SBjoern A. Zeeb /* Tx ampdu stat */ 1250*cbb3ec25SBjoern A. Zeeb for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++) 1251*cbb3ec25SBjoern A. Zeeb data[ei++] = phy->mt76->aggr_stats[i]; 1252*cbb3ec25SBjoern A. Zeeb data[ei++] = phy->mib.ba_miss_cnt; 1253*cbb3ec25SBjoern A. Zeeb 1254*cbb3ec25SBjoern A. Zeeb /* Tx Beamformer monitor */ 1255*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_ibf_ppdu_cnt; 1256*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_ebf_ppdu_cnt; 1257*cbb3ec25SBjoern A. Zeeb 1258*cbb3ec25SBjoern A. Zeeb /* Tx Beamformer Rx feedback monitor */ 1259*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_all_cnt; 1260*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_he_cnt; 1261*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_vht_cnt; 1262*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_ht_cnt; 1263*cbb3ec25SBjoern A. Zeeb 1264*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_bw; 1265*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_nc_cnt; 1266*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_nr_cnt; 1267*cbb3ec25SBjoern A. Zeeb 1268*cbb3ec25SBjoern A. Zeeb /* Tx Beamformee Rx NDPA & Tx feedback report */ 1269*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_fb_cpl_cnt; 1270*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_bf_fb_trig_cnt; 1271*cbb3ec25SBjoern A. Zeeb 1272*cbb3ec25SBjoern A. Zeeb /* Tx SU & MU counters */ 1273*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_mu_bf_cnt; 1274*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_mu_mpdu_cnt; 1275*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_mu_acked_mpdu_cnt; 1276*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_su_acked_mpdu_cnt; 1277*cbb3ec25SBjoern A. Zeeb 1278*cbb3ec25SBjoern A. Zeeb /* Tx amsdu info (pack-count histogram) */ 1279*cbb3ec25SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) 1280*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->tx_amsdu[i]; 1281*cbb3ec25SBjoern A. Zeeb 1282*cbb3ec25SBjoern A. Zeeb /* rx counters */ 1283*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_fifo_full_cnt; 1284*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_mpdu_cnt; 1285*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->channel_idle_cnt; 1286*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_vector_mismatch_cnt; 1287*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_delimiter_fail_cnt; 1288*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_len_mismatch_cnt; 1289*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_ampdu_cnt; 1290*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_ampdu_bytes_cnt; 1291*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_ampdu_valid_subframe_cnt; 1292*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_ampdu_valid_subframe_bytes_cnt; 1293*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_pfdrop_cnt; 1294*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_vec_queue_overflow_drop_cnt; 1295*cbb3ec25SBjoern A. Zeeb data[ei++] = mib->rx_ba_cnt; 1296*cbb3ec25SBjoern A. Zeeb 1297*cbb3ec25SBjoern A. Zeeb /* Add values for all stations owned by this vif */ 1298*cbb3ec25SBjoern A. Zeeb wi.initial_stat_idx = ei; 1299*cbb3ec25SBjoern A. Zeeb ieee80211_iterate_stations_atomic(hw, mt7996_ethtool_worker, &wi); 1300*cbb3ec25SBjoern A. Zeeb 1301*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 1302*cbb3ec25SBjoern A. Zeeb 1303*cbb3ec25SBjoern A. Zeeb if (wi.sta_count == 0) 1304*cbb3ec25SBjoern A. Zeeb return; 1305*cbb3ec25SBjoern A. Zeeb 1306*cbb3ec25SBjoern A. Zeeb ei += wi.worker_stat_count; 1307*cbb3ec25SBjoern A. Zeeb if (ei != MT7996_SSTATS_LEN) 1308*cbb3ec25SBjoern A. Zeeb dev_err(dev->mt76.dev, "ei: %d MT7996_SSTATS_LEN: %d", 1309*cbb3ec25SBjoern A. Zeeb ei, (int)MT7996_SSTATS_LEN); 1310*cbb3ec25SBjoern A. Zeeb } 1311*cbb3ec25SBjoern A. Zeeb 1312*cbb3ec25SBjoern A. Zeeb static void 1313*cbb3ec25SBjoern A. Zeeb mt7996_twt_teardown_request(struct ieee80211_hw *hw, 1314*cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta, 1315*cbb3ec25SBjoern A. Zeeb u8 flowid) 1316*cbb3ec25SBjoern A. Zeeb { 1317*cbb3ec25SBjoern A. Zeeb struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 1318*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = mt7996_hw_dev(hw); 1319*cbb3ec25SBjoern A. Zeeb 1320*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 1321*cbb3ec25SBjoern A. Zeeb mt7996_mac_twt_teardown_flow(dev, msta, flowid); 1322*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 1323*cbb3ec25SBjoern A. Zeeb } 1324*cbb3ec25SBjoern A. Zeeb 1325*cbb3ec25SBjoern A. Zeeb static int 1326*cbb3ec25SBjoern A. Zeeb mt7996_set_radar_background(struct ieee80211_hw *hw, 1327*cbb3ec25SBjoern A. Zeeb struct cfg80211_chan_def *chandef) 1328*cbb3ec25SBjoern A. Zeeb { 1329*cbb3ec25SBjoern A. Zeeb struct mt7996_phy *phy = mt7996_hw_phy(hw); 1330*cbb3ec25SBjoern A. Zeeb struct mt7996_dev *dev = phy->dev; 1331*cbb3ec25SBjoern A. Zeeb int ret = -EINVAL; 1332*cbb3ec25SBjoern A. Zeeb bool running; 1333*cbb3ec25SBjoern A. Zeeb 1334*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 1335*cbb3ec25SBjoern A. Zeeb 1336*cbb3ec25SBjoern A. Zeeb if (dev->mt76.region == NL80211_DFS_UNSET) 1337*cbb3ec25SBjoern A. Zeeb goto out; 1338*cbb3ec25SBjoern A. Zeeb 1339*cbb3ec25SBjoern A. Zeeb if (dev->rdd2_phy && dev->rdd2_phy != phy) { 1340*cbb3ec25SBjoern A. Zeeb /* rdd2 is already locked */ 1341*cbb3ec25SBjoern A. Zeeb ret = -EBUSY; 1342*cbb3ec25SBjoern A. Zeeb goto out; 1343*cbb3ec25SBjoern A. Zeeb } 1344*cbb3ec25SBjoern A. Zeeb 1345*cbb3ec25SBjoern A. Zeeb /* rdd2 already configured on a radar channel */ 1346*cbb3ec25SBjoern A. Zeeb running = dev->rdd2_phy && 1347*cbb3ec25SBjoern A. Zeeb cfg80211_chandef_valid(&dev->rdd2_chandef) && 1348*cbb3ec25SBjoern A. Zeeb !!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR); 1349*cbb3ec25SBjoern A. Zeeb 1350*cbb3ec25SBjoern A. Zeeb if (!chandef || running || 1351*cbb3ec25SBjoern A. Zeeb !(chandef->chan->flags & IEEE80211_CHAN_RADAR)) { 1352*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_rdd_background_enable(phy, NULL); 1353*cbb3ec25SBjoern A. Zeeb if (ret) 1354*cbb3ec25SBjoern A. Zeeb goto out; 1355*cbb3ec25SBjoern A. Zeeb 1356*cbb3ec25SBjoern A. Zeeb if (!running) 1357*cbb3ec25SBjoern A. Zeeb goto update_phy; 1358*cbb3ec25SBjoern A. Zeeb } 1359*cbb3ec25SBjoern A. Zeeb 1360*cbb3ec25SBjoern A. Zeeb ret = mt7996_mcu_rdd_background_enable(phy, chandef); 1361*cbb3ec25SBjoern A. Zeeb if (ret) 1362*cbb3ec25SBjoern A. Zeeb goto out; 1363*cbb3ec25SBjoern A. Zeeb 1364*cbb3ec25SBjoern A. Zeeb update_phy: 1365*cbb3ec25SBjoern A. Zeeb dev->rdd2_phy = chandef ? phy : NULL; 1366*cbb3ec25SBjoern A. Zeeb if (chandef) 1367*cbb3ec25SBjoern A. Zeeb dev->rdd2_chandef = *chandef; 1368*cbb3ec25SBjoern A. Zeeb out: 1369*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 1370*cbb3ec25SBjoern A. Zeeb 1371*cbb3ec25SBjoern A. Zeeb return ret; 1372*cbb3ec25SBjoern A. Zeeb } 1373*cbb3ec25SBjoern A. Zeeb 1374*cbb3ec25SBjoern A. Zeeb const struct ieee80211_ops mt7996_ops = { 1375*cbb3ec25SBjoern A. Zeeb .tx = mt7996_tx, 1376*cbb3ec25SBjoern A. Zeeb .start = mt7996_start, 1377*cbb3ec25SBjoern A. Zeeb .stop = mt7996_stop, 1378*cbb3ec25SBjoern A. Zeeb .add_interface = mt7996_add_interface, 1379*cbb3ec25SBjoern A. Zeeb .remove_interface = mt7996_remove_interface, 1380*cbb3ec25SBjoern A. Zeeb .config = mt7996_config, 1381*cbb3ec25SBjoern A. Zeeb .conf_tx = mt7996_conf_tx, 1382*cbb3ec25SBjoern A. Zeeb .configure_filter = mt7996_configure_filter, 1383*cbb3ec25SBjoern A. Zeeb .bss_info_changed = mt7996_bss_info_changed, 1384*cbb3ec25SBjoern A. Zeeb .sta_add = mt7996_sta_add, 1385*cbb3ec25SBjoern A. Zeeb .sta_remove = mt7996_sta_remove, 1386*cbb3ec25SBjoern A. Zeeb .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, 1387*cbb3ec25SBjoern A. Zeeb .sta_rc_update = mt7996_sta_rc_update, 1388*cbb3ec25SBjoern A. Zeeb .set_key = mt7996_set_key, 1389*cbb3ec25SBjoern A. Zeeb .ampdu_action = mt7996_ampdu_action, 1390*cbb3ec25SBjoern A. Zeeb .set_rts_threshold = mt7996_set_rts_threshold, 1391*cbb3ec25SBjoern A. Zeeb .wake_tx_queue = mt76_wake_tx_queue, 1392*cbb3ec25SBjoern A. Zeeb .sw_scan_start = mt76_sw_scan, 1393*cbb3ec25SBjoern A. Zeeb .sw_scan_complete = mt76_sw_scan_complete, 1394*cbb3ec25SBjoern A. Zeeb .release_buffered_frames = mt76_release_buffered_frames, 1395*cbb3ec25SBjoern A. Zeeb .get_txpower = mt76_get_txpower, 1396*cbb3ec25SBjoern A. Zeeb .channel_switch_beacon = mt7996_channel_switch_beacon, 1397*cbb3ec25SBjoern A. Zeeb .get_stats = mt7996_get_stats, 1398*cbb3ec25SBjoern A. Zeeb .get_et_sset_count = mt7996_get_et_sset_count, 1399*cbb3ec25SBjoern A. Zeeb .get_et_stats = mt7996_get_et_stats, 1400*cbb3ec25SBjoern A. Zeeb .get_et_strings = mt7996_get_et_strings, 1401*cbb3ec25SBjoern A. Zeeb .get_tsf = mt7996_get_tsf, 1402*cbb3ec25SBjoern A. Zeeb .set_tsf = mt7996_set_tsf, 1403*cbb3ec25SBjoern A. Zeeb .offset_tsf = mt7996_offset_tsf, 1404*cbb3ec25SBjoern A. Zeeb .get_survey = mt76_get_survey, 1405*cbb3ec25SBjoern A. Zeeb .get_antenna = mt76_get_antenna, 1406*cbb3ec25SBjoern A. Zeeb .set_antenna = mt7996_set_antenna, 1407*cbb3ec25SBjoern A. Zeeb .set_bitrate_mask = mt7996_set_bitrate_mask, 1408*cbb3ec25SBjoern A. Zeeb .set_coverage_class = mt7996_set_coverage_class, 1409*cbb3ec25SBjoern A. Zeeb .sta_statistics = mt7996_sta_statistics, 1410*cbb3ec25SBjoern A. Zeeb .sta_set_4addr = mt7996_sta_set_4addr, 1411*cbb3ec25SBjoern A. Zeeb .sta_set_decap_offload = mt7996_sta_set_decap_offload, 1412*cbb3ec25SBjoern A. Zeeb .add_twt_setup = mt7996_mac_add_twt_setup, 1413*cbb3ec25SBjoern A. Zeeb .twt_teardown_request = mt7996_twt_teardown_request, 1414*cbb3ec25SBjoern A. Zeeb #ifdef CONFIG_MAC80211_DEBUGFS 1415*cbb3ec25SBjoern A. Zeeb .sta_add_debugfs = mt7996_sta_add_debugfs, 1416*cbb3ec25SBjoern A. Zeeb #endif 1417*cbb3ec25SBjoern A. Zeeb .set_radar_background = mt7996_set_radar_background, 1418*cbb3ec25SBjoern A. Zeeb }; 1419