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> 8878161d5SRyder Lee #include "coredump.h" 998686cd2SShayne Chen #include "mt7996.h" 1098686cd2SShayne Chen #include "../dma.h" 1198686cd2SShayne Chen #include "mac.h" 1298686cd2SShayne Chen #include "mcu.h" 1398686cd2SShayne Chen 14ea5d99d0SRyder Lee #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2) 1598686cd2SShayne Chen 1698686cd2SShayne Chen #define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) 1798686cd2SShayne Chen #define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ 1898686cd2SShayne Chen IEEE80211_RADIOTAP_HE_##f) 1998686cd2SShayne Chen 2098686cd2SShayne Chen static const struct mt7996_dfs_radar_spec etsi_radar_specs = { 2198686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 2298686cd2SShayne Chen .radar_pattern = { 2398686cd2SShayne Chen [5] = { 1, 0, 6, 32, 28, 0, 990, 5010, 17, 1, 1 }, 2498686cd2SShayne Chen [6] = { 1, 0, 9, 32, 28, 0, 615, 5010, 27, 1, 1 }, 2598686cd2SShayne Chen [7] = { 1, 0, 15, 32, 28, 0, 240, 445, 27, 1, 1 }, 2698686cd2SShayne Chen [8] = { 1, 0, 12, 32, 28, 0, 240, 510, 42, 1, 1 }, 2798686cd2SShayne Chen [9] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 12, 32, 28, { }, 126 }, 2898686cd2SShayne Chen [10] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 15, 32, 24, { }, 126 }, 2998686cd2SShayne Chen [11] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 18, 32, 28, { }, 54 }, 3098686cd2SShayne Chen [12] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 27, 32, 24, { }, 54 }, 3198686cd2SShayne Chen }, 3298686cd2SShayne Chen }; 3398686cd2SShayne Chen 3498686cd2SShayne Chen static const struct mt7996_dfs_radar_spec fcc_radar_specs = { 3598686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 3698686cd2SShayne Chen .radar_pattern = { 3798686cd2SShayne Chen [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, 3898686cd2SShayne Chen [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, 3998686cd2SShayne Chen [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, 4098686cd2SShayne Chen [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, 4198686cd2SShayne Chen [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, 4298686cd2SShayne Chen }, 4398686cd2SShayne Chen }; 4498686cd2SShayne Chen 4598686cd2SShayne Chen static const struct mt7996_dfs_radar_spec jp_radar_specs = { 4698686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 4798686cd2SShayne Chen .radar_pattern = { 4898686cd2SShayne Chen [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, 4998686cd2SShayne Chen [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, 5098686cd2SShayne Chen [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, 5198686cd2SShayne Chen [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, 5298686cd2SShayne Chen [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, 5398686cd2SShayne Chen [13] = { 1, 0, 7, 32, 28, 0, 3836, 3856, 14, 1, 1 }, 5498686cd2SShayne Chen [14] = { 1, 0, 6, 32, 28, 0, 615, 5010, 110, 1, 1 }, 5598686cd2SShayne Chen [15] = { 1, 1, 0, 0, 0, 0, 15, 5010, 110, 0, 0, 12, 32, 28 }, 5698686cd2SShayne Chen }, 5798686cd2SShayne Chen }; 5898686cd2SShayne Chen 5998686cd2SShayne Chen static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev, 6098686cd2SShayne Chen u16 idx, bool unicast) 6198686cd2SShayne Chen { 6298686cd2SShayne Chen struct mt7996_sta *sta; 6398686cd2SShayne Chen struct mt76_wcid *wcid; 6498686cd2SShayne Chen 6598686cd2SShayne Chen if (idx >= ARRAY_SIZE(dev->mt76.wcid)) 6698686cd2SShayne Chen return NULL; 6798686cd2SShayne Chen 6898686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[idx]); 6998686cd2SShayne Chen if (unicast || !wcid) 7098686cd2SShayne Chen return wcid; 7198686cd2SShayne Chen 7298686cd2SShayne Chen if (!wcid->sta) 7398686cd2SShayne Chen return NULL; 7498686cd2SShayne Chen 7598686cd2SShayne Chen sta = container_of(wcid, struct mt7996_sta, wcid); 7698686cd2SShayne Chen if (!sta->vif) 7798686cd2SShayne Chen return NULL; 7898686cd2SShayne Chen 7998686cd2SShayne Chen return &sta->vif->sta.wcid; 8098686cd2SShayne Chen } 8198686cd2SShayne Chen 8298686cd2SShayne Chen bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask) 8398686cd2SShayne Chen { 8498686cd2SShayne Chen mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, 8598686cd2SShayne Chen FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); 8698686cd2SShayne Chen 8798686cd2SShayne Chen return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 8898686cd2SShayne Chen 0, 5000); 8998686cd2SShayne Chen } 9098686cd2SShayne Chen 9198686cd2SShayne Chen u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw) 9298686cd2SShayne Chen { 9398686cd2SShayne Chen mt76_wr(dev, MT_WTBLON_TOP_WDUCR, 9498686cd2SShayne Chen FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); 9598686cd2SShayne Chen 9698686cd2SShayne Chen return MT_WTBL_LMAC_OFFS(wcid, dw); 9798686cd2SShayne Chen } 9898686cd2SShayne Chen 9998686cd2SShayne Chen static void mt7996_mac_sta_poll(struct mt7996_dev *dev) 10098686cd2SShayne Chen { 10198686cd2SShayne Chen static const u8 ac_to_tid[] = { 10298686cd2SShayne Chen [IEEE80211_AC_BE] = 0, 10398686cd2SShayne Chen [IEEE80211_AC_BK] = 1, 10498686cd2SShayne Chen [IEEE80211_AC_VI] = 4, 10598686cd2SShayne Chen [IEEE80211_AC_VO] = 6 10698686cd2SShayne Chen }; 10798686cd2SShayne Chen struct ieee80211_sta *sta; 10898686cd2SShayne Chen struct mt7996_sta *msta; 10998686cd2SShayne Chen struct rate_info *rate; 11098686cd2SShayne Chen u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; 11198686cd2SShayne Chen LIST_HEAD(sta_poll_list); 11298686cd2SShayne Chen int i; 11398686cd2SShayne Chen 11498686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 11598686cd2SShayne Chen list_splice_init(&dev->sta_poll_list, &sta_poll_list); 11698686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 11798686cd2SShayne Chen 11898686cd2SShayne Chen rcu_read_lock(); 11998686cd2SShayne Chen 12098686cd2SShayne Chen while (true) { 12198686cd2SShayne Chen bool clear = false; 12298686cd2SShayne Chen u32 addr, val; 12398686cd2SShayne Chen u16 idx; 124ea5d99d0SRyder Lee s8 rssi[4]; 12598686cd2SShayne Chen u8 bw; 12698686cd2SShayne Chen 12798686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 12898686cd2SShayne Chen if (list_empty(&sta_poll_list)) { 12998686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 13098686cd2SShayne Chen break; 13198686cd2SShayne Chen } 13298686cd2SShayne Chen msta = list_first_entry(&sta_poll_list, 13398686cd2SShayne Chen struct mt7996_sta, poll_list); 13498686cd2SShayne Chen list_del_init(&msta->poll_list); 13598686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 13698686cd2SShayne Chen 13798686cd2SShayne Chen idx = msta->wcid.idx; 138ea5d99d0SRyder Lee 139ea5d99d0SRyder Lee /* refresh peer's airtime reporting */ 14098686cd2SShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20); 14198686cd2SShayne Chen 14298686cd2SShayne Chen for (i = 0; i < IEEE80211_NUM_ACS; i++) { 14398686cd2SShayne Chen u32 tx_last = msta->airtime_ac[i]; 14498686cd2SShayne Chen u32 rx_last = msta->airtime_ac[i + 4]; 14598686cd2SShayne Chen 14698686cd2SShayne Chen msta->airtime_ac[i] = mt76_rr(dev, addr); 14798686cd2SShayne Chen msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); 14898686cd2SShayne Chen 14998686cd2SShayne Chen tx_time[i] = msta->airtime_ac[i] - tx_last; 15098686cd2SShayne Chen rx_time[i] = msta->airtime_ac[i + 4] - rx_last; 15198686cd2SShayne Chen 15298686cd2SShayne Chen if ((tx_last | rx_last) & BIT(30)) 15398686cd2SShayne Chen clear = true; 15498686cd2SShayne Chen 15598686cd2SShayne Chen addr += 8; 15698686cd2SShayne Chen } 15798686cd2SShayne Chen 15898686cd2SShayne Chen if (clear) { 15998686cd2SShayne Chen mt7996_mac_wtbl_update(dev, idx, 16098686cd2SShayne Chen MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 16198686cd2SShayne Chen memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); 16298686cd2SShayne Chen } 16398686cd2SShayne Chen 16498686cd2SShayne Chen if (!msta->wcid.sta) 16598686cd2SShayne Chen continue; 16698686cd2SShayne Chen 16798686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, 16898686cd2SShayne Chen drv_priv); 16998686cd2SShayne Chen for (i = 0; i < IEEE80211_NUM_ACS; i++) { 17098686cd2SShayne Chen u8 q = mt76_connac_lmac_mapping(i); 17198686cd2SShayne Chen u32 tx_cur = tx_time[q]; 17298686cd2SShayne Chen u32 rx_cur = rx_time[q]; 17398686cd2SShayne Chen u8 tid = ac_to_tid[i]; 17498686cd2SShayne Chen 17598686cd2SShayne Chen if (!tx_cur && !rx_cur) 17698686cd2SShayne Chen continue; 17798686cd2SShayne Chen 17898686cd2SShayne Chen ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur); 17998686cd2SShayne Chen } 18098686cd2SShayne Chen 18198686cd2SShayne Chen /* We don't support reading GI info from txs packets. 18298686cd2SShayne Chen * For accurate tx status reporting and AQL improvement, 18398686cd2SShayne Chen * we need to make sure that flags match so polling GI 18498686cd2SShayne Chen * from per-sta counters directly. 18598686cd2SShayne Chen */ 18698686cd2SShayne Chen rate = &msta->wcid.rate; 18798686cd2SShayne Chen 18898686cd2SShayne Chen switch (rate->bw) { 18980f5a31dSShayne Chen case RATE_INFO_BW_320: 19080f5a31dSShayne Chen bw = IEEE80211_STA_RX_BW_320; 19180f5a31dSShayne Chen break; 19298686cd2SShayne Chen case RATE_INFO_BW_160: 19398686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_160; 19498686cd2SShayne Chen break; 19598686cd2SShayne Chen case RATE_INFO_BW_80: 19698686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_80; 19798686cd2SShayne Chen break; 19898686cd2SShayne Chen case RATE_INFO_BW_40: 19998686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_40; 20098686cd2SShayne Chen break; 20198686cd2SShayne Chen default: 20298686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_20; 20398686cd2SShayne Chen break; 20498686cd2SShayne Chen } 20598686cd2SShayne Chen 20698686cd2SShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 6); 20798686cd2SShayne Chen val = mt76_rr(dev, addr); 20880f5a31dSShayne Chen if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) { 20980f5a31dSShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 5); 21080f5a31dSShayne Chen val = mt76_rr(dev, addr); 21180f5a31dSShayne Chen rate->eht_gi = FIELD_GET(GENMASK(25, 24), val); 21280f5a31dSShayne Chen } else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { 21398686cd2SShayne Chen u8 offs = 24 + 2 * bw; 21498686cd2SShayne Chen 21598686cd2SShayne Chen rate->he_gi = (val & (0x3 << offs)) >> offs; 21698686cd2SShayne Chen } else if (rate->flags & 21798686cd2SShayne Chen (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) { 21898686cd2SShayne Chen if (val & BIT(12 + bw)) 21998686cd2SShayne Chen rate->flags |= RATE_INFO_FLAGS_SHORT_GI; 22098686cd2SShayne Chen else 22198686cd2SShayne Chen rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI; 22298686cd2SShayne Chen } 223ea5d99d0SRyder Lee 224ea5d99d0SRyder Lee /* get signal strength of resp frames (CTS/BA/ACK) */ 225ea5d99d0SRyder Lee addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34); 226ea5d99d0SRyder Lee val = mt76_rr(dev, addr); 227ea5d99d0SRyder Lee 228ea5d99d0SRyder Lee rssi[0] = to_rssi(GENMASK(7, 0), val); 229ea5d99d0SRyder Lee rssi[1] = to_rssi(GENMASK(15, 8), val); 230ea5d99d0SRyder Lee rssi[2] = to_rssi(GENMASK(23, 16), val); 231ea5d99d0SRyder Lee rssi[3] = to_rssi(GENMASK(31, 14), val); 232ea5d99d0SRyder Lee 233ea5d99d0SRyder Lee msta->ack_signal = 234ea5d99d0SRyder Lee mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); 235ea5d99d0SRyder Lee 236ea5d99d0SRyder Lee ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); 23798686cd2SShayne Chen } 23898686cd2SShayne Chen 23998686cd2SShayne Chen rcu_read_unlock(); 24098686cd2SShayne Chen } 24198686cd2SShayne Chen 242d75e739bSRyder Lee void mt7996_mac_enable_rtscts(struct mt7996_dev *dev, 243d75e739bSRyder Lee struct ieee80211_vif *vif, bool enable) 244d75e739bSRyder Lee { 245d75e739bSRyder Lee struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 246d75e739bSRyder Lee u32 addr; 247d75e739bSRyder Lee 248d75e739bSRyder Lee addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5); 249d75e739bSRyder Lee if (enable) 250d75e739bSRyder Lee mt76_set(dev, addr, BIT(5)); 251d75e739bSRyder Lee else 252d75e739bSRyder Lee mt76_clear(dev, addr, BIT(5)); 253d75e739bSRyder Lee } 254d75e739bSRyder Lee 25515ee62e7SRyder Lee void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev, 25615ee62e7SRyder Lee u8 tbl_idx, u16 rate_idx) 25715ee62e7SRyder Lee { 25815ee62e7SRyder Lee u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx; 25915ee62e7SRyder Lee 26015ee62e7SRyder Lee mt76_wr(dev, MT_WTBL_ITDR0, rate_idx); 26115ee62e7SRyder Lee /* use wtbl spe idx */ 26215ee62e7SRyder Lee mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL); 26315ee62e7SRyder Lee mt76_wr(dev, MT_WTBL_ITCR, ctrl); 26415ee62e7SRyder Lee } 26515ee62e7SRyder Lee 26698686cd2SShayne Chen static void 26798686cd2SShayne Chen mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, 26898686cd2SShayne Chen struct ieee80211_radiotap_he *he, 26998686cd2SShayne Chen __le32 *rxv) 27098686cd2SShayne Chen { 27163a37246SRyder Lee u32 ru, offs = 0; 27298686cd2SShayne Chen 27363a37246SRyder Lee ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC); 27498686cd2SShayne Chen 27598686cd2SShayne Chen status->bw = RATE_INFO_BW_HE_RU; 27698686cd2SShayne Chen 27798686cd2SShayne Chen switch (ru) { 27898686cd2SShayne Chen case 0 ... 36: 27998686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; 28098686cd2SShayne Chen offs = ru; 28198686cd2SShayne Chen break; 28298686cd2SShayne Chen case 37 ... 52: 28398686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; 28498686cd2SShayne Chen offs = ru - 37; 28598686cd2SShayne Chen break; 28698686cd2SShayne Chen case 53 ... 60: 28798686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; 28898686cd2SShayne Chen offs = ru - 53; 28998686cd2SShayne Chen break; 29098686cd2SShayne Chen case 61 ... 64: 29198686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; 29298686cd2SShayne Chen offs = ru - 61; 29398686cd2SShayne Chen break; 29498686cd2SShayne Chen case 65 ... 66: 29598686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; 29698686cd2SShayne Chen offs = ru - 65; 29798686cd2SShayne Chen break; 29898686cd2SShayne Chen case 67: 29998686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; 30098686cd2SShayne Chen break; 30198686cd2SShayne Chen case 68: 30298686cd2SShayne Chen status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; 30398686cd2SShayne Chen break; 30498686cd2SShayne Chen } 30598686cd2SShayne Chen 30698686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 30798686cd2SShayne Chen he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | 30898686cd2SShayne Chen le16_encode_bits(offs, 30998686cd2SShayne Chen IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); 31098686cd2SShayne Chen } 31198686cd2SShayne Chen 31298686cd2SShayne Chen static void 31398686cd2SShayne Chen mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) 31498686cd2SShayne Chen { 31598686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 31698686cd2SShayne Chen static const struct ieee80211_radiotap_he_mu mu_known = { 31798686cd2SShayne Chen .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | 31898686cd2SShayne Chen HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | 31998686cd2SShayne Chen HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | 32098686cd2SShayne Chen HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), 32198686cd2SShayne Chen .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), 32298686cd2SShayne Chen }; 32398686cd2SShayne Chen struct ieee80211_radiotap_he_mu *he_mu = NULL; 32498686cd2SShayne Chen 32598686cd2SShayne Chen status->flag |= RX_FLAG_RADIOTAP_HE_MU; 32698686cd2SShayne Chen 32798686cd2SShayne Chen he_mu = skb_push(skb, sizeof(mu_known)); 32898686cd2SShayne Chen memcpy(he_mu, &mu_known, sizeof(mu_known)); 32998686cd2SShayne Chen 33098686cd2SShayne Chen #define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) 33198686cd2SShayne Chen 33298686cd2SShayne Chen he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); 33398686cd2SShayne Chen if (status->he_dcm) 33498686cd2SShayne Chen he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); 33598686cd2SShayne Chen 33698686cd2SShayne Chen he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | 33798686cd2SShayne Chen MU_PREP(FLAGS2_SIG_B_SYMS_USERS, 33863a37246SRyder Lee le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER)); 33998686cd2SShayne Chen 34063a37246SRyder Lee he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff; 34198686cd2SShayne Chen 34298686cd2SShayne Chen if (status->bw >= RATE_INFO_BW_40) { 34398686cd2SShayne Chen he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); 34463a37246SRyder Lee he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff; 34598686cd2SShayne Chen } 34698686cd2SShayne Chen 34798686cd2SShayne Chen if (status->bw >= RATE_INFO_BW_80) { 34863a37246SRyder Lee u32 ru_h, ru_l; 34963a37246SRyder Lee 35063a37246SRyder Lee he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff; 35163a37246SRyder Lee 35263a37246SRyder Lee ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); 35363a37246SRyder Lee ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; 35463a37246SRyder Lee he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); 35598686cd2SShayne Chen } 35698686cd2SShayne Chen } 35798686cd2SShayne Chen 35898686cd2SShayne Chen static void 35998686cd2SShayne Chen mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode) 36098686cd2SShayne Chen { 36198686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 36298686cd2SShayne Chen static const struct ieee80211_radiotap_he known = { 36398686cd2SShayne Chen .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | 36498686cd2SShayne Chen HE_BITS(DATA1_DATA_DCM_KNOWN) | 36598686cd2SShayne Chen HE_BITS(DATA1_STBC_KNOWN) | 36698686cd2SShayne Chen HE_BITS(DATA1_CODING_KNOWN) | 36798686cd2SShayne Chen HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | 36898686cd2SShayne Chen HE_BITS(DATA1_DOPPLER_KNOWN) | 36998686cd2SShayne Chen HE_BITS(DATA1_SPTL_REUSE_KNOWN) | 37098686cd2SShayne Chen HE_BITS(DATA1_BSS_COLOR_KNOWN), 37198686cd2SShayne Chen .data2 = HE_BITS(DATA2_GI_KNOWN) | 37298686cd2SShayne Chen HE_BITS(DATA2_TXBF_KNOWN) | 37398686cd2SShayne Chen HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | 37498686cd2SShayne Chen HE_BITS(DATA2_TXOP_KNOWN), 37598686cd2SShayne Chen }; 37698686cd2SShayne Chen struct ieee80211_radiotap_he *he = NULL; 37763a37246SRyder Lee u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; 37898686cd2SShayne Chen 37998686cd2SShayne Chen status->flag |= RX_FLAG_RADIOTAP_HE; 38098686cd2SShayne Chen 38198686cd2SShayne Chen he = skb_push(skb, sizeof(known)); 38298686cd2SShayne Chen memcpy(he, &known, sizeof(known)); 38398686cd2SShayne Chen 38463a37246SRyder Lee he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | 38563a37246SRyder Lee HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); 38663a37246SRyder Lee he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); 38763a37246SRyder Lee he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | 38898686cd2SShayne Chen le16_encode_bits(ltf_size, 38998686cd2SShayne Chen IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); 39098686cd2SShayne Chen if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) 39198686cd2SShayne Chen he->data5 |= HE_BITS(DATA5_TXBF); 39263a37246SRyder Lee he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | 39363a37246SRyder Lee HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); 39498686cd2SShayne Chen 39598686cd2SShayne Chen switch (mode) { 39698686cd2SShayne Chen case MT_PHY_TYPE_HE_SU: 39798686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_FORMAT_SU) | 39898686cd2SShayne Chen HE_BITS(DATA1_UL_DL_KNOWN) | 39998686cd2SShayne Chen HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | 40098686cd2SShayne Chen HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 40198686cd2SShayne Chen 40263a37246SRyder Lee he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) | 40363a37246SRyder Lee HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 40498686cd2SShayne Chen break; 40598686cd2SShayne Chen case MT_PHY_TYPE_HE_EXT_SU: 40698686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | 40798686cd2SShayne Chen HE_BITS(DATA1_UL_DL_KNOWN) | 40898686cd2SShayne Chen HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 40998686cd2SShayne Chen 41063a37246SRyder Lee he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 41198686cd2SShayne Chen break; 41298686cd2SShayne Chen case MT_PHY_TYPE_HE_MU: 41398686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_FORMAT_MU) | 41498686cd2SShayne Chen HE_BITS(DATA1_UL_DL_KNOWN); 41598686cd2SShayne Chen 41663a37246SRyder Lee he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 41763a37246SRyder Lee he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); 41898686cd2SShayne Chen 41998686cd2SShayne Chen mt7996_mac_decode_he_radiotap_ru(status, he, rxv); 42098686cd2SShayne Chen mt7996_mac_decode_he_mu_radiotap(skb, rxv); 42198686cd2SShayne Chen break; 42298686cd2SShayne Chen case MT_PHY_TYPE_HE_TB: 42398686cd2SShayne Chen he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | 42498686cd2SShayne Chen HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | 42598686cd2SShayne Chen HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | 42698686cd2SShayne Chen HE_BITS(DATA1_SPTL_REUSE4_KNOWN); 42798686cd2SShayne Chen 42863a37246SRyder Lee he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) | 42963a37246SRyder Lee HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) | 43063a37246SRyder Lee HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) | 43163a37246SRyder Lee HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]); 43298686cd2SShayne Chen 43398686cd2SShayne Chen mt7996_mac_decode_he_radiotap_ru(status, he, rxv); 43498686cd2SShayne Chen break; 43598686cd2SShayne Chen default: 43698686cd2SShayne Chen break; 43798686cd2SShayne Chen } 43898686cd2SShayne Chen } 43998686cd2SShayne Chen 44098686cd2SShayne Chen /* The HW does not translate the mac header to 802.3 for mesh point */ 44198686cd2SShayne Chen static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) 44298686cd2SShayne Chen { 44398686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 44498686cd2SShayne Chen struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap); 44598686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)status->wcid; 44698686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 44798686cd2SShayne Chen struct ieee80211_sta *sta; 44898686cd2SShayne Chen struct ieee80211_vif *vif; 44998686cd2SShayne Chen struct ieee80211_hdr hdr; 45098686cd2SShayne Chen u16 frame_control; 45198686cd2SShayne Chen 45298686cd2SShayne Chen if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) != 45398686cd2SShayne Chen MT_RXD3_NORMAL_U2M) 45498686cd2SShayne Chen return -EINVAL; 45598686cd2SShayne Chen 45698686cd2SShayne Chen if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4)) 45798686cd2SShayne Chen return -EINVAL; 45898686cd2SShayne Chen 45998686cd2SShayne Chen if (!msta || !msta->vif) 46098686cd2SShayne Chen return -EINVAL; 46198686cd2SShayne Chen 46298686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); 46398686cd2SShayne Chen vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); 46498686cd2SShayne Chen 46598686cd2SShayne Chen /* store the info from RXD and ethhdr to avoid being overridden */ 46698686cd2SShayne Chen frame_control = le32_get_bits(rxd[8], MT_RXD8_FRAME_CONTROL); 46798686cd2SShayne Chen hdr.frame_control = cpu_to_le16(frame_control); 46898686cd2SShayne Chen hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_SEQ_CTRL)); 46998686cd2SShayne Chen hdr.duration_id = 0; 47098686cd2SShayne Chen 47198686cd2SShayne Chen ether_addr_copy(hdr.addr1, vif->addr); 47298686cd2SShayne Chen ether_addr_copy(hdr.addr2, sta->addr); 47398686cd2SShayne Chen switch (frame_control & (IEEE80211_FCTL_TODS | 47498686cd2SShayne Chen IEEE80211_FCTL_FROMDS)) { 47598686cd2SShayne Chen case 0: 47698686cd2SShayne Chen ether_addr_copy(hdr.addr3, vif->bss_conf.bssid); 47798686cd2SShayne Chen break; 47898686cd2SShayne Chen case IEEE80211_FCTL_FROMDS: 47998686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_source); 48098686cd2SShayne Chen break; 48198686cd2SShayne Chen case IEEE80211_FCTL_TODS: 48298686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_dest); 48398686cd2SShayne Chen break; 48498686cd2SShayne Chen case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS: 48598686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_dest); 48698686cd2SShayne Chen ether_addr_copy(hdr.addr4, eth_hdr->h_source); 48798686cd2SShayne Chen break; 48898686cd2SShayne Chen default: 489aed8d9b5SLorenzo Bianconi return -EINVAL; 49098686cd2SShayne Chen } 49198686cd2SShayne Chen 49298686cd2SShayne Chen skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2); 49398686cd2SShayne Chen if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) || 49498686cd2SShayne Chen eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX)) 49598686cd2SShayne Chen ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header); 49698686cd2SShayne Chen else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN) 49798686cd2SShayne Chen ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header); 49898686cd2SShayne Chen else 49998686cd2SShayne Chen skb_pull(skb, 2); 50098686cd2SShayne Chen 50198686cd2SShayne Chen if (ieee80211_has_order(hdr.frame_control)) 50298686cd2SShayne Chen memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[11], 50398686cd2SShayne Chen IEEE80211_HT_CTL_LEN); 50498686cd2SShayne Chen if (ieee80211_is_data_qos(hdr.frame_control)) { 50598686cd2SShayne Chen __le16 qos_ctrl; 50698686cd2SShayne Chen 50798686cd2SShayne Chen qos_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_QOS_CTL)); 50898686cd2SShayne Chen memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl, 50998686cd2SShayne Chen IEEE80211_QOS_CTL_LEN); 51098686cd2SShayne Chen } 51198686cd2SShayne Chen 51298686cd2SShayne Chen if (ieee80211_has_a4(hdr.frame_control)) 51398686cd2SShayne Chen memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr)); 51498686cd2SShayne Chen else 51598686cd2SShayne Chen memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6); 51698686cd2SShayne Chen 51798686cd2SShayne Chen return 0; 51898686cd2SShayne Chen } 51998686cd2SShayne Chen 52098686cd2SShayne Chen static int 52198686cd2SShayne Chen mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, 52298686cd2SShayne Chen struct mt76_rx_status *status, 52398686cd2SShayne Chen struct ieee80211_supported_band *sband, 52498686cd2SShayne Chen __le32 *rxv, u8 *mode) 52598686cd2SShayne Chen { 52698686cd2SShayne Chen u32 v0, v2; 52798686cd2SShayne Chen u8 stbc, gi, bw, dcm, nss; 52898686cd2SShayne Chen int i, idx; 52998686cd2SShayne Chen bool cck = false; 53098686cd2SShayne Chen 53198686cd2SShayne Chen v0 = le32_to_cpu(rxv[0]); 53298686cd2SShayne Chen v2 = le32_to_cpu(rxv[2]); 53398686cd2SShayne Chen 53498686cd2SShayne Chen idx = FIELD_GET(MT_PRXV_TX_RATE, v0); 53598686cd2SShayne Chen i = idx; 53698686cd2SShayne Chen nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1; 53798686cd2SShayne Chen 53898686cd2SShayne Chen stbc = FIELD_GET(MT_PRXV_HT_STBC, v2); 53998686cd2SShayne Chen gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2); 54098686cd2SShayne Chen *mode = FIELD_GET(MT_PRXV_TX_MODE, v2); 54198686cd2SShayne Chen dcm = FIELD_GET(MT_PRXV_DCM, v2); 54298686cd2SShayne Chen bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2); 54398686cd2SShayne Chen 54498686cd2SShayne Chen switch (*mode) { 54598686cd2SShayne Chen case MT_PHY_TYPE_CCK: 54698686cd2SShayne Chen cck = true; 54798686cd2SShayne Chen fallthrough; 54898686cd2SShayne Chen case MT_PHY_TYPE_OFDM: 54998686cd2SShayne Chen i = mt76_get_rate(&dev->mt76, sband, i, cck); 55098686cd2SShayne Chen break; 55198686cd2SShayne Chen case MT_PHY_TYPE_HT_GF: 55298686cd2SShayne Chen case MT_PHY_TYPE_HT: 55398686cd2SShayne Chen status->encoding = RX_ENC_HT; 55498686cd2SShayne Chen if (gi) 55598686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 55698686cd2SShayne Chen if (i > 31) 55798686cd2SShayne Chen return -EINVAL; 55898686cd2SShayne Chen break; 55998686cd2SShayne Chen case MT_PHY_TYPE_VHT: 56098686cd2SShayne Chen status->nss = nss; 56198686cd2SShayne Chen status->encoding = RX_ENC_VHT; 56298686cd2SShayne Chen if (gi) 56398686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 56498686cd2SShayne Chen if (i > 11) 56598686cd2SShayne Chen return -EINVAL; 56698686cd2SShayne Chen break; 56798686cd2SShayne Chen case MT_PHY_TYPE_HE_MU: 56898686cd2SShayne Chen case MT_PHY_TYPE_HE_SU: 56998686cd2SShayne Chen case MT_PHY_TYPE_HE_EXT_SU: 57098686cd2SShayne Chen case MT_PHY_TYPE_HE_TB: 57198686cd2SShayne Chen status->nss = nss; 57298686cd2SShayne Chen status->encoding = RX_ENC_HE; 57398686cd2SShayne Chen i &= GENMASK(3, 0); 57498686cd2SShayne Chen 57598686cd2SShayne Chen if (gi <= NL80211_RATE_INFO_HE_GI_3_2) 57698686cd2SShayne Chen status->he_gi = gi; 57798686cd2SShayne Chen 57898686cd2SShayne Chen status->he_dcm = dcm; 57998686cd2SShayne Chen break; 58080f5a31dSShayne Chen case MT_PHY_TYPE_EHT_SU: 58180f5a31dSShayne Chen case MT_PHY_TYPE_EHT_TRIG: 58280f5a31dSShayne Chen case MT_PHY_TYPE_EHT_MU: 58380f5a31dSShayne Chen status->nss = nss; 584021af945SShayne Chen status->encoding = RX_ENC_EHT; 585021af945SShayne Chen i &= GENMASK(3, 0); 586021af945SShayne Chen 587021af945SShayne Chen if (gi <= NL80211_RATE_INFO_EHT_GI_3_2) 588021af945SShayne Chen status->eht.gi = gi; 58980f5a31dSShayne Chen break; 59098686cd2SShayne Chen default: 59198686cd2SShayne Chen return -EINVAL; 59298686cd2SShayne Chen } 59398686cd2SShayne Chen status->rate_idx = i; 59498686cd2SShayne Chen 59598686cd2SShayne Chen switch (bw) { 59698686cd2SShayne Chen case IEEE80211_STA_RX_BW_20: 59798686cd2SShayne Chen break; 59898686cd2SShayne Chen case IEEE80211_STA_RX_BW_40: 59998686cd2SShayne Chen if (*mode & MT_PHY_TYPE_HE_EXT_SU && 60098686cd2SShayne Chen (idx & MT_PRXV_TX_ER_SU_106T)) { 60198686cd2SShayne Chen status->bw = RATE_INFO_BW_HE_RU; 60298686cd2SShayne Chen status->he_ru = 60398686cd2SShayne Chen NL80211_RATE_INFO_HE_RU_ALLOC_106; 60498686cd2SShayne Chen } else { 60598686cd2SShayne Chen status->bw = RATE_INFO_BW_40; 60698686cd2SShayne Chen } 60798686cd2SShayne Chen break; 60898686cd2SShayne Chen case IEEE80211_STA_RX_BW_80: 60998686cd2SShayne Chen status->bw = RATE_INFO_BW_80; 61098686cd2SShayne Chen break; 61198686cd2SShayne Chen case IEEE80211_STA_RX_BW_160: 61298686cd2SShayne Chen status->bw = RATE_INFO_BW_160; 61398686cd2SShayne Chen break; 61480f5a31dSShayne Chen case IEEE80211_STA_RX_BW_320: 61580f5a31dSShayne Chen status->bw = RATE_INFO_BW_320; 61680f5a31dSShayne Chen break; 61798686cd2SShayne Chen default: 61898686cd2SShayne Chen return -EINVAL; 61998686cd2SShayne Chen } 62098686cd2SShayne Chen 62198686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; 62298686cd2SShayne Chen if (*mode < MT_PHY_TYPE_HE_SU && gi) 62398686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 62498686cd2SShayne Chen 62598686cd2SShayne Chen return 0; 62698686cd2SShayne Chen } 62798686cd2SShayne Chen 62898686cd2SShayne Chen static int 62998686cd2SShayne Chen mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) 63098686cd2SShayne Chen { 63198686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 63298686cd2SShayne Chen struct mt76_phy *mphy = &dev->mt76.phy; 63398686cd2SShayne Chen struct mt7996_phy *phy = &dev->phy; 63498686cd2SShayne Chen struct ieee80211_supported_band *sband; 63598686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 63698686cd2SShayne Chen __le32 *rxv = NULL; 63798686cd2SShayne Chen u32 rxd0 = le32_to_cpu(rxd[0]); 63898686cd2SShayne Chen u32 rxd1 = le32_to_cpu(rxd[1]); 63998686cd2SShayne Chen u32 rxd2 = le32_to_cpu(rxd[2]); 64098686cd2SShayne Chen u32 rxd3 = le32_to_cpu(rxd[3]); 64198686cd2SShayne Chen u32 rxd4 = le32_to_cpu(rxd[4]); 64298686cd2SShayne Chen u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; 64398686cd2SShayne Chen u32 csum_status = *(u32 *)skb->cb; 64427db47abSRyder Lee u32 mesh_mask = MT_RXD0_MESH | MT_RXD0_MHCP; 64527db47abSRyder Lee bool is_mesh = (rxd0 & mesh_mask) == mesh_mask; 64698686cd2SShayne Chen bool unicast, insert_ccmp_hdr = false; 64798686cd2SShayne Chen u8 remove_pad, amsdu_info, band_idx; 64898686cd2SShayne Chen u8 mode = 0, qos_ctl = 0; 64998686cd2SShayne Chen bool hdr_trans; 65098686cd2SShayne Chen u16 hdr_gap; 65198686cd2SShayne Chen u16 seq_ctrl = 0; 65298686cd2SShayne Chen __le16 fc = 0; 65398686cd2SShayne Chen int idx; 65498686cd2SShayne Chen 65598686cd2SShayne Chen memset(status, 0, sizeof(*status)); 65698686cd2SShayne Chen 65798686cd2SShayne Chen band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1); 65898686cd2SShayne Chen mphy = dev->mt76.phys[band_idx]; 65998686cd2SShayne Chen phy = mphy->priv; 66098686cd2SShayne Chen status->phy_idx = mphy->band_idx; 66198686cd2SShayne Chen 66298686cd2SShayne Chen if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) 66398686cd2SShayne Chen return -EINVAL; 66498686cd2SShayne Chen 66598686cd2SShayne Chen if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) 66698686cd2SShayne Chen return -EINVAL; 66798686cd2SShayne Chen 66898686cd2SShayne Chen hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; 66998686cd2SShayne Chen if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) 67098686cd2SShayne Chen return -EINVAL; 67198686cd2SShayne Chen 67298686cd2SShayne Chen /* ICV error or CCMP/BIP/WPI MIC error */ 67398686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) 67498686cd2SShayne Chen status->flag |= RX_FLAG_ONLY_MONITOR; 67598686cd2SShayne Chen 67698686cd2SShayne Chen unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; 67798686cd2SShayne Chen idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); 67898686cd2SShayne Chen status->wcid = mt7996_rx_get_wcid(dev, idx, unicast); 67998686cd2SShayne Chen 68098686cd2SShayne Chen if (status->wcid) { 68198686cd2SShayne Chen struct mt7996_sta *msta; 68298686cd2SShayne Chen 68398686cd2SShayne Chen msta = container_of(status->wcid, struct mt7996_sta, wcid); 68498686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 68598686cd2SShayne Chen if (list_empty(&msta->poll_list)) 68698686cd2SShayne Chen list_add_tail(&msta->poll_list, &dev->sta_poll_list); 68798686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 68898686cd2SShayne Chen } 68998686cd2SShayne Chen 69098686cd2SShayne Chen status->freq = mphy->chandef.chan->center_freq; 69198686cd2SShayne Chen status->band = mphy->chandef.chan->band; 69298686cd2SShayne Chen if (status->band == NL80211_BAND_5GHZ) 69398686cd2SShayne Chen sband = &mphy->sband_5g.sband; 69498686cd2SShayne Chen else if (status->band == NL80211_BAND_6GHZ) 69598686cd2SShayne Chen sband = &mphy->sband_6g.sband; 69698686cd2SShayne Chen else 69798686cd2SShayne Chen sband = &mphy->sband_2g.sband; 69898686cd2SShayne Chen 69998686cd2SShayne Chen if (!sband->channels) 70098686cd2SShayne Chen return -EINVAL; 70198686cd2SShayne Chen 70298686cd2SShayne Chen if ((rxd0 & csum_mask) == csum_mask && 70398686cd2SShayne Chen !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) 70498686cd2SShayne Chen skb->ip_summed = CHECKSUM_UNNECESSARY; 70598686cd2SShayne Chen 70698686cd2SShayne Chen if (rxd1 & MT_RXD3_NORMAL_FCS_ERR) 70798686cd2SShayne Chen status->flag |= RX_FLAG_FAILED_FCS_CRC; 70898686cd2SShayne Chen 70998686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) 71098686cd2SShayne Chen status->flag |= RX_FLAG_MMIC_ERROR; 71198686cd2SShayne Chen 71298686cd2SShayne Chen if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && 71398686cd2SShayne Chen !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) { 71498686cd2SShayne Chen status->flag |= RX_FLAG_DECRYPTED; 71598686cd2SShayne Chen status->flag |= RX_FLAG_IV_STRIPPED; 71698686cd2SShayne Chen status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; 71798686cd2SShayne Chen } 71898686cd2SShayne Chen 71998686cd2SShayne Chen remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); 72098686cd2SShayne Chen 72198686cd2SShayne Chen if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) 72298686cd2SShayne Chen return -EINVAL; 72398686cd2SShayne Chen 72498686cd2SShayne Chen rxd += 8; 72598686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { 72698686cd2SShayne Chen u32 v0 = le32_to_cpu(rxd[0]); 72798686cd2SShayne Chen u32 v2 = le32_to_cpu(rxd[2]); 72898686cd2SShayne Chen 72998686cd2SShayne Chen fc = cpu_to_le16(FIELD_GET(MT_RXD8_FRAME_CONTROL, v0)); 73098686cd2SShayne Chen qos_ctl = FIELD_GET(MT_RXD10_QOS_CTL, v2); 73198686cd2SShayne Chen seq_ctrl = FIELD_GET(MT_RXD10_SEQ_CTRL, v2); 73298686cd2SShayne Chen 73398686cd2SShayne Chen rxd += 4; 73498686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 73598686cd2SShayne Chen return -EINVAL; 73698686cd2SShayne Chen } 73798686cd2SShayne Chen 73898686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_1) { 73998686cd2SShayne Chen u8 *data = (u8 *)rxd; 74098686cd2SShayne Chen 74198686cd2SShayne Chen if (status->flag & RX_FLAG_DECRYPTED) { 74298686cd2SShayne Chen switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) { 74398686cd2SShayne Chen case MT_CIPHER_AES_CCMP: 74498686cd2SShayne Chen case MT_CIPHER_CCMP_CCX: 74598686cd2SShayne Chen case MT_CIPHER_CCMP_256: 74698686cd2SShayne Chen insert_ccmp_hdr = 74798686cd2SShayne Chen FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); 74898686cd2SShayne Chen fallthrough; 74998686cd2SShayne Chen case MT_CIPHER_TKIP: 75098686cd2SShayne Chen case MT_CIPHER_TKIP_NO_MIC: 75198686cd2SShayne Chen case MT_CIPHER_GCMP: 75298686cd2SShayne Chen case MT_CIPHER_GCMP_256: 75398686cd2SShayne Chen status->iv[0] = data[5]; 75498686cd2SShayne Chen status->iv[1] = data[4]; 75598686cd2SShayne Chen status->iv[2] = data[3]; 75698686cd2SShayne Chen status->iv[3] = data[2]; 75798686cd2SShayne Chen status->iv[4] = data[1]; 75898686cd2SShayne Chen status->iv[5] = data[0]; 75998686cd2SShayne Chen break; 76098686cd2SShayne Chen default: 76198686cd2SShayne Chen break; 76298686cd2SShayne Chen } 76398686cd2SShayne Chen } 76498686cd2SShayne Chen rxd += 4; 76598686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 76698686cd2SShayne Chen return -EINVAL; 76798686cd2SShayne Chen } 76898686cd2SShayne Chen 76998686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { 77098686cd2SShayne Chen status->timestamp = le32_to_cpu(rxd[0]); 77198686cd2SShayne Chen status->flag |= RX_FLAG_MACTIME_START; 77298686cd2SShayne Chen 77398686cd2SShayne Chen if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { 77498686cd2SShayne Chen status->flag |= RX_FLAG_AMPDU_DETAILS; 77598686cd2SShayne Chen 77698686cd2SShayne Chen /* all subframes of an A-MPDU have the same timestamp */ 77798686cd2SShayne Chen if (phy->rx_ampdu_ts != status->timestamp) { 77898686cd2SShayne Chen if (!++phy->ampdu_ref) 77998686cd2SShayne Chen phy->ampdu_ref++; 78098686cd2SShayne Chen } 78198686cd2SShayne Chen phy->rx_ampdu_ts = status->timestamp; 78298686cd2SShayne Chen 78398686cd2SShayne Chen status->ampdu_ref = phy->ampdu_ref; 78498686cd2SShayne Chen } 78598686cd2SShayne Chen 78698686cd2SShayne Chen rxd += 4; 78798686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 78898686cd2SShayne Chen return -EINVAL; 78998686cd2SShayne Chen } 79098686cd2SShayne Chen 79198686cd2SShayne Chen /* RXD Group 3 - P-RXV */ 79298686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { 79398686cd2SShayne Chen u32 v3; 79498686cd2SShayne Chen int ret; 79598686cd2SShayne Chen 79698686cd2SShayne Chen rxv = rxd; 79798686cd2SShayne Chen rxd += 4; 79898686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 79998686cd2SShayne Chen return -EINVAL; 80098686cd2SShayne Chen 80198686cd2SShayne Chen v3 = le32_to_cpu(rxv[3]); 80298686cd2SShayne Chen 80398686cd2SShayne Chen status->chains = mphy->antenna_mask; 80498686cd2SShayne Chen status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v3); 80598686cd2SShayne Chen status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v3); 80698686cd2SShayne Chen status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v3); 80798686cd2SShayne Chen status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v3); 80898686cd2SShayne Chen 80998686cd2SShayne Chen /* RXD Group 5 - C-RXV */ 81098686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { 81198686cd2SShayne Chen rxd += 24; 81298686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 81398686cd2SShayne Chen return -EINVAL; 81498686cd2SShayne Chen } 81598686cd2SShayne Chen 81698686cd2SShayne Chen ret = mt7996_mac_fill_rx_rate(dev, status, sband, rxv, &mode); 81798686cd2SShayne Chen if (ret < 0) 81898686cd2SShayne Chen return ret; 81998686cd2SShayne Chen } 82098686cd2SShayne Chen 82198686cd2SShayne Chen amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); 82298686cd2SShayne Chen status->amsdu = !!amsdu_info; 82398686cd2SShayne Chen if (status->amsdu) { 82498686cd2SShayne Chen status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; 82598686cd2SShayne Chen status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; 82698686cd2SShayne Chen } 82798686cd2SShayne Chen 82898686cd2SShayne Chen hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; 82998686cd2SShayne Chen if (hdr_trans && ieee80211_has_morefrags(fc)) { 83098686cd2SShayne Chen if (mt7996_reverse_frag0_hdr_trans(skb, hdr_gap)) 83198686cd2SShayne Chen return -EINVAL; 83298686cd2SShayne Chen hdr_trans = false; 83398686cd2SShayne Chen } else { 83498686cd2SShayne Chen int pad_start = 0; 83598686cd2SShayne Chen 83698686cd2SShayne Chen skb_pull(skb, hdr_gap); 83727db47abSRyder Lee if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) { 83898686cd2SShayne Chen pad_start = ieee80211_get_hdrlen_from_skb(skb); 83927db47abSRyder Lee } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR) && 84027db47abSRyder Lee get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) { 84198686cd2SShayne Chen /* When header translation failure is indicated, 84298686cd2SShayne Chen * the hardware will insert an extra 2-byte field 84398686cd2SShayne Chen * containing the data length after the protocol 84498686cd2SShayne Chen * type field. 84598686cd2SShayne Chen */ 84627db47abSRyder Lee pad_start = 16; 84798686cd2SShayne Chen } 84898686cd2SShayne Chen 84998686cd2SShayne Chen if (pad_start) { 85098686cd2SShayne Chen memmove(skb->data + 2, skb->data, pad_start); 85198686cd2SShayne Chen skb_pull(skb, 2); 85298686cd2SShayne Chen } 85398686cd2SShayne Chen } 85498686cd2SShayne Chen 85598686cd2SShayne Chen if (!hdr_trans) { 85698686cd2SShayne Chen struct ieee80211_hdr *hdr; 85798686cd2SShayne Chen 85898686cd2SShayne Chen if (insert_ccmp_hdr) { 85998686cd2SShayne Chen u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); 86098686cd2SShayne Chen 86198686cd2SShayne Chen mt76_insert_ccmp_hdr(skb, key_id); 86298686cd2SShayne Chen } 86398686cd2SShayne Chen 86498686cd2SShayne Chen hdr = mt76_skb_get_hdr(skb); 86598686cd2SShayne Chen fc = hdr->frame_control; 86698686cd2SShayne Chen if (ieee80211_is_data_qos(fc)) { 86727db47abSRyder Lee u8 *qos = ieee80211_get_qos_ctl(hdr); 86827db47abSRyder Lee 86998686cd2SShayne Chen seq_ctrl = le16_to_cpu(hdr->seq_ctrl); 87027db47abSRyder Lee qos_ctl = *qos; 87127db47abSRyder Lee 87227db47abSRyder Lee /* Mesh DA/SA/Length will be stripped after hardware 87327db47abSRyder Lee * de-amsdu, so here needs to clear amsdu present bit 87427db47abSRyder Lee * to mark it as a normal mesh frame. 87527db47abSRyder Lee */ 87627db47abSRyder Lee if (ieee80211_has_a4(fc) && is_mesh && status->amsdu) 87727db47abSRyder Lee *qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; 87898686cd2SShayne Chen } 87998686cd2SShayne Chen } else { 88098686cd2SShayne Chen status->flag |= RX_FLAG_8023; 88198686cd2SShayne Chen } 88298686cd2SShayne Chen 88398686cd2SShayne Chen if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) 88498686cd2SShayne Chen mt7996_mac_decode_he_radiotap(skb, rxv, mode); 88598686cd2SShayne Chen 88698686cd2SShayne Chen if (!status->wcid || !ieee80211_is_data_qos(fc)) 88798686cd2SShayne Chen return 0; 88898686cd2SShayne Chen 88998686cd2SShayne Chen status->aggr = unicast && 89098686cd2SShayne Chen !ieee80211_is_qos_nullfunc(fc); 89198686cd2SShayne Chen status->qos_ctl = qos_ctl; 89298686cd2SShayne Chen status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); 89398686cd2SShayne Chen 89498686cd2SShayne Chen return 0; 89598686cd2SShayne Chen } 89698686cd2SShayne Chen 89798686cd2SShayne Chen static void 89898686cd2SShayne Chen mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi, 89998686cd2SShayne Chen struct sk_buff *skb, struct mt76_wcid *wcid) 90098686cd2SShayne Chen { 90198686cd2SShayne Chen u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 90298686cd2SShayne Chen u8 fc_type, fc_stype; 90398686cd2SShayne Chen u16 ethertype; 90498686cd2SShayne Chen bool wmm = false; 90598686cd2SShayne Chen u32 val; 90698686cd2SShayne Chen 90798686cd2SShayne Chen if (wcid->sta) { 90898686cd2SShayne Chen struct ieee80211_sta *sta; 90998686cd2SShayne Chen 91098686cd2SShayne Chen sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); 91198686cd2SShayne Chen wmm = sta->wme; 91298686cd2SShayne Chen } 91398686cd2SShayne Chen 91498686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | 91598686cd2SShayne Chen FIELD_PREP(MT_TXD1_TID, tid); 91698686cd2SShayne Chen 91798686cd2SShayne Chen ethertype = get_unaligned_be16(&skb->data[12]); 91898686cd2SShayne Chen if (ethertype >= ETH_P_802_3_MIN) 91998686cd2SShayne Chen val |= MT_TXD1_ETH_802_3; 92098686cd2SShayne Chen 92198686cd2SShayne Chen txwi[1] |= cpu_to_le32(val); 92298686cd2SShayne Chen 92398686cd2SShayne Chen fc_type = IEEE80211_FTYPE_DATA >> 2; 92498686cd2SShayne Chen fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; 92598686cd2SShayne Chen 92698686cd2SShayne Chen val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | 92798686cd2SShayne Chen FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); 92898686cd2SShayne Chen 92998686cd2SShayne Chen txwi[2] |= cpu_to_le32(val); 93098686cd2SShayne Chen } 93198686cd2SShayne Chen 93298686cd2SShayne Chen static void 93398686cd2SShayne Chen mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, 93498686cd2SShayne Chen struct sk_buff *skb, struct ieee80211_key_conf *key) 93598686cd2SShayne Chen { 93698686cd2SShayne Chen struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 93798686cd2SShayne Chen struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 93898686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 93998686cd2SShayne Chen bool multicast = is_multicast_ether_addr(hdr->addr1); 94098686cd2SShayne Chen u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 94198686cd2SShayne Chen __le16 fc = hdr->frame_control; 94298686cd2SShayne Chen u8 fc_type, fc_stype; 94398686cd2SShayne Chen u32 val; 94498686cd2SShayne Chen 94598686cd2SShayne Chen if (ieee80211_is_action(fc) && 94698686cd2SShayne Chen mgmt->u.action.category == WLAN_CATEGORY_BACK && 94798686cd2SShayne Chen mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) 94898686cd2SShayne Chen tid = MT_TX_ADDBA; 94998686cd2SShayne Chen else if (ieee80211_is_mgmt(hdr->frame_control)) 95098686cd2SShayne Chen tid = MT_TX_NORMAL; 95198686cd2SShayne Chen 95298686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | 95398686cd2SShayne Chen FIELD_PREP(MT_TXD1_HDR_INFO, 95498686cd2SShayne Chen ieee80211_get_hdrlen_from_skb(skb) / 2) | 95598686cd2SShayne Chen FIELD_PREP(MT_TXD1_TID, tid); 95698686cd2SShayne Chen 95798686cd2SShayne Chen if (!ieee80211_is_data(fc) || multicast || 95898686cd2SShayne Chen info->flags & IEEE80211_TX_CTL_USE_MINRATE) 95998686cd2SShayne Chen val |= MT_TXD1_FIXED_RATE; 96098686cd2SShayne Chen 96198686cd2SShayne Chen if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && 96298686cd2SShayne Chen key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { 96398686cd2SShayne Chen val |= MT_TXD1_BIP; 96498686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); 96598686cd2SShayne Chen } 96698686cd2SShayne Chen 96798686cd2SShayne Chen txwi[1] |= cpu_to_le32(val); 96898686cd2SShayne Chen 96998686cd2SShayne Chen fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; 97098686cd2SShayne Chen fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; 97198686cd2SShayne Chen 97298686cd2SShayne Chen val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | 97398686cd2SShayne Chen FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); 97498686cd2SShayne Chen 97598686cd2SShayne Chen txwi[2] |= cpu_to_le32(val); 97698686cd2SShayne Chen 97798686cd2SShayne Chen txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast)); 97898686cd2SShayne Chen if (ieee80211_is_beacon(fc)) { 97998686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); 98098686cd2SShayne Chen txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); 98198686cd2SShayne Chen } 98298686cd2SShayne Chen 98398686cd2SShayne Chen if (info->flags & IEEE80211_TX_CTL_INJECTED) { 98498686cd2SShayne Chen u16 seqno = le16_to_cpu(hdr->seq_ctrl); 98598686cd2SShayne Chen 98698686cd2SShayne Chen if (ieee80211_is_back_req(hdr->frame_control)) { 98798686cd2SShayne Chen struct ieee80211_bar *bar; 98898686cd2SShayne Chen 98998686cd2SShayne Chen bar = (struct ieee80211_bar *)skb->data; 99098686cd2SShayne Chen seqno = le16_to_cpu(bar->start_seq_num); 99198686cd2SShayne Chen } 99298686cd2SShayne Chen 99398686cd2SShayne Chen val = MT_TXD3_SN_VALID | 99498686cd2SShayne Chen FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); 99598686cd2SShayne Chen txwi[3] |= cpu_to_le32(val); 99698686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU); 99798686cd2SShayne Chen } 99898686cd2SShayne Chen } 99998686cd2SShayne Chen 100098686cd2SShayne Chen void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, 1001d0b6f86fSShayne Chen struct sk_buff *skb, struct mt76_wcid *wcid, 1002d0b6f86fSShayne Chen struct ieee80211_key_conf *key, int pid, 1003d0b6f86fSShayne Chen enum mt76_txq_id qid, u32 changed) 100498686cd2SShayne Chen { 100598686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 100698686cd2SShayne Chen struct ieee80211_vif *vif = info->control.vif; 100798686cd2SShayne Chen u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; 100898686cd2SShayne Chen u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; 100998686cd2SShayne Chen bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; 1010*ead44902SLorenzo Bianconi struct mt7996_vif *mvif; 101198686cd2SShayne Chen u16 tx_count = 15; 101298686cd2SShayne Chen u32 val; 101398686cd2SShayne Chen bool beacon = !!(changed & (BSS_CHANGED_BEACON | 101498686cd2SShayne Chen BSS_CHANGED_BEACON_ENABLED)); 101598686cd2SShayne Chen bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | 101698686cd2SShayne Chen BSS_CHANGED_FILS_DISCOVERY)); 101798686cd2SShayne Chen 1018*ead44902SLorenzo Bianconi mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL; 1019*ead44902SLorenzo Bianconi if (mvif) { 102098686cd2SShayne Chen omac_idx = mvif->mt76.omac_idx; 102198686cd2SShayne Chen wmm_idx = mvif->mt76.wmm_idx; 102298686cd2SShayne Chen band_idx = mvif->mt76.band_idx; 102398686cd2SShayne Chen } 102498686cd2SShayne Chen 102598686cd2SShayne Chen if (inband_disc) { 102698686cd2SShayne Chen p_fmt = MT_TX_TYPE_FW; 102798686cd2SShayne Chen q_idx = MT_LMAC_ALTX0; 102898686cd2SShayne Chen } else if (beacon) { 102998686cd2SShayne Chen p_fmt = MT_TX_TYPE_FW; 103098686cd2SShayne Chen q_idx = MT_LMAC_BCN0; 1031d0b6f86fSShayne Chen } else if (qid >= MT_TXQ_PSD) { 103298686cd2SShayne Chen p_fmt = MT_TX_TYPE_CT; 103398686cd2SShayne Chen q_idx = MT_LMAC_ALTX0; 103498686cd2SShayne Chen } else { 103598686cd2SShayne Chen p_fmt = MT_TX_TYPE_CT; 103698686cd2SShayne Chen q_idx = wmm_idx * MT7996_MAX_WMM_SETS + 103798686cd2SShayne Chen mt76_connac_lmac_mapping(skb_get_queue_mapping(skb)); 103898686cd2SShayne Chen } 103998686cd2SShayne Chen 104098686cd2SShayne Chen val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | 104198686cd2SShayne Chen FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | 104298686cd2SShayne Chen FIELD_PREP(MT_TXD0_Q_IDX, q_idx); 104398686cd2SShayne Chen txwi[0] = cpu_to_le32(val); 104498686cd2SShayne Chen 104598686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | 104698686cd2SShayne Chen FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); 104798686cd2SShayne Chen 104898686cd2SShayne Chen if (band_idx) 104998686cd2SShayne Chen val |= FIELD_PREP(MT_TXD1_TGID, band_idx); 105098686cd2SShayne Chen 105198686cd2SShayne Chen txwi[1] = cpu_to_le32(val); 105298686cd2SShayne Chen txwi[2] = 0; 105398686cd2SShayne Chen 105498686cd2SShayne Chen val = MT_TXD3_SW_POWER_MGMT | 105598686cd2SShayne Chen FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); 105698686cd2SShayne Chen if (key) 105798686cd2SShayne Chen val |= MT_TXD3_PROTECT_FRAME; 105898686cd2SShayne Chen if (info->flags & IEEE80211_TX_CTL_NO_ACK) 105998686cd2SShayne Chen val |= MT_TXD3_NO_ACK; 106098686cd2SShayne Chen if (wcid->amsdu) 106198686cd2SShayne Chen val |= MT_TXD3_HW_AMSDU; 106298686cd2SShayne Chen 106398686cd2SShayne Chen txwi[3] = cpu_to_le32(val); 106498686cd2SShayne Chen txwi[4] = 0; 106598686cd2SShayne Chen 106698686cd2SShayne Chen val = FIELD_PREP(MT_TXD5_PID, pid); 106798686cd2SShayne Chen if (pid >= MT_PACKET_ID_FIRST) 106898686cd2SShayne Chen val |= MT_TXD5_TX_STATUS_HOST; 106998686cd2SShayne Chen txwi[5] = cpu_to_le32(val); 107098686cd2SShayne Chen 107198686cd2SShayne Chen val = MT_TXD6_DIS_MAT | MT_TXD6_DAS | 107298686cd2SShayne Chen FIELD_PREP(MT_TXD6_MSDU_CNT, 1); 107398686cd2SShayne Chen txwi[6] = cpu_to_le32(val); 107498686cd2SShayne Chen txwi[7] = 0; 107598686cd2SShayne Chen 107698686cd2SShayne Chen if (is_8023) 107798686cd2SShayne Chen mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid); 107898686cd2SShayne Chen else 107998686cd2SShayne Chen mt7996_mac_write_txwi_80211(dev, txwi, skb, key); 108098686cd2SShayne Chen 108198686cd2SShayne Chen if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) { 1082ab0eec4bSRyder Lee struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 1083ab0eec4bSRyder Lee bool mcast = ieee80211_is_data(hdr->frame_control) && 1084ab0eec4bSRyder Lee is_multicast_ether_addr(hdr->addr1); 1085*ead44902SLorenzo Bianconi u8 idx = MT7996_BASIC_RATES_TBL; 108698686cd2SShayne Chen 1087*ead44902SLorenzo Bianconi if (mvif) { 1088ab0eec4bSRyder Lee if (mcast && mvif->mcast_rates_idx) 1089ab0eec4bSRyder Lee idx = mvif->mcast_rates_idx; 1090c2171b06SRyder Lee else if (beacon && mvif->beacon_rates_idx) 1091c2171b06SRyder Lee idx = mvif->beacon_rates_idx; 1092*ead44902SLorenzo Bianconi else 1093*ead44902SLorenzo Bianconi idx = mvif->basic_rates_idx; 1094*ead44902SLorenzo Bianconi } 1095ab0eec4bSRyder Lee 1096cdc26ee8SRyder Lee txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx)); 109798686cd2SShayne Chen txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); 109898686cd2SShayne Chen } 109998686cd2SShayne Chen } 110098686cd2SShayne Chen 110198686cd2SShayne Chen int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 110298686cd2SShayne Chen enum mt76_txq_id qid, struct mt76_wcid *wcid, 110398686cd2SShayne Chen struct ieee80211_sta *sta, 110498686cd2SShayne Chen struct mt76_tx_info *tx_info) 110598686cd2SShayne Chen { 110698686cd2SShayne Chen struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; 110798686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 110898686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); 110998686cd2SShayne Chen struct ieee80211_key_conf *key = info->control.hw_key; 111098686cd2SShayne Chen struct ieee80211_vif *vif = info->control.vif; 11113c38dfc1SLorenzo Bianconi struct mt76_connac_txp_common *txp; 111298686cd2SShayne Chen struct mt76_txwi_cache *t; 111398686cd2SShayne Chen int id, i, pid, nbuf = tx_info->nbuf - 1; 111498686cd2SShayne Chen bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; 111598686cd2SShayne Chen u8 *txwi = (u8 *)txwi_ptr; 111698686cd2SShayne Chen 111798686cd2SShayne Chen if (unlikely(tx_info->skb->len <= ETH_HLEN)) 111898686cd2SShayne Chen return -EINVAL; 111998686cd2SShayne Chen 112098686cd2SShayne Chen if (!wcid) 112198686cd2SShayne Chen wcid = &dev->mt76.global_wcid; 112298686cd2SShayne Chen 112398686cd2SShayne Chen if (sta) { 112498686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 112598686cd2SShayne Chen 112698686cd2SShayne Chen if (time_after(jiffies, msta->jiffies + HZ / 4)) { 112798686cd2SShayne Chen info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 112898686cd2SShayne Chen msta->jiffies = jiffies; 112998686cd2SShayne Chen } 113098686cd2SShayne Chen } 113198686cd2SShayne Chen 113298686cd2SShayne Chen t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); 113398686cd2SShayne Chen t->skb = tx_info->skb; 113498686cd2SShayne Chen 113598686cd2SShayne Chen id = mt76_token_consume(mdev, &t); 113698686cd2SShayne Chen if (id < 0) 113798686cd2SShayne Chen return id; 113898686cd2SShayne Chen 113998686cd2SShayne Chen pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); 1140d0b6f86fSShayne Chen mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, 1141d0b6f86fSShayne Chen pid, qid, 0); 114298686cd2SShayne Chen 11433c38dfc1SLorenzo Bianconi txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE); 114498686cd2SShayne Chen for (i = 0; i < nbuf; i++) { 11453c38dfc1SLorenzo Bianconi txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); 11463c38dfc1SLorenzo Bianconi txp->fw.len[i] = cpu_to_le16(tx_info->buf[i + 1].len); 114798686cd2SShayne Chen } 11483c38dfc1SLorenzo Bianconi txp->fw.nbuf = nbuf; 114998686cd2SShayne Chen 11503b522cadSRyder Lee txp->fw.flags = 11513b522cadSRyder Lee cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD); 115298686cd2SShayne Chen 115398686cd2SShayne Chen if (!key) 11543c38dfc1SLorenzo Bianconi txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); 115598686cd2SShayne Chen 115698686cd2SShayne Chen if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control)) 11573c38dfc1SLorenzo Bianconi txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); 115898686cd2SShayne Chen 115998686cd2SShayne Chen if (vif) { 116098686cd2SShayne Chen struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 116198686cd2SShayne Chen 11623c38dfc1SLorenzo Bianconi txp->fw.bss_idx = mvif->mt76.idx; 116398686cd2SShayne Chen } 116498686cd2SShayne Chen 11653c38dfc1SLorenzo Bianconi txp->fw.token = cpu_to_le16(id); 116698686cd2SShayne Chen if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) 11673c38dfc1SLorenzo Bianconi txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx); 116898686cd2SShayne Chen else 11693c38dfc1SLorenzo Bianconi txp->fw.rept_wds_wcid = cpu_to_le16(0xfff); 117098686cd2SShayne Chen tx_info->skb = DMA_DUMMY_DATA; 117198686cd2SShayne Chen 117298686cd2SShayne Chen /* pass partial skb header to fw */ 117398686cd2SShayne Chen tx_info->buf[1].len = MT_CT_PARSE_LEN; 117498686cd2SShayne Chen tx_info->buf[1].skip_unmap = true; 117598686cd2SShayne Chen tx_info->nbuf = MT_CT_DMA_BUF_NUM; 117698686cd2SShayne Chen 117798686cd2SShayne Chen return 0; 117898686cd2SShayne Chen } 117998686cd2SShayne Chen 118098686cd2SShayne Chen static void 118198686cd2SShayne Chen mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) 118298686cd2SShayne Chen { 118398686cd2SShayne Chen struct mt7996_sta *msta; 118498686cd2SShayne Chen u16 fc, tid; 118598686cd2SShayne Chen u32 val; 118698686cd2SShayne Chen 118798686cd2SShayne Chen if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) 118898686cd2SShayne Chen return; 118998686cd2SShayne Chen 119098686cd2SShayne Chen tid = le32_get_bits(txwi[1], MT_TXD1_TID); 119198686cd2SShayne Chen if (tid >= 6) /* skip VO queue */ 119298686cd2SShayne Chen return; 119398686cd2SShayne Chen 119498686cd2SShayne Chen val = le32_to_cpu(txwi[2]); 119598686cd2SShayne Chen fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | 119698686cd2SShayne Chen FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; 119798686cd2SShayne Chen if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) 119898686cd2SShayne Chen return; 119998686cd2SShayne Chen 120098686cd2SShayne Chen msta = (struct mt7996_sta *)sta->drv_priv; 120198686cd2SShayne Chen if (!test_and_set_bit(tid, &msta->ampdu_state)) 120298686cd2SShayne Chen ieee80211_start_tx_ba_session(sta, tid, 0); 120398686cd2SShayne Chen } 120498686cd2SShayne Chen 120598686cd2SShayne Chen static void 120698686cd2SShayne Chen mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t, 120798686cd2SShayne Chen struct ieee80211_sta *sta, struct list_head *free_list) 120898686cd2SShayne Chen { 120998686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 121098686cd2SShayne Chen struct mt76_wcid *wcid; 121198686cd2SShayne Chen __le32 *txwi; 121298686cd2SShayne Chen u16 wcid_idx; 121398686cd2SShayne Chen 121430495864SLorenzo Bianconi mt76_connac_txp_skb_unmap(mdev, t); 121598686cd2SShayne Chen if (!t->skb) 121698686cd2SShayne Chen goto out; 121798686cd2SShayne Chen 121898686cd2SShayne Chen txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); 121998686cd2SShayne Chen if (sta) { 122098686cd2SShayne Chen wcid = (struct mt76_wcid *)sta->drv_priv; 122198686cd2SShayne Chen wcid_idx = wcid->idx; 122298686cd2SShayne Chen 122398686cd2SShayne Chen if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) 122498686cd2SShayne Chen mt7996_tx_check_aggr(sta, txwi); 122598686cd2SShayne Chen } else { 122698686cd2SShayne Chen wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); 122798686cd2SShayne Chen } 122898686cd2SShayne Chen 122998686cd2SShayne Chen __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); 123098686cd2SShayne Chen 123198686cd2SShayne Chen out: 123298686cd2SShayne Chen t->skb = NULL; 123398686cd2SShayne Chen mt76_put_txwi(mdev, t); 123498686cd2SShayne Chen } 123598686cd2SShayne Chen 123698686cd2SShayne Chen static void 123798686cd2SShayne Chen mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) 123898686cd2SShayne Chen { 123998686cd2SShayne Chen __le32 *tx_free = (__le32 *)data, *cur_info; 124098686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 124198686cd2SShayne Chen struct mt76_phy *phy2 = mdev->phys[MT_BAND1]; 124298686cd2SShayne Chen struct mt76_phy *phy3 = mdev->phys[MT_BAND2]; 124398686cd2SShayne Chen struct mt76_txwi_cache *txwi; 124498686cd2SShayne Chen struct ieee80211_sta *sta = NULL; 124598686cd2SShayne Chen LIST_HEAD(free_list); 124698686cd2SShayne Chen struct sk_buff *skb, *tmp; 124798686cd2SShayne Chen void *end = data + len; 124898686cd2SShayne Chen bool wake = false; 124998686cd2SShayne Chen u16 total, count = 0; 125098686cd2SShayne Chen 125198686cd2SShayne Chen /* clean DMA queues and unmap buffers first */ 125298686cd2SShayne Chen mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); 125398686cd2SShayne Chen mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); 125498686cd2SShayne Chen if (phy2) { 125598686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy2->q_tx[MT_TXQ_PSD], false); 125698686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy2->q_tx[MT_TXQ_BE], false); 125798686cd2SShayne Chen } 125898686cd2SShayne Chen if (phy3) { 125998686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_PSD], false); 126098686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false); 126198686cd2SShayne Chen } 126298686cd2SShayne Chen 126398686cd2SShayne Chen if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4)) 126498686cd2SShayne Chen return; 126598686cd2SShayne Chen 126698686cd2SShayne Chen total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT); 126798686cd2SShayne Chen for (cur_info = &tx_free[2]; count < total; cur_info++) { 126898686cd2SShayne Chen u32 msdu, info; 126998686cd2SShayne Chen u8 i; 127098686cd2SShayne Chen 127198686cd2SShayne Chen if (WARN_ON_ONCE((void *)cur_info >= end)) 127298686cd2SShayne Chen return; 127398686cd2SShayne Chen /* 1'b1: new wcid pair. 127498686cd2SShayne Chen * 1'b0: msdu_id with the same 'wcid pair' as above. 127598686cd2SShayne Chen */ 127698686cd2SShayne Chen info = le32_to_cpu(*cur_info); 127798686cd2SShayne Chen if (info & MT_TXFREE_INFO_PAIR) { 127898686cd2SShayne Chen struct mt7996_sta *msta; 127998686cd2SShayne Chen struct mt76_wcid *wcid; 128098686cd2SShayne Chen u16 idx; 128198686cd2SShayne Chen 128298686cd2SShayne Chen idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); 128398686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[idx]); 128498686cd2SShayne Chen sta = wcid_to_sta(wcid); 128598686cd2SShayne Chen if (!sta) 128698686cd2SShayne Chen continue; 128798686cd2SShayne Chen 128898686cd2SShayne Chen msta = container_of(wcid, struct mt7996_sta, wcid); 128998686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 129098686cd2SShayne Chen if (list_empty(&msta->poll_list)) 129198686cd2SShayne Chen list_add_tail(&msta->poll_list, &dev->sta_poll_list); 129298686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 129398686cd2SShayne Chen continue; 129498686cd2SShayne Chen } 129598686cd2SShayne Chen 129698686cd2SShayne Chen if (info & MT_TXFREE_INFO_HEADER) 129798686cd2SShayne Chen continue; 129898686cd2SShayne Chen 129998686cd2SShayne Chen for (i = 0; i < 2; i++) { 130098686cd2SShayne Chen msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID; 130198686cd2SShayne Chen if (msdu == MT_TXFREE_INFO_MSDU_ID) 130298686cd2SShayne Chen continue; 130398686cd2SShayne Chen 130498686cd2SShayne Chen count++; 130598686cd2SShayne Chen txwi = mt76_token_release(mdev, msdu, &wake); 130698686cd2SShayne Chen if (!txwi) 130798686cd2SShayne Chen continue; 130898686cd2SShayne Chen 130998686cd2SShayne Chen mt7996_txwi_free(dev, txwi, sta, &free_list); 131098686cd2SShayne Chen } 131198686cd2SShayne Chen } 131298686cd2SShayne Chen 131398686cd2SShayne Chen mt7996_mac_sta_poll(dev); 131498686cd2SShayne Chen 131598686cd2SShayne Chen if (wake) 131698686cd2SShayne Chen mt76_set_tx_blocked(&dev->mt76, false); 131798686cd2SShayne Chen 131898686cd2SShayne Chen mt76_worker_schedule(&dev->mt76.tx_worker); 131998686cd2SShayne Chen 132098686cd2SShayne Chen list_for_each_entry_safe(skb, tmp, &free_list, list) { 132198686cd2SShayne Chen skb_list_del_init(skb); 132298686cd2SShayne Chen napi_consume_skb(skb, 1); 132398686cd2SShayne Chen } 132498686cd2SShayne Chen } 132598686cd2SShayne Chen 132698686cd2SShayne Chen static bool 132798686cd2SShayne Chen mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid, 132898686cd2SShayne Chen __le32 *txs_data, struct mt76_sta_stats *stats) 132998686cd2SShayne Chen { 133098686cd2SShayne Chen struct ieee80211_supported_band *sband; 133198686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 133298686cd2SShayne Chen struct mt76_phy *mphy; 133398686cd2SShayne Chen struct ieee80211_tx_info *info; 133498686cd2SShayne Chen struct sk_buff_head list; 133598686cd2SShayne Chen struct rate_info rate = {}; 133698686cd2SShayne Chen struct sk_buff *skb; 133798686cd2SShayne Chen bool cck = false; 133898686cd2SShayne Chen u32 txrate, txs, mode, stbc; 133998686cd2SShayne Chen 134098686cd2SShayne Chen mt76_tx_status_lock(mdev, &list); 134198686cd2SShayne Chen skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list); 134298686cd2SShayne Chen if (!skb) 134398686cd2SShayne Chen goto out_no_skb; 134498686cd2SShayne Chen 134598686cd2SShayne Chen txs = le32_to_cpu(txs_data[0]); 134698686cd2SShayne Chen 134798686cd2SShayne Chen info = IEEE80211_SKB_CB(skb); 134898686cd2SShayne Chen if (!(txs & MT_TXS0_ACK_ERROR_MASK)) 134998686cd2SShayne Chen info->flags |= IEEE80211_TX_STAT_ACK; 135098686cd2SShayne Chen 135198686cd2SShayne Chen info->status.ampdu_len = 1; 135298686cd2SShayne Chen info->status.ampdu_ack_len = !!(info->flags & 135398686cd2SShayne Chen IEEE80211_TX_STAT_ACK); 135498686cd2SShayne Chen 135598686cd2SShayne Chen info->status.rates[0].idx = -1; 135698686cd2SShayne Chen 135798686cd2SShayne Chen txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); 135898686cd2SShayne Chen 135998686cd2SShayne Chen rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); 136098686cd2SShayne Chen rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; 136198686cd2SShayne Chen stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC); 136298686cd2SShayne Chen 136398686cd2SShayne Chen if (stbc && rate.nss > 1) 136498686cd2SShayne Chen rate.nss >>= 1; 136598686cd2SShayne Chen 136698686cd2SShayne Chen if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) 136798686cd2SShayne Chen stats->tx_nss[rate.nss - 1]++; 136898686cd2SShayne Chen if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) 136998686cd2SShayne Chen stats->tx_mcs[rate.mcs]++; 137098686cd2SShayne Chen 137198686cd2SShayne Chen mode = FIELD_GET(MT_TX_RATE_MODE, txrate); 137298686cd2SShayne Chen switch (mode) { 137398686cd2SShayne Chen case MT_PHY_TYPE_CCK: 137498686cd2SShayne Chen cck = true; 137598686cd2SShayne Chen fallthrough; 137698686cd2SShayne Chen case MT_PHY_TYPE_OFDM: 137798686cd2SShayne Chen mphy = mt76_dev_phy(mdev, wcid->phy_idx); 137898686cd2SShayne Chen 137998686cd2SShayne Chen if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) 138098686cd2SShayne Chen sband = &mphy->sband_5g.sband; 138198686cd2SShayne Chen else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) 138298686cd2SShayne Chen sband = &mphy->sband_6g.sband; 138398686cd2SShayne Chen else 138498686cd2SShayne Chen sband = &mphy->sband_2g.sband; 138598686cd2SShayne Chen 138698686cd2SShayne Chen rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck); 138798686cd2SShayne Chen rate.legacy = sband->bitrates[rate.mcs].bitrate; 138898686cd2SShayne Chen break; 138998686cd2SShayne Chen case MT_PHY_TYPE_HT: 139098686cd2SShayne Chen case MT_PHY_TYPE_HT_GF: 139198686cd2SShayne Chen if (rate.mcs > 31) 139298686cd2SShayne Chen goto out; 139398686cd2SShayne Chen 139498686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_MCS; 139598686cd2SShayne Chen if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) 139698686cd2SShayne Chen rate.flags |= RATE_INFO_FLAGS_SHORT_GI; 139798686cd2SShayne Chen break; 139898686cd2SShayne Chen case MT_PHY_TYPE_VHT: 139998686cd2SShayne Chen if (rate.mcs > 9) 140098686cd2SShayne Chen goto out; 140198686cd2SShayne Chen 140298686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_VHT_MCS; 140398686cd2SShayne Chen break; 140498686cd2SShayne Chen case MT_PHY_TYPE_HE_SU: 140598686cd2SShayne Chen case MT_PHY_TYPE_HE_EXT_SU: 140698686cd2SShayne Chen case MT_PHY_TYPE_HE_TB: 140798686cd2SShayne Chen case MT_PHY_TYPE_HE_MU: 140898686cd2SShayne Chen if (rate.mcs > 11) 140998686cd2SShayne Chen goto out; 141098686cd2SShayne Chen 141198686cd2SShayne Chen rate.he_gi = wcid->rate.he_gi; 141298686cd2SShayne Chen rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); 141398686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_HE_MCS; 141498686cd2SShayne Chen break; 141580f5a31dSShayne Chen case MT_PHY_TYPE_EHT_SU: 141680f5a31dSShayne Chen case MT_PHY_TYPE_EHT_TRIG: 141780f5a31dSShayne Chen case MT_PHY_TYPE_EHT_MU: 141880f5a31dSShayne Chen if (rate.mcs > 13) 141980f5a31dSShayne Chen goto out; 142080f5a31dSShayne Chen 142180f5a31dSShayne Chen rate.eht_gi = wcid->rate.eht_gi; 142280f5a31dSShayne Chen rate.flags = RATE_INFO_FLAGS_EHT_MCS; 142380f5a31dSShayne Chen break; 142498686cd2SShayne Chen default: 142598686cd2SShayne Chen goto out; 142698686cd2SShayne Chen } 142798686cd2SShayne Chen 142898686cd2SShayne Chen stats->tx_mode[mode]++; 142998686cd2SShayne Chen 143098686cd2SShayne Chen switch (FIELD_GET(MT_TXS0_BW, txs)) { 143180f5a31dSShayne Chen case IEEE80211_STA_RX_BW_320: 143280f5a31dSShayne Chen rate.bw = RATE_INFO_BW_320; 143380f5a31dSShayne Chen stats->tx_bw[4]++; 143480f5a31dSShayne Chen break; 143598686cd2SShayne Chen case IEEE80211_STA_RX_BW_160: 143698686cd2SShayne Chen rate.bw = RATE_INFO_BW_160; 143798686cd2SShayne Chen stats->tx_bw[3]++; 143898686cd2SShayne Chen break; 143998686cd2SShayne Chen case IEEE80211_STA_RX_BW_80: 144098686cd2SShayne Chen rate.bw = RATE_INFO_BW_80; 144198686cd2SShayne Chen stats->tx_bw[2]++; 144298686cd2SShayne Chen break; 144398686cd2SShayne Chen case IEEE80211_STA_RX_BW_40: 144498686cd2SShayne Chen rate.bw = RATE_INFO_BW_40; 144598686cd2SShayne Chen stats->tx_bw[1]++; 144698686cd2SShayne Chen break; 144798686cd2SShayne Chen default: 144898686cd2SShayne Chen rate.bw = RATE_INFO_BW_20; 144998686cd2SShayne Chen stats->tx_bw[0]++; 145098686cd2SShayne Chen break; 145198686cd2SShayne Chen } 145298686cd2SShayne Chen wcid->rate = rate; 145398686cd2SShayne Chen 145498686cd2SShayne Chen out: 145598686cd2SShayne Chen mt76_tx_status_skb_done(mdev, skb, &list); 145698686cd2SShayne Chen 145798686cd2SShayne Chen out_no_skb: 145898686cd2SShayne Chen mt76_tx_status_unlock(mdev, &list); 145998686cd2SShayne Chen 146098686cd2SShayne Chen return !!skb; 146198686cd2SShayne Chen } 146298686cd2SShayne Chen 146398686cd2SShayne Chen static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) 146498686cd2SShayne Chen { 146598686cd2SShayne Chen struct mt7996_sta *msta = NULL; 146698686cd2SShayne Chen struct mt76_wcid *wcid; 146798686cd2SShayne Chen __le32 *txs_data = data; 146898686cd2SShayne Chen u16 wcidx; 146998686cd2SShayne Chen u8 pid; 147098686cd2SShayne Chen 147198686cd2SShayne Chen if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) 147298686cd2SShayne Chen return; 147398686cd2SShayne Chen 147498686cd2SShayne Chen wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); 147598686cd2SShayne Chen pid = le32_get_bits(txs_data[3], MT_TXS3_PID); 147698686cd2SShayne Chen 147798686cd2SShayne Chen if (pid < MT_PACKET_ID_FIRST) 147898686cd2SShayne Chen return; 147998686cd2SShayne Chen 148043482540SShayne Chen if (wcidx >= mt7996_wtbl_size(dev)) 148198686cd2SShayne Chen return; 148298686cd2SShayne Chen 148398686cd2SShayne Chen rcu_read_lock(); 148498686cd2SShayne Chen 148598686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[wcidx]); 148698686cd2SShayne Chen if (!wcid) 148798686cd2SShayne Chen goto out; 148898686cd2SShayne Chen 148998686cd2SShayne Chen msta = container_of(wcid, struct mt7996_sta, wcid); 149098686cd2SShayne Chen 149198686cd2SShayne Chen mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data, &msta->stats); 149298686cd2SShayne Chen 149398686cd2SShayne Chen if (!wcid->sta) 149498686cd2SShayne Chen goto out; 149598686cd2SShayne Chen 149698686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 149798686cd2SShayne Chen if (list_empty(&msta->poll_list)) 149898686cd2SShayne Chen list_add_tail(&msta->poll_list, &dev->sta_poll_list); 149998686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 150098686cd2SShayne Chen 150198686cd2SShayne Chen out: 150298686cd2SShayne Chen rcu_read_unlock(); 150398686cd2SShayne Chen } 150498686cd2SShayne Chen 150598686cd2SShayne Chen bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len) 150698686cd2SShayne Chen { 150798686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 150898686cd2SShayne Chen __le32 *rxd = (__le32 *)data; 150998686cd2SShayne Chen __le32 *end = (__le32 *)&rxd[len / 4]; 151098686cd2SShayne Chen enum rx_pkt_type type; 151198686cd2SShayne Chen 151298686cd2SShayne Chen type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); 151398686cd2SShayne Chen if (type != PKT_TYPE_NORMAL) { 151498686cd2SShayne Chen u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK); 151598686cd2SShayne Chen 151698686cd2SShayne Chen if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) == 151798686cd2SShayne Chen MT_RXD0_SW_PKT_TYPE_FRAME)) 151898686cd2SShayne Chen return true; 151998686cd2SShayne Chen } 152098686cd2SShayne Chen 152198686cd2SShayne Chen switch (type) { 152298686cd2SShayne Chen case PKT_TYPE_TXRX_NOTIFY: 152398686cd2SShayne Chen mt7996_mac_tx_free(dev, data, len); 152498686cd2SShayne Chen return false; 152598686cd2SShayne Chen case PKT_TYPE_TXS: 152698686cd2SShayne Chen for (rxd += 4; rxd + 8 <= end; rxd += 8) 152798686cd2SShayne Chen mt7996_mac_add_txs(dev, rxd); 152898686cd2SShayne Chen return false; 152998686cd2SShayne Chen case PKT_TYPE_RX_FW_MONITOR: 153098686cd2SShayne Chen mt7996_debugfs_rx_fw_monitor(dev, data, len); 153198686cd2SShayne Chen return false; 153298686cd2SShayne Chen default: 153398686cd2SShayne Chen return true; 153498686cd2SShayne Chen } 153598686cd2SShayne Chen } 153698686cd2SShayne Chen 153798686cd2SShayne Chen void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, 153898686cd2SShayne Chen struct sk_buff *skb, u32 *info) 153998686cd2SShayne Chen { 154098686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 154198686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 154298686cd2SShayne Chen __le32 *end = (__le32 *)&skb->data[skb->len]; 154398686cd2SShayne Chen enum rx_pkt_type type; 154498686cd2SShayne Chen 154598686cd2SShayne Chen type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); 154698686cd2SShayne Chen if (type != PKT_TYPE_NORMAL) { 154798686cd2SShayne Chen u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK); 154898686cd2SShayne Chen 154998686cd2SShayne Chen if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) == 155098686cd2SShayne Chen MT_RXD0_SW_PKT_TYPE_FRAME)) 155198686cd2SShayne Chen type = PKT_TYPE_NORMAL; 155298686cd2SShayne Chen } 155398686cd2SShayne Chen 155498686cd2SShayne Chen switch (type) { 155598686cd2SShayne Chen case PKT_TYPE_TXRX_NOTIFY: 155698686cd2SShayne Chen mt7996_mac_tx_free(dev, skb->data, skb->len); 155798686cd2SShayne Chen napi_consume_skb(skb, 1); 155898686cd2SShayne Chen break; 155998686cd2SShayne Chen case PKT_TYPE_RX_EVENT: 156098686cd2SShayne Chen mt7996_mcu_rx_event(dev, skb); 156198686cd2SShayne Chen break; 156298686cd2SShayne Chen case PKT_TYPE_TXS: 156398686cd2SShayne Chen for (rxd += 4; rxd + 8 <= end; rxd += 8) 156498686cd2SShayne Chen mt7996_mac_add_txs(dev, rxd); 156598686cd2SShayne Chen dev_kfree_skb(skb); 156698686cd2SShayne Chen break; 156798686cd2SShayne Chen case PKT_TYPE_RX_FW_MONITOR: 156898686cd2SShayne Chen mt7996_debugfs_rx_fw_monitor(dev, skb->data, skb->len); 156998686cd2SShayne Chen dev_kfree_skb(skb); 157098686cd2SShayne Chen break; 157198686cd2SShayne Chen case PKT_TYPE_NORMAL: 157298686cd2SShayne Chen if (!mt7996_mac_fill_rx(dev, skb)) { 157398686cd2SShayne Chen mt76_rx(&dev->mt76, q, skb); 157498686cd2SShayne Chen return; 157598686cd2SShayne Chen } 157698686cd2SShayne Chen fallthrough; 157798686cd2SShayne Chen default: 157898686cd2SShayne Chen dev_kfree_skb(skb); 157998686cd2SShayne Chen break; 158098686cd2SShayne Chen } 158198686cd2SShayne Chen } 158298686cd2SShayne Chen 158398686cd2SShayne Chen void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy) 158498686cd2SShayne Chen { 158598686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 158698686cd2SShayne Chen u32 reg = MT_WF_PHYRX_BAND_RX_CTRL1(phy->mt76->band_idx); 158798686cd2SShayne Chen 158898686cd2SShayne Chen mt76_clear(dev, reg, MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN); 158998686cd2SShayne Chen mt76_set(dev, reg, BIT(11) | BIT(9)); 159098686cd2SShayne Chen } 159198686cd2SShayne Chen 159298686cd2SShayne Chen void mt7996_mac_reset_counters(struct mt7996_phy *phy) 159398686cd2SShayne Chen { 159498686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 159598686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 159698686cd2SShayne Chen int i; 159798686cd2SShayne Chen 159898686cd2SShayne Chen for (i = 0; i < 16; i++) 159998686cd2SShayne Chen mt76_rr(dev, MT_TX_AGG_CNT(band_idx, i)); 160098686cd2SShayne Chen 160198686cd2SShayne Chen phy->mt76->survey_time = ktime_get_boottime(); 160298686cd2SShayne Chen 160398686cd2SShayne Chen memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats)); 160498686cd2SShayne Chen 160598686cd2SShayne Chen /* reset airtime counters */ 160698686cd2SShayne Chen mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band_idx), 160798686cd2SShayne Chen MT_WF_RMAC_MIB_RXTIME_CLR); 160898686cd2SShayne Chen 160998686cd2SShayne Chen mt7996_mcu_get_chan_mib_info(phy, true); 161098686cd2SShayne Chen } 161198686cd2SShayne Chen 161298686cd2SShayne Chen void mt7996_mac_set_timing(struct mt7996_phy *phy) 161398686cd2SShayne Chen { 161498686cd2SShayne Chen s16 coverage_class = phy->coverage_class; 161598686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 161698686cd2SShayne Chen struct mt7996_phy *phy2 = mt7996_phy2(dev); 161798686cd2SShayne Chen struct mt7996_phy *phy3 = mt7996_phy3(dev); 161898686cd2SShayne Chen u32 val, reg_offset; 161998686cd2SShayne Chen u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | 162098686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); 162198686cd2SShayne Chen u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | 162298686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); 162398686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 162498686cd2SShayne Chen int offset; 162598686cd2SShayne Chen bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); 162698686cd2SShayne Chen 162798686cd2SShayne Chen if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) 162898686cd2SShayne Chen return; 162998686cd2SShayne Chen 163098686cd2SShayne Chen if (phy2) 163198686cd2SShayne Chen coverage_class = max_t(s16, dev->phy.coverage_class, 163298686cd2SShayne Chen phy2->coverage_class); 163398686cd2SShayne Chen 163498686cd2SShayne Chen if (phy3) 163598686cd2SShayne Chen coverage_class = max_t(s16, coverage_class, 163698686cd2SShayne Chen phy3->coverage_class); 163798686cd2SShayne Chen 163898686cd2SShayne Chen mt76_set(dev, MT_ARB_SCR(band_idx), 163998686cd2SShayne Chen MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 164098686cd2SShayne Chen udelay(1); 164198686cd2SShayne Chen 164298686cd2SShayne Chen offset = 3 * coverage_class; 164398686cd2SShayne Chen reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | 164498686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); 164598686cd2SShayne Chen 164698686cd2SShayne Chen mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset); 164798686cd2SShayne Chen mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset); 164898686cd2SShayne Chen mt76_wr(dev, MT_TMAC_ICR0(band_idx), 164998686cd2SShayne Chen FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) | 165098686cd2SShayne Chen FIELD_PREP(MT_IFS_RIFS, 2) | 165198686cd2SShayne Chen FIELD_PREP(MT_IFS_SIFS, 10) | 165298686cd2SShayne Chen FIELD_PREP(MT_IFS_SLOT, phy->slottime)); 165398686cd2SShayne Chen 165498686cd2SShayne Chen if (!a_band) 165598686cd2SShayne Chen mt76_wr(dev, MT_TMAC_ICR1(band_idx), 165698686cd2SShayne Chen FIELD_PREP(MT_IFS_EIFS_CCK, 314)); 165798686cd2SShayne Chen 165898686cd2SShayne Chen if (phy->slottime < 20 || a_band) 165998686cd2SShayne Chen val = MT7996_CFEND_RATE_DEFAULT; 166098686cd2SShayne Chen else 166198686cd2SShayne Chen val = MT7996_CFEND_RATE_11B; 166298686cd2SShayne Chen 1663793445cfSShayne Chen mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val); 166498686cd2SShayne Chen mt76_clear(dev, MT_ARB_SCR(band_idx), 166598686cd2SShayne Chen MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 166698686cd2SShayne Chen } 166798686cd2SShayne Chen 166898686cd2SShayne Chen void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band) 166998686cd2SShayne Chen { 167098686cd2SShayne Chen mt76_set(dev, MT_WF_PHYRX_CSD_BAND_RXTD12(band), 167198686cd2SShayne Chen MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY | 167298686cd2SShayne Chen MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR); 167398686cd2SShayne Chen 167498686cd2SShayne Chen mt76_set(dev, MT_WF_PHYRX_BAND_RX_CTRL1(band), 167598686cd2SShayne Chen FIELD_PREP(MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN, 0x5)); 167698686cd2SShayne Chen } 167798686cd2SShayne Chen 167898686cd2SShayne Chen static u8 167998686cd2SShayne Chen mt7996_phy_get_nf(struct mt7996_phy *phy, u8 band_idx) 168098686cd2SShayne Chen { 168198686cd2SShayne Chen static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; 168298686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 168398686cd2SShayne Chen u32 val, sum = 0, n = 0; 168498686cd2SShayne Chen int ant, i; 168598686cd2SShayne Chen 168698686cd2SShayne Chen for (ant = 0; ant < hweight8(phy->mt76->antenna_mask); ant++) { 168798686cd2SShayne Chen u32 reg = MT_WF_PHYRX_CSD_IRPI(band_idx, ant); 168898686cd2SShayne Chen 168998686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { 169098686cd2SShayne Chen val = mt76_rr(dev, reg); 169198686cd2SShayne Chen sum += val * nf_power[i]; 169298686cd2SShayne Chen n += val; 169398686cd2SShayne Chen } 169498686cd2SShayne Chen } 169598686cd2SShayne Chen 169698686cd2SShayne Chen return n ? sum / n : 0; 169798686cd2SShayne Chen } 169898686cd2SShayne Chen 169998686cd2SShayne Chen void mt7996_update_channel(struct mt76_phy *mphy) 170098686cd2SShayne Chen { 170198686cd2SShayne Chen struct mt7996_phy *phy = (struct mt7996_phy *)mphy->priv; 170298686cd2SShayne Chen struct mt76_channel_state *state = mphy->chan_state; 170398686cd2SShayne Chen int nf; 170498686cd2SShayne Chen 170598686cd2SShayne Chen mt7996_mcu_get_chan_mib_info(phy, false); 170698686cd2SShayne Chen 170798686cd2SShayne Chen nf = mt7996_phy_get_nf(phy, mphy->band_idx); 170898686cd2SShayne Chen if (!phy->noise) 170998686cd2SShayne Chen phy->noise = nf << 4; 171098686cd2SShayne Chen else if (nf) 171198686cd2SShayne Chen phy->noise += nf - (phy->noise >> 4); 171298686cd2SShayne Chen 171398686cd2SShayne Chen state->noise = -(phy->noise >> 4); 171498686cd2SShayne Chen } 171598686cd2SShayne Chen 171698686cd2SShayne Chen static bool 171798686cd2SShayne Chen mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state) 171898686cd2SShayne Chen { 171998686cd2SShayne Chen bool ret; 172098686cd2SShayne Chen 172198686cd2SShayne Chen ret = wait_event_timeout(dev->reset_wait, 172227015b6fSBo Jiao (READ_ONCE(dev->recovery.state) & state), 172398686cd2SShayne Chen MT7996_RESET_TIMEOUT); 172498686cd2SShayne Chen 172598686cd2SShayne Chen WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); 172698686cd2SShayne Chen return ret; 172798686cd2SShayne Chen } 172898686cd2SShayne Chen 172998686cd2SShayne Chen static void 173098686cd2SShayne Chen mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) 173198686cd2SShayne Chen { 173298686cd2SShayne Chen struct ieee80211_hw *hw = priv; 173398686cd2SShayne Chen 173498686cd2SShayne Chen switch (vif->type) { 173598686cd2SShayne Chen case NL80211_IFTYPE_MESH_POINT: 173698686cd2SShayne Chen case NL80211_IFTYPE_ADHOC: 173798686cd2SShayne Chen case NL80211_IFTYPE_AP: 173898686cd2SShayne Chen mt7996_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); 173998686cd2SShayne Chen break; 174098686cd2SShayne Chen default: 174198686cd2SShayne Chen break; 174298686cd2SShayne Chen } 174398686cd2SShayne Chen } 174498686cd2SShayne Chen 174598686cd2SShayne Chen static void 174698686cd2SShayne Chen mt7996_update_beacons(struct mt7996_dev *dev) 174798686cd2SShayne Chen { 174898686cd2SShayne Chen struct mt76_phy *phy2, *phy3; 174998686cd2SShayne Chen 175098686cd2SShayne Chen ieee80211_iterate_active_interfaces(dev->mt76.hw, 175198686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 175298686cd2SShayne Chen mt7996_update_vif_beacon, dev->mt76.hw); 175398686cd2SShayne Chen 175498686cd2SShayne Chen phy2 = dev->mt76.phys[MT_BAND1]; 175598686cd2SShayne Chen if (!phy2) 175698686cd2SShayne Chen return; 175798686cd2SShayne Chen 175898686cd2SShayne Chen ieee80211_iterate_active_interfaces(phy2->hw, 175998686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 176098686cd2SShayne Chen mt7996_update_vif_beacon, phy2->hw); 176198686cd2SShayne Chen 176298686cd2SShayne Chen phy3 = dev->mt76.phys[MT_BAND2]; 176398686cd2SShayne Chen if (!phy3) 176498686cd2SShayne Chen return; 176598686cd2SShayne Chen 176698686cd2SShayne Chen ieee80211_iterate_active_interfaces(phy3->hw, 176798686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 176898686cd2SShayne Chen mt7996_update_vif_beacon, phy3->hw); 176998686cd2SShayne Chen } 177098686cd2SShayne Chen 177198686cd2SShayne Chen void mt7996_tx_token_put(struct mt7996_dev *dev) 177298686cd2SShayne Chen { 177398686cd2SShayne Chen struct mt76_txwi_cache *txwi; 177498686cd2SShayne Chen int id; 177598686cd2SShayne Chen 177698686cd2SShayne Chen spin_lock_bh(&dev->mt76.token_lock); 177798686cd2SShayne Chen idr_for_each_entry(&dev->mt76.token, txwi, id) { 177898686cd2SShayne Chen mt7996_txwi_free(dev, txwi, NULL, NULL); 177998686cd2SShayne Chen dev->mt76.token_count--; 178098686cd2SShayne Chen } 178198686cd2SShayne Chen spin_unlock_bh(&dev->mt76.token_lock); 178298686cd2SShayne Chen idr_destroy(&dev->mt76.token); 178398686cd2SShayne Chen } 178498686cd2SShayne Chen 178527015b6fSBo Jiao static int 178627015b6fSBo Jiao mt7996_mac_restart(struct mt7996_dev *dev) 178727015b6fSBo Jiao { 178827015b6fSBo Jiao struct mt7996_phy *phy2, *phy3; 178927015b6fSBo Jiao struct mt76_dev *mdev = &dev->mt76; 179027015b6fSBo Jiao int i, ret; 179127015b6fSBo Jiao 179227015b6fSBo Jiao phy2 = mt7996_phy2(dev); 179327015b6fSBo Jiao phy3 = mt7996_phy3(dev); 179427015b6fSBo Jiao 179527015b6fSBo Jiao if (dev->hif2) { 179627015b6fSBo Jiao mt76_wr(dev, MT_INT1_MASK_CSR, 0x0); 179727015b6fSBo Jiao mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0); 179827015b6fSBo Jiao } 179927015b6fSBo Jiao 180027015b6fSBo Jiao if (dev_is_pci(mdev->dev)) { 180127015b6fSBo Jiao mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); 180227015b6fSBo Jiao if (dev->hif2) 180327015b6fSBo Jiao mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0); 180427015b6fSBo Jiao } 180527015b6fSBo Jiao 180627015b6fSBo Jiao set_bit(MT76_RESET, &dev->mphy.state); 180727015b6fSBo Jiao set_bit(MT76_MCU_RESET, &dev->mphy.state); 180827015b6fSBo Jiao wake_up(&dev->mt76.mcu.wait); 180927015b6fSBo Jiao if (phy2) { 181027015b6fSBo Jiao set_bit(MT76_RESET, &phy2->mt76->state); 181127015b6fSBo Jiao set_bit(MT76_MCU_RESET, &phy2->mt76->state); 181227015b6fSBo Jiao } 181327015b6fSBo Jiao if (phy3) { 181427015b6fSBo Jiao set_bit(MT76_RESET, &phy3->mt76->state); 181527015b6fSBo Jiao set_bit(MT76_MCU_RESET, &phy3->mt76->state); 181627015b6fSBo Jiao } 181727015b6fSBo Jiao 181827015b6fSBo Jiao /* lock/unlock all queues to ensure that no tx is pending */ 181927015b6fSBo Jiao mt76_txq_schedule_all(&dev->mphy); 182027015b6fSBo Jiao if (phy2) 182127015b6fSBo Jiao mt76_txq_schedule_all(phy2->mt76); 182227015b6fSBo Jiao if (phy3) 182327015b6fSBo Jiao mt76_txq_schedule_all(phy3->mt76); 182427015b6fSBo Jiao 182527015b6fSBo Jiao /* disable all tx/rx napi */ 182627015b6fSBo Jiao mt76_worker_disable(&dev->mt76.tx_worker); 182727015b6fSBo Jiao mt76_for_each_q_rx(mdev, i) { 182827015b6fSBo Jiao if (mdev->q_rx[i].ndesc) 182927015b6fSBo Jiao napi_disable(&dev->mt76.napi[i]); 183027015b6fSBo Jiao } 183127015b6fSBo Jiao napi_disable(&dev->mt76.tx_napi); 183227015b6fSBo Jiao 183327015b6fSBo Jiao /* token reinit */ 183427015b6fSBo Jiao mt7996_tx_token_put(dev); 183527015b6fSBo Jiao idr_init(&dev->mt76.token); 183627015b6fSBo Jiao 183727015b6fSBo Jiao mt7996_dma_reset(dev, true); 183827015b6fSBo Jiao 183927015b6fSBo Jiao local_bh_disable(); 184027015b6fSBo Jiao mt76_for_each_q_rx(mdev, i) { 184127015b6fSBo Jiao if (mdev->q_rx[i].ndesc) { 184227015b6fSBo Jiao napi_enable(&dev->mt76.napi[i]); 184327015b6fSBo Jiao napi_schedule(&dev->mt76.napi[i]); 184427015b6fSBo Jiao } 184527015b6fSBo Jiao } 184627015b6fSBo Jiao local_bh_enable(); 184727015b6fSBo Jiao clear_bit(MT76_MCU_RESET, &dev->mphy.state); 184827015b6fSBo Jiao clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 184927015b6fSBo Jiao 185027015b6fSBo Jiao mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); 185127015b6fSBo Jiao mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); 185227015b6fSBo Jiao if (dev->hif2) { 185327015b6fSBo Jiao mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask); 185427015b6fSBo Jiao mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0); 185527015b6fSBo Jiao } 185627015b6fSBo Jiao if (dev_is_pci(mdev->dev)) { 185727015b6fSBo Jiao mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 185827015b6fSBo Jiao if (dev->hif2) 185927015b6fSBo Jiao mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); 186027015b6fSBo Jiao } 186127015b6fSBo Jiao 186227015b6fSBo Jiao /* load firmware */ 186327015b6fSBo Jiao ret = mt7996_mcu_init_firmware(dev); 186427015b6fSBo Jiao if (ret) 186527015b6fSBo Jiao goto out; 186627015b6fSBo Jiao 186727015b6fSBo Jiao /* set the necessary init items */ 186827015b6fSBo Jiao ret = mt7996_mcu_set_eeprom(dev); 186927015b6fSBo Jiao if (ret) 187027015b6fSBo Jiao goto out; 187127015b6fSBo Jiao 187227015b6fSBo Jiao mt7996_mac_init(dev); 187327015b6fSBo Jiao mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband); 187427015b6fSBo Jiao mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband); 187527015b6fSBo Jiao mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband); 187627015b6fSBo Jiao ret = mt7996_txbf_init(dev); 187727015b6fSBo Jiao 187827015b6fSBo Jiao if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) { 187927015b6fSBo Jiao ret = mt7996_run(dev->mphy.hw); 188027015b6fSBo Jiao if (ret) 188127015b6fSBo Jiao goto out; 188227015b6fSBo Jiao } 188327015b6fSBo Jiao 188427015b6fSBo Jiao if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) { 188527015b6fSBo Jiao ret = mt7996_run(phy2->mt76->hw); 188627015b6fSBo Jiao if (ret) 188727015b6fSBo Jiao goto out; 188827015b6fSBo Jiao } 188927015b6fSBo Jiao 189027015b6fSBo Jiao if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) { 189127015b6fSBo Jiao ret = mt7996_run(phy3->mt76->hw); 189227015b6fSBo Jiao if (ret) 189327015b6fSBo Jiao goto out; 189427015b6fSBo Jiao } 189527015b6fSBo Jiao 189627015b6fSBo Jiao out: 189727015b6fSBo Jiao /* reset done */ 189827015b6fSBo Jiao clear_bit(MT76_RESET, &dev->mphy.state); 189927015b6fSBo Jiao if (phy2) 190027015b6fSBo Jiao clear_bit(MT76_RESET, &phy2->mt76->state); 190127015b6fSBo Jiao if (phy3) 190227015b6fSBo Jiao clear_bit(MT76_RESET, &phy3->mt76->state); 190327015b6fSBo Jiao 190427015b6fSBo Jiao local_bh_disable(); 190527015b6fSBo Jiao napi_enable(&dev->mt76.tx_napi); 190627015b6fSBo Jiao napi_schedule(&dev->mt76.tx_napi); 190727015b6fSBo Jiao local_bh_enable(); 190827015b6fSBo Jiao 190927015b6fSBo Jiao mt76_worker_enable(&dev->mt76.tx_worker); 191027015b6fSBo Jiao return ret; 191127015b6fSBo Jiao } 191227015b6fSBo Jiao 191327015b6fSBo Jiao static void 191427015b6fSBo Jiao mt7996_mac_full_reset(struct mt7996_dev *dev) 191527015b6fSBo Jiao { 191627015b6fSBo Jiao struct mt7996_phy *phy2, *phy3; 191727015b6fSBo Jiao int i; 191827015b6fSBo Jiao 191927015b6fSBo Jiao phy2 = mt7996_phy2(dev); 192027015b6fSBo Jiao phy3 = mt7996_phy3(dev); 192127015b6fSBo Jiao dev->recovery.hw_full_reset = true; 192227015b6fSBo Jiao 192327015b6fSBo Jiao wake_up(&dev->mt76.mcu.wait); 192427015b6fSBo Jiao ieee80211_stop_queues(mt76_hw(dev)); 192527015b6fSBo Jiao if (phy2) 192627015b6fSBo Jiao ieee80211_stop_queues(phy2->mt76->hw); 192727015b6fSBo Jiao if (phy3) 192827015b6fSBo Jiao ieee80211_stop_queues(phy3->mt76->hw); 192927015b6fSBo Jiao 193027015b6fSBo Jiao cancel_delayed_work_sync(&dev->mphy.mac_work); 193127015b6fSBo Jiao if (phy2) 193227015b6fSBo Jiao cancel_delayed_work_sync(&phy2->mt76->mac_work); 193327015b6fSBo Jiao if (phy3) 193427015b6fSBo Jiao cancel_delayed_work_sync(&phy3->mt76->mac_work); 193527015b6fSBo Jiao 193627015b6fSBo Jiao mutex_lock(&dev->mt76.mutex); 193727015b6fSBo Jiao for (i = 0; i < 10; i++) { 193827015b6fSBo Jiao if (!mt7996_mac_restart(dev)) 193927015b6fSBo Jiao break; 194027015b6fSBo Jiao } 194127015b6fSBo Jiao mutex_unlock(&dev->mt76.mutex); 194227015b6fSBo Jiao 194327015b6fSBo Jiao if (i == 10) 194427015b6fSBo Jiao dev_err(dev->mt76.dev, "chip full reset failed\n"); 194527015b6fSBo Jiao 194627015b6fSBo Jiao ieee80211_restart_hw(mt76_hw(dev)); 194727015b6fSBo Jiao if (phy2) 194827015b6fSBo Jiao ieee80211_restart_hw(phy2->mt76->hw); 194927015b6fSBo Jiao if (phy3) 195027015b6fSBo Jiao ieee80211_restart_hw(phy3->mt76->hw); 195127015b6fSBo Jiao 195227015b6fSBo Jiao ieee80211_wake_queues(mt76_hw(dev)); 195327015b6fSBo Jiao if (phy2) 195427015b6fSBo Jiao ieee80211_wake_queues(phy2->mt76->hw); 195527015b6fSBo Jiao if (phy3) 195627015b6fSBo Jiao ieee80211_wake_queues(phy3->mt76->hw); 195727015b6fSBo Jiao 195827015b6fSBo Jiao dev->recovery.hw_full_reset = false; 195927015b6fSBo Jiao ieee80211_queue_delayed_work(mt76_hw(dev), 196027015b6fSBo Jiao &dev->mphy.mac_work, 196127015b6fSBo Jiao MT7996_WATCHDOG_TIME); 196227015b6fSBo Jiao if (phy2) 196327015b6fSBo Jiao ieee80211_queue_delayed_work(phy2->mt76->hw, 196427015b6fSBo Jiao &phy2->mt76->mac_work, 196527015b6fSBo Jiao MT7996_WATCHDOG_TIME); 196627015b6fSBo Jiao if (phy3) 196727015b6fSBo Jiao ieee80211_queue_delayed_work(phy3->mt76->hw, 196827015b6fSBo Jiao &phy3->mt76->mac_work, 196927015b6fSBo Jiao MT7996_WATCHDOG_TIME); 197027015b6fSBo Jiao } 197127015b6fSBo Jiao 197298686cd2SShayne Chen void mt7996_mac_reset_work(struct work_struct *work) 197398686cd2SShayne Chen { 197498686cd2SShayne Chen struct mt7996_phy *phy2, *phy3; 197598686cd2SShayne Chen struct mt7996_dev *dev; 197698686cd2SShayne Chen int i; 197798686cd2SShayne Chen 197898686cd2SShayne Chen dev = container_of(work, struct mt7996_dev, reset_work); 197998686cd2SShayne Chen phy2 = mt7996_phy2(dev); 198098686cd2SShayne Chen phy3 = mt7996_phy3(dev); 198198686cd2SShayne Chen 198227015b6fSBo Jiao /* chip full reset */ 198327015b6fSBo Jiao if (dev->recovery.restart) { 198427015b6fSBo Jiao /* disable WA/WM WDT */ 198527015b6fSBo Jiao mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA, 198627015b6fSBo Jiao MT_MCU_CMD_WDT_MASK); 198727015b6fSBo Jiao 198827015b6fSBo Jiao if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT) 198927015b6fSBo Jiao dev->recovery.wa_reset_count++; 199027015b6fSBo Jiao else 199127015b6fSBo Jiao dev->recovery.wm_reset_count++; 199227015b6fSBo Jiao 199327015b6fSBo Jiao mt7996_mac_full_reset(dev); 199427015b6fSBo Jiao 199527015b6fSBo Jiao /* enable mcu irq */ 199627015b6fSBo Jiao mt7996_irq_enable(dev, MT_INT_MCU_CMD); 199727015b6fSBo Jiao mt7996_irq_disable(dev, 0); 199827015b6fSBo Jiao 199927015b6fSBo Jiao /* enable WA/WM WDT */ 200027015b6fSBo Jiao mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK); 200127015b6fSBo Jiao 200227015b6fSBo Jiao dev->recovery.state = MT_MCU_CMD_NORMAL_STATE; 200327015b6fSBo Jiao dev->recovery.restart = false; 200427015b6fSBo Jiao return; 200527015b6fSBo Jiao } 200627015b6fSBo Jiao 200727015b6fSBo Jiao if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) 200898686cd2SShayne Chen return; 200998686cd2SShayne Chen 201027015b6fSBo Jiao dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.", 201127015b6fSBo Jiao wiphy_name(dev->mt76.hw->wiphy)); 201298686cd2SShayne Chen ieee80211_stop_queues(mt76_hw(dev)); 201398686cd2SShayne Chen if (phy2) 201498686cd2SShayne Chen ieee80211_stop_queues(phy2->mt76->hw); 201598686cd2SShayne Chen if (phy3) 201698686cd2SShayne Chen ieee80211_stop_queues(phy3->mt76->hw); 201798686cd2SShayne Chen 201898686cd2SShayne Chen set_bit(MT76_RESET, &dev->mphy.state); 201998686cd2SShayne Chen set_bit(MT76_MCU_RESET, &dev->mphy.state); 202098686cd2SShayne Chen wake_up(&dev->mt76.mcu.wait); 202198686cd2SShayne Chen cancel_delayed_work_sync(&dev->mphy.mac_work); 202298686cd2SShayne Chen if (phy2) { 202398686cd2SShayne Chen set_bit(MT76_RESET, &phy2->mt76->state); 202498686cd2SShayne Chen cancel_delayed_work_sync(&phy2->mt76->mac_work); 202598686cd2SShayne Chen } 202698686cd2SShayne Chen if (phy3) { 202798686cd2SShayne Chen set_bit(MT76_RESET, &phy3->mt76->state); 202898686cd2SShayne Chen cancel_delayed_work_sync(&phy3->mt76->mac_work); 202998686cd2SShayne Chen } 203098686cd2SShayne Chen mt76_worker_disable(&dev->mt76.tx_worker); 203198686cd2SShayne Chen mt76_for_each_q_rx(&dev->mt76, i) 203298686cd2SShayne Chen napi_disable(&dev->mt76.napi[i]); 203398686cd2SShayne Chen napi_disable(&dev->mt76.tx_napi); 203498686cd2SShayne Chen 203598686cd2SShayne Chen mutex_lock(&dev->mt76.mutex); 203698686cd2SShayne Chen 203798686cd2SShayne Chen mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); 203898686cd2SShayne Chen 203998686cd2SShayne Chen if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { 204027015b6fSBo Jiao mt7996_dma_reset(dev, false); 204198686cd2SShayne Chen 204298686cd2SShayne Chen mt7996_tx_token_put(dev); 204398686cd2SShayne Chen idr_init(&dev->mt76.token); 204498686cd2SShayne Chen 204598686cd2SShayne Chen mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); 204698686cd2SShayne Chen mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); 204798686cd2SShayne Chen } 204898686cd2SShayne Chen 204998686cd2SShayne Chen clear_bit(MT76_MCU_RESET, &dev->mphy.state); 205098686cd2SShayne Chen clear_bit(MT76_RESET, &dev->mphy.state); 205198686cd2SShayne Chen if (phy2) 205298686cd2SShayne Chen clear_bit(MT76_RESET, &phy2->mt76->state); 205398686cd2SShayne Chen if (phy3) 205498686cd2SShayne Chen clear_bit(MT76_RESET, &phy3->mt76->state); 205598686cd2SShayne Chen 205698686cd2SShayne Chen local_bh_disable(); 205798686cd2SShayne Chen mt76_for_each_q_rx(&dev->mt76, i) { 205898686cd2SShayne Chen napi_enable(&dev->mt76.napi[i]); 205998686cd2SShayne Chen napi_schedule(&dev->mt76.napi[i]); 206098686cd2SShayne Chen } 206198686cd2SShayne Chen local_bh_enable(); 206298686cd2SShayne Chen 2063ec193b41SLorenzo Bianconi tasklet_schedule(&dev->mt76.irq_tasklet); 206498686cd2SShayne Chen 206598686cd2SShayne Chen mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); 206698686cd2SShayne Chen mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); 206798686cd2SShayne Chen 206898686cd2SShayne Chen mt76_worker_enable(&dev->mt76.tx_worker); 206998686cd2SShayne Chen 207098686cd2SShayne Chen local_bh_disable(); 207198686cd2SShayne Chen napi_enable(&dev->mt76.tx_napi); 207298686cd2SShayne Chen napi_schedule(&dev->mt76.tx_napi); 207398686cd2SShayne Chen local_bh_enable(); 207498686cd2SShayne Chen 207598686cd2SShayne Chen ieee80211_wake_queues(mt76_hw(dev)); 207698686cd2SShayne Chen if (phy2) 207798686cd2SShayne Chen ieee80211_wake_queues(phy2->mt76->hw); 207898686cd2SShayne Chen if (phy3) 207998686cd2SShayne Chen ieee80211_wake_queues(phy3->mt76->hw); 208098686cd2SShayne Chen 208198686cd2SShayne Chen mutex_unlock(&dev->mt76.mutex); 208298686cd2SShayne Chen 208398686cd2SShayne Chen mt7996_update_beacons(dev); 208498686cd2SShayne Chen 208598686cd2SShayne Chen ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, 208698686cd2SShayne Chen MT7996_WATCHDOG_TIME); 208798686cd2SShayne Chen if (phy2) 208898686cd2SShayne Chen ieee80211_queue_delayed_work(phy2->mt76->hw, 208998686cd2SShayne Chen &phy2->mt76->mac_work, 209098686cd2SShayne Chen MT7996_WATCHDOG_TIME); 209198686cd2SShayne Chen if (phy3) 209298686cd2SShayne Chen ieee80211_queue_delayed_work(phy3->mt76->hw, 209398686cd2SShayne Chen &phy3->mt76->mac_work, 209498686cd2SShayne Chen MT7996_WATCHDOG_TIME); 209527015b6fSBo Jiao dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.", 209627015b6fSBo Jiao wiphy_name(dev->mt76.hw->wiphy)); 209727015b6fSBo Jiao } 209827015b6fSBo Jiao 2099878161d5SRyder Lee /* firmware coredump */ 2100878161d5SRyder Lee void mt7996_mac_dump_work(struct work_struct *work) 2101878161d5SRyder Lee { 2102878161d5SRyder Lee const struct mt7996_mem_region *mem_region; 2103878161d5SRyder Lee struct mt7996_crash_data *crash_data; 2104878161d5SRyder Lee struct mt7996_dev *dev; 2105878161d5SRyder Lee struct mt7996_mem_hdr *hdr; 2106878161d5SRyder Lee size_t buf_len; 2107878161d5SRyder Lee int i; 2108878161d5SRyder Lee u32 num; 2109878161d5SRyder Lee u8 *buf; 2110878161d5SRyder Lee 2111878161d5SRyder Lee dev = container_of(work, struct mt7996_dev, dump_work); 2112878161d5SRyder Lee 2113878161d5SRyder Lee mutex_lock(&dev->dump_mutex); 2114878161d5SRyder Lee 2115878161d5SRyder Lee crash_data = mt7996_coredump_new(dev); 2116878161d5SRyder Lee if (!crash_data) { 2117878161d5SRyder Lee mutex_unlock(&dev->dump_mutex); 2118878161d5SRyder Lee goto skip_coredump; 2119878161d5SRyder Lee } 2120878161d5SRyder Lee 2121878161d5SRyder Lee mem_region = mt7996_coredump_get_mem_layout(dev, &num); 2122878161d5SRyder Lee if (!mem_region || !crash_data->memdump_buf_len) { 2123878161d5SRyder Lee mutex_unlock(&dev->dump_mutex); 2124878161d5SRyder Lee goto skip_memdump; 2125878161d5SRyder Lee } 2126878161d5SRyder Lee 2127878161d5SRyder Lee buf = crash_data->memdump_buf; 2128878161d5SRyder Lee buf_len = crash_data->memdump_buf_len; 2129878161d5SRyder Lee 2130878161d5SRyder Lee /* dumping memory content... */ 2131878161d5SRyder Lee memset(buf, 0, buf_len); 2132878161d5SRyder Lee for (i = 0; i < num; i++) { 2133878161d5SRyder Lee if (mem_region->len > buf_len) { 2134878161d5SRyder Lee dev_warn(dev->mt76.dev, "%s len %zu is too large\n", 2135878161d5SRyder Lee mem_region->name, mem_region->len); 2136878161d5SRyder Lee break; 2137878161d5SRyder Lee } 2138878161d5SRyder Lee 2139878161d5SRyder Lee /* reserve space for the header */ 2140878161d5SRyder Lee hdr = (void *)buf; 2141878161d5SRyder Lee buf += sizeof(*hdr); 2142878161d5SRyder Lee buf_len -= sizeof(*hdr); 2143878161d5SRyder Lee 2144878161d5SRyder Lee mt7996_memcpy_fromio(dev, buf, mem_region->start, 2145878161d5SRyder Lee mem_region->len); 2146878161d5SRyder Lee 2147878161d5SRyder Lee hdr->start = mem_region->start; 2148878161d5SRyder Lee hdr->len = mem_region->len; 2149878161d5SRyder Lee 2150878161d5SRyder Lee if (!mem_region->len) 2151878161d5SRyder Lee /* note: the header remains, just with zero length */ 2152878161d5SRyder Lee break; 2153878161d5SRyder Lee 2154878161d5SRyder Lee buf += mem_region->len; 2155878161d5SRyder Lee buf_len -= mem_region->len; 2156878161d5SRyder Lee 2157878161d5SRyder Lee mem_region++; 2158878161d5SRyder Lee } 2159878161d5SRyder Lee 2160878161d5SRyder Lee mutex_unlock(&dev->dump_mutex); 2161878161d5SRyder Lee 2162878161d5SRyder Lee skip_memdump: 2163878161d5SRyder Lee mt7996_coredump_submit(dev); 2164878161d5SRyder Lee skip_coredump: 2165878161d5SRyder Lee queue_work(dev->mt76.wq, &dev->reset_work); 2166878161d5SRyder Lee } 2167878161d5SRyder Lee 216827015b6fSBo Jiao void mt7996_reset(struct mt7996_dev *dev) 216927015b6fSBo Jiao { 217027015b6fSBo Jiao if (!dev->recovery.hw_init_done) 217127015b6fSBo Jiao return; 217227015b6fSBo Jiao 217327015b6fSBo Jiao if (dev->recovery.hw_full_reset) 217427015b6fSBo Jiao return; 217527015b6fSBo Jiao 217627015b6fSBo Jiao /* wm/wa exception: do full recovery */ 217727015b6fSBo Jiao if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) { 217827015b6fSBo Jiao dev->recovery.restart = true; 217927015b6fSBo Jiao dev_info(dev->mt76.dev, 218027015b6fSBo Jiao "%s indicated firmware crash, attempting recovery\n", 218127015b6fSBo Jiao wiphy_name(dev->mt76.hw->wiphy)); 218227015b6fSBo Jiao 218327015b6fSBo Jiao mt7996_irq_disable(dev, MT_INT_MCU_CMD); 2184878161d5SRyder Lee queue_work(dev->mt76.wq, &dev->dump_work); 218527015b6fSBo Jiao return; 218627015b6fSBo Jiao } 218727015b6fSBo Jiao 218827015b6fSBo Jiao queue_work(dev->mt76.wq, &dev->reset_work); 218927015b6fSBo Jiao wake_up(&dev->reset_wait); 219098686cd2SShayne Chen } 219198686cd2SShayne Chen 219298686cd2SShayne Chen void mt7996_mac_update_stats(struct mt7996_phy *phy) 219398686cd2SShayne Chen { 219498686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 219598686cd2SShayne Chen struct mib_stats *mib = &phy->mib; 219698686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 219798686cd2SShayne Chen u32 cnt; 219898686cd2SShayne Chen int i; 219998686cd2SShayne Chen 220098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR1(band_idx)); 220198686cd2SShayne Chen mib->fcs_err_cnt += cnt; 220298686cd2SShayne Chen 220398686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR33(band_idx)); 220498686cd2SShayne Chen mib->rx_fifo_full_cnt += cnt; 220598686cd2SShayne Chen 220698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR31(band_idx)); 220798686cd2SShayne Chen mib->rx_mpdu_cnt += cnt; 220898686cd2SShayne Chen 220998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR6(band_idx)); 221098686cd2SShayne Chen mib->channel_idle_cnt += FIELD_GET(MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK, cnt); 221198686cd2SShayne Chen 221298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RVSR0(band_idx)); 221398686cd2SShayne Chen mib->rx_vector_mismatch_cnt += cnt; 221498686cd2SShayne Chen 221598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR35(band_idx)); 221698686cd2SShayne Chen mib->rx_delimiter_fail_cnt += cnt; 221798686cd2SShayne Chen 221898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR36(band_idx)); 221998686cd2SShayne Chen mib->rx_len_mismatch_cnt += cnt; 222098686cd2SShayne Chen 222198686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR0(band_idx)); 222298686cd2SShayne Chen mib->tx_ampdu_cnt += cnt; 222398686cd2SShayne Chen 222498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR2(band_idx)); 222598686cd2SShayne Chen mib->tx_stop_q_empty_cnt += cnt; 222698686cd2SShayne Chen 222798686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR3(band_idx)); 222898686cd2SShayne Chen mib->tx_mpdu_attempts_cnt += cnt; 222998686cd2SShayne Chen 223098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR4(band_idx)); 223198686cd2SShayne Chen mib->tx_mpdu_success_cnt += cnt; 223298686cd2SShayne Chen 223398686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR27(band_idx)); 223498686cd2SShayne Chen mib->rx_ampdu_cnt += cnt; 223598686cd2SShayne Chen 223698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR28(band_idx)); 223798686cd2SShayne Chen mib->rx_ampdu_bytes_cnt += cnt; 223898686cd2SShayne Chen 223998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR29(band_idx)); 224098686cd2SShayne Chen mib->rx_ampdu_valid_subframe_cnt += cnt; 224198686cd2SShayne Chen 224298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR30(band_idx)); 224398686cd2SShayne Chen mib->rx_ampdu_valid_subframe_bytes_cnt += cnt; 224498686cd2SShayne Chen 224598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR27(band_idx)); 224698686cd2SShayne Chen mib->tx_rwp_fail_cnt += FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT, cnt); 224798686cd2SShayne Chen 224898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR28(band_idx)); 224998686cd2SShayne Chen mib->tx_rwp_need_cnt += FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT, cnt); 225098686cd2SShayne Chen 225198686cd2SShayne Chen cnt = mt76_rr(dev, MT_UMIB_RPDCR(band_idx)); 225298686cd2SShayne Chen mib->rx_pfdrop_cnt += cnt; 225398686cd2SShayne Chen 225498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RVSR1(band_idx)); 225598686cd2SShayne Chen mib->rx_vec_queue_overflow_drop_cnt += cnt; 225698686cd2SShayne Chen 225798686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR1(band_idx)); 225898686cd2SShayne Chen mib->rx_ba_cnt += cnt; 225998686cd2SShayne Chen 226098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR0(band_idx)); 226198686cd2SShayne Chen mib->tx_bf_ebf_ppdu_cnt += cnt; 226298686cd2SShayne Chen 226398686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR1(band_idx)); 226498686cd2SShayne Chen mib->tx_bf_ibf_ppdu_cnt += cnt; 226598686cd2SShayne Chen 226698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR2(band_idx)); 226798686cd2SShayne Chen mib->tx_mu_bf_cnt += cnt; 226898686cd2SShayne Chen 226998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR5(band_idx)); 227098686cd2SShayne Chen mib->tx_mu_mpdu_cnt += cnt; 227198686cd2SShayne Chen 227298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR6(band_idx)); 227398686cd2SShayne Chen mib->tx_mu_acked_mpdu_cnt += cnt; 227498686cd2SShayne Chen 227598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR7(band_idx)); 227698686cd2SShayne Chen mib->tx_su_acked_mpdu_cnt += cnt; 227798686cd2SShayne Chen 227898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR3(band_idx)); 227998686cd2SShayne Chen mib->tx_bf_rx_fb_ht_cnt += cnt; 228098686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 228198686cd2SShayne Chen 228298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR4(band_idx)); 228398686cd2SShayne Chen mib->tx_bf_rx_fb_vht_cnt += cnt; 228498686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 228598686cd2SShayne Chen 228698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR5(band_idx)); 228798686cd2SShayne Chen mib->tx_bf_rx_fb_he_cnt += cnt; 228898686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 228998686cd2SShayne Chen 229098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR6(band_idx)); 229198686cd2SShayne Chen mib->tx_bf_rx_fb_eht_cnt += cnt; 229298686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 229398686cd2SShayne Chen 229498686cd2SShayne Chen cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(band_idx)); 229598686cd2SShayne Chen mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt); 229698686cd2SShayne Chen mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt); 229798686cd2SShayne Chen mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt); 229898686cd2SShayne Chen 229998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR7(band_idx)); 230098686cd2SShayne Chen mib->tx_bf_fb_trig_cnt += cnt; 230198686cd2SShayne Chen 230298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR17(band_idx)); 230398686cd2SShayne Chen mib->tx_bf_fb_cpl_cnt += cnt; 230498686cd2SShayne Chen 230598686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { 230698686cd2SShayne Chen cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); 230798686cd2SShayne Chen mib->tx_amsdu[i] += cnt; 230898686cd2SShayne Chen mib->tx_amsdu_cnt += cnt; 230998686cd2SShayne Chen } 231098686cd2SShayne Chen 231198686cd2SShayne Chen /* rts count */ 231298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR5(band_idx)); 231398686cd2SShayne Chen mib->rts_cnt += cnt; 231498686cd2SShayne Chen 231598686cd2SShayne Chen /* rts retry count */ 231698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR6(band_idx)); 231798686cd2SShayne Chen mib->rts_retries_cnt += cnt; 231898686cd2SShayne Chen 231998686cd2SShayne Chen /* ba miss count */ 232098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR0(band_idx)); 232198686cd2SShayne Chen mib->ba_miss_cnt += cnt; 232298686cd2SShayne Chen 232398686cd2SShayne Chen /* ack fail count */ 232498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BFTFCR(band_idx)); 232598686cd2SShayne Chen mib->ack_fail_cnt += cnt; 232698686cd2SShayne Chen 232798686cd2SShayne Chen for (i = 0; i < 16; i++) { 232898686cd2SShayne Chen cnt = mt76_rr(dev, MT_TX_AGG_CNT(band_idx, i)); 232998686cd2SShayne Chen phy->mt76->aggr_stats[i] += cnt; 233098686cd2SShayne Chen } 233198686cd2SShayne Chen } 233298686cd2SShayne Chen 233398686cd2SShayne Chen void mt7996_mac_sta_rc_work(struct work_struct *work) 233498686cd2SShayne Chen { 233598686cd2SShayne Chen struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work); 233698686cd2SShayne Chen struct ieee80211_sta *sta; 233798686cd2SShayne Chen struct ieee80211_vif *vif; 233898686cd2SShayne Chen struct mt7996_sta *msta; 233998686cd2SShayne Chen u32 changed; 234098686cd2SShayne Chen LIST_HEAD(list); 234198686cd2SShayne Chen 234298686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 234398686cd2SShayne Chen list_splice_init(&dev->sta_rc_list, &list); 234498686cd2SShayne Chen 234598686cd2SShayne Chen while (!list_empty(&list)) { 234698686cd2SShayne Chen msta = list_first_entry(&list, struct mt7996_sta, rc_list); 234798686cd2SShayne Chen list_del_init(&msta->rc_list); 234898686cd2SShayne Chen changed = msta->changed; 234998686cd2SShayne Chen msta->changed = 0; 235098686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 235198686cd2SShayne Chen 235298686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); 235398686cd2SShayne Chen vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); 235498686cd2SShayne Chen 235598686cd2SShayne Chen if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | 235698686cd2SShayne Chen IEEE80211_RC_NSS_CHANGED | 235798686cd2SShayne Chen IEEE80211_RC_BW_CHANGED)) 235898686cd2SShayne Chen mt7996_mcu_add_rate_ctrl(dev, vif, sta, true); 235998686cd2SShayne Chen 236098686cd2SShayne Chen /* TODO: smps change */ 236198686cd2SShayne Chen 236298686cd2SShayne Chen spin_lock_bh(&dev->sta_poll_lock); 236398686cd2SShayne Chen } 236498686cd2SShayne Chen 236598686cd2SShayne Chen spin_unlock_bh(&dev->sta_poll_lock); 236698686cd2SShayne Chen } 236798686cd2SShayne Chen 236898686cd2SShayne Chen void mt7996_mac_work(struct work_struct *work) 236998686cd2SShayne Chen { 237098686cd2SShayne Chen struct mt7996_phy *phy; 237198686cd2SShayne Chen struct mt76_phy *mphy; 237298686cd2SShayne Chen 237398686cd2SShayne Chen mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, 237498686cd2SShayne Chen mac_work.work); 237598686cd2SShayne Chen phy = mphy->priv; 237698686cd2SShayne Chen 237798686cd2SShayne Chen mutex_lock(&mphy->dev->mutex); 237898686cd2SShayne Chen 237998686cd2SShayne Chen mt76_update_survey(mphy); 238098686cd2SShayne Chen if (++mphy->mac_work_count == 5) { 238198686cd2SShayne Chen mphy->mac_work_count = 0; 238298686cd2SShayne Chen 238398686cd2SShayne Chen mt7996_mac_update_stats(phy); 238498686cd2SShayne Chen } 238598686cd2SShayne Chen 238698686cd2SShayne Chen mutex_unlock(&mphy->dev->mutex); 238798686cd2SShayne Chen 238898686cd2SShayne Chen mt76_tx_status_check(mphy->dev, false); 238998686cd2SShayne Chen 239098686cd2SShayne Chen ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, 239198686cd2SShayne Chen MT7996_WATCHDOG_TIME); 239298686cd2SShayne Chen } 239398686cd2SShayne Chen 239498686cd2SShayne Chen static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy) 239598686cd2SShayne Chen { 239698686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 239798686cd2SShayne Chen 239898686cd2SShayne Chen if (phy->rdd_state & BIT(0)) 239998686cd2SShayne Chen mt7996_mcu_rdd_cmd(dev, RDD_STOP, 0, 240098686cd2SShayne Chen MT_RX_SEL0, 0); 240198686cd2SShayne Chen if (phy->rdd_state & BIT(1)) 240298686cd2SShayne Chen mt7996_mcu_rdd_cmd(dev, RDD_STOP, 1, 240398686cd2SShayne Chen MT_RX_SEL0, 0); 240498686cd2SShayne Chen } 240598686cd2SShayne Chen 240698686cd2SShayne Chen static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int chain) 240798686cd2SShayne Chen { 240898686cd2SShayne Chen int err, region; 240998686cd2SShayne Chen 241098686cd2SShayne Chen switch (dev->mt76.region) { 241198686cd2SShayne Chen case NL80211_DFS_ETSI: 241298686cd2SShayne Chen region = 0; 241398686cd2SShayne Chen break; 241498686cd2SShayne Chen case NL80211_DFS_JP: 241598686cd2SShayne Chen region = 2; 241698686cd2SShayne Chen break; 241798686cd2SShayne Chen case NL80211_DFS_FCC: 241898686cd2SShayne Chen default: 241998686cd2SShayne Chen region = 1; 242098686cd2SShayne Chen break; 242198686cd2SShayne Chen } 242298686cd2SShayne Chen 242398686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_START, chain, 242498686cd2SShayne Chen MT_RX_SEL0, region); 242598686cd2SShayne Chen if (err < 0) 242698686cd2SShayne Chen return err; 242798686cd2SShayne Chen 242898686cd2SShayne Chen return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, chain, 242998686cd2SShayne Chen MT_RX_SEL0, 1); 243098686cd2SShayne Chen } 243198686cd2SShayne Chen 243298686cd2SShayne Chen static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy) 243398686cd2SShayne Chen { 243498686cd2SShayne Chen struct cfg80211_chan_def *chandef = &phy->mt76->chandef; 243598686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 243698686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 243798686cd2SShayne Chen int err; 243898686cd2SShayne Chen 243998686cd2SShayne Chen /* start CAC */ 244098686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_START, band_idx, 244198686cd2SShayne Chen MT_RX_SEL0, 0); 244298686cd2SShayne Chen if (err < 0) 244398686cd2SShayne Chen return err; 244498686cd2SShayne Chen 244598686cd2SShayne Chen err = mt7996_dfs_start_rdd(dev, band_idx); 244698686cd2SShayne Chen if (err < 0) 244798686cd2SShayne Chen return err; 244898686cd2SShayne Chen 244998686cd2SShayne Chen phy->rdd_state |= BIT(band_idx); 245098686cd2SShayne Chen 245198686cd2SShayne Chen if (chandef->width == NL80211_CHAN_WIDTH_160 || 245298686cd2SShayne Chen chandef->width == NL80211_CHAN_WIDTH_80P80) { 245398686cd2SShayne Chen err = mt7996_dfs_start_rdd(dev, 1); 245498686cd2SShayne Chen if (err < 0) 245598686cd2SShayne Chen return err; 245698686cd2SShayne Chen 245798686cd2SShayne Chen phy->rdd_state |= BIT(1); 245898686cd2SShayne Chen } 245998686cd2SShayne Chen 246098686cd2SShayne Chen return 0; 246198686cd2SShayne Chen } 246298686cd2SShayne Chen 246398686cd2SShayne Chen static int 246498686cd2SShayne Chen mt7996_dfs_init_radar_specs(struct mt7996_phy *phy) 246598686cd2SShayne Chen { 246698686cd2SShayne Chen const struct mt7996_dfs_radar_spec *radar_specs; 246798686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 246898686cd2SShayne Chen int err, i; 246998686cd2SShayne Chen 247098686cd2SShayne Chen switch (dev->mt76.region) { 247198686cd2SShayne Chen case NL80211_DFS_FCC: 247298686cd2SShayne Chen radar_specs = &fcc_radar_specs; 247398686cd2SShayne Chen err = mt7996_mcu_set_fcc5_lpn(dev, 8); 247498686cd2SShayne Chen if (err < 0) 247598686cd2SShayne Chen return err; 247698686cd2SShayne Chen break; 247798686cd2SShayne Chen case NL80211_DFS_ETSI: 247898686cd2SShayne Chen radar_specs = &etsi_radar_specs; 247998686cd2SShayne Chen break; 248098686cd2SShayne Chen case NL80211_DFS_JP: 248198686cd2SShayne Chen radar_specs = &jp_radar_specs; 248298686cd2SShayne Chen break; 248398686cd2SShayne Chen default: 248498686cd2SShayne Chen return -EINVAL; 248598686cd2SShayne Chen } 248698686cd2SShayne Chen 248798686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) { 248898686cd2SShayne Chen err = mt7996_mcu_set_radar_th(dev, i, 248998686cd2SShayne Chen &radar_specs->radar_pattern[i]); 249098686cd2SShayne Chen if (err < 0) 249198686cd2SShayne Chen return err; 249298686cd2SShayne Chen } 249398686cd2SShayne Chen 249498686cd2SShayne Chen return mt7996_mcu_set_pulse_th(dev, &radar_specs->pulse_th); 249598686cd2SShayne Chen } 249698686cd2SShayne Chen 249798686cd2SShayne Chen int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy) 249898686cd2SShayne Chen { 249998686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 250098686cd2SShayne Chen enum mt76_dfs_state dfs_state, prev_state; 250198686cd2SShayne Chen int err; 250298686cd2SShayne Chen 250398686cd2SShayne Chen prev_state = phy->mt76->dfs_state; 250498686cd2SShayne Chen dfs_state = mt76_phy_dfs_state(phy->mt76); 250598686cd2SShayne Chen 250698686cd2SShayne Chen if (prev_state == dfs_state) 250798686cd2SShayne Chen return 0; 250898686cd2SShayne Chen 250998686cd2SShayne Chen if (prev_state == MT_DFS_STATE_UNKNOWN) 251098686cd2SShayne Chen mt7996_dfs_stop_radar_detector(phy); 251198686cd2SShayne Chen 251298686cd2SShayne Chen if (dfs_state == MT_DFS_STATE_DISABLED) 251398686cd2SShayne Chen goto stop; 251498686cd2SShayne Chen 251598686cd2SShayne Chen if (prev_state <= MT_DFS_STATE_DISABLED) { 251698686cd2SShayne Chen err = mt7996_dfs_init_radar_specs(phy); 251798686cd2SShayne Chen if (err < 0) 251898686cd2SShayne Chen return err; 251998686cd2SShayne Chen 252098686cd2SShayne Chen err = mt7996_dfs_start_radar_detector(phy); 252198686cd2SShayne Chen if (err < 0) 252298686cd2SShayne Chen return err; 252398686cd2SShayne Chen 252498686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_CAC; 252598686cd2SShayne Chen } 252698686cd2SShayne Chen 252798686cd2SShayne Chen if (dfs_state == MT_DFS_STATE_CAC) 252898686cd2SShayne Chen return 0; 252998686cd2SShayne Chen 253098686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_END, 253198686cd2SShayne Chen phy->mt76->band_idx, MT_RX_SEL0, 0); 253298686cd2SShayne Chen if (err < 0) { 253398686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; 253498686cd2SShayne Chen return err; 253598686cd2SShayne Chen } 253698686cd2SShayne Chen 253798686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_ACTIVE; 253898686cd2SShayne Chen return 0; 253998686cd2SShayne Chen 254098686cd2SShayne Chen stop: 254198686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_NORMAL_START, 254298686cd2SShayne Chen phy->mt76->band_idx, MT_RX_SEL0, 0); 254398686cd2SShayne Chen if (err < 0) 254498686cd2SShayne Chen return err; 254598686cd2SShayne Chen 254698686cd2SShayne Chen mt7996_dfs_stop_radar_detector(phy); 254798686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_DISABLED; 254898686cd2SShayne Chen 254998686cd2SShayne Chen return 0; 255098686cd2SShayne Chen } 255198686cd2SShayne Chen 255298686cd2SShayne Chen static int 255398686cd2SShayne Chen mt7996_mac_twt_duration_align(int duration) 255498686cd2SShayne Chen { 255598686cd2SShayne Chen return duration << 8; 255698686cd2SShayne Chen } 255798686cd2SShayne Chen 255898686cd2SShayne Chen static u64 255998686cd2SShayne Chen mt7996_mac_twt_sched_list_add(struct mt7996_dev *dev, 256098686cd2SShayne Chen struct mt7996_twt_flow *flow) 256198686cd2SShayne Chen { 256298686cd2SShayne Chen struct mt7996_twt_flow *iter, *iter_next; 256398686cd2SShayne Chen u32 duration = flow->duration << 8; 256498686cd2SShayne Chen u64 start_tsf; 256598686cd2SShayne Chen 256698686cd2SShayne Chen iter = list_first_entry_or_null(&dev->twt_list, 256798686cd2SShayne Chen struct mt7996_twt_flow, list); 256898686cd2SShayne Chen if (!iter || !iter->sched || iter->start_tsf > duration) { 256998686cd2SShayne Chen /* add flow as first entry in the list */ 257098686cd2SShayne Chen list_add(&flow->list, &dev->twt_list); 257198686cd2SShayne Chen return 0; 257298686cd2SShayne Chen } 257398686cd2SShayne Chen 257498686cd2SShayne Chen list_for_each_entry_safe(iter, iter_next, &dev->twt_list, list) { 257598686cd2SShayne Chen start_tsf = iter->start_tsf + 257698686cd2SShayne Chen mt7996_mac_twt_duration_align(iter->duration); 257798686cd2SShayne Chen if (list_is_last(&iter->list, &dev->twt_list)) 257898686cd2SShayne Chen break; 257998686cd2SShayne Chen 258098686cd2SShayne Chen if (!iter_next->sched || 258198686cd2SShayne Chen iter_next->start_tsf > start_tsf + duration) { 258298686cd2SShayne Chen list_add(&flow->list, &iter->list); 258398686cd2SShayne Chen goto out; 258498686cd2SShayne Chen } 258598686cd2SShayne Chen } 258698686cd2SShayne Chen 258798686cd2SShayne Chen /* add flow as last entry in the list */ 258898686cd2SShayne Chen list_add_tail(&flow->list, &dev->twt_list); 258998686cd2SShayne Chen out: 259098686cd2SShayne Chen return start_tsf; 259198686cd2SShayne Chen } 259298686cd2SShayne Chen 259398686cd2SShayne Chen static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt) 259498686cd2SShayne Chen { 259598686cd2SShayne Chen struct ieee80211_twt_params *twt_agrt; 259698686cd2SShayne Chen u64 interval, duration; 259798686cd2SShayne Chen u16 mantissa; 259898686cd2SShayne Chen u8 exp; 259998686cd2SShayne Chen 260098686cd2SShayne Chen /* only individual agreement supported */ 260198686cd2SShayne Chen if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) 260298686cd2SShayne Chen return -EOPNOTSUPP; 260398686cd2SShayne Chen 260498686cd2SShayne Chen /* only 256us unit supported */ 260598686cd2SShayne Chen if (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) 260698686cd2SShayne Chen return -EOPNOTSUPP; 260798686cd2SShayne Chen 260898686cd2SShayne Chen twt_agrt = (struct ieee80211_twt_params *)twt->params; 260998686cd2SShayne Chen 261098686cd2SShayne Chen /* explicit agreement not supported */ 261198686cd2SShayne Chen if (!(twt_agrt->req_type & cpu_to_le16(IEEE80211_TWT_REQTYPE_IMPLICIT))) 261298686cd2SShayne Chen return -EOPNOTSUPP; 261398686cd2SShayne Chen 261498686cd2SShayne Chen exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, 261598686cd2SShayne Chen le16_to_cpu(twt_agrt->req_type)); 261698686cd2SShayne Chen mantissa = le16_to_cpu(twt_agrt->mantissa); 261798686cd2SShayne Chen duration = twt_agrt->min_twt_dur << 8; 261898686cd2SShayne Chen 261998686cd2SShayne Chen interval = (u64)mantissa << exp; 262098686cd2SShayne Chen if (interval < duration) 262198686cd2SShayne Chen return -EOPNOTSUPP; 262298686cd2SShayne Chen 262398686cd2SShayne Chen return 0; 262498686cd2SShayne Chen } 262598686cd2SShayne Chen 262698686cd2SShayne Chen void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, 262798686cd2SShayne Chen struct ieee80211_sta *sta, 262898686cd2SShayne Chen struct ieee80211_twt_setup *twt) 262998686cd2SShayne Chen { 263098686cd2SShayne Chen enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT; 263198686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 263298686cd2SShayne Chen struct ieee80211_twt_params *twt_agrt = (void *)twt->params; 263398686cd2SShayne Chen u16 req_type = le16_to_cpu(twt_agrt->req_type); 263498686cd2SShayne Chen enum ieee80211_twt_setup_cmd sta_setup_cmd; 263598686cd2SShayne Chen struct mt7996_dev *dev = mt7996_hw_dev(hw); 263698686cd2SShayne Chen struct mt7996_twt_flow *flow; 263798686cd2SShayne Chen int flowid, table_id; 263898686cd2SShayne Chen u8 exp; 263998686cd2SShayne Chen 264098686cd2SShayne Chen if (mt7996_mac_check_twt_req(twt)) 264198686cd2SShayne Chen goto out; 264298686cd2SShayne Chen 264398686cd2SShayne Chen mutex_lock(&dev->mt76.mutex); 264498686cd2SShayne Chen 264598686cd2SShayne Chen if (dev->twt.n_agrt == MT7996_MAX_TWT_AGRT) 264698686cd2SShayne Chen goto unlock; 264798686cd2SShayne Chen 264898686cd2SShayne Chen if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) 264998686cd2SShayne Chen goto unlock; 265098686cd2SShayne Chen 265198686cd2SShayne Chen flowid = ffs(~msta->twt.flowid_mask) - 1; 265298686cd2SShayne Chen le16p_replace_bits(&twt_agrt->req_type, flowid, 265398686cd2SShayne Chen IEEE80211_TWT_REQTYPE_FLOWID); 265498686cd2SShayne Chen 265598686cd2SShayne Chen table_id = ffs(~dev->twt.table_mask) - 1; 265698686cd2SShayne Chen exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); 265798686cd2SShayne Chen sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type); 265898686cd2SShayne Chen 265998686cd2SShayne Chen flow = &msta->twt.flow[flowid]; 266098686cd2SShayne Chen memset(flow, 0, sizeof(*flow)); 266198686cd2SShayne Chen INIT_LIST_HEAD(&flow->list); 266298686cd2SShayne Chen flow->wcid = msta->wcid.idx; 266398686cd2SShayne Chen flow->table_id = table_id; 266498686cd2SShayne Chen flow->id = flowid; 266598686cd2SShayne Chen flow->duration = twt_agrt->min_twt_dur; 266698686cd2SShayne Chen flow->mantissa = twt_agrt->mantissa; 266798686cd2SShayne Chen flow->exp = exp; 266898686cd2SShayne Chen flow->protection = !!(req_type & IEEE80211_TWT_REQTYPE_PROTECTION); 266998686cd2SShayne Chen flow->flowtype = !!(req_type & IEEE80211_TWT_REQTYPE_FLOWTYPE); 267098686cd2SShayne Chen flow->trigger = !!(req_type & IEEE80211_TWT_REQTYPE_TRIGGER); 267198686cd2SShayne Chen 267298686cd2SShayne Chen if (sta_setup_cmd == TWT_SETUP_CMD_REQUEST || 267398686cd2SShayne Chen sta_setup_cmd == TWT_SETUP_CMD_SUGGEST) { 267498686cd2SShayne Chen u64 interval = (u64)le16_to_cpu(twt_agrt->mantissa) << exp; 267598686cd2SShayne Chen u64 flow_tsf, curr_tsf; 267698686cd2SShayne Chen u32 rem; 267798686cd2SShayne Chen 267898686cd2SShayne Chen flow->sched = true; 267998686cd2SShayne Chen flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow); 268098686cd2SShayne Chen curr_tsf = __mt7996_get_tsf(hw, msta->vif); 268198686cd2SShayne Chen div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem); 268298686cd2SShayne Chen flow_tsf = curr_tsf + interval - rem; 268398686cd2SShayne Chen twt_agrt->twt = cpu_to_le64(flow_tsf); 268498686cd2SShayne Chen } else { 268598686cd2SShayne Chen list_add_tail(&flow->list, &dev->twt_list); 268698686cd2SShayne Chen } 268798686cd2SShayne Chen flow->tsf = le64_to_cpu(twt_agrt->twt); 268898686cd2SShayne Chen 268998686cd2SShayne Chen if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD)) 269098686cd2SShayne Chen goto unlock; 269198686cd2SShayne Chen 269298686cd2SShayne Chen setup_cmd = TWT_SETUP_CMD_ACCEPT; 269398686cd2SShayne Chen dev->twt.table_mask |= BIT(table_id); 269498686cd2SShayne Chen msta->twt.flowid_mask |= BIT(flowid); 269598686cd2SShayne Chen dev->twt.n_agrt++; 269698686cd2SShayne Chen 269798686cd2SShayne Chen unlock: 269898686cd2SShayne Chen mutex_unlock(&dev->mt76.mutex); 269998686cd2SShayne Chen out: 270098686cd2SShayne Chen le16p_replace_bits(&twt_agrt->req_type, setup_cmd, 270198686cd2SShayne Chen IEEE80211_TWT_REQTYPE_SETUP_CMD); 270298686cd2SShayne Chen twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | 270398686cd2SShayne Chen (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); 270498686cd2SShayne Chen } 270598686cd2SShayne Chen 270698686cd2SShayne Chen void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, 270798686cd2SShayne Chen struct mt7996_sta *msta, 270898686cd2SShayne Chen u8 flowid) 270998686cd2SShayne Chen { 271098686cd2SShayne Chen struct mt7996_twt_flow *flow; 271198686cd2SShayne Chen 271298686cd2SShayne Chen lockdep_assert_held(&dev->mt76.mutex); 271398686cd2SShayne Chen 271498686cd2SShayne Chen if (flowid >= ARRAY_SIZE(msta->twt.flow)) 271598686cd2SShayne Chen return; 271698686cd2SShayne Chen 271798686cd2SShayne Chen if (!(msta->twt.flowid_mask & BIT(flowid))) 271898686cd2SShayne Chen return; 271998686cd2SShayne Chen 272098686cd2SShayne Chen flow = &msta->twt.flow[flowid]; 272198686cd2SShayne Chen if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, 272298686cd2SShayne Chen MCU_TWT_AGRT_DELETE)) 272398686cd2SShayne Chen return; 272498686cd2SShayne Chen 272598686cd2SShayne Chen list_del_init(&flow->list); 272698686cd2SShayne Chen msta->twt.flowid_mask &= ~BIT(flowid); 272798686cd2SShayne Chen dev->twt.table_mask &= ~BIT(flow->table_id); 272898686cd2SShayne Chen dev->twt.n_agrt--; 272998686cd2SShayne Chen } 2730