198686cd2SShayne Chen // SPDX-License-Identifier: ISC 298686cd2SShayne Chen /* 398686cd2SShayne Chen * Copyright (C) 2022 MediaTek Inc. 498686cd2SShayne Chen */ 598686cd2SShayne Chen 698686cd2SShayne Chen #include <linux/etherdevice.h> 798686cd2SShayne Chen #include <linux/timekeeping.h> 898686cd2SShayne Chen #include "mt7996.h" 998686cd2SShayne Chen #include "../dma.h" 1098686cd2SShayne Chen #include "mac.h" 1198686cd2SShayne Chen #include "mcu.h" 1298686cd2SShayne Chen 13ea5d99d0SRyder Lee #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2) 1498686cd2SShayne Chen 1598686cd2SShayne Chen #define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) 1698686cd2SShayne Chen #define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ 1798686cd2SShayne Chen IEEE80211_RADIOTAP_HE_##f) 1898686cd2SShayne Chen 1998686cd2SShayne Chen static const struct mt7996_dfs_radar_spec etsi_radar_specs = { 2098686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 2198686cd2SShayne Chen .radar_pattern = { 2298686cd2SShayne Chen [5] = { 1, 0, 6, 32, 28, 0, 990, 5010, 17, 1, 1 }, 2398686cd2SShayne Chen [6] = { 1, 0, 9, 32, 28, 0, 615, 5010, 27, 1, 1 }, 2498686cd2SShayne Chen [7] = { 1, 0, 15, 32, 28, 0, 240, 445, 27, 1, 1 }, 2598686cd2SShayne Chen [8] = { 1, 0, 12, 32, 28, 0, 240, 510, 42, 1, 1 }, 2698686cd2SShayne Chen [9] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 12, 32, 28, { }, 126 }, 2798686cd2SShayne Chen [10] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 15, 32, 24, { }, 126 }, 2898686cd2SShayne Chen [11] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 18, 32, 28, { }, 54 }, 2998686cd2SShayne Chen [12] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 27, 32, 24, { }, 54 }, 3098686cd2SShayne Chen }, 3198686cd2SShayne Chen }; 3298686cd2SShayne Chen 3398686cd2SShayne Chen static const struct mt7996_dfs_radar_spec fcc_radar_specs = { 3498686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 3598686cd2SShayne Chen .radar_pattern = { 3698686cd2SShayne Chen [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, 3798686cd2SShayne Chen [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, 3898686cd2SShayne Chen [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, 3998686cd2SShayne Chen [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, 4098686cd2SShayne Chen [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, 4198686cd2SShayne Chen }, 4298686cd2SShayne Chen }; 4398686cd2SShayne Chen 4498686cd2SShayne Chen static const struct mt7996_dfs_radar_spec jp_radar_specs = { 4598686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 4698686cd2SShayne Chen .radar_pattern = { 4798686cd2SShayne Chen [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, 4898686cd2SShayne Chen [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, 4998686cd2SShayne Chen [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, 5098686cd2SShayne Chen [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, 5198686cd2SShayne Chen [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, 5298686cd2SShayne Chen [13] = { 1, 0, 7, 32, 28, 0, 3836, 3856, 14, 1, 1 }, 5398686cd2SShayne Chen [14] = { 1, 0, 6, 32, 28, 0, 615, 5010, 110, 1, 1 }, 5498686cd2SShayne Chen [15] = { 1, 1, 0, 0, 0, 0, 15, 5010, 110, 0, 0, 12, 32, 28 }, 5598686cd2SShayne Chen }, 5698686cd2SShayne Chen }; 5798686cd2SShayne Chen 5898686cd2SShayne Chen static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev, 5998686cd2SShayne Chen u16 idx, bool unicast) 6098686cd2SShayne Chen { 6198686cd2SShayne Chen struct mt7996_sta *sta; 6298686cd2SShayne Chen struct mt76_wcid *wcid; 6398686cd2SShayne Chen 6498686cd2SShayne Chen if (idx >= ARRAY_SIZE(dev->mt76.wcid)) 6598686cd2SShayne Chen return NULL; 6698686cd2SShayne Chen 6798686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[idx]); 6898686cd2SShayne Chen if (unicast || !wcid) 6998686cd2SShayne Chen return wcid; 7098686cd2SShayne Chen 7198686cd2SShayne Chen if (!wcid->sta) 7298686cd2SShayne Chen return NULL; 7398686cd2SShayne Chen 7498686cd2SShayne Chen sta = container_of(wcid, struct mt7996_sta, wcid); 7598686cd2SShayne Chen if (!sta->vif) 7698686cd2SShayne Chen return NULL; 7798686cd2SShayne Chen 7898686cd2SShayne Chen return &sta->vif->sta.wcid; 7998686cd2SShayne Chen } 8098686cd2SShayne Chen 8198686cd2SShayne Chen void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) 8298686cd2SShayne Chen { 8398686cd2SShayne Chen } 8498686cd2SShayne Chen 8598686cd2SShayne Chen bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask) 8698686cd2SShayne Chen { 8798686cd2SShayne Chen mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, 8898686cd2SShayne Chen FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); 8998686cd2SShayne Chen 9098686cd2SShayne Chen return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 9198686cd2SShayne Chen 0, 5000); 9298686cd2SShayne Chen } 9398686cd2SShayne Chen 9498686cd2SShayne Chen u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw) 9598686cd2SShayne Chen { 9698686cd2SShayne Chen mt76_wr(dev, MT_WTBLON_TOP_WDUCR, 9798686cd2SShayne Chen FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); 9898686cd2SShayne Chen 9998686cd2SShayne Chen return MT_WTBL_LMAC_OFFS(wcid, dw); 10098686cd2SShayne Chen } 10198686cd2SShayne Chen 10298686cd2SShayne Chen static void mt7996_mac_sta_poll(struct mt7996_dev *dev) 10398686cd2SShayne Chen { 10498686cd2SShayne Chen static const u8 ac_to_tid[] = { 10598686cd2SShayne Chen [IEEE80211_AC_BE] = 0, 10698686cd2SShayne Chen [IEEE80211_AC_BK] = 1, 10798686cd2SShayne Chen [IEEE80211_AC_VI] = 4, 10898686cd2SShayne Chen [IEEE80211_AC_VO] = 6 10998686cd2SShayne Chen }; 11098686cd2SShayne Chen struct ieee80211_sta *sta; 11198686cd2SShayne Chen struct mt7996_sta *msta; 11298686cd2SShayne Chen struct rate_info *rate; 11398686cd2SShayne Chen u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; 11498686cd2SShayne Chen LIST_HEAD(sta_poll_list); 11598686cd2SShayne Chen int i; 11698686cd2SShayne Chen 11798686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 11898686cd2SShayne Chen list_splice_init(&dev->sta_poll_list, &sta_poll_list); 11998686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 12098686cd2SShayne Chen 12198686cd2SShayne Chen rcu_read_lock(); 12298686cd2SShayne Chen 12398686cd2SShayne Chen while (true) { 12498686cd2SShayne Chen bool clear = false; 12598686cd2SShayne Chen u32 addr, val; 12698686cd2SShayne Chen u16 idx; 127ea5d99d0SRyder Lee s8 rssi[4]; 12898686cd2SShayne Chen u8 bw; 12998686cd2SShayne Chen 13098686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 13198686cd2SShayne Chen if (list_empty(&sta_poll_list)) { 13298686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 13398686cd2SShayne Chen break; 13498686cd2SShayne Chen } 13598686cd2SShayne Chen msta = list_first_entry(&sta_poll_list, 13698686cd2SShayne Chen struct mt7996_sta, poll_list); 13798686cd2SShayne Chen list_del_init(&msta->poll_list); 13898686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 13998686cd2SShayne Chen 14098686cd2SShayne Chen idx = msta->wcid.idx; 141ea5d99d0SRyder Lee 142ea5d99d0SRyder Lee /* refresh peer's airtime reporting */ 14398686cd2SShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20); 14498686cd2SShayne Chen 14598686cd2SShayne Chen for (i = 0; i < IEEE80211_NUM_ACS; i++) { 14698686cd2SShayne Chen u32 tx_last = msta->airtime_ac[i]; 14798686cd2SShayne Chen u32 rx_last = msta->airtime_ac[i + 4]; 14898686cd2SShayne Chen 14998686cd2SShayne Chen msta->airtime_ac[i] = mt76_rr(dev, addr); 15098686cd2SShayne Chen msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); 15198686cd2SShayne Chen 15298686cd2SShayne Chen tx_time[i] = msta->airtime_ac[i] - tx_last; 15398686cd2SShayne Chen rx_time[i] = msta->airtime_ac[i + 4] - rx_last; 15498686cd2SShayne Chen 15598686cd2SShayne Chen if ((tx_last | rx_last) & BIT(30)) 15698686cd2SShayne Chen clear = true; 15798686cd2SShayne Chen 15898686cd2SShayne Chen addr += 8; 15998686cd2SShayne Chen } 16098686cd2SShayne Chen 16198686cd2SShayne Chen if (clear) { 16298686cd2SShayne Chen mt7996_mac_wtbl_update(dev, idx, 16398686cd2SShayne Chen MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 16498686cd2SShayne Chen memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); 16598686cd2SShayne Chen } 16698686cd2SShayne Chen 16798686cd2SShayne Chen if (!msta->wcid.sta) 16898686cd2SShayne Chen continue; 16998686cd2SShayne Chen 17098686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, 17198686cd2SShayne Chen drv_priv); 17298686cd2SShayne Chen for (i = 0; i < IEEE80211_NUM_ACS; i++) { 17398686cd2SShayne Chen u8 q = mt76_connac_lmac_mapping(i); 17498686cd2SShayne Chen u32 tx_cur = tx_time[q]; 17598686cd2SShayne Chen u32 rx_cur = rx_time[q]; 17698686cd2SShayne Chen u8 tid = ac_to_tid[i]; 17798686cd2SShayne Chen 17898686cd2SShayne Chen if (!tx_cur && !rx_cur) 17998686cd2SShayne Chen continue; 18098686cd2SShayne Chen 18198686cd2SShayne Chen ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur); 18298686cd2SShayne Chen } 18398686cd2SShayne Chen 18498686cd2SShayne Chen /* We don't support reading GI info from txs packets. 18598686cd2SShayne Chen * For accurate tx status reporting and AQL improvement, 18698686cd2SShayne Chen * we need to make sure that flags match so polling GI 18798686cd2SShayne Chen * from per-sta counters directly. 18898686cd2SShayne Chen */ 18998686cd2SShayne Chen rate = &msta->wcid.rate; 19098686cd2SShayne Chen 19198686cd2SShayne Chen switch (rate->bw) { 19280f5a31dSShayne Chen case RATE_INFO_BW_320: 19380f5a31dSShayne Chen bw = IEEE80211_STA_RX_BW_320; 19480f5a31dSShayne Chen break; 19598686cd2SShayne Chen case RATE_INFO_BW_160: 19698686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_160; 19798686cd2SShayne Chen break; 19898686cd2SShayne Chen case RATE_INFO_BW_80: 19998686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_80; 20098686cd2SShayne Chen break; 20198686cd2SShayne Chen case RATE_INFO_BW_40: 20298686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_40; 20398686cd2SShayne Chen break; 20498686cd2SShayne Chen default: 20598686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_20; 20698686cd2SShayne Chen break; 20798686cd2SShayne Chen } 20898686cd2SShayne Chen 20998686cd2SShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 6); 21098686cd2SShayne Chen val = mt76_rr(dev, addr); 21180f5a31dSShayne Chen if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) { 21280f5a31dSShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 5); 21380f5a31dSShayne Chen val = mt76_rr(dev, addr); 21480f5a31dSShayne Chen rate->eht_gi = FIELD_GET(GENMASK(25, 24), val); 21580f5a31dSShayne Chen } else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { 21698686cd2SShayne Chen u8 offs = 24 + 2 * bw; 21798686cd2SShayne Chen 21898686cd2SShayne Chen rate->he_gi = (val & (0x3 << offs)) >> offs; 21998686cd2SShayne Chen } else if (rate->flags & 22098686cd2SShayne Chen (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) { 22198686cd2SShayne Chen if (val & BIT(12 + bw)) 22298686cd2SShayne Chen rate->flags |= RATE_INFO_FLAGS_SHORT_GI; 22398686cd2SShayne Chen else 22498686cd2SShayne Chen rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI; 22598686cd2SShayne Chen } 226ea5d99d0SRyder Lee 227ea5d99d0SRyder Lee /* get signal strength of resp frames (CTS/BA/ACK) */ 228ea5d99d0SRyder Lee addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34); 229ea5d99d0SRyder Lee val = mt76_rr(dev, addr); 230ea5d99d0SRyder Lee 231ea5d99d0SRyder Lee rssi[0] = to_rssi(GENMASK(7, 0), val); 232ea5d99d0SRyder Lee rssi[1] = to_rssi(GENMASK(15, 8), val); 233ea5d99d0SRyder Lee rssi[2] = to_rssi(GENMASK(23, 16), val); 234ea5d99d0SRyder Lee rssi[3] = to_rssi(GENMASK(31, 14), val); 235ea5d99d0SRyder Lee 236ea5d99d0SRyder Lee msta->ack_signal = 237ea5d99d0SRyder Lee mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); 238ea5d99d0SRyder Lee 239ea5d99d0SRyder Lee ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); 24098686cd2SShayne Chen } 24198686cd2SShayne Chen 24298686cd2SShayne Chen rcu_read_unlock(); 24398686cd2SShayne Chen } 24498686cd2SShayne Chen 245d75e739bSRyder Lee void mt7996_mac_enable_rtscts(struct mt7996_dev *dev, 246d75e739bSRyder Lee struct ieee80211_vif *vif, bool enable) 247d75e739bSRyder Lee { 248d75e739bSRyder Lee struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 249d75e739bSRyder Lee u32 addr; 250d75e739bSRyder Lee 251d75e739bSRyder Lee addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5); 252d75e739bSRyder Lee if (enable) 253d75e739bSRyder Lee mt76_set(dev, addr, BIT(5)); 254d75e739bSRyder Lee else 255d75e739bSRyder Lee mt76_clear(dev, addr, BIT(5)); 256d75e739bSRyder Lee } 257d75e739bSRyder Lee 25898686cd2SShayne Chen static void 25998686cd2SShayne Chen mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, 26098686cd2SShayne Chen struct ieee80211_radiotap_he *he, 26198686cd2SShayne Chen __le32 *rxv) 26298686cd2SShayne Chen { 263*63a37246SRyder Lee u32 ru, offs = 0; 26498686cd2SShayne Chen 265*63a37246SRyder Lee ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC); 26698686cd2SShayne Chen 26798686cd2SShayne Chen status->bw = RATE_INFO_BW_HE_RU; 26898686cd2SShayne Chen 26998686cd2SShayne Chen switch (ru) { 27098686cd2SShayne Chen case 0 ... 36: 27198686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; 27298686cd2SShayne Chen offs = ru; 27398686cd2SShayne Chen break; 27498686cd2SShayne Chen case 37 ... 52: 27598686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; 27698686cd2SShayne Chen offs = ru - 37; 27798686cd2SShayne Chen break; 27898686cd2SShayne Chen case 53 ... 60: 27998686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; 28098686cd2SShayne Chen offs = ru - 53; 28198686cd2SShayne Chen break; 28298686cd2SShayne Chen case 61 ... 64: 28398686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; 28498686cd2SShayne Chen offs = ru - 61; 28598686cd2SShayne Chen break; 28698686cd2SShayne Chen case 65 ... 66: 28798686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; 28898686cd2SShayne Chen offs = ru - 65; 28998686cd2SShayne Chen break; 29098686cd2SShayne Chen case 67: 29198686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; 29298686cd2SShayne Chen break; 29398686cd2SShayne Chen case 68: 29498686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; 29598686cd2SShayne Chen break; 29698686cd2SShayne Chen } 29798686cd2SShayne Chen 29898686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 29998686cd2SShayne Chen he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | 30098686cd2SShayne Chen le16_encode_bits(offs, 30198686cd2SShayne Chen IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); 30298686cd2SShayne Chen } 30398686cd2SShayne Chen 30498686cd2SShayne Chen static void 30598686cd2SShayne Chen mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) 30698686cd2SShayne Chen { 30798686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 30898686cd2SShayne Chen static const struct ieee80211_radiotap_he_mu mu_known = { 30998686cd2SShayne Chen .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | 31098686cd2SShayne Chen HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | 31198686cd2SShayne Chen HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | 31298686cd2SShayne Chen HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), 31398686cd2SShayne Chen .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), 31498686cd2SShayne Chen }; 31598686cd2SShayne Chen struct ieee80211_radiotap_he_mu *he_mu = NULL; 31698686cd2SShayne Chen 31798686cd2SShayne Chen status->flag |= RX_FLAG_RADIOTAP_HE_MU; 31898686cd2SShayne Chen 31998686cd2SShayne Chen he_mu = skb_push(skb, sizeof(mu_known)); 32098686cd2SShayne Chen memcpy(he_mu, &mu_known, sizeof(mu_known)); 32198686cd2SShayne Chen 32298686cd2SShayne Chen #define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) 32398686cd2SShayne Chen 32498686cd2SShayne Chen he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); 32598686cd2SShayne Chen if (status->he_dcm) 32698686cd2SShayne Chen he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); 32798686cd2SShayne Chen 32898686cd2SShayne Chen he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | 32998686cd2SShayne Chen MU_PREP(FLAGS2_SIG_B_SYMS_USERS, 330*63a37246SRyder Lee le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER)); 33198686cd2SShayne Chen 332*63a37246SRyder Lee he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff; 33398686cd2SShayne Chen 33498686cd2SShayne Chen if (status->bw >= RATE_INFO_BW_40) { 33598686cd2SShayne Chen he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); 336*63a37246SRyder Lee he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff; 33798686cd2SShayne Chen } 33898686cd2SShayne Chen 33998686cd2SShayne Chen if (status->bw >= RATE_INFO_BW_80) { 340*63a37246SRyder Lee u32 ru_h, ru_l; 341*63a37246SRyder Lee 342*63a37246SRyder Lee he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff; 343*63a37246SRyder Lee 344*63a37246SRyder Lee ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); 345*63a37246SRyder Lee ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; 346*63a37246SRyder Lee he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); 34798686cd2SShayne Chen } 34898686cd2SShayne Chen } 34998686cd2SShayne Chen 35098686cd2SShayne Chen static void 35198686cd2SShayne Chen mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode) 35298686cd2SShayne Chen { 35398686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 35498686cd2SShayne Chen static const struct ieee80211_radiotap_he known = { 35598686cd2SShayne Chen .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | 35698686cd2SShayne Chen HE_BITS(DATA1_DATA_DCM_KNOWN) | 35798686cd2SShayne Chen HE_BITS(DATA1_STBC_KNOWN) | 35898686cd2SShayne Chen HE_BITS(DATA1_CODING_KNOWN) | 35998686cd2SShayne Chen HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | 36098686cd2SShayne Chen HE_BITS(DATA1_DOPPLER_KNOWN) | 36198686cd2SShayne Chen HE_BITS(DATA1_SPTL_REUSE_KNOWN) | 36298686cd2SShayne Chen HE_BITS(DATA1_BSS_COLOR_KNOWN), 36398686cd2SShayne Chen .data2 = HE_BITS(DATA2_GI_KNOWN) | 36498686cd2SShayne Chen HE_BITS(DATA2_TXBF_KNOWN) | 36598686cd2SShayne Chen HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | 36698686cd2SShayne Chen HE_BITS(DATA2_TXOP_KNOWN), 36798686cd2SShayne Chen }; 36898686cd2SShayne Chen struct ieee80211_radiotap_he *he = NULL; 369*63a37246SRyder Lee u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; 37098686cd2SShayne Chen 37198686cd2SShayne Chen status->flag |= RX_FLAG_RADIOTAP_HE; 37298686cd2SShayne Chen 37398686cd2SShayne Chen he = skb_push(skb, sizeof(known)); 37498686cd2SShayne Chen memcpy(he, &known, sizeof(known)); 37598686cd2SShayne Chen 376*63a37246SRyder Lee he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | 377*63a37246SRyder Lee HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); 378*63a37246SRyder Lee he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); 379*63a37246SRyder Lee he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | 38098686cd2SShayne Chen le16_encode_bits(ltf_size, 38198686cd2SShayne Chen IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); 38298686cd2SShayne Chen if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) 38398686cd2SShayne Chen he->data5 |= HE_BITS(DATA5_TXBF); 384*63a37246SRyder Lee he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | 385*63a37246SRyder Lee HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); 38698686cd2SShayne Chen 38798686cd2SShayne Chen switch (mode) { 38898686cd2SShayne Chen case MT_PHY_TYPE_HE_SU: 38998686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_FORMAT_SU) | 39098686cd2SShayne Chen HE_BITS(DATA1_UL_DL_KNOWN) | 39198686cd2SShayne Chen HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | 39298686cd2SShayne Chen HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 39398686cd2SShayne Chen 394*63a37246SRyder Lee he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) | 395*63a37246SRyder Lee HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 39698686cd2SShayne Chen break; 39798686cd2SShayne Chen case MT_PHY_TYPE_HE_EXT_SU: 39898686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | 39998686cd2SShayne Chen HE_BITS(DATA1_UL_DL_KNOWN) | 40098686cd2SShayne Chen HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 40198686cd2SShayne Chen 402*63a37246SRyder Lee he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 40398686cd2SShayne Chen break; 40498686cd2SShayne Chen case MT_PHY_TYPE_HE_MU: 40598686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_FORMAT_MU) | 40698686cd2SShayne Chen HE_BITS(DATA1_UL_DL_KNOWN); 40798686cd2SShayne Chen 408*63a37246SRyder Lee he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 409*63a37246SRyder Lee he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); 41098686cd2SShayne Chen 41198686cd2SShayne Chen mt7996_mac_decode_he_radiotap_ru(status, he, rxv); 41298686cd2SShayne Chen mt7996_mac_decode_he_mu_radiotap(skb, rxv); 41398686cd2SShayne Chen break; 41498686cd2SShayne Chen case MT_PHY_TYPE_HE_TB: 41598686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | 41698686cd2SShayne Chen HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | 41798686cd2SShayne Chen HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | 41898686cd2SShayne Chen HE_BITS(DATA1_SPTL_REUSE4_KNOWN); 41998686cd2SShayne Chen 420*63a37246SRyder Lee he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) | 421*63a37246SRyder Lee HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) | 422*63a37246SRyder Lee HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) | 423*63a37246SRyder Lee HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]); 42498686cd2SShayne Chen 42598686cd2SShayne Chen mt7996_mac_decode_he_radiotap_ru(status, he, rxv); 42698686cd2SShayne Chen break; 42798686cd2SShayne Chen default: 42898686cd2SShayne Chen break; 42998686cd2SShayne Chen } 43098686cd2SShayne Chen } 43198686cd2SShayne Chen 43298686cd2SShayne Chen /* The HW does not translate the mac header to 802.3 for mesh point */ 43398686cd2SShayne Chen static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) 43498686cd2SShayne Chen { 43598686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 43698686cd2SShayne Chen struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap); 43798686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)status->wcid; 43898686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 43998686cd2SShayne Chen struct ieee80211_sta *sta; 44098686cd2SShayne Chen struct ieee80211_vif *vif; 44198686cd2SShayne Chen struct ieee80211_hdr hdr; 44298686cd2SShayne Chen u16 frame_control; 44398686cd2SShayne Chen 44498686cd2SShayne Chen if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) != 44598686cd2SShayne Chen MT_RXD3_NORMAL_U2M) 44698686cd2SShayne Chen return -EINVAL; 44798686cd2SShayne Chen 44898686cd2SShayne Chen if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4)) 44998686cd2SShayne Chen return -EINVAL; 45098686cd2SShayne Chen 45198686cd2SShayne Chen if (!msta || !msta->vif) 45298686cd2SShayne Chen return -EINVAL; 45398686cd2SShayne Chen 45498686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); 45598686cd2SShayne Chen vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); 45698686cd2SShayne Chen 45798686cd2SShayne Chen /* store the info from RXD and ethhdr to avoid being overridden */ 45898686cd2SShayne Chen frame_control = le32_get_bits(rxd[8], MT_RXD8_FRAME_CONTROL); 45998686cd2SShayne Chen hdr.frame_control = cpu_to_le16(frame_control); 46098686cd2SShayne Chen hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_SEQ_CTRL)); 46198686cd2SShayne Chen hdr.duration_id = 0; 46298686cd2SShayne Chen 46398686cd2SShayne Chen ether_addr_copy(hdr.addr1, vif->addr); 46498686cd2SShayne Chen ether_addr_copy(hdr.addr2, sta->addr); 46598686cd2SShayne Chen switch (frame_control & (IEEE80211_FCTL_TODS | 46698686cd2SShayne Chen IEEE80211_FCTL_FROMDS)) { 46798686cd2SShayne Chen case 0: 46898686cd2SShayne Chen ether_addr_copy(hdr.addr3, vif->bss_conf.bssid); 46998686cd2SShayne Chen break; 47098686cd2SShayne Chen case IEEE80211_FCTL_FROMDS: 47198686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_source); 47298686cd2SShayne Chen break; 47398686cd2SShayne Chen case IEEE80211_FCTL_TODS: 47498686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_dest); 47598686cd2SShayne Chen break; 47698686cd2SShayne Chen case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS: 47798686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_dest); 47898686cd2SShayne Chen ether_addr_copy(hdr.addr4, eth_hdr->h_source); 47998686cd2SShayne Chen break; 48098686cd2SShayne Chen default: 481aed8d9b5SLorenzo Bianconi return -EINVAL; 48298686cd2SShayne Chen } 48398686cd2SShayne Chen 48498686cd2SShayne Chen skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2); 48598686cd2SShayne Chen if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) || 48698686cd2SShayne Chen eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX)) 48798686cd2SShayne Chen ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header); 48898686cd2SShayne Chen else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN) 48998686cd2SShayne Chen ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header); 49098686cd2SShayne Chen else 49198686cd2SShayne Chen skb_pull(skb, 2); 49298686cd2SShayne Chen 49398686cd2SShayne Chen if (ieee80211_has_order(hdr.frame_control)) 49498686cd2SShayne Chen memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[11], 49598686cd2SShayne Chen IEEE80211_HT_CTL_LEN); 49698686cd2SShayne Chen if (ieee80211_is_data_qos(hdr.frame_control)) { 49798686cd2SShayne Chen __le16 qos_ctrl; 49898686cd2SShayne Chen 49998686cd2SShayne Chen qos_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_QOS_CTL)); 50098686cd2SShayne Chen memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl, 50198686cd2SShayne Chen IEEE80211_QOS_CTL_LEN); 50298686cd2SShayne Chen } 50398686cd2SShayne Chen 50498686cd2SShayne Chen if (ieee80211_has_a4(hdr.frame_control)) 50598686cd2SShayne Chen memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr)); 50698686cd2SShayne Chen else 50798686cd2SShayne Chen memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6); 50898686cd2SShayne Chen 50998686cd2SShayne Chen return 0; 51098686cd2SShayne Chen } 51198686cd2SShayne Chen 51298686cd2SShayne Chen static int 51398686cd2SShayne Chen mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, 51498686cd2SShayne Chen struct mt76_rx_status *status, 51598686cd2SShayne Chen struct ieee80211_supported_band *sband, 51698686cd2SShayne Chen __le32 *rxv, u8 *mode) 51798686cd2SShayne Chen { 51898686cd2SShayne Chen u32 v0, v2; 51998686cd2SShayne Chen u8 stbc, gi, bw, dcm, nss; 52098686cd2SShayne Chen int i, idx; 52198686cd2SShayne Chen bool cck = false; 52298686cd2SShayne Chen 52398686cd2SShayne Chen v0 = le32_to_cpu(rxv[0]); 52498686cd2SShayne Chen v2 = le32_to_cpu(rxv[2]); 52598686cd2SShayne Chen 52698686cd2SShayne Chen idx = FIELD_GET(MT_PRXV_TX_RATE, v0); 52798686cd2SShayne Chen i = idx; 52898686cd2SShayne Chen nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1; 52998686cd2SShayne Chen 53098686cd2SShayne Chen stbc = FIELD_GET(MT_PRXV_HT_STBC, v2); 53198686cd2SShayne Chen gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2); 53298686cd2SShayne Chen *mode = FIELD_GET(MT_PRXV_TX_MODE, v2); 53398686cd2SShayne Chen dcm = FIELD_GET(MT_PRXV_DCM, v2); 53498686cd2SShayne Chen bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2); 53598686cd2SShayne Chen 53698686cd2SShayne Chen switch (*mode) { 53798686cd2SShayne Chen case MT_PHY_TYPE_CCK: 53898686cd2SShayne Chen cck = true; 53998686cd2SShayne Chen fallthrough; 54098686cd2SShayne Chen case MT_PHY_TYPE_OFDM: 54198686cd2SShayne Chen i = mt76_get_rate(&dev->mt76, sband, i, cck); 54298686cd2SShayne Chen break; 54398686cd2SShayne Chen case MT_PHY_TYPE_HT_GF: 54498686cd2SShayne Chen case MT_PHY_TYPE_HT: 54598686cd2SShayne Chen status->encoding = RX_ENC_HT; 54698686cd2SShayne Chen if (gi) 54798686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 54898686cd2SShayne Chen if (i > 31) 54998686cd2SShayne Chen return -EINVAL; 55098686cd2SShayne Chen break; 55198686cd2SShayne Chen case MT_PHY_TYPE_VHT: 55298686cd2SShayne Chen status->nss = nss; 55398686cd2SShayne Chen status->encoding = RX_ENC_VHT; 55498686cd2SShayne Chen if (gi) 55598686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 55698686cd2SShayne Chen if (i > 11) 55798686cd2SShayne Chen return -EINVAL; 55898686cd2SShayne Chen break; 55998686cd2SShayne Chen case MT_PHY_TYPE_HE_MU: 56098686cd2SShayne Chen case MT_PHY_TYPE_HE_SU: 56198686cd2SShayne Chen case MT_PHY_TYPE_HE_EXT_SU: 56298686cd2SShayne Chen case MT_PHY_TYPE_HE_TB: 56398686cd2SShayne Chen status->nss = nss; 56498686cd2SShayne Chen status->encoding = RX_ENC_HE; 56598686cd2SShayne Chen i &= GENMASK(3, 0); 56698686cd2SShayne Chen 56798686cd2SShayne Chen if (gi <= NL80211_RATE_INFO_HE_GI_3_2) 56898686cd2SShayne Chen status->he_gi = gi; 56998686cd2SShayne Chen 57098686cd2SShayne Chen status->he_dcm = dcm; 57198686cd2SShayne Chen break; 57280f5a31dSShayne Chen case MT_PHY_TYPE_EHT_SU: 57380f5a31dSShayne Chen case MT_PHY_TYPE_EHT_TRIG: 57480f5a31dSShayne Chen case MT_PHY_TYPE_EHT_MU: 57580f5a31dSShayne Chen /* TODO: currently report rx rate with HE rate */ 57680f5a31dSShayne Chen status->nss = nss; 57780f5a31dSShayne Chen status->encoding = RX_ENC_HE; 57880f5a31dSShayne Chen bw = min_t(int, bw, IEEE80211_STA_RX_BW_160); 57980f5a31dSShayne Chen i = min_t(int, i & 0xf, 11); 58080f5a31dSShayne Chen break; 58198686cd2SShayne Chen default: 58298686cd2SShayne Chen return -EINVAL; 58398686cd2SShayne Chen } 58498686cd2SShayne Chen status->rate_idx = i; 58598686cd2SShayne Chen 58698686cd2SShayne Chen switch (bw) { 58798686cd2SShayne Chen case IEEE80211_STA_RX_BW_20: 58898686cd2SShayne Chen break; 58998686cd2SShayne Chen case IEEE80211_STA_RX_BW_40: 59098686cd2SShayne Chen if (*mode & MT_PHY_TYPE_HE_EXT_SU && 59198686cd2SShayne Chen (idx & MT_PRXV_TX_ER_SU_106T)) { 59298686cd2SShayne Chen status->bw = RATE_INFO_BW_HE_RU; 59398686cd2SShayne Chen status->he_ru = 59498686cd2SShayne Chen NL80211_RATE_INFO_HE_RU_ALLOC_106; 59598686cd2SShayne Chen } else { 59698686cd2SShayne Chen status->bw = RATE_INFO_BW_40; 59798686cd2SShayne Chen } 59898686cd2SShayne Chen break; 59998686cd2SShayne Chen case IEEE80211_STA_RX_BW_80: 60098686cd2SShayne Chen status->bw = RATE_INFO_BW_80; 60198686cd2SShayne Chen break; 60298686cd2SShayne Chen case IEEE80211_STA_RX_BW_160: 60398686cd2SShayne Chen status->bw = RATE_INFO_BW_160; 60498686cd2SShayne Chen break; 60580f5a31dSShayne Chen case IEEE80211_STA_RX_BW_320: 60680f5a31dSShayne Chen status->bw = RATE_INFO_BW_320; 60780f5a31dSShayne Chen break; 60898686cd2SShayne Chen default: 60998686cd2SShayne Chen return -EINVAL; 61098686cd2SShayne Chen } 61198686cd2SShayne Chen 61298686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; 61398686cd2SShayne Chen if (*mode < MT_PHY_TYPE_HE_SU && gi) 61498686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 61598686cd2SShayne Chen 61698686cd2SShayne Chen return 0; 61798686cd2SShayne Chen } 61898686cd2SShayne Chen 61998686cd2SShayne Chen static int 62098686cd2SShayne Chen mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) 62198686cd2SShayne Chen { 62298686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 62398686cd2SShayne Chen struct mt76_phy *mphy = &dev->mt76.phy; 62498686cd2SShayne Chen struct mt7996_phy *phy = &dev->phy; 62598686cd2SShayne Chen struct ieee80211_supported_band *sband; 62698686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 62798686cd2SShayne Chen __le32 *rxv = NULL; 62898686cd2SShayne Chen u32 rxd0 = le32_to_cpu(rxd[0]); 62998686cd2SShayne Chen u32 rxd1 = le32_to_cpu(rxd[1]); 63098686cd2SShayne Chen u32 rxd2 = le32_to_cpu(rxd[2]); 63198686cd2SShayne Chen u32 rxd3 = le32_to_cpu(rxd[3]); 63298686cd2SShayne Chen u32 rxd4 = le32_to_cpu(rxd[4]); 63398686cd2SShayne Chen u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; 63498686cd2SShayne Chen u32 csum_status = *(u32 *)skb->cb; 63598686cd2SShayne Chen bool unicast, insert_ccmp_hdr = false; 63698686cd2SShayne Chen u8 remove_pad, amsdu_info, band_idx; 63798686cd2SShayne Chen u8 mode = 0, qos_ctl = 0; 63898686cd2SShayne Chen bool hdr_trans; 63998686cd2SShayne Chen u16 hdr_gap; 64098686cd2SShayne Chen u16 seq_ctrl = 0; 64198686cd2SShayne Chen __le16 fc = 0; 64298686cd2SShayne Chen int idx; 64398686cd2SShayne Chen 64498686cd2SShayne Chen memset(status, 0, sizeof(*status)); 64598686cd2SShayne Chen 64698686cd2SShayne Chen band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1); 64798686cd2SShayne Chen mphy = dev->mt76.phys[band_idx]; 64898686cd2SShayne Chen phy = mphy->priv; 64998686cd2SShayne Chen status->phy_idx = mphy->band_idx; 65098686cd2SShayne Chen 65198686cd2SShayne Chen if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) 65298686cd2SShayne Chen return -EINVAL; 65398686cd2SShayne Chen 65498686cd2SShayne Chen if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) 65598686cd2SShayne Chen return -EINVAL; 65698686cd2SShayne Chen 65798686cd2SShayne Chen hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; 65898686cd2SShayne Chen if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) 65998686cd2SShayne Chen return -EINVAL; 66098686cd2SShayne Chen 66198686cd2SShayne Chen /* ICV error or CCMP/BIP/WPI MIC error */ 66298686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) 66398686cd2SShayne Chen status->flag |= RX_FLAG_ONLY_MONITOR; 66498686cd2SShayne Chen 66598686cd2SShayne Chen unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; 66698686cd2SShayne Chen idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); 66798686cd2SShayne Chen status->wcid = mt7996_rx_get_wcid(dev, idx, unicast); 66898686cd2SShayne Chen 66998686cd2SShayne Chen if (status->wcid) { 67098686cd2SShayne Chen struct mt7996_sta *msta; 67198686cd2SShayne Chen 67298686cd2SShayne Chen msta = container_of(status->wcid, struct mt7996_sta, wcid); 67398686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 67498686cd2SShayne Chen if (list_empty(&msta->poll_list)) 67598686cd2SShayne Chen list_add_tail(&msta->poll_list, &dev->sta_poll_list); 67698686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 67798686cd2SShayne Chen } 67898686cd2SShayne Chen 67998686cd2SShayne Chen status->freq = mphy->chandef.chan->center_freq; 68098686cd2SShayne Chen status->band = mphy->chandef.chan->band; 68198686cd2SShayne Chen if (status->band == NL80211_BAND_5GHZ) 68298686cd2SShayne Chen sband = &mphy->sband_5g.sband; 68398686cd2SShayne Chen else if (status->band == NL80211_BAND_6GHZ) 68498686cd2SShayne Chen sband = &mphy->sband_6g.sband; 68598686cd2SShayne Chen else 68698686cd2SShayne Chen sband = &mphy->sband_2g.sband; 68798686cd2SShayne Chen 68898686cd2SShayne Chen if (!sband->channels) 68998686cd2SShayne Chen return -EINVAL; 69098686cd2SShayne Chen 69198686cd2SShayne Chen if ((rxd0 & csum_mask) == csum_mask && 69298686cd2SShayne Chen !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) 69398686cd2SShayne Chen skb->ip_summed = CHECKSUM_UNNECESSARY; 69498686cd2SShayne Chen 69598686cd2SShayne Chen if (rxd1 & MT_RXD3_NORMAL_FCS_ERR) 69698686cd2SShayne Chen status->flag |= RX_FLAG_FAILED_FCS_CRC; 69798686cd2SShayne Chen 69898686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) 69998686cd2SShayne Chen status->flag |= RX_FLAG_MMIC_ERROR; 70098686cd2SShayne Chen 70198686cd2SShayne Chen if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && 70298686cd2SShayne Chen !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) { 70398686cd2SShayne Chen status->flag |= RX_FLAG_DECRYPTED; 70498686cd2SShayne Chen status->flag |= RX_FLAG_IV_STRIPPED; 70598686cd2SShayne Chen status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; 70698686cd2SShayne Chen } 70798686cd2SShayne Chen 70898686cd2SShayne Chen remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); 70998686cd2SShayne Chen 71098686cd2SShayne Chen if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) 71198686cd2SShayne Chen return -EINVAL; 71298686cd2SShayne Chen 71398686cd2SShayne Chen rxd += 8; 71498686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { 71598686cd2SShayne Chen u32 v0 = le32_to_cpu(rxd[0]); 71698686cd2SShayne Chen u32 v2 = le32_to_cpu(rxd[2]); 71798686cd2SShayne Chen 71898686cd2SShayne Chen fc = cpu_to_le16(FIELD_GET(MT_RXD8_FRAME_CONTROL, v0)); 71998686cd2SShayne Chen qos_ctl = FIELD_GET(MT_RXD10_QOS_CTL, v2); 72098686cd2SShayne Chen seq_ctrl = FIELD_GET(MT_RXD10_SEQ_CTRL, v2); 72198686cd2SShayne Chen 72298686cd2SShayne Chen rxd += 4; 72398686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 72498686cd2SShayne Chen return -EINVAL; 72598686cd2SShayne Chen } 72698686cd2SShayne Chen 72798686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_1) { 72898686cd2SShayne Chen u8 *data = (u8 *)rxd; 72998686cd2SShayne Chen 73098686cd2SShayne Chen if (status->flag & RX_FLAG_DECRYPTED) { 73198686cd2SShayne Chen switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) { 73298686cd2SShayne Chen case MT_CIPHER_AES_CCMP: 73398686cd2SShayne Chen case MT_CIPHER_CCMP_CCX: 73498686cd2SShayne Chen case MT_CIPHER_CCMP_256: 73598686cd2SShayne Chen insert_ccmp_hdr = 73698686cd2SShayne Chen FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); 73798686cd2SShayne Chen fallthrough; 73898686cd2SShayne Chen case MT_CIPHER_TKIP: 73998686cd2SShayne Chen case MT_CIPHER_TKIP_NO_MIC: 74098686cd2SShayne Chen case MT_CIPHER_GCMP: 74198686cd2SShayne Chen case MT_CIPHER_GCMP_256: 74298686cd2SShayne Chen status->iv[0] = data[5]; 74398686cd2SShayne Chen status->iv[1] = data[4]; 74498686cd2SShayne Chen status->iv[2] = data[3]; 74598686cd2SShayne Chen status->iv[3] = data[2]; 74698686cd2SShayne Chen status->iv[4] = data[1]; 74798686cd2SShayne Chen status->iv[5] = data[0]; 74898686cd2SShayne Chen break; 74998686cd2SShayne Chen default: 75098686cd2SShayne Chen break; 75198686cd2SShayne Chen } 75298686cd2SShayne Chen } 75398686cd2SShayne Chen rxd += 4; 75498686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 75598686cd2SShayne Chen return -EINVAL; 75698686cd2SShayne Chen } 75798686cd2SShayne Chen 75898686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { 75998686cd2SShayne Chen status->timestamp = le32_to_cpu(rxd[0]); 76098686cd2SShayne Chen status->flag |= RX_FLAG_MACTIME_START; 76198686cd2SShayne Chen 76298686cd2SShayne Chen if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { 76398686cd2SShayne Chen status->flag |= RX_FLAG_AMPDU_DETAILS; 76498686cd2SShayne Chen 76598686cd2SShayne Chen /* all subframes of an A-MPDU have the same timestamp */ 76698686cd2SShayne Chen if (phy->rx_ampdu_ts != status->timestamp) { 76798686cd2SShayne Chen if (!++phy->ampdu_ref) 76898686cd2SShayne Chen phy->ampdu_ref++; 76998686cd2SShayne Chen } 77098686cd2SShayne Chen phy->rx_ampdu_ts = status->timestamp; 77198686cd2SShayne Chen 77298686cd2SShayne Chen status->ampdu_ref = phy->ampdu_ref; 77398686cd2SShayne Chen } 77498686cd2SShayne Chen 77598686cd2SShayne Chen rxd += 4; 77698686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 77798686cd2SShayne Chen return -EINVAL; 77898686cd2SShayne Chen } 77998686cd2SShayne Chen 78098686cd2SShayne Chen /* RXD Group 3 - P-RXV */ 78198686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { 78298686cd2SShayne Chen u32 v3; 78398686cd2SShayne Chen int ret; 78498686cd2SShayne Chen 78598686cd2SShayne Chen rxv = rxd; 78698686cd2SShayne Chen rxd += 4; 78798686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 78898686cd2SShayne Chen return -EINVAL; 78998686cd2SShayne Chen 79098686cd2SShayne Chen v3 = le32_to_cpu(rxv[3]); 79198686cd2SShayne Chen 79298686cd2SShayne Chen status->chains = mphy->antenna_mask; 79398686cd2SShayne Chen status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v3); 79498686cd2SShayne Chen status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v3); 79598686cd2SShayne Chen status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v3); 79698686cd2SShayne Chen status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v3); 79798686cd2SShayne Chen 79898686cd2SShayne Chen /* RXD Group 5 - C-RXV */ 79998686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { 80098686cd2SShayne Chen rxd += 24; 80198686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 80298686cd2SShayne Chen return -EINVAL; 80398686cd2SShayne Chen } 80498686cd2SShayne Chen 80598686cd2SShayne Chen ret = mt7996_mac_fill_rx_rate(dev, status, sband, rxv, &mode); 80698686cd2SShayne Chen if (ret < 0) 80798686cd2SShayne Chen return ret; 80898686cd2SShayne Chen } 80998686cd2SShayne Chen 81098686cd2SShayne Chen amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); 81198686cd2SShayne Chen status->amsdu = !!amsdu_info; 81298686cd2SShayne Chen if (status->amsdu) { 81398686cd2SShayne Chen status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; 81498686cd2SShayne Chen status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; 81598686cd2SShayne Chen } 81698686cd2SShayne Chen 81798686cd2SShayne Chen hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; 81898686cd2SShayne Chen if (hdr_trans && ieee80211_has_morefrags(fc)) { 81998686cd2SShayne Chen if (mt7996_reverse_frag0_hdr_trans(skb, hdr_gap)) 82098686cd2SShayne Chen return -EINVAL; 82198686cd2SShayne Chen hdr_trans = false; 82298686cd2SShayne Chen } else { 82398686cd2SShayne Chen int pad_start = 0; 82498686cd2SShayne Chen 82598686cd2SShayne Chen skb_pull(skb, hdr_gap); 82698686cd2SShayne Chen if (!hdr_trans && status->amsdu) { 82798686cd2SShayne Chen pad_start = ieee80211_get_hdrlen_from_skb(skb); 82898686cd2SShayne Chen } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { 82998686cd2SShayne Chen /* When header translation failure is indicated, 83098686cd2SShayne Chen * the hardware will insert an extra 2-byte field 83198686cd2SShayne Chen * containing the data length after the protocol 83298686cd2SShayne Chen * type field. 83398686cd2SShayne Chen */ 83498686cd2SShayne Chen pad_start = 12; 83598686cd2SShayne Chen if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) 83698686cd2SShayne Chen pad_start += 4; 83798686cd2SShayne Chen else 83898686cd2SShayne Chen pad_start = 0; 83998686cd2SShayne Chen } 84098686cd2SShayne Chen 84198686cd2SShayne Chen if (pad_start) { 84298686cd2SShayne Chen memmove(skb->data + 2, skb->data, pad_start); 84398686cd2SShayne Chen skb_pull(skb, 2); 84498686cd2SShayne Chen } 84598686cd2SShayne Chen } 84698686cd2SShayne Chen 84798686cd2SShayne Chen if (!hdr_trans) { 84898686cd2SShayne Chen struct ieee80211_hdr *hdr; 84998686cd2SShayne Chen 85098686cd2SShayne Chen if (insert_ccmp_hdr) { 85198686cd2SShayne Chen u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); 85298686cd2SShayne Chen 85398686cd2SShayne Chen mt76_insert_ccmp_hdr(skb, key_id); 85498686cd2SShayne Chen } 85598686cd2SShayne Chen 85698686cd2SShayne Chen hdr = mt76_skb_get_hdr(skb); 85798686cd2SShayne Chen fc = hdr->frame_control; 85898686cd2SShayne Chen if (ieee80211_is_data_qos(fc)) { 85998686cd2SShayne Chen seq_ctrl = le16_to_cpu(hdr->seq_ctrl); 86098686cd2SShayne Chen qos_ctl = *ieee80211_get_qos_ctl(hdr); 86198686cd2SShayne Chen } 86298686cd2SShayne Chen } else { 86398686cd2SShayne Chen status->flag |= RX_FLAG_8023; 86498686cd2SShayne Chen } 86598686cd2SShayne Chen 86698686cd2SShayne Chen if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) 86798686cd2SShayne Chen mt7996_mac_decode_he_radiotap(skb, rxv, mode); 86898686cd2SShayne Chen 86998686cd2SShayne Chen if (!status->wcid || !ieee80211_is_data_qos(fc)) 87098686cd2SShayne Chen return 0; 87198686cd2SShayne Chen 87298686cd2SShayne Chen status->aggr = unicast && 87398686cd2SShayne Chen !ieee80211_is_qos_nullfunc(fc); 87498686cd2SShayne Chen status->qos_ctl = qos_ctl; 87598686cd2SShayne Chen status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); 87698686cd2SShayne Chen 87798686cd2SShayne Chen return 0; 87898686cd2SShayne Chen } 87998686cd2SShayne Chen 88098686cd2SShayne Chen static void 88198686cd2SShayne Chen mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi, 88298686cd2SShayne Chen struct sk_buff *skb, struct mt76_wcid *wcid) 88398686cd2SShayne Chen { 88498686cd2SShayne Chen u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 88598686cd2SShayne Chen u8 fc_type, fc_stype; 88698686cd2SShayne Chen u16 ethertype; 88798686cd2SShayne Chen bool wmm = false; 88898686cd2SShayne Chen u32 val; 88998686cd2SShayne Chen 89098686cd2SShayne Chen if (wcid->sta) { 89198686cd2SShayne Chen struct ieee80211_sta *sta; 89298686cd2SShayne Chen 89398686cd2SShayne Chen sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); 89498686cd2SShayne Chen wmm = sta->wme; 89598686cd2SShayne Chen } 89698686cd2SShayne Chen 89798686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | 89898686cd2SShayne Chen FIELD_PREP(MT_TXD1_TID, tid); 89998686cd2SShayne Chen 90098686cd2SShayne Chen ethertype = get_unaligned_be16(&skb->data[12]); 90198686cd2SShayne Chen if (ethertype >= ETH_P_802_3_MIN) 90298686cd2SShayne Chen val |= MT_TXD1_ETH_802_3; 90398686cd2SShayne Chen 90498686cd2SShayne Chen txwi[1] |= cpu_to_le32(val); 90598686cd2SShayne Chen 90698686cd2SShayne Chen fc_type = IEEE80211_FTYPE_DATA >> 2; 90798686cd2SShayne Chen fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; 90898686cd2SShayne Chen 90998686cd2SShayne Chen val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | 91098686cd2SShayne Chen FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); 91198686cd2SShayne Chen 91298686cd2SShayne Chen txwi[2] |= cpu_to_le32(val); 91398686cd2SShayne Chen } 91498686cd2SShayne Chen 91598686cd2SShayne Chen static void 91698686cd2SShayne Chen mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, 91798686cd2SShayne Chen struct sk_buff *skb, struct ieee80211_key_conf *key) 91898686cd2SShayne Chen { 91998686cd2SShayne Chen struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 92098686cd2SShayne Chen struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 92198686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 92298686cd2SShayne Chen bool multicast = is_multicast_ether_addr(hdr->addr1); 92398686cd2SShayne Chen u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 92498686cd2SShayne Chen __le16 fc = hdr->frame_control; 92598686cd2SShayne Chen u8 fc_type, fc_stype; 92698686cd2SShayne Chen u32 val; 92798686cd2SShayne Chen 92898686cd2SShayne Chen if (ieee80211_is_action(fc) && 92998686cd2SShayne Chen mgmt->u.action.category == WLAN_CATEGORY_BACK && 93098686cd2SShayne Chen mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) 93198686cd2SShayne Chen tid = MT_TX_ADDBA; 93298686cd2SShayne Chen else if (ieee80211_is_mgmt(hdr->frame_control)) 93398686cd2SShayne Chen tid = MT_TX_NORMAL; 93498686cd2SShayne Chen 93598686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | 93698686cd2SShayne Chen FIELD_PREP(MT_TXD1_HDR_INFO, 93798686cd2SShayne Chen ieee80211_get_hdrlen_from_skb(skb) / 2) | 93898686cd2SShayne Chen FIELD_PREP(MT_TXD1_TID, tid); 93998686cd2SShayne Chen 94098686cd2SShayne Chen if (!ieee80211_is_data(fc) || multicast || 94198686cd2SShayne Chen info->flags & IEEE80211_TX_CTL_USE_MINRATE) 94298686cd2SShayne Chen val |= MT_TXD1_FIXED_RATE; 94398686cd2SShayne Chen 94498686cd2SShayne Chen if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && 94598686cd2SShayne Chen key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { 94698686cd2SShayne Chen val |= MT_TXD1_BIP; 94798686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); 94898686cd2SShayne Chen } 94998686cd2SShayne Chen 95098686cd2SShayne Chen txwi[1] |= cpu_to_le32(val); 95198686cd2SShayne Chen 95298686cd2SShayne Chen fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; 95398686cd2SShayne Chen fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; 95498686cd2SShayne Chen 95598686cd2SShayne Chen val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | 95698686cd2SShayne Chen FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); 95798686cd2SShayne Chen 95898686cd2SShayne Chen txwi[2] |= cpu_to_le32(val); 95998686cd2SShayne Chen 96098686cd2SShayne Chen txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast)); 96198686cd2SShayne Chen if (ieee80211_is_beacon(fc)) { 96298686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); 96398686cd2SShayne Chen txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); 96498686cd2SShayne Chen } 96598686cd2SShayne Chen 96698686cd2SShayne Chen if (info->flags & IEEE80211_TX_CTL_INJECTED) { 96798686cd2SShayne Chen u16 seqno = le16_to_cpu(hdr->seq_ctrl); 96898686cd2SShayne Chen 96998686cd2SShayne Chen if (ieee80211_is_back_req(hdr->frame_control)) { 97098686cd2SShayne Chen struct ieee80211_bar *bar; 97198686cd2SShayne Chen 97298686cd2SShayne Chen bar = (struct ieee80211_bar *)skb->data; 97398686cd2SShayne Chen seqno = le16_to_cpu(bar->start_seq_num); 97498686cd2SShayne Chen } 97598686cd2SShayne Chen 97698686cd2SShayne Chen val = MT_TXD3_SN_VALID | 97798686cd2SShayne Chen FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); 97898686cd2SShayne Chen txwi[3] |= cpu_to_le32(val); 97998686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU); 98098686cd2SShayne Chen } 98198686cd2SShayne Chen } 98298686cd2SShayne Chen 98398686cd2SShayne Chen void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, 98498686cd2SShayne Chen struct sk_buff *skb, struct mt76_wcid *wcid, int pid, 98598686cd2SShayne Chen struct ieee80211_key_conf *key, u32 changed) 98698686cd2SShayne Chen { 98798686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 98898686cd2SShayne Chen struct ieee80211_vif *vif = info->control.vif; 98998686cd2SShayne Chen struct mt76_phy *mphy = &dev->mphy; 99098686cd2SShayne Chen u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; 99198686cd2SShayne Chen u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; 99298686cd2SShayne Chen bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; 99398686cd2SShayne Chen u16 tx_count = 15; 99498686cd2SShayne Chen u32 val; 99598686cd2SShayne Chen bool beacon = !!(changed & (BSS_CHANGED_BEACON | 99698686cd2SShayne Chen BSS_CHANGED_BEACON_ENABLED)); 99798686cd2SShayne Chen bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | 99898686cd2SShayne Chen BSS_CHANGED_FILS_DISCOVERY)); 99998686cd2SShayne Chen 100098686cd2SShayne Chen if (vif) { 100198686cd2SShayne Chen struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 100298686cd2SShayne Chen 100398686cd2SShayne Chen omac_idx = mvif->mt76.omac_idx; 100498686cd2SShayne Chen wmm_idx = mvif->mt76.wmm_idx; 100598686cd2SShayne Chen band_idx = mvif->mt76.band_idx; 100698686cd2SShayne Chen } 100798686cd2SShayne Chen 100898686cd2SShayne Chen mphy = mt76_dev_phy(&dev->mt76, band_idx); 100998686cd2SShayne Chen 101098686cd2SShayne Chen if (inband_disc) { 101198686cd2SShayne Chen p_fmt = MT_TX_TYPE_FW; 101298686cd2SShayne Chen q_idx = MT_LMAC_ALTX0; 101398686cd2SShayne Chen } else if (beacon) { 101498686cd2SShayne Chen p_fmt = MT_TX_TYPE_FW; 101598686cd2SShayne Chen q_idx = MT_LMAC_BCN0; 101698686cd2SShayne Chen } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) { 101798686cd2SShayne Chen p_fmt = MT_TX_TYPE_CT; 101898686cd2SShayne Chen q_idx = MT_LMAC_ALTX0; 101998686cd2SShayne Chen } else { 102098686cd2SShayne Chen p_fmt = MT_TX_TYPE_CT; 102198686cd2SShayne Chen q_idx = wmm_idx * MT7996_MAX_WMM_SETS + 102298686cd2SShayne Chen mt76_connac_lmac_mapping(skb_get_queue_mapping(skb)); 102398686cd2SShayne Chen } 102498686cd2SShayne Chen 102598686cd2SShayne Chen val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | 102698686cd2SShayne Chen FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | 102798686cd2SShayne Chen FIELD_PREP(MT_TXD0_Q_IDX, q_idx); 102898686cd2SShayne Chen txwi[0] = cpu_to_le32(val); 102998686cd2SShayne Chen 103098686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | 103198686cd2SShayne Chen FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); 103298686cd2SShayne Chen 103398686cd2SShayne Chen if (band_idx) 103498686cd2SShayne Chen val |= FIELD_PREP(MT_TXD1_TGID, band_idx); 103598686cd2SShayne Chen 103698686cd2SShayne Chen txwi[1] = cpu_to_le32(val); 103798686cd2SShayne Chen txwi[2] = 0; 103898686cd2SShayne Chen 103998686cd2SShayne Chen val = MT_TXD3_SW_POWER_MGMT | 104098686cd2SShayne Chen FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); 104198686cd2SShayne Chen if (key) 104298686cd2SShayne Chen val |= MT_TXD3_PROTECT_FRAME; 104398686cd2SShayne Chen if (info->flags & IEEE80211_TX_CTL_NO_ACK) 104498686cd2SShayne Chen val |= MT_TXD3_NO_ACK; 104598686cd2SShayne Chen if (wcid->amsdu) 104698686cd2SShayne Chen val |= MT_TXD3_HW_AMSDU; 104798686cd2SShayne Chen 104898686cd2SShayne Chen txwi[3] = cpu_to_le32(val); 104998686cd2SShayne Chen txwi[4] = 0; 105098686cd2SShayne Chen 105198686cd2SShayne Chen val = FIELD_PREP(MT_TXD5_PID, pid); 105298686cd2SShayne Chen if (pid >= MT_PACKET_ID_FIRST) 105398686cd2SShayne Chen val |= MT_TXD5_TX_STATUS_HOST; 105498686cd2SShayne Chen txwi[5] = cpu_to_le32(val); 105598686cd2SShayne Chen 105698686cd2SShayne Chen val = MT_TXD6_DIS_MAT | MT_TXD6_DAS | 105798686cd2SShayne Chen FIELD_PREP(MT_TXD6_MSDU_CNT, 1); 105898686cd2SShayne Chen txwi[6] = cpu_to_le32(val); 105998686cd2SShayne Chen txwi[7] = 0; 106098686cd2SShayne Chen 106198686cd2SShayne Chen if (is_8023) 106298686cd2SShayne Chen mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid); 106398686cd2SShayne Chen else 106498686cd2SShayne Chen mt7996_mac_write_txwi_80211(dev, txwi, skb, key); 106598686cd2SShayne Chen 106698686cd2SShayne Chen if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) { 106798686cd2SShayne Chen /* Fixed rata is available just for 802.11 txd */ 106898686cd2SShayne Chen struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 106998686cd2SShayne Chen bool multicast = is_multicast_ether_addr(hdr->addr1); 10700b8e2d69SLorenzo Bianconi u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, 10710b8e2d69SLorenzo Bianconi multicast); 107298686cd2SShayne Chen 107398686cd2SShayne Chen /* fix to bw 20 */ 107498686cd2SShayne Chen val = MT_TXD6_FIXED_BW | 107598686cd2SShayne Chen FIELD_PREP(MT_TXD6_BW, 0) | 107698686cd2SShayne Chen FIELD_PREP(MT_TXD6_TX_RATE, rate); 107798686cd2SShayne Chen 107898686cd2SShayne Chen txwi[6] |= cpu_to_le32(val); 107998686cd2SShayne Chen txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); 108098686cd2SShayne Chen } 108198686cd2SShayne Chen } 108298686cd2SShayne Chen 108398686cd2SShayne Chen int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 108498686cd2SShayne Chen enum mt76_txq_id qid, struct mt76_wcid *wcid, 108598686cd2SShayne Chen struct ieee80211_sta *sta, 108698686cd2SShayne Chen struct mt76_tx_info *tx_info) 108798686cd2SShayne Chen { 108898686cd2SShayne Chen struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; 108998686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 109098686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); 109198686cd2SShayne Chen struct ieee80211_key_conf *key = info->control.hw_key; 109298686cd2SShayne Chen struct ieee80211_vif *vif = info->control.vif; 10933c38dfc1SLorenzo Bianconi struct mt76_connac_txp_common *txp; 109498686cd2SShayne Chen struct mt76_txwi_cache *t; 109598686cd2SShayne Chen int id, i, pid, nbuf = tx_info->nbuf - 1; 109698686cd2SShayne Chen bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; 109798686cd2SShayne Chen u8 *txwi = (u8 *)txwi_ptr; 109898686cd2SShayne Chen 109998686cd2SShayne Chen if (unlikely(tx_info->skb->len <= ETH_HLEN)) 110098686cd2SShayne Chen return -EINVAL; 110198686cd2SShayne Chen 110298686cd2SShayne Chen if (!wcid) 110398686cd2SShayne Chen wcid = &dev->mt76.global_wcid; 110498686cd2SShayne Chen 110598686cd2SShayne Chen if (sta) { 110698686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 110798686cd2SShayne Chen 110898686cd2SShayne Chen if (time_after(jiffies, msta->jiffies + HZ / 4)) { 110998686cd2SShayne Chen info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 111098686cd2SShayne Chen msta->jiffies = jiffies; 111198686cd2SShayne Chen } 111298686cd2SShayne Chen } 111398686cd2SShayne Chen 111498686cd2SShayne Chen t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); 111598686cd2SShayne Chen t->skb = tx_info->skb; 111698686cd2SShayne Chen 111798686cd2SShayne Chen id = mt76_token_consume(mdev, &t); 111898686cd2SShayne Chen if (id < 0) 111998686cd2SShayne Chen return id; 112098686cd2SShayne Chen 112198686cd2SShayne Chen pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); 112298686cd2SShayne Chen memset(txwi_ptr, 0, MT_TXD_SIZE); 112398686cd2SShayne Chen /* Transmit non qos data by 802.11 header and need to fill txd by host*/ 112498686cd2SShayne Chen if (!is_8023 || pid >= MT_PACKET_ID_FIRST) 112598686cd2SShayne Chen mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, 112698686cd2SShayne Chen key, 0); 112798686cd2SShayne Chen 11283c38dfc1SLorenzo Bianconi txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE); 112998686cd2SShayne Chen for (i = 0; i < nbuf; i++) { 11303c38dfc1SLorenzo Bianconi txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); 11313c38dfc1SLorenzo Bianconi txp->fw.len[i] = cpu_to_le16(tx_info->buf[i + 1].len); 113298686cd2SShayne Chen } 11333c38dfc1SLorenzo Bianconi txp->fw.nbuf = nbuf; 113498686cd2SShayne Chen 11353c38dfc1SLorenzo Bianconi txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST); 113698686cd2SShayne Chen 113798686cd2SShayne Chen if (!is_8023 || pid >= MT_PACKET_ID_FIRST) 11383c38dfc1SLorenzo Bianconi txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD); 113998686cd2SShayne Chen 114098686cd2SShayne Chen if (!key) 11413c38dfc1SLorenzo Bianconi txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); 114298686cd2SShayne Chen 114398686cd2SShayne Chen if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control)) 11443c38dfc1SLorenzo Bianconi txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); 114598686cd2SShayne Chen 114698686cd2SShayne Chen if (vif) { 114798686cd2SShayne Chen struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 114898686cd2SShayne Chen 11493c38dfc1SLorenzo Bianconi txp->fw.bss_idx = mvif->mt76.idx; 115098686cd2SShayne Chen } 115198686cd2SShayne Chen 11523c38dfc1SLorenzo Bianconi txp->fw.token = cpu_to_le16(id); 115398686cd2SShayne Chen if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) 11543c38dfc1SLorenzo Bianconi txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx); 115598686cd2SShayne Chen else 11563c38dfc1SLorenzo Bianconi txp->fw.rept_wds_wcid = cpu_to_le16(0xfff); 115798686cd2SShayne Chen tx_info->skb = DMA_DUMMY_DATA; 115898686cd2SShayne Chen 115998686cd2SShayne Chen /* pass partial skb header to fw */ 116098686cd2SShayne Chen tx_info->buf[1].len = MT_CT_PARSE_LEN; 116198686cd2SShayne Chen tx_info->buf[1].skip_unmap = true; 116298686cd2SShayne Chen tx_info->nbuf = MT_CT_DMA_BUF_NUM; 116398686cd2SShayne Chen 116498686cd2SShayne Chen return 0; 116598686cd2SShayne Chen } 116698686cd2SShayne Chen 116798686cd2SShayne Chen static void 116898686cd2SShayne Chen mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) 116998686cd2SShayne Chen { 117098686cd2SShayne Chen struct mt7996_sta *msta; 117198686cd2SShayne Chen u16 fc, tid; 117298686cd2SShayne Chen u32 val; 117398686cd2SShayne Chen 117498686cd2SShayne Chen if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) 117598686cd2SShayne Chen return; 117698686cd2SShayne Chen 117798686cd2SShayne Chen tid = le32_get_bits(txwi[1], MT_TXD1_TID); 117898686cd2SShayne Chen if (tid >= 6) /* skip VO queue */ 117998686cd2SShayne Chen return; 118098686cd2SShayne Chen 118198686cd2SShayne Chen val = le32_to_cpu(txwi[2]); 118298686cd2SShayne Chen fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | 118398686cd2SShayne Chen FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; 118498686cd2SShayne Chen if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) 118598686cd2SShayne Chen return; 118698686cd2SShayne Chen 118798686cd2SShayne Chen msta = (struct mt7996_sta *)sta->drv_priv; 118898686cd2SShayne Chen if (!test_and_set_bit(tid, &msta->ampdu_state)) 118998686cd2SShayne Chen ieee80211_start_tx_ba_session(sta, tid, 0); 119098686cd2SShayne Chen } 119198686cd2SShayne Chen 119298686cd2SShayne Chen static void 119398686cd2SShayne Chen mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t, 119498686cd2SShayne Chen struct ieee80211_sta *sta, struct list_head *free_list) 119598686cd2SShayne Chen { 119698686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 119798686cd2SShayne Chen struct mt76_wcid *wcid; 119898686cd2SShayne Chen __le32 *txwi; 119998686cd2SShayne Chen u16 wcid_idx; 120098686cd2SShayne Chen 120130495864SLorenzo Bianconi mt76_connac_txp_skb_unmap(mdev, t); 120298686cd2SShayne Chen if (!t->skb) 120398686cd2SShayne Chen goto out; 120498686cd2SShayne Chen 120598686cd2SShayne Chen txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); 120698686cd2SShayne Chen if (sta) { 120798686cd2SShayne Chen wcid = (struct mt76_wcid *)sta->drv_priv; 120898686cd2SShayne Chen wcid_idx = wcid->idx; 120998686cd2SShayne Chen 121098686cd2SShayne Chen if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) 121198686cd2SShayne Chen mt7996_tx_check_aggr(sta, txwi); 121298686cd2SShayne Chen } else { 121398686cd2SShayne Chen wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); 121498686cd2SShayne Chen } 121598686cd2SShayne Chen 121698686cd2SShayne Chen __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); 121798686cd2SShayne Chen 121898686cd2SShayne Chen out: 121998686cd2SShayne Chen t->skb = NULL; 122098686cd2SShayne Chen mt76_put_txwi(mdev, t); 122198686cd2SShayne Chen } 122298686cd2SShayne Chen 122398686cd2SShayne Chen static void 122498686cd2SShayne Chen mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) 122598686cd2SShayne Chen { 122698686cd2SShayne Chen __le32 *tx_free = (__le32 *)data, *cur_info; 122798686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 122898686cd2SShayne Chen struct mt76_phy *phy2 = mdev->phys[MT_BAND1]; 122998686cd2SShayne Chen struct mt76_phy *phy3 = mdev->phys[MT_BAND2]; 123098686cd2SShayne Chen struct mt76_txwi_cache *txwi; 123198686cd2SShayne Chen struct ieee80211_sta *sta = NULL; 123298686cd2SShayne Chen LIST_HEAD(free_list); 123398686cd2SShayne Chen struct sk_buff *skb, *tmp; 123498686cd2SShayne Chen void *end = data + len; 123598686cd2SShayne Chen bool wake = false; 123698686cd2SShayne Chen u16 total, count = 0; 123798686cd2SShayne Chen 123898686cd2SShayne Chen /* clean DMA queues and unmap buffers first */ 123998686cd2SShayne Chen mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); 124098686cd2SShayne Chen mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); 124198686cd2SShayne Chen if (phy2) { 124298686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy2->q_tx[MT_TXQ_PSD], false); 124398686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy2->q_tx[MT_TXQ_BE], false); 124498686cd2SShayne Chen } 124598686cd2SShayne Chen if (phy3) { 124698686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_PSD], false); 124798686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false); 124898686cd2SShayne Chen } 124998686cd2SShayne Chen 125098686cd2SShayne Chen if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4)) 125198686cd2SShayne Chen return; 125298686cd2SShayne Chen 125398686cd2SShayne Chen total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT); 125498686cd2SShayne Chen for (cur_info = &tx_free[2]; count < total; cur_info++) { 125598686cd2SShayne Chen u32 msdu, info; 125698686cd2SShayne Chen u8 i; 125798686cd2SShayne Chen 125898686cd2SShayne Chen if (WARN_ON_ONCE((void *)cur_info >= end)) 125998686cd2SShayne Chen return; 126098686cd2SShayne Chen /* 1'b1: new wcid pair. 126198686cd2SShayne Chen * 1'b0: msdu_id with the same 'wcid pair' as above. 126298686cd2SShayne Chen */ 126398686cd2SShayne Chen info = le32_to_cpu(*cur_info); 126498686cd2SShayne Chen if (info & MT_TXFREE_INFO_PAIR) { 126598686cd2SShayne Chen struct mt7996_sta *msta; 126698686cd2SShayne Chen struct mt76_wcid *wcid; 126798686cd2SShayne Chen u16 idx; 126898686cd2SShayne Chen 126998686cd2SShayne Chen idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); 127098686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[idx]); 127198686cd2SShayne Chen sta = wcid_to_sta(wcid); 127298686cd2SShayne Chen if (!sta) 127398686cd2SShayne Chen continue; 127498686cd2SShayne Chen 127598686cd2SShayne Chen msta = container_of(wcid, struct mt7996_sta, wcid); 127698686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 127798686cd2SShayne Chen if (list_empty(&msta->poll_list)) 127898686cd2SShayne Chen list_add_tail(&msta->poll_list, &dev->sta_poll_list); 127998686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 128098686cd2SShayne Chen continue; 128198686cd2SShayne Chen } 128298686cd2SShayne Chen 128398686cd2SShayne Chen if (info & MT_TXFREE_INFO_HEADER) 128498686cd2SShayne Chen continue; 128598686cd2SShayne Chen 128698686cd2SShayne Chen for (i = 0; i < 2; i++) { 128798686cd2SShayne Chen msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID; 128898686cd2SShayne Chen if (msdu == MT_TXFREE_INFO_MSDU_ID) 128998686cd2SShayne Chen continue; 129098686cd2SShayne Chen 129198686cd2SShayne Chen count++; 129298686cd2SShayne Chen txwi = mt76_token_release(mdev, msdu, &wake); 129398686cd2SShayne Chen if (!txwi) 129498686cd2SShayne Chen continue; 129598686cd2SShayne Chen 129698686cd2SShayne Chen mt7996_txwi_free(dev, txwi, sta, &free_list); 129798686cd2SShayne Chen } 129898686cd2SShayne Chen } 129998686cd2SShayne Chen 130098686cd2SShayne Chen mt7996_mac_sta_poll(dev); 130198686cd2SShayne Chen 130298686cd2SShayne Chen if (wake) 130398686cd2SShayne Chen mt76_set_tx_blocked(&dev->mt76, false); 130498686cd2SShayne Chen 130598686cd2SShayne Chen mt76_worker_schedule(&dev->mt76.tx_worker); 130698686cd2SShayne Chen 130798686cd2SShayne Chen list_for_each_entry_safe(skb, tmp, &free_list, list) { 130898686cd2SShayne Chen skb_list_del_init(skb); 130998686cd2SShayne Chen napi_consume_skb(skb, 1); 131098686cd2SShayne Chen } 131198686cd2SShayne Chen } 131298686cd2SShayne Chen 131398686cd2SShayne Chen static bool 131498686cd2SShayne Chen mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid, 131598686cd2SShayne Chen __le32 *txs_data, struct mt76_sta_stats *stats) 131698686cd2SShayne Chen { 131798686cd2SShayne Chen struct ieee80211_supported_band *sband; 131898686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 131998686cd2SShayne Chen struct mt76_phy *mphy; 132098686cd2SShayne Chen struct ieee80211_tx_info *info; 132198686cd2SShayne Chen struct sk_buff_head list; 132298686cd2SShayne Chen struct rate_info rate = {}; 132398686cd2SShayne Chen struct sk_buff *skb; 132498686cd2SShayne Chen bool cck = false; 132598686cd2SShayne Chen u32 txrate, txs, mode, stbc; 132698686cd2SShayne Chen 132798686cd2SShayne Chen mt76_tx_status_lock(mdev, &list); 132898686cd2SShayne Chen skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list); 132998686cd2SShayne Chen if (!skb) 133098686cd2SShayne Chen goto out_no_skb; 133198686cd2SShayne Chen 133298686cd2SShayne Chen txs = le32_to_cpu(txs_data[0]); 133398686cd2SShayne Chen 133498686cd2SShayne Chen info = IEEE80211_SKB_CB(skb); 133598686cd2SShayne Chen if (!(txs & MT_TXS0_ACK_ERROR_MASK)) 133698686cd2SShayne Chen info->flags |= IEEE80211_TX_STAT_ACK; 133798686cd2SShayne Chen 133898686cd2SShayne Chen info->status.ampdu_len = 1; 133998686cd2SShayne Chen info->status.ampdu_ack_len = !!(info->flags & 134098686cd2SShayne Chen IEEE80211_TX_STAT_ACK); 134198686cd2SShayne Chen 134298686cd2SShayne Chen info->status.rates[0].idx = -1; 134398686cd2SShayne Chen 134498686cd2SShayne Chen txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); 134598686cd2SShayne Chen 134698686cd2SShayne Chen rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); 134798686cd2SShayne Chen rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; 134898686cd2SShayne Chen stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC); 134998686cd2SShayne Chen 135098686cd2SShayne Chen if (stbc && rate.nss > 1) 135198686cd2SShayne Chen rate.nss >>= 1; 135298686cd2SShayne Chen 135398686cd2SShayne Chen if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) 135498686cd2SShayne Chen stats->tx_nss[rate.nss - 1]++; 135598686cd2SShayne Chen if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) 135698686cd2SShayne Chen stats->tx_mcs[rate.mcs]++; 135798686cd2SShayne Chen 135898686cd2SShayne Chen mode = FIELD_GET(MT_TX_RATE_MODE, txrate); 135998686cd2SShayne Chen switch (mode) { 136098686cd2SShayne Chen case MT_PHY_TYPE_CCK: 136198686cd2SShayne Chen cck = true; 136298686cd2SShayne Chen fallthrough; 136398686cd2SShayne Chen case MT_PHY_TYPE_OFDM: 136498686cd2SShayne Chen mphy = mt76_dev_phy(mdev, wcid->phy_idx); 136598686cd2SShayne Chen 136698686cd2SShayne Chen if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) 136798686cd2SShayne Chen sband = &mphy->sband_5g.sband; 136898686cd2SShayne Chen else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) 136998686cd2SShayne Chen sband = &mphy->sband_6g.sband; 137098686cd2SShayne Chen else 137198686cd2SShayne Chen sband = &mphy->sband_2g.sband; 137298686cd2SShayne Chen 137398686cd2SShayne Chen rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck); 137498686cd2SShayne Chen rate.legacy = sband->bitrates[rate.mcs].bitrate; 137598686cd2SShayne Chen break; 137698686cd2SShayne Chen case MT_PHY_TYPE_HT: 137798686cd2SShayne Chen case MT_PHY_TYPE_HT_GF: 137898686cd2SShayne Chen if (rate.mcs > 31) 137998686cd2SShayne Chen goto out; 138098686cd2SShayne Chen 138198686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_MCS; 138298686cd2SShayne Chen if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) 138398686cd2SShayne Chen rate.flags |= RATE_INFO_FLAGS_SHORT_GI; 138498686cd2SShayne Chen break; 138598686cd2SShayne Chen case MT_PHY_TYPE_VHT: 138698686cd2SShayne Chen if (rate.mcs > 9) 138798686cd2SShayne Chen goto out; 138898686cd2SShayne Chen 138998686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_VHT_MCS; 139098686cd2SShayne Chen break; 139198686cd2SShayne Chen case MT_PHY_TYPE_HE_SU: 139298686cd2SShayne Chen case MT_PHY_TYPE_HE_EXT_SU: 139398686cd2SShayne Chen case MT_PHY_TYPE_HE_TB: 139498686cd2SShayne Chen case MT_PHY_TYPE_HE_MU: 139598686cd2SShayne Chen if (rate.mcs > 11) 139698686cd2SShayne Chen goto out; 139798686cd2SShayne Chen 139898686cd2SShayne Chen rate.he_gi = wcid->rate.he_gi; 139998686cd2SShayne Chen rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); 140098686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_HE_MCS; 140198686cd2SShayne Chen break; 140280f5a31dSShayne Chen case MT_PHY_TYPE_EHT_SU: 140380f5a31dSShayne Chen case MT_PHY_TYPE_EHT_TRIG: 140480f5a31dSShayne Chen case MT_PHY_TYPE_EHT_MU: 140580f5a31dSShayne Chen if (rate.mcs > 13) 140680f5a31dSShayne Chen goto out; 140780f5a31dSShayne Chen 140880f5a31dSShayne Chen rate.eht_gi = wcid->rate.eht_gi; 140980f5a31dSShayne Chen rate.flags = RATE_INFO_FLAGS_EHT_MCS; 141080f5a31dSShayne Chen break; 141198686cd2SShayne Chen default: 141298686cd2SShayne Chen goto out; 141398686cd2SShayne Chen } 141498686cd2SShayne Chen 141598686cd2SShayne Chen stats->tx_mode[mode]++; 141698686cd2SShayne Chen 141798686cd2SShayne Chen switch (FIELD_GET(MT_TXS0_BW, txs)) { 141880f5a31dSShayne Chen case IEEE80211_STA_RX_BW_320: 141980f5a31dSShayne Chen rate.bw = RATE_INFO_BW_320; 142080f5a31dSShayne Chen stats->tx_bw[4]++; 142180f5a31dSShayne Chen break; 142298686cd2SShayne Chen case IEEE80211_STA_RX_BW_160: 142398686cd2SShayne Chen rate.bw = RATE_INFO_BW_160; 142498686cd2SShayne Chen stats->tx_bw[3]++; 142598686cd2SShayne Chen break; 142698686cd2SShayne Chen case IEEE80211_STA_RX_BW_80: 142798686cd2SShayne Chen rate.bw = RATE_INFO_BW_80; 142898686cd2SShayne Chen stats->tx_bw[2]++; 142998686cd2SShayne Chen break; 143098686cd2SShayne Chen case IEEE80211_STA_RX_BW_40: 143198686cd2SShayne Chen rate.bw = RATE_INFO_BW_40; 143298686cd2SShayne Chen stats->tx_bw[1]++; 143398686cd2SShayne Chen break; 143498686cd2SShayne Chen default: 143598686cd2SShayne Chen rate.bw = RATE_INFO_BW_20; 143698686cd2SShayne Chen stats->tx_bw[0]++; 143798686cd2SShayne Chen break; 143898686cd2SShayne Chen } 143998686cd2SShayne Chen wcid->rate = rate; 144098686cd2SShayne Chen 144198686cd2SShayne Chen out: 144298686cd2SShayne Chen mt76_tx_status_skb_done(mdev, skb, &list); 144398686cd2SShayne Chen 144498686cd2SShayne Chen out_no_skb: 144598686cd2SShayne Chen mt76_tx_status_unlock(mdev, &list); 144698686cd2SShayne Chen 144798686cd2SShayne Chen return !!skb; 144898686cd2SShayne Chen } 144998686cd2SShayne Chen 145098686cd2SShayne Chen static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) 145198686cd2SShayne Chen { 145298686cd2SShayne Chen struct mt7996_sta *msta = NULL; 145398686cd2SShayne Chen struct mt76_wcid *wcid; 145498686cd2SShayne Chen __le32 *txs_data = data; 145598686cd2SShayne Chen u16 wcidx; 145698686cd2SShayne Chen u8 pid; 145798686cd2SShayne Chen 145898686cd2SShayne Chen if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) 145998686cd2SShayne Chen return; 146098686cd2SShayne Chen 146198686cd2SShayne Chen wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); 146298686cd2SShayne Chen pid = le32_get_bits(txs_data[3], MT_TXS3_PID); 146398686cd2SShayne Chen 146498686cd2SShayne Chen if (pid < MT_PACKET_ID_FIRST) 146598686cd2SShayne Chen return; 146698686cd2SShayne Chen 146743482540SShayne Chen if (wcidx >= mt7996_wtbl_size(dev)) 146898686cd2SShayne Chen return; 146998686cd2SShayne Chen 147098686cd2SShayne Chen rcu_read_lock(); 147198686cd2SShayne Chen 147298686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[wcidx]); 147398686cd2SShayne Chen if (!wcid) 147498686cd2SShayne Chen goto out; 147598686cd2SShayne Chen 147698686cd2SShayne Chen msta = container_of(wcid, struct mt7996_sta, wcid); 147798686cd2SShayne Chen 147898686cd2SShayne Chen mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data, &msta->stats); 147998686cd2SShayne Chen 148098686cd2SShayne Chen if (!wcid->sta) 148198686cd2SShayne Chen goto out; 148298686cd2SShayne Chen 148398686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 148498686cd2SShayne Chen if (list_empty(&msta->poll_list)) 148598686cd2SShayne Chen list_add_tail(&msta->poll_list, &dev->sta_poll_list); 148698686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 148798686cd2SShayne Chen 148898686cd2SShayne Chen out: 148998686cd2SShayne Chen rcu_read_unlock(); 149098686cd2SShayne Chen } 149198686cd2SShayne Chen 149298686cd2SShayne Chen bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len) 149398686cd2SShayne Chen { 149498686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 149598686cd2SShayne Chen __le32 *rxd = (__le32 *)data; 149698686cd2SShayne Chen __le32 *end = (__le32 *)&rxd[len / 4]; 149798686cd2SShayne Chen enum rx_pkt_type type; 149898686cd2SShayne Chen 149998686cd2SShayne Chen type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); 150098686cd2SShayne Chen if (type != PKT_TYPE_NORMAL) { 150198686cd2SShayne Chen u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK); 150298686cd2SShayne Chen 150398686cd2SShayne Chen if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) == 150498686cd2SShayne Chen MT_RXD0_SW_PKT_TYPE_FRAME)) 150598686cd2SShayne Chen return true; 150698686cd2SShayne Chen } 150798686cd2SShayne Chen 150898686cd2SShayne Chen switch (type) { 150998686cd2SShayne Chen case PKT_TYPE_TXRX_NOTIFY: 151098686cd2SShayne Chen mt7996_mac_tx_free(dev, data, len); 151198686cd2SShayne Chen return false; 151298686cd2SShayne Chen case PKT_TYPE_TXS: 151398686cd2SShayne Chen for (rxd += 4; rxd + 8 <= end; rxd += 8) 151498686cd2SShayne Chen mt7996_mac_add_txs(dev, rxd); 151598686cd2SShayne Chen return false; 151698686cd2SShayne Chen case PKT_TYPE_RX_FW_MONITOR: 151798686cd2SShayne Chen mt7996_debugfs_rx_fw_monitor(dev, data, len); 151898686cd2SShayne Chen return false; 151998686cd2SShayne Chen default: 152098686cd2SShayne Chen return true; 152198686cd2SShayne Chen } 152298686cd2SShayne Chen } 152398686cd2SShayne Chen 152498686cd2SShayne Chen void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, 152598686cd2SShayne Chen struct sk_buff *skb, u32 *info) 152698686cd2SShayne Chen { 152798686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 152898686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 152998686cd2SShayne Chen __le32 *end = (__le32 *)&skb->data[skb->len]; 153098686cd2SShayne Chen enum rx_pkt_type type; 153198686cd2SShayne Chen 153298686cd2SShayne Chen type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); 153398686cd2SShayne Chen if (type != PKT_TYPE_NORMAL) { 153498686cd2SShayne Chen u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK); 153598686cd2SShayne Chen 153698686cd2SShayne Chen if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) == 153798686cd2SShayne Chen MT_RXD0_SW_PKT_TYPE_FRAME)) 153898686cd2SShayne Chen type = PKT_TYPE_NORMAL; 153998686cd2SShayne Chen } 154098686cd2SShayne Chen 154198686cd2SShayne Chen switch (type) { 154298686cd2SShayne Chen case PKT_TYPE_TXRX_NOTIFY: 154398686cd2SShayne Chen mt7996_mac_tx_free(dev, skb->data, skb->len); 154498686cd2SShayne Chen napi_consume_skb(skb, 1); 154598686cd2SShayne Chen break; 154698686cd2SShayne Chen case PKT_TYPE_RX_EVENT: 154798686cd2SShayne Chen mt7996_mcu_rx_event(dev, skb); 154898686cd2SShayne Chen break; 154998686cd2SShayne Chen case PKT_TYPE_TXS: 155098686cd2SShayne Chen for (rxd += 4; rxd + 8 <= end; rxd += 8) 155198686cd2SShayne Chen mt7996_mac_add_txs(dev, rxd); 155298686cd2SShayne Chen dev_kfree_skb(skb); 155398686cd2SShayne Chen break; 155498686cd2SShayne Chen case PKT_TYPE_RX_FW_MONITOR: 155598686cd2SShayne Chen mt7996_debugfs_rx_fw_monitor(dev, skb->data, skb->len); 155698686cd2SShayne Chen dev_kfree_skb(skb); 155798686cd2SShayne Chen break; 155898686cd2SShayne Chen case PKT_TYPE_NORMAL: 155998686cd2SShayne Chen if (!mt7996_mac_fill_rx(dev, skb)) { 156098686cd2SShayne Chen mt76_rx(&dev->mt76, q, skb); 156198686cd2SShayne Chen return; 156298686cd2SShayne Chen } 156398686cd2SShayne Chen fallthrough; 156498686cd2SShayne Chen default: 156598686cd2SShayne Chen dev_kfree_skb(skb); 156698686cd2SShayne Chen break; 156798686cd2SShayne Chen } 156898686cd2SShayne Chen } 156998686cd2SShayne Chen 157098686cd2SShayne Chen void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy) 157198686cd2SShayne Chen { 157298686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 157398686cd2SShayne Chen u32 reg = MT_WF_PHYRX_BAND_RX_CTRL1(phy->mt76->band_idx); 157498686cd2SShayne Chen 157598686cd2SShayne Chen mt76_clear(dev, reg, MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN); 157698686cd2SShayne Chen mt76_set(dev, reg, BIT(11) | BIT(9)); 157798686cd2SShayne Chen } 157898686cd2SShayne Chen 157998686cd2SShayne Chen void mt7996_mac_reset_counters(struct mt7996_phy *phy) 158098686cd2SShayne Chen { 158198686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 158298686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 158398686cd2SShayne Chen int i; 158498686cd2SShayne Chen 158598686cd2SShayne Chen for (i = 0; i < 16; i++) 158698686cd2SShayne Chen mt76_rr(dev, MT_TX_AGG_CNT(band_idx, i)); 158798686cd2SShayne Chen 158898686cd2SShayne Chen phy->mt76->survey_time = ktime_get_boottime(); 158998686cd2SShayne Chen 159098686cd2SShayne Chen memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats)); 159198686cd2SShayne Chen 159298686cd2SShayne Chen /* reset airtime counters */ 159398686cd2SShayne Chen mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band_idx), 159498686cd2SShayne Chen MT_WF_RMAC_MIB_RXTIME_CLR); 159598686cd2SShayne Chen 159698686cd2SShayne Chen mt7996_mcu_get_chan_mib_info(phy, true); 159798686cd2SShayne Chen } 159898686cd2SShayne Chen 159998686cd2SShayne Chen void mt7996_mac_set_timing(struct mt7996_phy *phy) 160098686cd2SShayne Chen { 160198686cd2SShayne Chen s16 coverage_class = phy->coverage_class; 160298686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 160398686cd2SShayne Chen struct mt7996_phy *phy2 = mt7996_phy2(dev); 160498686cd2SShayne Chen struct mt7996_phy *phy3 = mt7996_phy3(dev); 160598686cd2SShayne Chen u32 val, reg_offset; 160698686cd2SShayne Chen u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | 160798686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); 160898686cd2SShayne Chen u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | 160998686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); 161098686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 161198686cd2SShayne Chen int offset; 161298686cd2SShayne Chen bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); 161398686cd2SShayne Chen 161498686cd2SShayne Chen if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) 161598686cd2SShayne Chen return; 161698686cd2SShayne Chen 161798686cd2SShayne Chen if (phy2) 161898686cd2SShayne Chen coverage_class = max_t(s16, dev->phy.coverage_class, 161998686cd2SShayne Chen phy2->coverage_class); 162098686cd2SShayne Chen 162198686cd2SShayne Chen if (phy3) 162298686cd2SShayne Chen coverage_class = max_t(s16, coverage_class, 162398686cd2SShayne Chen phy3->coverage_class); 162498686cd2SShayne Chen 162598686cd2SShayne Chen mt76_set(dev, MT_ARB_SCR(band_idx), 162698686cd2SShayne Chen MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 162798686cd2SShayne Chen udelay(1); 162898686cd2SShayne Chen 162998686cd2SShayne Chen offset = 3 * coverage_class; 163098686cd2SShayne Chen reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | 163198686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); 163298686cd2SShayne Chen 163398686cd2SShayne Chen mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset); 163498686cd2SShayne Chen mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset); 163598686cd2SShayne Chen mt76_wr(dev, MT_TMAC_ICR0(band_idx), 163698686cd2SShayne Chen FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) | 163798686cd2SShayne Chen FIELD_PREP(MT_IFS_RIFS, 2) | 163898686cd2SShayne Chen FIELD_PREP(MT_IFS_SIFS, 10) | 163998686cd2SShayne Chen FIELD_PREP(MT_IFS_SLOT, phy->slottime)); 164098686cd2SShayne Chen 164198686cd2SShayne Chen if (!a_band) 164298686cd2SShayne Chen mt76_wr(dev, MT_TMAC_ICR1(band_idx), 164398686cd2SShayne Chen FIELD_PREP(MT_IFS_EIFS_CCK, 314)); 164498686cd2SShayne Chen 164598686cd2SShayne Chen if (phy->slottime < 20 || a_band) 164698686cd2SShayne Chen val = MT7996_CFEND_RATE_DEFAULT; 164798686cd2SShayne Chen else 164898686cd2SShayne Chen val = MT7996_CFEND_RATE_11B; 164998686cd2SShayne Chen 1650793445cfSShayne Chen mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val); 165198686cd2SShayne Chen mt76_clear(dev, MT_ARB_SCR(band_idx), 165298686cd2SShayne Chen MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 165398686cd2SShayne Chen } 165498686cd2SShayne Chen 165598686cd2SShayne Chen void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band) 165698686cd2SShayne Chen { 165798686cd2SShayne Chen mt76_set(dev, MT_WF_PHYRX_CSD_BAND_RXTD12(band), 165898686cd2SShayne Chen MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY | 165998686cd2SShayne Chen MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR); 166098686cd2SShayne Chen 166198686cd2SShayne Chen mt76_set(dev, MT_WF_PHYRX_BAND_RX_CTRL1(band), 166298686cd2SShayne Chen FIELD_PREP(MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN, 0x5)); 166398686cd2SShayne Chen } 166498686cd2SShayne Chen 166598686cd2SShayne Chen static u8 166698686cd2SShayne Chen mt7996_phy_get_nf(struct mt7996_phy *phy, u8 band_idx) 166798686cd2SShayne Chen { 166898686cd2SShayne Chen static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; 166998686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 167098686cd2SShayne Chen u32 val, sum = 0, n = 0; 167198686cd2SShayne Chen int ant, i; 167298686cd2SShayne Chen 167398686cd2SShayne Chen for (ant = 0; ant < hweight8(phy->mt76->antenna_mask); ant++) { 167498686cd2SShayne Chen u32 reg = MT_WF_PHYRX_CSD_IRPI(band_idx, ant); 167598686cd2SShayne Chen 167698686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { 167798686cd2SShayne Chen val = mt76_rr(dev, reg); 167898686cd2SShayne Chen sum += val * nf_power[i]; 167998686cd2SShayne Chen n += val; 168098686cd2SShayne Chen } 168198686cd2SShayne Chen } 168298686cd2SShayne Chen 168398686cd2SShayne Chen return n ? sum / n : 0; 168498686cd2SShayne Chen } 168598686cd2SShayne Chen 168698686cd2SShayne Chen void mt7996_update_channel(struct mt76_phy *mphy) 168798686cd2SShayne Chen { 168898686cd2SShayne Chen struct mt7996_phy *phy = (struct mt7996_phy *)mphy->priv; 168998686cd2SShayne Chen struct mt76_channel_state *state = mphy->chan_state; 169098686cd2SShayne Chen int nf; 169198686cd2SShayne Chen 169298686cd2SShayne Chen mt7996_mcu_get_chan_mib_info(phy, false); 169398686cd2SShayne Chen 169498686cd2SShayne Chen nf = mt7996_phy_get_nf(phy, mphy->band_idx); 169598686cd2SShayne Chen if (!phy->noise) 169698686cd2SShayne Chen phy->noise = nf << 4; 169798686cd2SShayne Chen else if (nf) 169898686cd2SShayne Chen phy->noise += nf - (phy->noise >> 4); 169998686cd2SShayne Chen 170098686cd2SShayne Chen state->noise = -(phy->noise >> 4); 170198686cd2SShayne Chen } 170298686cd2SShayne Chen 170398686cd2SShayne Chen static bool 170498686cd2SShayne Chen mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state) 170598686cd2SShayne Chen { 170698686cd2SShayne Chen bool ret; 170798686cd2SShayne Chen 170898686cd2SShayne Chen ret = wait_event_timeout(dev->reset_wait, 170998686cd2SShayne Chen (READ_ONCE(dev->reset_state) & state), 171098686cd2SShayne Chen MT7996_RESET_TIMEOUT); 171198686cd2SShayne Chen 171298686cd2SShayne Chen WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); 171398686cd2SShayne Chen return ret; 171498686cd2SShayne Chen } 171598686cd2SShayne Chen 171698686cd2SShayne Chen static void 171798686cd2SShayne Chen mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) 171898686cd2SShayne Chen { 171998686cd2SShayne Chen struct ieee80211_hw *hw = priv; 172098686cd2SShayne Chen 172198686cd2SShayne Chen switch (vif->type) { 172298686cd2SShayne Chen case NL80211_IFTYPE_MESH_POINT: 172398686cd2SShayne Chen case NL80211_IFTYPE_ADHOC: 172498686cd2SShayne Chen case NL80211_IFTYPE_AP: 172598686cd2SShayne Chen mt7996_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); 172698686cd2SShayne Chen break; 172798686cd2SShayne Chen default: 172898686cd2SShayne Chen break; 172998686cd2SShayne Chen } 173098686cd2SShayne Chen } 173198686cd2SShayne Chen 173298686cd2SShayne Chen static void 173398686cd2SShayne Chen mt7996_update_beacons(struct mt7996_dev *dev) 173498686cd2SShayne Chen { 173598686cd2SShayne Chen struct mt76_phy *phy2, *phy3; 173698686cd2SShayne Chen 173798686cd2SShayne Chen ieee80211_iterate_active_interfaces(dev->mt76.hw, 173898686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 173998686cd2SShayne Chen mt7996_update_vif_beacon, dev->mt76.hw); 174098686cd2SShayne Chen 174198686cd2SShayne Chen phy2 = dev->mt76.phys[MT_BAND1]; 174298686cd2SShayne Chen if (!phy2) 174398686cd2SShayne Chen return; 174498686cd2SShayne Chen 174598686cd2SShayne Chen ieee80211_iterate_active_interfaces(phy2->hw, 174698686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 174798686cd2SShayne Chen mt7996_update_vif_beacon, phy2->hw); 174898686cd2SShayne Chen 174998686cd2SShayne Chen phy3 = dev->mt76.phys[MT_BAND2]; 175098686cd2SShayne Chen if (!phy3) 175198686cd2SShayne Chen return; 175298686cd2SShayne Chen 175398686cd2SShayne Chen ieee80211_iterate_active_interfaces(phy3->hw, 175498686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 175598686cd2SShayne Chen mt7996_update_vif_beacon, phy3->hw); 175698686cd2SShayne Chen } 175798686cd2SShayne Chen 175898686cd2SShayne Chen static void 175998686cd2SShayne Chen mt7996_dma_reset(struct mt7996_dev *dev) 176098686cd2SShayne Chen { 176198686cd2SShayne Chen struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1]; 176298686cd2SShayne Chen struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2]; 176398686cd2SShayne Chen u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); 176498686cd2SShayne Chen int i; 176598686cd2SShayne Chen 176698686cd2SShayne Chen mt76_clear(dev, MT_WFDMA0_GLO_CFG, 176798686cd2SShayne Chen MT_WFDMA0_GLO_CFG_TX_DMA_EN | 176898686cd2SShayne Chen MT_WFDMA0_GLO_CFG_RX_DMA_EN); 176998686cd2SShayne Chen 177098686cd2SShayne Chen if (dev->hif2) 177198686cd2SShayne Chen mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, 177298686cd2SShayne Chen MT_WFDMA0_GLO_CFG_TX_DMA_EN | 177398686cd2SShayne Chen MT_WFDMA0_GLO_CFG_RX_DMA_EN); 177498686cd2SShayne Chen 177598686cd2SShayne Chen usleep_range(1000, 2000); 177698686cd2SShayne Chen 177798686cd2SShayne Chen for (i = 0; i < __MT_TXQ_MAX; i++) { 177898686cd2SShayne Chen mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); 177998686cd2SShayne Chen if (phy2) 178098686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true); 178198686cd2SShayne Chen if (phy3) 178298686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true); 178398686cd2SShayne Chen } 178498686cd2SShayne Chen 178598686cd2SShayne Chen for (i = 0; i < __MT_MCUQ_MAX; i++) 178698686cd2SShayne Chen mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); 178798686cd2SShayne Chen 178898686cd2SShayne Chen mt76_for_each_q_rx(&dev->mt76, i) 178998686cd2SShayne Chen mt76_queue_rx_reset(dev, i); 179098686cd2SShayne Chen 179198686cd2SShayne Chen mt76_tx_status_check(&dev->mt76, true); 179298686cd2SShayne Chen 179398686cd2SShayne Chen /* re-init prefetch settings after reset */ 179498686cd2SShayne Chen mt7996_dma_prefetch(dev); 179598686cd2SShayne Chen 179698686cd2SShayne Chen mt76_set(dev, MT_WFDMA0_GLO_CFG, 179798686cd2SShayne Chen MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); 179898686cd2SShayne Chen 179998686cd2SShayne Chen if (dev->hif2) 180098686cd2SShayne Chen mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, 180198686cd2SShayne Chen MT_WFDMA0_GLO_CFG_TX_DMA_EN | 180298686cd2SShayne Chen MT_WFDMA0_GLO_CFG_RX_DMA_EN); 180398686cd2SShayne Chen } 180498686cd2SShayne Chen 180598686cd2SShayne Chen void mt7996_tx_token_put(struct mt7996_dev *dev) 180698686cd2SShayne Chen { 180798686cd2SShayne Chen struct mt76_txwi_cache *txwi; 180898686cd2SShayne Chen int id; 180998686cd2SShayne Chen 181098686cd2SShayne Chen spin_lock_bh(&dev->mt76.token_lock); 181198686cd2SShayne Chen idr_for_each_entry(&dev->mt76.token, txwi, id) { 181298686cd2SShayne Chen mt7996_txwi_free(dev, txwi, NULL, NULL); 181398686cd2SShayne Chen dev->mt76.token_count--; 181498686cd2SShayne Chen } 181598686cd2SShayne Chen spin_unlock_bh(&dev->mt76.token_lock); 181698686cd2SShayne Chen idr_destroy(&dev->mt76.token); 181798686cd2SShayne Chen } 181898686cd2SShayne Chen 181998686cd2SShayne Chen /* system error recovery */ 182098686cd2SShayne Chen void mt7996_mac_reset_work(struct work_struct *work) 182198686cd2SShayne Chen { 182298686cd2SShayne Chen struct mt7996_phy *phy2, *phy3; 182398686cd2SShayne Chen struct mt7996_dev *dev; 182498686cd2SShayne Chen int i; 182598686cd2SShayne Chen 182698686cd2SShayne Chen dev = container_of(work, struct mt7996_dev, reset_work); 182798686cd2SShayne Chen phy2 = mt7996_phy2(dev); 182898686cd2SShayne Chen phy3 = mt7996_phy3(dev); 182998686cd2SShayne Chen 183098686cd2SShayne Chen if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA)) 183198686cd2SShayne Chen return; 183298686cd2SShayne Chen 183398686cd2SShayne Chen ieee80211_stop_queues(mt76_hw(dev)); 183498686cd2SShayne Chen if (phy2) 183598686cd2SShayne Chen ieee80211_stop_queues(phy2->mt76->hw); 183698686cd2SShayne Chen if (phy3) 183798686cd2SShayne Chen ieee80211_stop_queues(phy3->mt76->hw); 183898686cd2SShayne Chen 183998686cd2SShayne Chen set_bit(MT76_RESET, &dev->mphy.state); 184098686cd2SShayne Chen set_bit(MT76_MCU_RESET, &dev->mphy.state); 184198686cd2SShayne Chen wake_up(&dev->mt76.mcu.wait); 184298686cd2SShayne Chen cancel_delayed_work_sync(&dev->mphy.mac_work); 184398686cd2SShayne Chen if (phy2) { 184498686cd2SShayne Chen set_bit(MT76_RESET, &phy2->mt76->state); 184598686cd2SShayne Chen cancel_delayed_work_sync(&phy2->mt76->mac_work); 184698686cd2SShayne Chen } 184798686cd2SShayne Chen if (phy3) { 184898686cd2SShayne Chen set_bit(MT76_RESET, &phy3->mt76->state); 184998686cd2SShayne Chen cancel_delayed_work_sync(&phy3->mt76->mac_work); 185098686cd2SShayne Chen } 185198686cd2SShayne Chen mt76_worker_disable(&dev->mt76.tx_worker); 185298686cd2SShayne Chen mt76_for_each_q_rx(&dev->mt76, i) 185398686cd2SShayne Chen napi_disable(&dev->mt76.napi[i]); 185498686cd2SShayne Chen napi_disable(&dev->mt76.tx_napi); 185598686cd2SShayne Chen 185698686cd2SShayne Chen mutex_lock(&dev->mt76.mutex); 185798686cd2SShayne Chen 185898686cd2SShayne Chen mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); 185998686cd2SShayne Chen 186098686cd2SShayne Chen if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { 186198686cd2SShayne Chen mt7996_dma_reset(dev); 186298686cd2SShayne Chen 186398686cd2SShayne Chen mt7996_tx_token_put(dev); 186498686cd2SShayne Chen idr_init(&dev->mt76.token); 186598686cd2SShayne Chen 186698686cd2SShayne Chen mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); 186798686cd2SShayne Chen mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); 186898686cd2SShayne Chen } 186998686cd2SShayne Chen 187098686cd2SShayne Chen clear_bit(MT76_MCU_RESET, &dev->mphy.state); 187198686cd2SShayne Chen clear_bit(MT76_RESET, &dev->mphy.state); 187298686cd2SShayne Chen if (phy2) 187398686cd2SShayne Chen clear_bit(MT76_RESET, &phy2->mt76->state); 187498686cd2SShayne Chen if (phy3) 187598686cd2SShayne Chen clear_bit(MT76_RESET, &phy3->mt76->state); 187698686cd2SShayne Chen 187798686cd2SShayne Chen local_bh_disable(); 187898686cd2SShayne Chen mt76_for_each_q_rx(&dev->mt76, i) { 187998686cd2SShayne Chen napi_enable(&dev->mt76.napi[i]); 188098686cd2SShayne Chen napi_schedule(&dev->mt76.napi[i]); 188198686cd2SShayne Chen } 188298686cd2SShayne Chen local_bh_enable(); 188398686cd2SShayne Chen 188498686cd2SShayne Chen tasklet_schedule(&dev->irq_tasklet); 188598686cd2SShayne Chen 188698686cd2SShayne Chen mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); 188798686cd2SShayne Chen mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); 188898686cd2SShayne Chen 188998686cd2SShayne Chen mt76_worker_enable(&dev->mt76.tx_worker); 189098686cd2SShayne Chen 189198686cd2SShayne Chen local_bh_disable(); 189298686cd2SShayne Chen napi_enable(&dev->mt76.tx_napi); 189398686cd2SShayne Chen napi_schedule(&dev->mt76.tx_napi); 189498686cd2SShayne Chen local_bh_enable(); 189598686cd2SShayne Chen 189698686cd2SShayne Chen ieee80211_wake_queues(mt76_hw(dev)); 189798686cd2SShayne Chen if (phy2) 189898686cd2SShayne Chen ieee80211_wake_queues(phy2->mt76->hw); 189998686cd2SShayne Chen if (phy3) 190098686cd2SShayne Chen ieee80211_wake_queues(phy3->mt76->hw); 190198686cd2SShayne Chen 190298686cd2SShayne Chen mutex_unlock(&dev->mt76.mutex); 190398686cd2SShayne Chen 190498686cd2SShayne Chen mt7996_update_beacons(dev); 190598686cd2SShayne Chen 190698686cd2SShayne Chen ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, 190798686cd2SShayne Chen MT7996_WATCHDOG_TIME); 190898686cd2SShayne Chen if (phy2) 190998686cd2SShayne Chen ieee80211_queue_delayed_work(phy2->mt76->hw, 191098686cd2SShayne Chen &phy2->mt76->mac_work, 191198686cd2SShayne Chen MT7996_WATCHDOG_TIME); 191298686cd2SShayne Chen if (phy3) 191398686cd2SShayne Chen ieee80211_queue_delayed_work(phy3->mt76->hw, 191498686cd2SShayne Chen &phy3->mt76->mac_work, 191598686cd2SShayne Chen MT7996_WATCHDOG_TIME); 191698686cd2SShayne Chen } 191798686cd2SShayne Chen 191898686cd2SShayne Chen void mt7996_mac_update_stats(struct mt7996_phy *phy) 191998686cd2SShayne Chen { 192098686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 192198686cd2SShayne Chen struct mib_stats *mib = &phy->mib; 192298686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 192398686cd2SShayne Chen u32 cnt; 192498686cd2SShayne Chen int i; 192598686cd2SShayne Chen 192698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR1(band_idx)); 192798686cd2SShayne Chen mib->fcs_err_cnt += cnt; 192898686cd2SShayne Chen 192998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR33(band_idx)); 193098686cd2SShayne Chen mib->rx_fifo_full_cnt += cnt; 193198686cd2SShayne Chen 193298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR31(band_idx)); 193398686cd2SShayne Chen mib->rx_mpdu_cnt += cnt; 193498686cd2SShayne Chen 193598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR6(band_idx)); 193698686cd2SShayne Chen mib->channel_idle_cnt += FIELD_GET(MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK, cnt); 193798686cd2SShayne Chen 193898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RVSR0(band_idx)); 193998686cd2SShayne Chen mib->rx_vector_mismatch_cnt += cnt; 194098686cd2SShayne Chen 194198686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR35(band_idx)); 194298686cd2SShayne Chen mib->rx_delimiter_fail_cnt += cnt; 194398686cd2SShayne Chen 194498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR36(band_idx)); 194598686cd2SShayne Chen mib->rx_len_mismatch_cnt += cnt; 194698686cd2SShayne Chen 194798686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR0(band_idx)); 194898686cd2SShayne Chen mib->tx_ampdu_cnt += cnt; 194998686cd2SShayne Chen 195098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR2(band_idx)); 195198686cd2SShayne Chen mib->tx_stop_q_empty_cnt += cnt; 195298686cd2SShayne Chen 195398686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR3(band_idx)); 195498686cd2SShayne Chen mib->tx_mpdu_attempts_cnt += cnt; 195598686cd2SShayne Chen 195698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR4(band_idx)); 195798686cd2SShayne Chen mib->tx_mpdu_success_cnt += cnt; 195898686cd2SShayne Chen 195998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR27(band_idx)); 196098686cd2SShayne Chen mib->rx_ampdu_cnt += cnt; 196198686cd2SShayne Chen 196298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR28(band_idx)); 196398686cd2SShayne Chen mib->rx_ampdu_bytes_cnt += cnt; 196498686cd2SShayne Chen 196598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR29(band_idx)); 196698686cd2SShayne Chen mib->rx_ampdu_valid_subframe_cnt += cnt; 196798686cd2SShayne Chen 196898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR30(band_idx)); 196998686cd2SShayne Chen mib->rx_ampdu_valid_subframe_bytes_cnt += cnt; 197098686cd2SShayne Chen 197198686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR27(band_idx)); 197298686cd2SShayne Chen mib->tx_rwp_fail_cnt += FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT, cnt); 197398686cd2SShayne Chen 197498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR28(band_idx)); 197598686cd2SShayne Chen mib->tx_rwp_need_cnt += FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT, cnt); 197698686cd2SShayne Chen 197798686cd2SShayne Chen cnt = mt76_rr(dev, MT_UMIB_RPDCR(band_idx)); 197898686cd2SShayne Chen mib->rx_pfdrop_cnt += cnt; 197998686cd2SShayne Chen 198098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RVSR1(band_idx)); 198198686cd2SShayne Chen mib->rx_vec_queue_overflow_drop_cnt += cnt; 198298686cd2SShayne Chen 198398686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR1(band_idx)); 198498686cd2SShayne Chen mib->rx_ba_cnt += cnt; 198598686cd2SShayne Chen 198698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR0(band_idx)); 198798686cd2SShayne Chen mib->tx_bf_ebf_ppdu_cnt += cnt; 198898686cd2SShayne Chen 198998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR1(band_idx)); 199098686cd2SShayne Chen mib->tx_bf_ibf_ppdu_cnt += cnt; 199198686cd2SShayne Chen 199298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR2(band_idx)); 199398686cd2SShayne Chen mib->tx_mu_bf_cnt += cnt; 199498686cd2SShayne Chen 199598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR5(band_idx)); 199698686cd2SShayne Chen mib->tx_mu_mpdu_cnt += cnt; 199798686cd2SShayne Chen 199898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR6(band_idx)); 199998686cd2SShayne Chen mib->tx_mu_acked_mpdu_cnt += cnt; 200098686cd2SShayne Chen 200198686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR7(band_idx)); 200298686cd2SShayne Chen mib->tx_su_acked_mpdu_cnt += cnt; 200398686cd2SShayne Chen 200498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR3(band_idx)); 200598686cd2SShayne Chen mib->tx_bf_rx_fb_ht_cnt += cnt; 200698686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 200798686cd2SShayne Chen 200898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR4(band_idx)); 200998686cd2SShayne Chen mib->tx_bf_rx_fb_vht_cnt += cnt; 201098686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 201198686cd2SShayne Chen 201298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR5(band_idx)); 201398686cd2SShayne Chen mib->tx_bf_rx_fb_he_cnt += cnt; 201498686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 201598686cd2SShayne Chen 201698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR6(band_idx)); 201798686cd2SShayne Chen mib->tx_bf_rx_fb_eht_cnt += cnt; 201898686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 201998686cd2SShayne Chen 202098686cd2SShayne Chen cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(band_idx)); 202198686cd2SShayne Chen mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt); 202298686cd2SShayne Chen mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt); 202398686cd2SShayne Chen mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt); 202498686cd2SShayne Chen 202598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR7(band_idx)); 202698686cd2SShayne Chen mib->tx_bf_fb_trig_cnt += cnt; 202798686cd2SShayne Chen 202898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR17(band_idx)); 202998686cd2SShayne Chen mib->tx_bf_fb_cpl_cnt += cnt; 203098686cd2SShayne Chen 203198686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { 203298686cd2SShayne Chen cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); 203398686cd2SShayne Chen mib->tx_amsdu[i] += cnt; 203498686cd2SShayne Chen mib->tx_amsdu_cnt += cnt; 203598686cd2SShayne Chen } 203698686cd2SShayne Chen 203798686cd2SShayne Chen /* rts count */ 203898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR5(band_idx)); 203998686cd2SShayne Chen mib->rts_cnt += cnt; 204098686cd2SShayne Chen 204198686cd2SShayne Chen /* rts retry count */ 204298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR6(band_idx)); 204398686cd2SShayne Chen mib->rts_retries_cnt += cnt; 204498686cd2SShayne Chen 204598686cd2SShayne Chen /* ba miss count */ 204698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR0(band_idx)); 204798686cd2SShayne Chen mib->ba_miss_cnt += cnt; 204898686cd2SShayne Chen 204998686cd2SShayne Chen /* ack fail count */ 205098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BFTFCR(band_idx)); 205198686cd2SShayne Chen mib->ack_fail_cnt += cnt; 205298686cd2SShayne Chen 205398686cd2SShayne Chen for (i = 0; i < 16; i++) { 205498686cd2SShayne Chen cnt = mt76_rr(dev, MT_TX_AGG_CNT(band_idx, i)); 205598686cd2SShayne Chen phy->mt76->aggr_stats[i] += cnt; 205698686cd2SShayne Chen } 205798686cd2SShayne Chen } 205898686cd2SShayne Chen 205998686cd2SShayne Chen void mt7996_mac_sta_rc_work(struct work_struct *work) 206098686cd2SShayne Chen { 206198686cd2SShayne Chen struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work); 206298686cd2SShayne Chen struct ieee80211_sta *sta; 206398686cd2SShayne Chen struct ieee80211_vif *vif; 206498686cd2SShayne Chen struct mt7996_sta *msta; 206598686cd2SShayne Chen u32 changed; 206698686cd2SShayne Chen LIST_HEAD(list); 206798686cd2SShayne Chen 206898686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 206998686cd2SShayne Chen list_splice_init(&dev->sta_rc_list, &list); 207098686cd2SShayne Chen 207198686cd2SShayne Chen while (!list_empty(&list)) { 207298686cd2SShayne Chen msta = list_first_entry(&list, struct mt7996_sta, rc_list); 207398686cd2SShayne Chen list_del_init(&msta->rc_list); 207498686cd2SShayne Chen changed = msta->changed; 207598686cd2SShayne Chen msta->changed = 0; 207698686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 207798686cd2SShayne Chen 207898686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); 207998686cd2SShayne Chen vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); 208098686cd2SShayne Chen 208198686cd2SShayne Chen if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | 208298686cd2SShayne Chen IEEE80211_RC_NSS_CHANGED | 208398686cd2SShayne Chen IEEE80211_RC_BW_CHANGED)) 208498686cd2SShayne Chen mt7996_mcu_add_rate_ctrl(dev, vif, sta, true); 208598686cd2SShayne Chen 208698686cd2SShayne Chen /* TODO: smps change */ 208798686cd2SShayne Chen 208898686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 208998686cd2SShayne Chen } 209098686cd2SShayne Chen 209198686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 209298686cd2SShayne Chen } 209398686cd2SShayne Chen 209498686cd2SShayne Chen void mt7996_mac_work(struct work_struct *work) 209598686cd2SShayne Chen { 209698686cd2SShayne Chen struct mt7996_phy *phy; 209798686cd2SShayne Chen struct mt76_phy *mphy; 209898686cd2SShayne Chen 209998686cd2SShayne Chen mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, 210098686cd2SShayne Chen mac_work.work); 210198686cd2SShayne Chen phy = mphy->priv; 210298686cd2SShayne Chen 210398686cd2SShayne Chen mutex_lock(&mphy->dev->mutex); 210498686cd2SShayne Chen 210598686cd2SShayne Chen mt76_update_survey(mphy); 210698686cd2SShayne Chen if (++mphy->mac_work_count == 5) { 210798686cd2SShayne Chen mphy->mac_work_count = 0; 210898686cd2SShayne Chen 210998686cd2SShayne Chen mt7996_mac_update_stats(phy); 211098686cd2SShayne Chen } 211198686cd2SShayne Chen 211298686cd2SShayne Chen mutex_unlock(&mphy->dev->mutex); 211398686cd2SShayne Chen 211498686cd2SShayne Chen mt76_tx_status_check(mphy->dev, false); 211598686cd2SShayne Chen 211698686cd2SShayne Chen ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, 211798686cd2SShayne Chen MT7996_WATCHDOG_TIME); 211898686cd2SShayne Chen } 211998686cd2SShayne Chen 212098686cd2SShayne Chen static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy) 212198686cd2SShayne Chen { 212298686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 212398686cd2SShayne Chen 212498686cd2SShayne Chen if (phy->rdd_state & BIT(0)) 212598686cd2SShayne Chen mt7996_mcu_rdd_cmd(dev, RDD_STOP, 0, 212698686cd2SShayne Chen MT_RX_SEL0, 0); 212798686cd2SShayne Chen if (phy->rdd_state & BIT(1)) 212898686cd2SShayne Chen mt7996_mcu_rdd_cmd(dev, RDD_STOP, 1, 212998686cd2SShayne Chen MT_RX_SEL0, 0); 213098686cd2SShayne Chen } 213198686cd2SShayne Chen 213298686cd2SShayne Chen static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int chain) 213398686cd2SShayne Chen { 213498686cd2SShayne Chen int err, region; 213598686cd2SShayne Chen 213698686cd2SShayne Chen switch (dev->mt76.region) { 213798686cd2SShayne Chen case NL80211_DFS_ETSI: 213898686cd2SShayne Chen region = 0; 213998686cd2SShayne Chen break; 214098686cd2SShayne Chen case NL80211_DFS_JP: 214198686cd2SShayne Chen region = 2; 214298686cd2SShayne Chen break; 214398686cd2SShayne Chen case NL80211_DFS_FCC: 214498686cd2SShayne Chen default: 214598686cd2SShayne Chen region = 1; 214698686cd2SShayne Chen break; 214798686cd2SShayne Chen } 214898686cd2SShayne Chen 214998686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_START, chain, 215098686cd2SShayne Chen MT_RX_SEL0, region); 215198686cd2SShayne Chen if (err < 0) 215298686cd2SShayne Chen return err; 215398686cd2SShayne Chen 215498686cd2SShayne Chen return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, chain, 215598686cd2SShayne Chen MT_RX_SEL0, 1); 215698686cd2SShayne Chen } 215798686cd2SShayne Chen 215898686cd2SShayne Chen static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy) 215998686cd2SShayne Chen { 216098686cd2SShayne Chen struct cfg80211_chan_def *chandef = &phy->mt76->chandef; 216198686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 216298686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 216398686cd2SShayne Chen int err; 216498686cd2SShayne Chen 216598686cd2SShayne Chen /* start CAC */ 216698686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_START, band_idx, 216798686cd2SShayne Chen MT_RX_SEL0, 0); 216898686cd2SShayne Chen if (err < 0) 216998686cd2SShayne Chen return err; 217098686cd2SShayne Chen 217198686cd2SShayne Chen err = mt7996_dfs_start_rdd(dev, band_idx); 217298686cd2SShayne Chen if (err < 0) 217398686cd2SShayne Chen return err; 217498686cd2SShayne Chen 217598686cd2SShayne Chen phy->rdd_state |= BIT(band_idx); 217698686cd2SShayne Chen 217798686cd2SShayne Chen if (chandef->width == NL80211_CHAN_WIDTH_160 || 217898686cd2SShayne Chen chandef->width == NL80211_CHAN_WIDTH_80P80) { 217998686cd2SShayne Chen err = mt7996_dfs_start_rdd(dev, 1); 218098686cd2SShayne Chen if (err < 0) 218198686cd2SShayne Chen return err; 218298686cd2SShayne Chen 218398686cd2SShayne Chen phy->rdd_state |= BIT(1); 218498686cd2SShayne Chen } 218598686cd2SShayne Chen 218698686cd2SShayne Chen return 0; 218798686cd2SShayne Chen } 218898686cd2SShayne Chen 218998686cd2SShayne Chen static int 219098686cd2SShayne Chen mt7996_dfs_init_radar_specs(struct mt7996_phy *phy) 219198686cd2SShayne Chen { 219298686cd2SShayne Chen const struct mt7996_dfs_radar_spec *radar_specs; 219398686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 219498686cd2SShayne Chen int err, i; 219598686cd2SShayne Chen 219698686cd2SShayne Chen switch (dev->mt76.region) { 219798686cd2SShayne Chen case NL80211_DFS_FCC: 219898686cd2SShayne Chen radar_specs = &fcc_radar_specs; 219998686cd2SShayne Chen err = mt7996_mcu_set_fcc5_lpn(dev, 8); 220098686cd2SShayne Chen if (err < 0) 220198686cd2SShayne Chen return err; 220298686cd2SShayne Chen break; 220398686cd2SShayne Chen case NL80211_DFS_ETSI: 220498686cd2SShayne Chen radar_specs = &etsi_radar_specs; 220598686cd2SShayne Chen break; 220698686cd2SShayne Chen case NL80211_DFS_JP: 220798686cd2SShayne Chen radar_specs = &jp_radar_specs; 220898686cd2SShayne Chen break; 220998686cd2SShayne Chen default: 221098686cd2SShayne Chen return -EINVAL; 221198686cd2SShayne Chen } 221298686cd2SShayne Chen 221398686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) { 221498686cd2SShayne Chen err = mt7996_mcu_set_radar_th(dev, i, 221598686cd2SShayne Chen &radar_specs->radar_pattern[i]); 221698686cd2SShayne Chen if (err < 0) 221798686cd2SShayne Chen return err; 221898686cd2SShayne Chen } 221998686cd2SShayne Chen 222098686cd2SShayne Chen return mt7996_mcu_set_pulse_th(dev, &radar_specs->pulse_th); 222198686cd2SShayne Chen } 222298686cd2SShayne Chen 222398686cd2SShayne Chen int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy) 222498686cd2SShayne Chen { 222598686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 222698686cd2SShayne Chen enum mt76_dfs_state dfs_state, prev_state; 222798686cd2SShayne Chen int err; 222898686cd2SShayne Chen 222998686cd2SShayne Chen prev_state = phy->mt76->dfs_state; 223098686cd2SShayne Chen dfs_state = mt76_phy_dfs_state(phy->mt76); 223198686cd2SShayne Chen 223298686cd2SShayne Chen if (prev_state == dfs_state) 223398686cd2SShayne Chen return 0; 223498686cd2SShayne Chen 223598686cd2SShayne Chen if (prev_state == MT_DFS_STATE_UNKNOWN) 223698686cd2SShayne Chen mt7996_dfs_stop_radar_detector(phy); 223798686cd2SShayne Chen 223898686cd2SShayne Chen if (dfs_state == MT_DFS_STATE_DISABLED) 223998686cd2SShayne Chen goto stop; 224098686cd2SShayne Chen 224198686cd2SShayne Chen if (prev_state <= MT_DFS_STATE_DISABLED) { 224298686cd2SShayne Chen err = mt7996_dfs_init_radar_specs(phy); 224398686cd2SShayne Chen if (err < 0) 224498686cd2SShayne Chen return err; 224598686cd2SShayne Chen 224698686cd2SShayne Chen err = mt7996_dfs_start_radar_detector(phy); 224798686cd2SShayne Chen if (err < 0) 224898686cd2SShayne Chen return err; 224998686cd2SShayne Chen 225098686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_CAC; 225198686cd2SShayne Chen } 225298686cd2SShayne Chen 225398686cd2SShayne Chen if (dfs_state == MT_DFS_STATE_CAC) 225498686cd2SShayne Chen return 0; 225598686cd2SShayne Chen 225698686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_END, 225798686cd2SShayne Chen phy->mt76->band_idx, MT_RX_SEL0, 0); 225898686cd2SShayne Chen if (err < 0) { 225998686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; 226098686cd2SShayne Chen return err; 226198686cd2SShayne Chen } 226298686cd2SShayne Chen 226398686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_ACTIVE; 226498686cd2SShayne Chen return 0; 226598686cd2SShayne Chen 226698686cd2SShayne Chen stop: 226798686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_NORMAL_START, 226898686cd2SShayne Chen phy->mt76->band_idx, MT_RX_SEL0, 0); 226998686cd2SShayne Chen if (err < 0) 227098686cd2SShayne Chen return err; 227198686cd2SShayne Chen 227298686cd2SShayne Chen mt7996_dfs_stop_radar_detector(phy); 227398686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_DISABLED; 227498686cd2SShayne Chen 227598686cd2SShayne Chen return 0; 227698686cd2SShayne Chen } 227798686cd2SShayne Chen 227898686cd2SShayne Chen static int 227998686cd2SShayne Chen mt7996_mac_twt_duration_align(int duration) 228098686cd2SShayne Chen { 228198686cd2SShayne Chen return duration << 8; 228298686cd2SShayne Chen } 228398686cd2SShayne Chen 228498686cd2SShayne Chen static u64 228598686cd2SShayne Chen mt7996_mac_twt_sched_list_add(struct mt7996_dev *dev, 228698686cd2SShayne Chen struct mt7996_twt_flow *flow) 228798686cd2SShayne Chen { 228898686cd2SShayne Chen struct mt7996_twt_flow *iter, *iter_next; 228998686cd2SShayne Chen u32 duration = flow->duration << 8; 229098686cd2SShayne Chen u64 start_tsf; 229198686cd2SShayne Chen 229298686cd2SShayne Chen iter = list_first_entry_or_null(&dev->twt_list, 229398686cd2SShayne Chen struct mt7996_twt_flow, list); 229498686cd2SShayne Chen if (!iter || !iter->sched || iter->start_tsf > duration) { 229598686cd2SShayne Chen /* add flow as first entry in the list */ 229698686cd2SShayne Chen list_add(&flow->list, &dev->twt_list); 229798686cd2SShayne Chen return 0; 229898686cd2SShayne Chen } 229998686cd2SShayne Chen 230098686cd2SShayne Chen list_for_each_entry_safe(iter, iter_next, &dev->twt_list, list) { 230198686cd2SShayne Chen start_tsf = iter->start_tsf + 230298686cd2SShayne Chen mt7996_mac_twt_duration_align(iter->duration); 230398686cd2SShayne Chen if (list_is_last(&iter->list, &dev->twt_list)) 230498686cd2SShayne Chen break; 230598686cd2SShayne Chen 230698686cd2SShayne Chen if (!iter_next->sched || 230798686cd2SShayne Chen iter_next->start_tsf > start_tsf + duration) { 230898686cd2SShayne Chen list_add(&flow->list, &iter->list); 230998686cd2SShayne Chen goto out; 231098686cd2SShayne Chen } 231198686cd2SShayne Chen } 231298686cd2SShayne Chen 231398686cd2SShayne Chen /* add flow as last entry in the list */ 231498686cd2SShayne Chen list_add_tail(&flow->list, &dev->twt_list); 231598686cd2SShayne Chen out: 231698686cd2SShayne Chen return start_tsf; 231798686cd2SShayne Chen } 231898686cd2SShayne Chen 231998686cd2SShayne Chen static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt) 232098686cd2SShayne Chen { 232198686cd2SShayne Chen struct ieee80211_twt_params *twt_agrt; 232298686cd2SShayne Chen u64 interval, duration; 232398686cd2SShayne Chen u16 mantissa; 232498686cd2SShayne Chen u8 exp; 232598686cd2SShayne Chen 232698686cd2SShayne Chen /* only individual agreement supported */ 232798686cd2SShayne Chen if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) 232898686cd2SShayne Chen return -EOPNOTSUPP; 232998686cd2SShayne Chen 233098686cd2SShayne Chen /* only 256us unit supported */ 233198686cd2SShayne Chen if (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) 233298686cd2SShayne Chen return -EOPNOTSUPP; 233398686cd2SShayne Chen 233498686cd2SShayne Chen twt_agrt = (struct ieee80211_twt_params *)twt->params; 233598686cd2SShayne Chen 233698686cd2SShayne Chen /* explicit agreement not supported */ 233798686cd2SShayne Chen if (!(twt_agrt->req_type & cpu_to_le16(IEEE80211_TWT_REQTYPE_IMPLICIT))) 233898686cd2SShayne Chen return -EOPNOTSUPP; 233998686cd2SShayne Chen 234098686cd2SShayne Chen exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, 234198686cd2SShayne Chen le16_to_cpu(twt_agrt->req_type)); 234298686cd2SShayne Chen mantissa = le16_to_cpu(twt_agrt->mantissa); 234398686cd2SShayne Chen duration = twt_agrt->min_twt_dur << 8; 234498686cd2SShayne Chen 234598686cd2SShayne Chen interval = (u64)mantissa << exp; 234698686cd2SShayne Chen if (interval < duration) 234798686cd2SShayne Chen return -EOPNOTSUPP; 234898686cd2SShayne Chen 234998686cd2SShayne Chen return 0; 235098686cd2SShayne Chen } 235198686cd2SShayne Chen 235298686cd2SShayne Chen void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, 235398686cd2SShayne Chen struct ieee80211_sta *sta, 235498686cd2SShayne Chen struct ieee80211_twt_setup *twt) 235598686cd2SShayne Chen { 235698686cd2SShayne Chen enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT; 235798686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 235898686cd2SShayne Chen struct ieee80211_twt_params *twt_agrt = (void *)twt->params; 235998686cd2SShayne Chen u16 req_type = le16_to_cpu(twt_agrt->req_type); 236098686cd2SShayne Chen enum ieee80211_twt_setup_cmd sta_setup_cmd; 236198686cd2SShayne Chen struct mt7996_dev *dev = mt7996_hw_dev(hw); 236298686cd2SShayne Chen struct mt7996_twt_flow *flow; 236398686cd2SShayne Chen int flowid, table_id; 236498686cd2SShayne Chen u8 exp; 236598686cd2SShayne Chen 236698686cd2SShayne Chen if (mt7996_mac_check_twt_req(twt)) 236798686cd2SShayne Chen goto out; 236898686cd2SShayne Chen 236998686cd2SShayne Chen mutex_lock(&dev->mt76.mutex); 237098686cd2SShayne Chen 237198686cd2SShayne Chen if (dev->twt.n_agrt == MT7996_MAX_TWT_AGRT) 237298686cd2SShayne Chen goto unlock; 237398686cd2SShayne Chen 237498686cd2SShayne Chen if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) 237598686cd2SShayne Chen goto unlock; 237698686cd2SShayne Chen 237798686cd2SShayne Chen flowid = ffs(~msta->twt.flowid_mask) - 1; 237898686cd2SShayne Chen le16p_replace_bits(&twt_agrt->req_type, flowid, 237998686cd2SShayne Chen IEEE80211_TWT_REQTYPE_FLOWID); 238098686cd2SShayne Chen 238198686cd2SShayne Chen table_id = ffs(~dev->twt.table_mask) - 1; 238298686cd2SShayne Chen exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); 238398686cd2SShayne Chen sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type); 238498686cd2SShayne Chen 238598686cd2SShayne Chen flow = &msta->twt.flow[flowid]; 238698686cd2SShayne Chen memset(flow, 0, sizeof(*flow)); 238798686cd2SShayne Chen INIT_LIST_HEAD(&flow->list); 238898686cd2SShayne Chen flow->wcid = msta->wcid.idx; 238998686cd2SShayne Chen flow->table_id = table_id; 239098686cd2SShayne Chen flow->id = flowid; 239198686cd2SShayne Chen flow->duration = twt_agrt->min_twt_dur; 239298686cd2SShayne Chen flow->mantissa = twt_agrt->mantissa; 239398686cd2SShayne Chen flow->exp = exp; 239498686cd2SShayne Chen flow->protection = !!(req_type & IEEE80211_TWT_REQTYPE_PROTECTION); 239598686cd2SShayne Chen flow->flowtype = !!(req_type & IEEE80211_TWT_REQTYPE_FLOWTYPE); 239698686cd2SShayne Chen flow->trigger = !!(req_type & IEEE80211_TWT_REQTYPE_TRIGGER); 239798686cd2SShayne Chen 239898686cd2SShayne Chen if (sta_setup_cmd == TWT_SETUP_CMD_REQUEST || 239998686cd2SShayne Chen sta_setup_cmd == TWT_SETUP_CMD_SUGGEST) { 240098686cd2SShayne Chen u64 interval = (u64)le16_to_cpu(twt_agrt->mantissa) << exp; 240198686cd2SShayne Chen u64 flow_tsf, curr_tsf; 240298686cd2SShayne Chen u32 rem; 240398686cd2SShayne Chen 240498686cd2SShayne Chen flow->sched = true; 240598686cd2SShayne Chen flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow); 240698686cd2SShayne Chen curr_tsf = __mt7996_get_tsf(hw, msta->vif); 240798686cd2SShayne Chen div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem); 240898686cd2SShayne Chen flow_tsf = curr_tsf + interval - rem; 240998686cd2SShayne Chen twt_agrt->twt = cpu_to_le64(flow_tsf); 241098686cd2SShayne Chen } else { 241198686cd2SShayne Chen list_add_tail(&flow->list, &dev->twt_list); 241298686cd2SShayne Chen } 241398686cd2SShayne Chen flow->tsf = le64_to_cpu(twt_agrt->twt); 241498686cd2SShayne Chen 241598686cd2SShayne Chen if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD)) 241698686cd2SShayne Chen goto unlock; 241798686cd2SShayne Chen 241898686cd2SShayne Chen setup_cmd = TWT_SETUP_CMD_ACCEPT; 241998686cd2SShayne Chen dev->twt.table_mask |= BIT(table_id); 242098686cd2SShayne Chen msta->twt.flowid_mask |= BIT(flowid); 242198686cd2SShayne Chen dev->twt.n_agrt++; 242298686cd2SShayne Chen 242398686cd2SShayne Chen unlock: 242498686cd2SShayne Chen mutex_unlock(&dev->mt76.mutex); 242598686cd2SShayne Chen out: 242698686cd2SShayne Chen le16p_replace_bits(&twt_agrt->req_type, setup_cmd, 242798686cd2SShayne Chen IEEE80211_TWT_REQTYPE_SETUP_CMD); 242898686cd2SShayne Chen twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | 242998686cd2SShayne Chen (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); 243098686cd2SShayne Chen } 243198686cd2SShayne Chen 243298686cd2SShayne Chen void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, 243398686cd2SShayne Chen struct mt7996_sta *msta, 243498686cd2SShayne Chen u8 flowid) 243598686cd2SShayne Chen { 243698686cd2SShayne Chen struct mt7996_twt_flow *flow; 243798686cd2SShayne Chen 243898686cd2SShayne Chen lockdep_assert_held(&dev->mt76.mutex); 243998686cd2SShayne Chen 244098686cd2SShayne Chen if (flowid >= ARRAY_SIZE(msta->twt.flow)) 244198686cd2SShayne Chen return; 244298686cd2SShayne Chen 244398686cd2SShayne Chen if (!(msta->twt.flowid_mask & BIT(flowid))) 244498686cd2SShayne Chen return; 244598686cd2SShayne Chen 244698686cd2SShayne Chen flow = &msta->twt.flow[flowid]; 244798686cd2SShayne Chen if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, 244898686cd2SShayne Chen MCU_TWT_AGRT_DELETE)) 244998686cd2SShayne Chen return; 245098686cd2SShayne Chen 245198686cd2SShayne Chen list_del_init(&flow->list); 245298686cd2SShayne Chen msta->twt.flowid_mask &= ~BIT(flowid); 245398686cd2SShayne Chen dev->twt.table_mask &= ~BIT(flow->table_id); 245498686cd2SShayne Chen dev->twt.n_agrt--; 245598686cd2SShayne Chen } 2456