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 static const struct mt7996_dfs_radar_spec etsi_radar_specs = { 1798686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 1898686cd2SShayne Chen .radar_pattern = { 1998686cd2SShayne Chen [5] = { 1, 0, 6, 32, 28, 0, 990, 5010, 17, 1, 1 }, 2098686cd2SShayne Chen [6] = { 1, 0, 9, 32, 28, 0, 615, 5010, 27, 1, 1 }, 2198686cd2SShayne Chen [7] = { 1, 0, 15, 32, 28, 0, 240, 445, 27, 1, 1 }, 2298686cd2SShayne Chen [8] = { 1, 0, 12, 32, 28, 0, 240, 510, 42, 1, 1 }, 2398686cd2SShayne Chen [9] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 12, 32, 28, { }, 126 }, 2498686cd2SShayne Chen [10] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 15, 32, 24, { }, 126 }, 2598686cd2SShayne Chen [11] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 18, 32, 28, { }, 54 }, 2698686cd2SShayne Chen [12] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 27, 32, 24, { }, 54 }, 2798686cd2SShayne Chen }, 2898686cd2SShayne Chen }; 2998686cd2SShayne Chen 3098686cd2SShayne Chen static const struct mt7996_dfs_radar_spec fcc_radar_specs = { 3198686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 3298686cd2SShayne Chen .radar_pattern = { 3398686cd2SShayne Chen [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, 3498686cd2SShayne Chen [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, 3598686cd2SShayne Chen [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, 3698686cd2SShayne Chen [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, 3798686cd2SShayne Chen [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, 3898686cd2SShayne Chen }, 3998686cd2SShayne Chen }; 4098686cd2SShayne Chen 4198686cd2SShayne Chen static const struct mt7996_dfs_radar_spec jp_radar_specs = { 4298686cd2SShayne Chen .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 4398686cd2SShayne Chen .radar_pattern = { 4498686cd2SShayne Chen [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, 4598686cd2SShayne Chen [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, 4698686cd2SShayne Chen [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, 4798686cd2SShayne Chen [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, 4898686cd2SShayne Chen [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, 4998686cd2SShayne Chen [13] = { 1, 0, 7, 32, 28, 0, 3836, 3856, 14, 1, 1 }, 5098686cd2SShayne Chen [14] = { 1, 0, 6, 32, 28, 0, 615, 5010, 110, 1, 1 }, 5198686cd2SShayne Chen [15] = { 1, 1, 0, 0, 0, 0, 15, 5010, 110, 0, 0, 12, 32, 28 }, 5298686cd2SShayne Chen }, 5398686cd2SShayne Chen }; 5498686cd2SShayne Chen 5598686cd2SShayne Chen static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev, 5698686cd2SShayne Chen u16 idx, bool unicast) 5798686cd2SShayne Chen { 5898686cd2SShayne Chen struct mt7996_sta *sta; 5998686cd2SShayne Chen struct mt76_wcid *wcid; 6098686cd2SShayne Chen 6198686cd2SShayne Chen if (idx >= ARRAY_SIZE(dev->mt76.wcid)) 6298686cd2SShayne Chen return NULL; 6398686cd2SShayne Chen 6498686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[idx]); 6598686cd2SShayne Chen if (unicast || !wcid) 6698686cd2SShayne Chen return wcid; 6798686cd2SShayne Chen 6898686cd2SShayne Chen if (!wcid->sta) 6998686cd2SShayne Chen return NULL; 7098686cd2SShayne Chen 7198686cd2SShayne Chen sta = container_of(wcid, struct mt7996_sta, wcid); 7298686cd2SShayne Chen if (!sta->vif) 7398686cd2SShayne Chen return NULL; 7498686cd2SShayne Chen 7598686cd2SShayne Chen return &sta->vif->sta.wcid; 7698686cd2SShayne Chen } 7798686cd2SShayne Chen 7898686cd2SShayne Chen bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask) 7998686cd2SShayne Chen { 8098686cd2SShayne Chen mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, 8198686cd2SShayne Chen FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); 8298686cd2SShayne Chen 8398686cd2SShayne Chen return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 8498686cd2SShayne Chen 0, 5000); 8598686cd2SShayne Chen } 8698686cd2SShayne Chen 8798686cd2SShayne Chen u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw) 8898686cd2SShayne Chen { 8998686cd2SShayne Chen mt76_wr(dev, MT_WTBLON_TOP_WDUCR, 9098686cd2SShayne Chen FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); 9198686cd2SShayne Chen 9298686cd2SShayne Chen return MT_WTBL_LMAC_OFFS(wcid, dw); 9398686cd2SShayne Chen } 9498686cd2SShayne Chen 9598686cd2SShayne Chen static void mt7996_mac_sta_poll(struct mt7996_dev *dev) 9698686cd2SShayne Chen { 9798686cd2SShayne Chen static const u8 ac_to_tid[] = { 9898686cd2SShayne Chen [IEEE80211_AC_BE] = 0, 9998686cd2SShayne Chen [IEEE80211_AC_BK] = 1, 10098686cd2SShayne Chen [IEEE80211_AC_VI] = 4, 10198686cd2SShayne Chen [IEEE80211_AC_VO] = 6 10298686cd2SShayne Chen }; 10398686cd2SShayne Chen struct ieee80211_sta *sta; 10498686cd2SShayne Chen struct mt7996_sta *msta; 10598686cd2SShayne Chen struct rate_info *rate; 10698686cd2SShayne Chen u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; 10798686cd2SShayne Chen LIST_HEAD(sta_poll_list); 10898686cd2SShayne Chen int i; 10998686cd2SShayne Chen 110ea0f3867SLorenzo Bianconi spin_lock_bh(&dev->mt76.sta_poll_lock); 111ea0f3867SLorenzo Bianconi list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); 112ea0f3867SLorenzo Bianconi spin_unlock_bh(&dev->mt76.sta_poll_lock); 11398686cd2SShayne Chen 11498686cd2SShayne Chen rcu_read_lock(); 11598686cd2SShayne Chen 11698686cd2SShayne Chen while (true) { 11798686cd2SShayne Chen bool clear = false; 11898686cd2SShayne Chen u32 addr, val; 11998686cd2SShayne Chen u16 idx; 120ea5d99d0SRyder Lee s8 rssi[4]; 12198686cd2SShayne Chen u8 bw; 12298686cd2SShayne Chen 123ea0f3867SLorenzo Bianconi spin_lock_bh(&dev->mt76.sta_poll_lock); 12498686cd2SShayne Chen if (list_empty(&sta_poll_list)) { 125ea0f3867SLorenzo Bianconi spin_unlock_bh(&dev->mt76.sta_poll_lock); 12698686cd2SShayne Chen break; 12798686cd2SShayne Chen } 12898686cd2SShayne Chen msta = list_first_entry(&sta_poll_list, 129e3b0311fSLorenzo Bianconi struct mt7996_sta, wcid.poll_list); 130e3b0311fSLorenzo Bianconi list_del_init(&msta->wcid.poll_list); 131ea0f3867SLorenzo Bianconi spin_unlock_bh(&dev->mt76.sta_poll_lock); 13298686cd2SShayne Chen 13398686cd2SShayne Chen idx = msta->wcid.idx; 134ea5d99d0SRyder Lee 135ea5d99d0SRyder Lee /* refresh peer's airtime reporting */ 13698686cd2SShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20); 13798686cd2SShayne Chen 13898686cd2SShayne Chen for (i = 0; i < IEEE80211_NUM_ACS; i++) { 13998686cd2SShayne Chen u32 tx_last = msta->airtime_ac[i]; 14098686cd2SShayne Chen u32 rx_last = msta->airtime_ac[i + 4]; 14198686cd2SShayne Chen 14298686cd2SShayne Chen msta->airtime_ac[i] = mt76_rr(dev, addr); 14398686cd2SShayne Chen msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); 14498686cd2SShayne Chen 14598686cd2SShayne Chen tx_time[i] = msta->airtime_ac[i] - tx_last; 14698686cd2SShayne Chen rx_time[i] = msta->airtime_ac[i + 4] - rx_last; 14798686cd2SShayne Chen 14898686cd2SShayne Chen if ((tx_last | rx_last) & BIT(30)) 14998686cd2SShayne Chen clear = true; 15098686cd2SShayne Chen 15198686cd2SShayne Chen addr += 8; 15298686cd2SShayne Chen } 15398686cd2SShayne Chen 15498686cd2SShayne Chen if (clear) { 15598686cd2SShayne Chen mt7996_mac_wtbl_update(dev, idx, 15698686cd2SShayne Chen MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 15798686cd2SShayne Chen memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); 15898686cd2SShayne Chen } 15998686cd2SShayne Chen 16098686cd2SShayne Chen if (!msta->wcid.sta) 16198686cd2SShayne Chen continue; 16298686cd2SShayne Chen 16398686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, 16498686cd2SShayne Chen drv_priv); 16598686cd2SShayne Chen for (i = 0; i < IEEE80211_NUM_ACS; i++) { 16698686cd2SShayne Chen u8 q = mt76_connac_lmac_mapping(i); 16798686cd2SShayne Chen u32 tx_cur = tx_time[q]; 16898686cd2SShayne Chen u32 rx_cur = rx_time[q]; 16998686cd2SShayne Chen u8 tid = ac_to_tid[i]; 17098686cd2SShayne Chen 17198686cd2SShayne Chen if (!tx_cur && !rx_cur) 17298686cd2SShayne Chen continue; 17398686cd2SShayne Chen 17498686cd2SShayne Chen ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur); 17598686cd2SShayne Chen } 17698686cd2SShayne Chen 17798686cd2SShayne Chen /* We don't support reading GI info from txs packets. 17898686cd2SShayne Chen * For accurate tx status reporting and AQL improvement, 17998686cd2SShayne Chen * we need to make sure that flags match so polling GI 18098686cd2SShayne Chen * from per-sta counters directly. 18198686cd2SShayne Chen */ 18298686cd2SShayne Chen rate = &msta->wcid.rate; 18398686cd2SShayne Chen 18498686cd2SShayne Chen switch (rate->bw) { 18580f5a31dSShayne Chen case RATE_INFO_BW_320: 18680f5a31dSShayne Chen bw = IEEE80211_STA_RX_BW_320; 18780f5a31dSShayne Chen break; 18898686cd2SShayne Chen case RATE_INFO_BW_160: 18998686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_160; 19098686cd2SShayne Chen break; 19198686cd2SShayne Chen case RATE_INFO_BW_80: 19298686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_80; 19398686cd2SShayne Chen break; 19498686cd2SShayne Chen case RATE_INFO_BW_40: 19598686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_40; 19698686cd2SShayne Chen break; 19798686cd2SShayne Chen default: 19898686cd2SShayne Chen bw = IEEE80211_STA_RX_BW_20; 19998686cd2SShayne Chen break; 20098686cd2SShayne Chen } 20198686cd2SShayne Chen 20298686cd2SShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 6); 20398686cd2SShayne Chen val = mt76_rr(dev, addr); 20480f5a31dSShayne Chen if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) { 20580f5a31dSShayne Chen addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 5); 20680f5a31dSShayne Chen val = mt76_rr(dev, addr); 20780f5a31dSShayne Chen rate->eht_gi = FIELD_GET(GENMASK(25, 24), val); 20880f5a31dSShayne Chen } else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { 20998686cd2SShayne Chen u8 offs = 24 + 2 * bw; 21098686cd2SShayne Chen 21198686cd2SShayne Chen rate->he_gi = (val & (0x3 << offs)) >> offs; 21298686cd2SShayne Chen } else if (rate->flags & 21398686cd2SShayne Chen (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) { 21498686cd2SShayne Chen if (val & BIT(12 + bw)) 21598686cd2SShayne Chen rate->flags |= RATE_INFO_FLAGS_SHORT_GI; 21698686cd2SShayne Chen else 21798686cd2SShayne Chen rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI; 21898686cd2SShayne Chen } 219ea5d99d0SRyder Lee 220ea5d99d0SRyder Lee /* get signal strength of resp frames (CTS/BA/ACK) */ 221ea5d99d0SRyder Lee addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34); 222ea5d99d0SRyder Lee val = mt76_rr(dev, addr); 223ea5d99d0SRyder Lee 224ea5d99d0SRyder Lee rssi[0] = to_rssi(GENMASK(7, 0), val); 225ea5d99d0SRyder Lee rssi[1] = to_rssi(GENMASK(15, 8), val); 226ea5d99d0SRyder Lee rssi[2] = to_rssi(GENMASK(23, 16), val); 227ea5d99d0SRyder Lee rssi[3] = to_rssi(GENMASK(31, 14), val); 228ea5d99d0SRyder Lee 229ea5d99d0SRyder Lee msta->ack_signal = 230ea5d99d0SRyder Lee mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); 231ea5d99d0SRyder Lee 232ea5d99d0SRyder Lee ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); 23398686cd2SShayne Chen } 23498686cd2SShayne Chen 23598686cd2SShayne Chen rcu_read_unlock(); 23698686cd2SShayne Chen } 23798686cd2SShayne Chen 238d75e739bSRyder Lee void mt7996_mac_enable_rtscts(struct mt7996_dev *dev, 239d75e739bSRyder Lee struct ieee80211_vif *vif, bool enable) 240d75e739bSRyder Lee { 241d75e739bSRyder Lee struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 242d75e739bSRyder Lee u32 addr; 243d75e739bSRyder Lee 244d75e739bSRyder Lee addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5); 245d75e739bSRyder Lee if (enable) 246d75e739bSRyder Lee mt76_set(dev, addr, BIT(5)); 247d75e739bSRyder Lee else 248d75e739bSRyder Lee mt76_clear(dev, addr, BIT(5)); 249d75e739bSRyder Lee } 250d75e739bSRyder Lee 25115ee62e7SRyder Lee void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev, 25215ee62e7SRyder Lee u8 tbl_idx, u16 rate_idx) 25315ee62e7SRyder Lee { 25415ee62e7SRyder Lee u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx; 25515ee62e7SRyder Lee 25615ee62e7SRyder Lee mt76_wr(dev, MT_WTBL_ITDR0, rate_idx); 25715ee62e7SRyder Lee /* use wtbl spe idx */ 25815ee62e7SRyder Lee mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL); 25915ee62e7SRyder Lee mt76_wr(dev, MT_WTBL_ITCR, ctrl); 26015ee62e7SRyder Lee } 26115ee62e7SRyder Lee 26298686cd2SShayne Chen /* The HW does not translate the mac header to 802.3 for mesh point */ 26398686cd2SShayne Chen static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) 26498686cd2SShayne Chen { 26598686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 26698686cd2SShayne Chen struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap); 26798686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)status->wcid; 26898686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 26998686cd2SShayne Chen struct ieee80211_sta *sta; 27098686cd2SShayne Chen struct ieee80211_vif *vif; 27198686cd2SShayne Chen struct ieee80211_hdr hdr; 27298686cd2SShayne Chen u16 frame_control; 27398686cd2SShayne Chen 27498686cd2SShayne Chen if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) != 27598686cd2SShayne Chen MT_RXD3_NORMAL_U2M) 27698686cd2SShayne Chen return -EINVAL; 27798686cd2SShayne Chen 27898686cd2SShayne Chen if (!(le32_to_cpu(rxd[1]) & MT_RXD1_NORMAL_GROUP_4)) 27998686cd2SShayne Chen return -EINVAL; 28098686cd2SShayne Chen 28198686cd2SShayne Chen if (!msta || !msta->vif) 28298686cd2SShayne Chen return -EINVAL; 28398686cd2SShayne Chen 28498686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); 28598686cd2SShayne Chen vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); 28698686cd2SShayne Chen 28798686cd2SShayne Chen /* store the info from RXD and ethhdr to avoid being overridden */ 28898686cd2SShayne Chen frame_control = le32_get_bits(rxd[8], MT_RXD8_FRAME_CONTROL); 28998686cd2SShayne Chen hdr.frame_control = cpu_to_le16(frame_control); 29098686cd2SShayne Chen hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_SEQ_CTRL)); 29198686cd2SShayne Chen hdr.duration_id = 0; 29298686cd2SShayne Chen 29398686cd2SShayne Chen ether_addr_copy(hdr.addr1, vif->addr); 29498686cd2SShayne Chen ether_addr_copy(hdr.addr2, sta->addr); 29598686cd2SShayne Chen switch (frame_control & (IEEE80211_FCTL_TODS | 29698686cd2SShayne Chen IEEE80211_FCTL_FROMDS)) { 29798686cd2SShayne Chen case 0: 29898686cd2SShayne Chen ether_addr_copy(hdr.addr3, vif->bss_conf.bssid); 29998686cd2SShayne Chen break; 30098686cd2SShayne Chen case IEEE80211_FCTL_FROMDS: 30198686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_source); 30298686cd2SShayne Chen break; 30398686cd2SShayne Chen case IEEE80211_FCTL_TODS: 30498686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_dest); 30598686cd2SShayne Chen break; 30698686cd2SShayne Chen case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS: 30798686cd2SShayne Chen ether_addr_copy(hdr.addr3, eth_hdr->h_dest); 30898686cd2SShayne Chen ether_addr_copy(hdr.addr4, eth_hdr->h_source); 30998686cd2SShayne Chen break; 31098686cd2SShayne Chen default: 311aed8d9b5SLorenzo Bianconi return -EINVAL; 31298686cd2SShayne Chen } 31398686cd2SShayne Chen 31498686cd2SShayne Chen skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2); 31598686cd2SShayne Chen if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) || 31698686cd2SShayne Chen eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX)) 31798686cd2SShayne Chen ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header); 31898686cd2SShayne Chen else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN) 31998686cd2SShayne Chen ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header); 32098686cd2SShayne Chen else 32198686cd2SShayne Chen skb_pull(skb, 2); 32298686cd2SShayne Chen 32398686cd2SShayne Chen if (ieee80211_has_order(hdr.frame_control)) 32498686cd2SShayne Chen memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[11], 32598686cd2SShayne Chen IEEE80211_HT_CTL_LEN); 32698686cd2SShayne Chen if (ieee80211_is_data_qos(hdr.frame_control)) { 32798686cd2SShayne Chen __le16 qos_ctrl; 32898686cd2SShayne Chen 32998686cd2SShayne Chen qos_ctrl = cpu_to_le16(le32_get_bits(rxd[10], MT_RXD10_QOS_CTL)); 33098686cd2SShayne Chen memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl, 33198686cd2SShayne Chen IEEE80211_QOS_CTL_LEN); 33298686cd2SShayne Chen } 33398686cd2SShayne Chen 33498686cd2SShayne Chen if (ieee80211_has_a4(hdr.frame_control)) 33598686cd2SShayne Chen memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr)); 33698686cd2SShayne Chen else 33798686cd2SShayne Chen memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6); 33898686cd2SShayne Chen 33998686cd2SShayne Chen return 0; 34098686cd2SShayne Chen } 34198686cd2SShayne Chen 34298686cd2SShayne Chen static int 34398686cd2SShayne Chen mt7996_mac_fill_rx_rate(struct mt7996_dev *dev, 34498686cd2SShayne Chen struct mt76_rx_status *status, 34598686cd2SShayne Chen struct ieee80211_supported_band *sband, 34698686cd2SShayne Chen __le32 *rxv, u8 *mode) 34798686cd2SShayne Chen { 34898686cd2SShayne Chen u32 v0, v2; 34998686cd2SShayne Chen u8 stbc, gi, bw, dcm, nss; 35098686cd2SShayne Chen int i, idx; 35198686cd2SShayne Chen bool cck = false; 35298686cd2SShayne Chen 35398686cd2SShayne Chen v0 = le32_to_cpu(rxv[0]); 35498686cd2SShayne Chen v2 = le32_to_cpu(rxv[2]); 35598686cd2SShayne Chen 35698686cd2SShayne Chen idx = FIELD_GET(MT_PRXV_TX_RATE, v0); 35798686cd2SShayne Chen i = idx; 35898686cd2SShayne Chen nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1; 35998686cd2SShayne Chen 36098686cd2SShayne Chen stbc = FIELD_GET(MT_PRXV_HT_STBC, v2); 36198686cd2SShayne Chen gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2); 36298686cd2SShayne Chen *mode = FIELD_GET(MT_PRXV_TX_MODE, v2); 36398686cd2SShayne Chen dcm = FIELD_GET(MT_PRXV_DCM, v2); 36498686cd2SShayne Chen bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2); 36598686cd2SShayne Chen 36698686cd2SShayne Chen switch (*mode) { 36798686cd2SShayne Chen case MT_PHY_TYPE_CCK: 36898686cd2SShayne Chen cck = true; 36998686cd2SShayne Chen fallthrough; 37098686cd2SShayne Chen case MT_PHY_TYPE_OFDM: 37198686cd2SShayne Chen i = mt76_get_rate(&dev->mt76, sband, i, cck); 37298686cd2SShayne Chen break; 37398686cd2SShayne Chen case MT_PHY_TYPE_HT_GF: 37498686cd2SShayne Chen case MT_PHY_TYPE_HT: 37598686cd2SShayne Chen status->encoding = RX_ENC_HT; 37698686cd2SShayne Chen if (gi) 37798686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 37898686cd2SShayne Chen if (i > 31) 37998686cd2SShayne Chen return -EINVAL; 38098686cd2SShayne Chen break; 38198686cd2SShayne Chen case MT_PHY_TYPE_VHT: 38298686cd2SShayne Chen status->nss = nss; 38398686cd2SShayne Chen status->encoding = RX_ENC_VHT; 38498686cd2SShayne Chen if (gi) 38598686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 38698686cd2SShayne Chen if (i > 11) 38798686cd2SShayne Chen return -EINVAL; 38898686cd2SShayne Chen break; 38998686cd2SShayne Chen case MT_PHY_TYPE_HE_MU: 39098686cd2SShayne Chen case MT_PHY_TYPE_HE_SU: 39198686cd2SShayne Chen case MT_PHY_TYPE_HE_EXT_SU: 39298686cd2SShayne Chen case MT_PHY_TYPE_HE_TB: 39398686cd2SShayne Chen status->nss = nss; 39498686cd2SShayne Chen status->encoding = RX_ENC_HE; 39598686cd2SShayne Chen i &= GENMASK(3, 0); 39698686cd2SShayne Chen 39798686cd2SShayne Chen if (gi <= NL80211_RATE_INFO_HE_GI_3_2) 39898686cd2SShayne Chen status->he_gi = gi; 39998686cd2SShayne Chen 40098686cd2SShayne Chen status->he_dcm = dcm; 40198686cd2SShayne Chen break; 40280f5a31dSShayne Chen case MT_PHY_TYPE_EHT_SU: 40380f5a31dSShayne Chen case MT_PHY_TYPE_EHT_TRIG: 40480f5a31dSShayne Chen case MT_PHY_TYPE_EHT_MU: 40580f5a31dSShayne Chen status->nss = nss; 406021af945SShayne Chen status->encoding = RX_ENC_EHT; 407021af945SShayne Chen i &= GENMASK(3, 0); 408021af945SShayne Chen 409021af945SShayne Chen if (gi <= NL80211_RATE_INFO_EHT_GI_3_2) 410021af945SShayne Chen status->eht.gi = gi; 41180f5a31dSShayne Chen break; 41298686cd2SShayne Chen default: 41398686cd2SShayne Chen return -EINVAL; 41498686cd2SShayne Chen } 41598686cd2SShayne Chen status->rate_idx = i; 41698686cd2SShayne Chen 41798686cd2SShayne Chen switch (bw) { 41898686cd2SShayne Chen case IEEE80211_STA_RX_BW_20: 41998686cd2SShayne Chen break; 42098686cd2SShayne Chen case IEEE80211_STA_RX_BW_40: 42198686cd2SShayne Chen if (*mode & MT_PHY_TYPE_HE_EXT_SU && 42298686cd2SShayne Chen (idx & MT_PRXV_TX_ER_SU_106T)) { 42398686cd2SShayne Chen status->bw = RATE_INFO_BW_HE_RU; 42498686cd2SShayne Chen status->he_ru = 42598686cd2SShayne Chen NL80211_RATE_INFO_HE_RU_ALLOC_106; 42698686cd2SShayne Chen } else { 42798686cd2SShayne Chen status->bw = RATE_INFO_BW_40; 42898686cd2SShayne Chen } 42998686cd2SShayne Chen break; 43098686cd2SShayne Chen case IEEE80211_STA_RX_BW_80: 43198686cd2SShayne Chen status->bw = RATE_INFO_BW_80; 43298686cd2SShayne Chen break; 43398686cd2SShayne Chen case IEEE80211_STA_RX_BW_160: 43498686cd2SShayne Chen status->bw = RATE_INFO_BW_160; 43598686cd2SShayne Chen break; 43680f5a31dSShayne Chen case IEEE80211_STA_RX_BW_320: 43780f5a31dSShayne Chen status->bw = RATE_INFO_BW_320; 43880f5a31dSShayne Chen break; 43998686cd2SShayne Chen default: 44098686cd2SShayne Chen return -EINVAL; 44198686cd2SShayne Chen } 44298686cd2SShayne Chen 44398686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; 44498686cd2SShayne Chen if (*mode < MT_PHY_TYPE_HE_SU && gi) 44598686cd2SShayne Chen status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 44698686cd2SShayne Chen 44798686cd2SShayne Chen return 0; 44898686cd2SShayne Chen } 44998686cd2SShayne Chen 45098686cd2SShayne Chen static int 45198686cd2SShayne Chen mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) 45298686cd2SShayne Chen { 45398686cd2SShayne Chen struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 45498686cd2SShayne Chen struct mt76_phy *mphy = &dev->mt76.phy; 45598686cd2SShayne Chen struct mt7996_phy *phy = &dev->phy; 45698686cd2SShayne Chen struct ieee80211_supported_band *sband; 45798686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 45898686cd2SShayne Chen __le32 *rxv = NULL; 45998686cd2SShayne Chen u32 rxd0 = le32_to_cpu(rxd[0]); 46098686cd2SShayne Chen u32 rxd1 = le32_to_cpu(rxd[1]); 46198686cd2SShayne Chen u32 rxd2 = le32_to_cpu(rxd[2]); 46298686cd2SShayne Chen u32 rxd3 = le32_to_cpu(rxd[3]); 46398686cd2SShayne Chen u32 rxd4 = le32_to_cpu(rxd[4]); 46498686cd2SShayne Chen u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; 46598686cd2SShayne Chen u32 csum_status = *(u32 *)skb->cb; 46627db47abSRyder Lee u32 mesh_mask = MT_RXD0_MESH | MT_RXD0_MHCP; 46727db47abSRyder Lee bool is_mesh = (rxd0 & mesh_mask) == mesh_mask; 46898686cd2SShayne Chen bool unicast, insert_ccmp_hdr = false; 46998686cd2SShayne Chen u8 remove_pad, amsdu_info, band_idx; 47098686cd2SShayne Chen u8 mode = 0, qos_ctl = 0; 47198686cd2SShayne Chen bool hdr_trans; 47298686cd2SShayne Chen u16 hdr_gap; 47398686cd2SShayne Chen u16 seq_ctrl = 0; 47498686cd2SShayne Chen __le16 fc = 0; 47598686cd2SShayne Chen int idx; 47698686cd2SShayne Chen 47798686cd2SShayne Chen memset(status, 0, sizeof(*status)); 47898686cd2SShayne Chen 47998686cd2SShayne Chen band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1); 48098686cd2SShayne Chen mphy = dev->mt76.phys[band_idx]; 48198686cd2SShayne Chen phy = mphy->priv; 48298686cd2SShayne Chen status->phy_idx = mphy->band_idx; 48398686cd2SShayne Chen 48498686cd2SShayne Chen if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) 48598686cd2SShayne Chen return -EINVAL; 48698686cd2SShayne Chen 48798686cd2SShayne Chen if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) 48898686cd2SShayne Chen return -EINVAL; 48998686cd2SShayne Chen 49098686cd2SShayne Chen hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; 49198686cd2SShayne Chen if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) 49298686cd2SShayne Chen return -EINVAL; 49398686cd2SShayne Chen 49498686cd2SShayne Chen /* ICV error or CCMP/BIP/WPI MIC error */ 49598686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) 49698686cd2SShayne Chen status->flag |= RX_FLAG_ONLY_MONITOR; 49798686cd2SShayne Chen 49898686cd2SShayne Chen unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; 49998686cd2SShayne Chen idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); 50098686cd2SShayne Chen status->wcid = mt7996_rx_get_wcid(dev, idx, unicast); 50198686cd2SShayne Chen 50298686cd2SShayne Chen if (status->wcid) { 50398686cd2SShayne Chen struct mt7996_sta *msta; 50498686cd2SShayne Chen 50598686cd2SShayne Chen msta = container_of(status->wcid, struct mt7996_sta, wcid); 506ea0f3867SLorenzo Bianconi spin_lock_bh(&dev->mt76.sta_poll_lock); 507e3b0311fSLorenzo Bianconi if (list_empty(&msta->wcid.poll_list)) 508e3b0311fSLorenzo Bianconi list_add_tail(&msta->wcid.poll_list, 509ea0f3867SLorenzo Bianconi &dev->mt76.sta_poll_list); 510ea0f3867SLorenzo Bianconi spin_unlock_bh(&dev->mt76.sta_poll_lock); 51198686cd2SShayne Chen } 51298686cd2SShayne Chen 51398686cd2SShayne Chen status->freq = mphy->chandef.chan->center_freq; 51498686cd2SShayne Chen status->band = mphy->chandef.chan->band; 51598686cd2SShayne Chen if (status->band == NL80211_BAND_5GHZ) 51698686cd2SShayne Chen sband = &mphy->sband_5g.sband; 51798686cd2SShayne Chen else if (status->band == NL80211_BAND_6GHZ) 51898686cd2SShayne Chen sband = &mphy->sband_6g.sband; 51998686cd2SShayne Chen else 52098686cd2SShayne Chen sband = &mphy->sband_2g.sband; 52198686cd2SShayne Chen 52298686cd2SShayne Chen if (!sband->channels) 52398686cd2SShayne Chen return -EINVAL; 52498686cd2SShayne Chen 52598686cd2SShayne Chen if ((rxd0 & csum_mask) == csum_mask && 52698686cd2SShayne Chen !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) 52798686cd2SShayne Chen skb->ip_summed = CHECKSUM_UNNECESSARY; 52898686cd2SShayne Chen 52998686cd2SShayne Chen if (rxd1 & MT_RXD3_NORMAL_FCS_ERR) 53098686cd2SShayne Chen status->flag |= RX_FLAG_FAILED_FCS_CRC; 53198686cd2SShayne Chen 53298686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) 53398686cd2SShayne Chen status->flag |= RX_FLAG_MMIC_ERROR; 53498686cd2SShayne Chen 53598686cd2SShayne Chen if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && 53698686cd2SShayne Chen !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) { 53798686cd2SShayne Chen status->flag |= RX_FLAG_DECRYPTED; 53898686cd2SShayne Chen status->flag |= RX_FLAG_IV_STRIPPED; 53998686cd2SShayne Chen status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; 54098686cd2SShayne Chen } 54198686cd2SShayne Chen 54298686cd2SShayne Chen remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); 54398686cd2SShayne Chen 54498686cd2SShayne Chen if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) 54598686cd2SShayne Chen return -EINVAL; 54698686cd2SShayne Chen 54798686cd2SShayne Chen rxd += 8; 54898686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { 54998686cd2SShayne Chen u32 v0 = le32_to_cpu(rxd[0]); 55098686cd2SShayne Chen u32 v2 = le32_to_cpu(rxd[2]); 55198686cd2SShayne Chen 55298686cd2SShayne Chen fc = cpu_to_le16(FIELD_GET(MT_RXD8_FRAME_CONTROL, v0)); 55398686cd2SShayne Chen qos_ctl = FIELD_GET(MT_RXD10_QOS_CTL, v2); 55498686cd2SShayne Chen seq_ctrl = FIELD_GET(MT_RXD10_SEQ_CTRL, v2); 55598686cd2SShayne Chen 55698686cd2SShayne Chen rxd += 4; 55798686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 55898686cd2SShayne Chen return -EINVAL; 55998686cd2SShayne Chen } 56098686cd2SShayne Chen 56198686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_1) { 56298686cd2SShayne Chen u8 *data = (u8 *)rxd; 56398686cd2SShayne Chen 56498686cd2SShayne Chen if (status->flag & RX_FLAG_DECRYPTED) { 56598686cd2SShayne Chen switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) { 56698686cd2SShayne Chen case MT_CIPHER_AES_CCMP: 56798686cd2SShayne Chen case MT_CIPHER_CCMP_CCX: 56898686cd2SShayne Chen case MT_CIPHER_CCMP_256: 56998686cd2SShayne Chen insert_ccmp_hdr = 57098686cd2SShayne Chen FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); 57198686cd2SShayne Chen fallthrough; 57298686cd2SShayne Chen case MT_CIPHER_TKIP: 57398686cd2SShayne Chen case MT_CIPHER_TKIP_NO_MIC: 57498686cd2SShayne Chen case MT_CIPHER_GCMP: 57598686cd2SShayne Chen case MT_CIPHER_GCMP_256: 57698686cd2SShayne Chen status->iv[0] = data[5]; 57798686cd2SShayne Chen status->iv[1] = data[4]; 57898686cd2SShayne Chen status->iv[2] = data[3]; 57998686cd2SShayne Chen status->iv[3] = data[2]; 58098686cd2SShayne Chen status->iv[4] = data[1]; 58198686cd2SShayne Chen status->iv[5] = data[0]; 58298686cd2SShayne Chen break; 58398686cd2SShayne Chen default: 58498686cd2SShayne Chen break; 58598686cd2SShayne Chen } 58698686cd2SShayne Chen } 58798686cd2SShayne Chen rxd += 4; 58898686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 58998686cd2SShayne Chen return -EINVAL; 59098686cd2SShayne Chen } 59198686cd2SShayne Chen 59298686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { 59398686cd2SShayne Chen status->timestamp = le32_to_cpu(rxd[0]); 59498686cd2SShayne Chen status->flag |= RX_FLAG_MACTIME_START; 59598686cd2SShayne Chen 59698686cd2SShayne Chen if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { 59798686cd2SShayne Chen status->flag |= RX_FLAG_AMPDU_DETAILS; 59898686cd2SShayne Chen 59998686cd2SShayne Chen /* all subframes of an A-MPDU have the same timestamp */ 60098686cd2SShayne Chen if (phy->rx_ampdu_ts != status->timestamp) { 60198686cd2SShayne Chen if (!++phy->ampdu_ref) 60298686cd2SShayne Chen phy->ampdu_ref++; 60398686cd2SShayne Chen } 60498686cd2SShayne Chen phy->rx_ampdu_ts = status->timestamp; 60598686cd2SShayne Chen 60698686cd2SShayne Chen status->ampdu_ref = phy->ampdu_ref; 60798686cd2SShayne Chen } 60898686cd2SShayne Chen 60998686cd2SShayne Chen rxd += 4; 61098686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 61198686cd2SShayne Chen return -EINVAL; 61298686cd2SShayne Chen } 61398686cd2SShayne Chen 61498686cd2SShayne Chen /* RXD Group 3 - P-RXV */ 61598686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { 61698686cd2SShayne Chen u32 v3; 61798686cd2SShayne Chen int ret; 61898686cd2SShayne Chen 61998686cd2SShayne Chen rxv = rxd; 62098686cd2SShayne Chen rxd += 4; 62198686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 62298686cd2SShayne Chen return -EINVAL; 62398686cd2SShayne Chen 62498686cd2SShayne Chen v3 = le32_to_cpu(rxv[3]); 62598686cd2SShayne Chen 62698686cd2SShayne Chen status->chains = mphy->antenna_mask; 62798686cd2SShayne Chen status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v3); 62898686cd2SShayne Chen status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v3); 62998686cd2SShayne Chen status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v3); 63098686cd2SShayne Chen status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v3); 63198686cd2SShayne Chen 63298686cd2SShayne Chen /* RXD Group 5 - C-RXV */ 63398686cd2SShayne Chen if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { 63498686cd2SShayne Chen rxd += 24; 63598686cd2SShayne Chen if ((u8 *)rxd - skb->data >= skb->len) 63698686cd2SShayne Chen return -EINVAL; 63798686cd2SShayne Chen } 63898686cd2SShayne Chen 63998686cd2SShayne Chen ret = mt7996_mac_fill_rx_rate(dev, status, sband, rxv, &mode); 64098686cd2SShayne Chen if (ret < 0) 64198686cd2SShayne Chen return ret; 64298686cd2SShayne Chen } 64398686cd2SShayne Chen 64498686cd2SShayne Chen amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); 64598686cd2SShayne Chen status->amsdu = !!amsdu_info; 64698686cd2SShayne Chen if (status->amsdu) { 64798686cd2SShayne Chen status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; 64898686cd2SShayne Chen status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; 64998686cd2SShayne Chen } 65098686cd2SShayne Chen 65198686cd2SShayne Chen hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; 65298686cd2SShayne Chen if (hdr_trans && ieee80211_has_morefrags(fc)) { 65398686cd2SShayne Chen if (mt7996_reverse_frag0_hdr_trans(skb, hdr_gap)) 65498686cd2SShayne Chen return -EINVAL; 65598686cd2SShayne Chen hdr_trans = false; 65698686cd2SShayne Chen } else { 65798686cd2SShayne Chen int pad_start = 0; 65898686cd2SShayne Chen 65998686cd2SShayne Chen skb_pull(skb, hdr_gap); 66027db47abSRyder Lee if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) { 66198686cd2SShayne Chen pad_start = ieee80211_get_hdrlen_from_skb(skb); 662c55b4e78SRyder Lee } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { 66398686cd2SShayne Chen /* When header translation failure is indicated, 66498686cd2SShayne Chen * the hardware will insert an extra 2-byte field 66598686cd2SShayne Chen * containing the data length after the protocol 666c55b4e78SRyder Lee * type field. This happens either when the LLC-SNAP 667c55b4e78SRyder Lee * pattern did not match, or if a VLAN header was 668c55b4e78SRyder Lee * detected. 66998686cd2SShayne Chen */ 670c55b4e78SRyder Lee pad_start = 12; 671c55b4e78SRyder Lee if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) 672c55b4e78SRyder Lee pad_start += 4; 673c55b4e78SRyder Lee else 674c55b4e78SRyder Lee pad_start = 0; 67598686cd2SShayne Chen } 67698686cd2SShayne Chen 67798686cd2SShayne Chen if (pad_start) { 67898686cd2SShayne Chen memmove(skb->data + 2, skb->data, pad_start); 67998686cd2SShayne Chen skb_pull(skb, 2); 68098686cd2SShayne Chen } 68198686cd2SShayne Chen } 68298686cd2SShayne Chen 68398686cd2SShayne Chen if (!hdr_trans) { 68498686cd2SShayne Chen struct ieee80211_hdr *hdr; 68598686cd2SShayne Chen 68698686cd2SShayne Chen if (insert_ccmp_hdr) { 68798686cd2SShayne Chen u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); 68898686cd2SShayne Chen 68998686cd2SShayne Chen mt76_insert_ccmp_hdr(skb, key_id); 69098686cd2SShayne Chen } 69198686cd2SShayne Chen 69298686cd2SShayne Chen hdr = mt76_skb_get_hdr(skb); 69398686cd2SShayne Chen fc = hdr->frame_control; 69498686cd2SShayne Chen if (ieee80211_is_data_qos(fc)) { 69527db47abSRyder Lee u8 *qos = ieee80211_get_qos_ctl(hdr); 69627db47abSRyder Lee 69798686cd2SShayne Chen seq_ctrl = le16_to_cpu(hdr->seq_ctrl); 69827db47abSRyder Lee qos_ctl = *qos; 69927db47abSRyder Lee 70027db47abSRyder Lee /* Mesh DA/SA/Length will be stripped after hardware 70127db47abSRyder Lee * de-amsdu, so here needs to clear amsdu present bit 70227db47abSRyder Lee * to mark it as a normal mesh frame. 70327db47abSRyder Lee */ 70427db47abSRyder Lee if (ieee80211_has_a4(fc) && is_mesh && status->amsdu) 70527db47abSRyder Lee *qos &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; 70698686cd2SShayne Chen } 70798686cd2SShayne Chen } else { 70898686cd2SShayne Chen status->flag |= RX_FLAG_8023; 70998686cd2SShayne Chen } 71098686cd2SShayne Chen 71198686cd2SShayne Chen if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) 712*46d3304dSLorenzo Bianconi mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); 71398686cd2SShayne Chen 71498686cd2SShayne Chen if (!status->wcid || !ieee80211_is_data_qos(fc)) 71598686cd2SShayne Chen return 0; 71698686cd2SShayne Chen 71798686cd2SShayne Chen status->aggr = unicast && 71898686cd2SShayne Chen !ieee80211_is_qos_nullfunc(fc); 71998686cd2SShayne Chen status->qos_ctl = qos_ctl; 72098686cd2SShayne Chen status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); 72198686cd2SShayne Chen 72298686cd2SShayne Chen return 0; 72398686cd2SShayne Chen } 72498686cd2SShayne Chen 72598686cd2SShayne Chen static void 72698686cd2SShayne Chen mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi, 72798686cd2SShayne Chen struct sk_buff *skb, struct mt76_wcid *wcid) 72898686cd2SShayne Chen { 72998686cd2SShayne Chen u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 73098686cd2SShayne Chen u8 fc_type, fc_stype; 73198686cd2SShayne Chen u16 ethertype; 73298686cd2SShayne Chen bool wmm = false; 73398686cd2SShayne Chen u32 val; 73498686cd2SShayne Chen 73598686cd2SShayne Chen if (wcid->sta) { 73698686cd2SShayne Chen struct ieee80211_sta *sta; 73798686cd2SShayne Chen 73898686cd2SShayne Chen sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv); 73998686cd2SShayne Chen wmm = sta->wme; 74098686cd2SShayne Chen } 74198686cd2SShayne Chen 74298686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | 74398686cd2SShayne Chen FIELD_PREP(MT_TXD1_TID, tid); 74498686cd2SShayne Chen 74598686cd2SShayne Chen ethertype = get_unaligned_be16(&skb->data[12]); 74698686cd2SShayne Chen if (ethertype >= ETH_P_802_3_MIN) 74798686cd2SShayne Chen val |= MT_TXD1_ETH_802_3; 74898686cd2SShayne Chen 74998686cd2SShayne Chen txwi[1] |= cpu_to_le32(val); 75098686cd2SShayne Chen 75198686cd2SShayne Chen fc_type = IEEE80211_FTYPE_DATA >> 2; 75298686cd2SShayne Chen fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; 75398686cd2SShayne Chen 75498686cd2SShayne Chen val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | 75598686cd2SShayne Chen FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); 75698686cd2SShayne Chen 75798686cd2SShayne Chen txwi[2] |= cpu_to_le32(val); 75898686cd2SShayne Chen } 75998686cd2SShayne Chen 76098686cd2SShayne Chen static void 76198686cd2SShayne Chen mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi, 76298686cd2SShayne Chen struct sk_buff *skb, struct ieee80211_key_conf *key) 76398686cd2SShayne Chen { 76498686cd2SShayne Chen struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 76598686cd2SShayne Chen struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 76698686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 76798686cd2SShayne Chen bool multicast = is_multicast_ether_addr(hdr->addr1); 76898686cd2SShayne Chen u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; 76998686cd2SShayne Chen __le16 fc = hdr->frame_control; 77098686cd2SShayne Chen u8 fc_type, fc_stype; 77198686cd2SShayne Chen u32 val; 77298686cd2SShayne Chen 77398686cd2SShayne Chen if (ieee80211_is_action(fc) && 77498686cd2SShayne Chen mgmt->u.action.category == WLAN_CATEGORY_BACK && 77598686cd2SShayne Chen mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) 77698686cd2SShayne Chen tid = MT_TX_ADDBA; 77798686cd2SShayne Chen else if (ieee80211_is_mgmt(hdr->frame_control)) 77898686cd2SShayne Chen tid = MT_TX_NORMAL; 77998686cd2SShayne Chen 78098686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | 78198686cd2SShayne Chen FIELD_PREP(MT_TXD1_HDR_INFO, 78298686cd2SShayne Chen ieee80211_get_hdrlen_from_skb(skb) / 2) | 78398686cd2SShayne Chen FIELD_PREP(MT_TXD1_TID, tid); 78498686cd2SShayne Chen 78598686cd2SShayne Chen if (!ieee80211_is_data(fc) || multicast || 78698686cd2SShayne Chen info->flags & IEEE80211_TX_CTL_USE_MINRATE) 78798686cd2SShayne Chen val |= MT_TXD1_FIXED_RATE; 78898686cd2SShayne Chen 78998686cd2SShayne Chen if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && 79098686cd2SShayne Chen key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { 79198686cd2SShayne Chen val |= MT_TXD1_BIP; 79298686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); 79398686cd2SShayne Chen } 79498686cd2SShayne Chen 79598686cd2SShayne Chen txwi[1] |= cpu_to_le32(val); 79698686cd2SShayne Chen 79798686cd2SShayne Chen fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; 79898686cd2SShayne Chen fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; 79998686cd2SShayne Chen 80098686cd2SShayne Chen val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | 80198686cd2SShayne Chen FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); 80298686cd2SShayne Chen 80398686cd2SShayne Chen txwi[2] |= cpu_to_le32(val); 80498686cd2SShayne Chen 80598686cd2SShayne Chen txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast)); 80698686cd2SShayne Chen if (ieee80211_is_beacon(fc)) { 80798686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); 80898686cd2SShayne Chen txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); 80998686cd2SShayne Chen } 81098686cd2SShayne Chen 81198686cd2SShayne Chen if (info->flags & IEEE80211_TX_CTL_INJECTED) { 81298686cd2SShayne Chen u16 seqno = le16_to_cpu(hdr->seq_ctrl); 81398686cd2SShayne Chen 81498686cd2SShayne Chen if (ieee80211_is_back_req(hdr->frame_control)) { 81598686cd2SShayne Chen struct ieee80211_bar *bar; 81698686cd2SShayne Chen 81798686cd2SShayne Chen bar = (struct ieee80211_bar *)skb->data; 81898686cd2SShayne Chen seqno = le16_to_cpu(bar->start_seq_num); 81998686cd2SShayne Chen } 82098686cd2SShayne Chen 82198686cd2SShayne Chen val = MT_TXD3_SN_VALID | 82298686cd2SShayne Chen FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno)); 82398686cd2SShayne Chen txwi[3] |= cpu_to_le32(val); 82498686cd2SShayne Chen txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU); 82598686cd2SShayne Chen } 82698686cd2SShayne Chen } 82798686cd2SShayne Chen 82898686cd2SShayne Chen void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, 829d0b6f86fSShayne Chen struct sk_buff *skb, struct mt76_wcid *wcid, 830d0b6f86fSShayne Chen struct ieee80211_key_conf *key, int pid, 831d0b6f86fSShayne Chen enum mt76_txq_id qid, u32 changed) 83298686cd2SShayne Chen { 83398686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 83498686cd2SShayne Chen struct ieee80211_vif *vif = info->control.vif; 83598686cd2SShayne Chen u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; 83698686cd2SShayne Chen u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; 83798686cd2SShayne Chen bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; 8380cb065b9SLorenzo Bianconi struct mt76_vif *mvif; 83998686cd2SShayne Chen u16 tx_count = 15; 84098686cd2SShayne Chen u32 val; 84198686cd2SShayne Chen bool beacon = !!(changed & (BSS_CHANGED_BEACON | 84298686cd2SShayne Chen BSS_CHANGED_BEACON_ENABLED)); 84398686cd2SShayne Chen bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | 84498686cd2SShayne Chen BSS_CHANGED_FILS_DISCOVERY)); 84598686cd2SShayne Chen 8460cb065b9SLorenzo Bianconi mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL; 847ead44902SLorenzo Bianconi if (mvif) { 8480cb065b9SLorenzo Bianconi omac_idx = mvif->omac_idx; 8490cb065b9SLorenzo Bianconi wmm_idx = mvif->wmm_idx; 8500cb065b9SLorenzo Bianconi band_idx = mvif->band_idx; 85198686cd2SShayne Chen } 85298686cd2SShayne Chen 85398686cd2SShayne Chen if (inband_disc) { 85498686cd2SShayne Chen p_fmt = MT_TX_TYPE_FW; 85598686cd2SShayne Chen q_idx = MT_LMAC_ALTX0; 85698686cd2SShayne Chen } else if (beacon) { 85798686cd2SShayne Chen p_fmt = MT_TX_TYPE_FW; 85898686cd2SShayne Chen q_idx = MT_LMAC_BCN0; 859d0b6f86fSShayne Chen } else if (qid >= MT_TXQ_PSD) { 86098686cd2SShayne Chen p_fmt = MT_TX_TYPE_CT; 86198686cd2SShayne Chen q_idx = MT_LMAC_ALTX0; 86298686cd2SShayne Chen } else { 86398686cd2SShayne Chen p_fmt = MT_TX_TYPE_CT; 86498686cd2SShayne Chen q_idx = wmm_idx * MT7996_MAX_WMM_SETS + 86598686cd2SShayne Chen mt76_connac_lmac_mapping(skb_get_queue_mapping(skb)); 86698686cd2SShayne Chen } 86798686cd2SShayne Chen 86898686cd2SShayne Chen val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | 86998686cd2SShayne Chen FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | 87098686cd2SShayne Chen FIELD_PREP(MT_TXD0_Q_IDX, q_idx); 87198686cd2SShayne Chen txwi[0] = cpu_to_le32(val); 87298686cd2SShayne Chen 87398686cd2SShayne Chen val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | 87498686cd2SShayne Chen FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); 87598686cd2SShayne Chen 87698686cd2SShayne Chen if (band_idx) 87798686cd2SShayne Chen val |= FIELD_PREP(MT_TXD1_TGID, band_idx); 87898686cd2SShayne Chen 87998686cd2SShayne Chen txwi[1] = cpu_to_le32(val); 88098686cd2SShayne Chen txwi[2] = 0; 88198686cd2SShayne Chen 88298686cd2SShayne Chen val = MT_TXD3_SW_POWER_MGMT | 88398686cd2SShayne Chen FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); 88498686cd2SShayne Chen if (key) 88598686cd2SShayne Chen val |= MT_TXD3_PROTECT_FRAME; 88698686cd2SShayne Chen if (info->flags & IEEE80211_TX_CTL_NO_ACK) 88798686cd2SShayne Chen val |= MT_TXD3_NO_ACK; 88898686cd2SShayne Chen if (wcid->amsdu) 88998686cd2SShayne Chen val |= MT_TXD3_HW_AMSDU; 89098686cd2SShayne Chen 89198686cd2SShayne Chen txwi[3] = cpu_to_le32(val); 89298686cd2SShayne Chen txwi[4] = 0; 89398686cd2SShayne Chen 89498686cd2SShayne Chen val = FIELD_PREP(MT_TXD5_PID, pid); 89598686cd2SShayne Chen if (pid >= MT_PACKET_ID_FIRST) 89698686cd2SShayne Chen val |= MT_TXD5_TX_STATUS_HOST; 89798686cd2SShayne Chen txwi[5] = cpu_to_le32(val); 89898686cd2SShayne Chen 89998686cd2SShayne Chen val = MT_TXD6_DIS_MAT | MT_TXD6_DAS | 90098686cd2SShayne Chen FIELD_PREP(MT_TXD6_MSDU_CNT, 1); 90198686cd2SShayne Chen txwi[6] = cpu_to_le32(val); 90298686cd2SShayne Chen txwi[7] = 0; 90398686cd2SShayne Chen 90498686cd2SShayne Chen if (is_8023) 90598686cd2SShayne Chen mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid); 90698686cd2SShayne Chen else 90798686cd2SShayne Chen mt7996_mac_write_txwi_80211(dev, txwi, skb, key); 90898686cd2SShayne Chen 90998686cd2SShayne Chen if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) { 910ab0eec4bSRyder Lee struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 911ab0eec4bSRyder Lee bool mcast = ieee80211_is_data(hdr->frame_control) && 912ab0eec4bSRyder Lee is_multicast_ether_addr(hdr->addr1); 913ead44902SLorenzo Bianconi u8 idx = MT7996_BASIC_RATES_TBL; 91498686cd2SShayne Chen 915ead44902SLorenzo Bianconi if (mvif) { 916ab0eec4bSRyder Lee if (mcast && mvif->mcast_rates_idx) 917ab0eec4bSRyder Lee idx = mvif->mcast_rates_idx; 918c2171b06SRyder Lee else if (beacon && mvif->beacon_rates_idx) 919c2171b06SRyder Lee idx = mvif->beacon_rates_idx; 920ead44902SLorenzo Bianconi else 921ead44902SLorenzo Bianconi idx = mvif->basic_rates_idx; 922ead44902SLorenzo Bianconi } 923ab0eec4bSRyder Lee 924cdc26ee8SRyder Lee txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx)); 92598686cd2SShayne Chen txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); 92698686cd2SShayne Chen } 92798686cd2SShayne Chen } 92898686cd2SShayne Chen 92998686cd2SShayne Chen int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 93098686cd2SShayne Chen enum mt76_txq_id qid, struct mt76_wcid *wcid, 93198686cd2SShayne Chen struct ieee80211_sta *sta, 93298686cd2SShayne Chen struct mt76_tx_info *tx_info) 93398686cd2SShayne Chen { 93498686cd2SShayne Chen struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; 93598686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 93698686cd2SShayne Chen struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); 93798686cd2SShayne Chen struct ieee80211_key_conf *key = info->control.hw_key; 93898686cd2SShayne Chen struct ieee80211_vif *vif = info->control.vif; 9393c38dfc1SLorenzo Bianconi struct mt76_connac_txp_common *txp; 94098686cd2SShayne Chen struct mt76_txwi_cache *t; 94198686cd2SShayne Chen int id, i, pid, nbuf = tx_info->nbuf - 1; 94298686cd2SShayne Chen bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; 94398686cd2SShayne Chen u8 *txwi = (u8 *)txwi_ptr; 94498686cd2SShayne Chen 94598686cd2SShayne Chen if (unlikely(tx_info->skb->len <= ETH_HLEN)) 94698686cd2SShayne Chen return -EINVAL; 94798686cd2SShayne Chen 94898686cd2SShayne Chen if (!wcid) 94998686cd2SShayne Chen wcid = &dev->mt76.global_wcid; 95098686cd2SShayne Chen 95198686cd2SShayne Chen if (sta) { 95298686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 95398686cd2SShayne Chen 95498686cd2SShayne Chen if (time_after(jiffies, msta->jiffies + HZ / 4)) { 95598686cd2SShayne Chen info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 95698686cd2SShayne Chen msta->jiffies = jiffies; 95798686cd2SShayne Chen } 95898686cd2SShayne Chen } 95998686cd2SShayne Chen 96098686cd2SShayne Chen t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); 96198686cd2SShayne Chen t->skb = tx_info->skb; 96298686cd2SShayne Chen 96398686cd2SShayne Chen id = mt76_token_consume(mdev, &t); 96498686cd2SShayne Chen if (id < 0) 96598686cd2SShayne Chen return id; 96698686cd2SShayne Chen 96798686cd2SShayne Chen pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); 968d0b6f86fSShayne Chen mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key, 969d0b6f86fSShayne Chen pid, qid, 0); 97098686cd2SShayne Chen 9713c38dfc1SLorenzo Bianconi txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE); 97298686cd2SShayne Chen for (i = 0; i < nbuf; i++) { 9733c38dfc1SLorenzo Bianconi txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); 9743c38dfc1SLorenzo Bianconi txp->fw.len[i] = cpu_to_le16(tx_info->buf[i + 1].len); 97598686cd2SShayne Chen } 9763c38dfc1SLorenzo Bianconi txp->fw.nbuf = nbuf; 97798686cd2SShayne Chen 9783b522cadSRyder Lee txp->fw.flags = 9793b522cadSRyder Lee cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD); 98098686cd2SShayne Chen 98198686cd2SShayne Chen if (!key) 9823c38dfc1SLorenzo Bianconi txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); 98398686cd2SShayne Chen 98498686cd2SShayne Chen if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control)) 9853c38dfc1SLorenzo Bianconi txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); 98698686cd2SShayne Chen 98798686cd2SShayne Chen if (vif) { 98898686cd2SShayne Chen struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; 98998686cd2SShayne Chen 9903c38dfc1SLorenzo Bianconi txp->fw.bss_idx = mvif->mt76.idx; 99198686cd2SShayne Chen } 99298686cd2SShayne Chen 9933c38dfc1SLorenzo Bianconi txp->fw.token = cpu_to_le16(id); 99498686cd2SShayne Chen if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) 9953c38dfc1SLorenzo Bianconi txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx); 99698686cd2SShayne Chen else 9973c38dfc1SLorenzo Bianconi txp->fw.rept_wds_wcid = cpu_to_le16(0xfff); 99898686cd2SShayne Chen tx_info->skb = DMA_DUMMY_DATA; 99998686cd2SShayne Chen 100098686cd2SShayne Chen /* pass partial skb header to fw */ 100198686cd2SShayne Chen tx_info->buf[1].len = MT_CT_PARSE_LEN; 100298686cd2SShayne Chen tx_info->buf[1].skip_unmap = true; 100398686cd2SShayne Chen tx_info->nbuf = MT_CT_DMA_BUF_NUM; 100498686cd2SShayne Chen 100598686cd2SShayne Chen return 0; 100698686cd2SShayne Chen } 100798686cd2SShayne Chen 100898686cd2SShayne Chen static void 100998686cd2SShayne Chen mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) 101098686cd2SShayne Chen { 101198686cd2SShayne Chen struct mt7996_sta *msta; 101298686cd2SShayne Chen u16 fc, tid; 101398686cd2SShayne Chen u32 val; 101498686cd2SShayne Chen 101598686cd2SShayne Chen if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) 101698686cd2SShayne Chen return; 101798686cd2SShayne Chen 101898686cd2SShayne Chen tid = le32_get_bits(txwi[1], MT_TXD1_TID); 101998686cd2SShayne Chen if (tid >= 6) /* skip VO queue */ 102098686cd2SShayne Chen return; 102198686cd2SShayne Chen 102298686cd2SShayne Chen val = le32_to_cpu(txwi[2]); 102398686cd2SShayne Chen fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | 102498686cd2SShayne Chen FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; 102598686cd2SShayne Chen if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) 102698686cd2SShayne Chen return; 102798686cd2SShayne Chen 102898686cd2SShayne Chen msta = (struct mt7996_sta *)sta->drv_priv; 1029ef591d74SLorenzo Bianconi if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) 103098686cd2SShayne Chen ieee80211_start_tx_ba_session(sta, tid, 0); 103198686cd2SShayne Chen } 103298686cd2SShayne Chen 103398686cd2SShayne Chen static void 103498686cd2SShayne Chen mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t, 103598686cd2SShayne Chen struct ieee80211_sta *sta, struct list_head *free_list) 103698686cd2SShayne Chen { 103798686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 103898686cd2SShayne Chen struct mt76_wcid *wcid; 103998686cd2SShayne Chen __le32 *txwi; 104098686cd2SShayne Chen u16 wcid_idx; 104198686cd2SShayne Chen 104230495864SLorenzo Bianconi mt76_connac_txp_skb_unmap(mdev, t); 104398686cd2SShayne Chen if (!t->skb) 104498686cd2SShayne Chen goto out; 104598686cd2SShayne Chen 104698686cd2SShayne Chen txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); 104798686cd2SShayne Chen if (sta) { 104898686cd2SShayne Chen wcid = (struct mt76_wcid *)sta->drv_priv; 104998686cd2SShayne Chen wcid_idx = wcid->idx; 105098686cd2SShayne Chen 105198686cd2SShayne Chen if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) 105298686cd2SShayne Chen mt7996_tx_check_aggr(sta, txwi); 105398686cd2SShayne Chen } else { 105498686cd2SShayne Chen wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); 105598686cd2SShayne Chen } 105698686cd2SShayne Chen 105798686cd2SShayne Chen __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); 105898686cd2SShayne Chen 105998686cd2SShayne Chen out: 106098686cd2SShayne Chen t->skb = NULL; 106198686cd2SShayne Chen mt76_put_txwi(mdev, t); 106298686cd2SShayne Chen } 106398686cd2SShayne Chen 106498686cd2SShayne Chen static void 106598686cd2SShayne Chen mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) 106698686cd2SShayne Chen { 106798686cd2SShayne Chen __le32 *tx_free = (__le32 *)data, *cur_info; 106898686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 106998686cd2SShayne Chen struct mt76_phy *phy2 = mdev->phys[MT_BAND1]; 107098686cd2SShayne Chen struct mt76_phy *phy3 = mdev->phys[MT_BAND2]; 107198686cd2SShayne Chen struct mt76_txwi_cache *txwi; 107298686cd2SShayne Chen struct ieee80211_sta *sta = NULL; 107398686cd2SShayne Chen LIST_HEAD(free_list); 107498686cd2SShayne Chen struct sk_buff *skb, *tmp; 107598686cd2SShayne Chen void *end = data + len; 107698686cd2SShayne Chen bool wake = false; 107798686cd2SShayne Chen u16 total, count = 0; 107898686cd2SShayne Chen 107998686cd2SShayne Chen /* clean DMA queues and unmap buffers first */ 108098686cd2SShayne Chen mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); 108198686cd2SShayne Chen mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); 108298686cd2SShayne Chen if (phy2) { 108398686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy2->q_tx[MT_TXQ_PSD], false); 108498686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy2->q_tx[MT_TXQ_BE], false); 108598686cd2SShayne Chen } 108698686cd2SShayne Chen if (phy3) { 108798686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_PSD], false); 108898686cd2SShayne Chen mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false); 108998686cd2SShayne Chen } 109098686cd2SShayne Chen 109198686cd2SShayne Chen if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4)) 109298686cd2SShayne Chen return; 109398686cd2SShayne Chen 109498686cd2SShayne Chen total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT); 109598686cd2SShayne Chen for (cur_info = &tx_free[2]; count < total; cur_info++) { 109698686cd2SShayne Chen u32 msdu, info; 109798686cd2SShayne Chen u8 i; 109898686cd2SShayne Chen 109998686cd2SShayne Chen if (WARN_ON_ONCE((void *)cur_info >= end)) 110098686cd2SShayne Chen return; 110198686cd2SShayne Chen /* 1'b1: new wcid pair. 110298686cd2SShayne Chen * 1'b0: msdu_id with the same 'wcid pair' as above. 110398686cd2SShayne Chen */ 110498686cd2SShayne Chen info = le32_to_cpu(*cur_info); 110598686cd2SShayne Chen if (info & MT_TXFREE_INFO_PAIR) { 110698686cd2SShayne Chen struct mt7996_sta *msta; 110798686cd2SShayne Chen struct mt76_wcid *wcid; 110898686cd2SShayne Chen u16 idx; 110998686cd2SShayne Chen 111098686cd2SShayne Chen idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); 111198686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[idx]); 111298686cd2SShayne Chen sta = wcid_to_sta(wcid); 111398686cd2SShayne Chen if (!sta) 111498686cd2SShayne Chen continue; 111598686cd2SShayne Chen 111698686cd2SShayne Chen msta = container_of(wcid, struct mt7996_sta, wcid); 1117ea0f3867SLorenzo Bianconi spin_lock_bh(&mdev->sta_poll_lock); 1118e3b0311fSLorenzo Bianconi if (list_empty(&msta->wcid.poll_list)) 1119e3b0311fSLorenzo Bianconi list_add_tail(&msta->wcid.poll_list, 1120ea0f3867SLorenzo Bianconi &mdev->sta_poll_list); 1121ea0f3867SLorenzo Bianconi spin_unlock_bh(&mdev->sta_poll_lock); 112298686cd2SShayne Chen continue; 112398686cd2SShayne Chen } 112498686cd2SShayne Chen 112598686cd2SShayne Chen if (info & MT_TXFREE_INFO_HEADER) 112698686cd2SShayne Chen continue; 112798686cd2SShayne Chen 112898686cd2SShayne Chen for (i = 0; i < 2; i++) { 112998686cd2SShayne Chen msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID; 113098686cd2SShayne Chen if (msdu == MT_TXFREE_INFO_MSDU_ID) 113198686cd2SShayne Chen continue; 113298686cd2SShayne Chen 113398686cd2SShayne Chen count++; 113498686cd2SShayne Chen txwi = mt76_token_release(mdev, msdu, &wake); 113598686cd2SShayne Chen if (!txwi) 113698686cd2SShayne Chen continue; 113798686cd2SShayne Chen 113898686cd2SShayne Chen mt7996_txwi_free(dev, txwi, sta, &free_list); 113998686cd2SShayne Chen } 114098686cd2SShayne Chen } 114198686cd2SShayne Chen 114298686cd2SShayne Chen mt7996_mac_sta_poll(dev); 114398686cd2SShayne Chen 114498686cd2SShayne Chen if (wake) 114598686cd2SShayne Chen mt76_set_tx_blocked(&dev->mt76, false); 114698686cd2SShayne Chen 114798686cd2SShayne Chen mt76_worker_schedule(&dev->mt76.tx_worker); 114898686cd2SShayne Chen 114998686cd2SShayne Chen list_for_each_entry_safe(skb, tmp, &free_list, list) { 115098686cd2SShayne Chen skb_list_del_init(skb); 115198686cd2SShayne Chen napi_consume_skb(skb, 1); 115298686cd2SShayne Chen } 115398686cd2SShayne Chen } 115498686cd2SShayne Chen 115598686cd2SShayne Chen static bool 1156d82e7c67SLorenzo Bianconi mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, 1157d82e7c67SLorenzo Bianconi int pid, __le32 *txs_data) 115898686cd2SShayne Chen { 1159d82e7c67SLorenzo Bianconi struct mt76_sta_stats *stats = &wcid->stats; 116098686cd2SShayne Chen struct ieee80211_supported_band *sband; 116198686cd2SShayne Chen struct mt76_dev *mdev = &dev->mt76; 116298686cd2SShayne Chen struct mt76_phy *mphy; 116398686cd2SShayne Chen struct ieee80211_tx_info *info; 116498686cd2SShayne Chen struct sk_buff_head list; 116598686cd2SShayne Chen struct rate_info rate = {}; 116698686cd2SShayne Chen struct sk_buff *skb; 116798686cd2SShayne Chen bool cck = false; 116898686cd2SShayne Chen u32 txrate, txs, mode, stbc; 116998686cd2SShayne Chen 117098686cd2SShayne Chen mt76_tx_status_lock(mdev, &list); 117198686cd2SShayne Chen skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list); 117298686cd2SShayne Chen if (!skb) 117398686cd2SShayne Chen goto out_no_skb; 117498686cd2SShayne Chen 117598686cd2SShayne Chen txs = le32_to_cpu(txs_data[0]); 117698686cd2SShayne Chen 117798686cd2SShayne Chen info = IEEE80211_SKB_CB(skb); 117898686cd2SShayne Chen if (!(txs & MT_TXS0_ACK_ERROR_MASK)) 117998686cd2SShayne Chen info->flags |= IEEE80211_TX_STAT_ACK; 118098686cd2SShayne Chen 118198686cd2SShayne Chen info->status.ampdu_len = 1; 118298686cd2SShayne Chen info->status.ampdu_ack_len = !!(info->flags & 118398686cd2SShayne Chen IEEE80211_TX_STAT_ACK); 118498686cd2SShayne Chen 118598686cd2SShayne Chen info->status.rates[0].idx = -1; 118698686cd2SShayne Chen 118798686cd2SShayne Chen txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); 118898686cd2SShayne Chen 118998686cd2SShayne Chen rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); 119098686cd2SShayne Chen rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; 119198686cd2SShayne Chen stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC); 119298686cd2SShayne Chen 119398686cd2SShayne Chen if (stbc && rate.nss > 1) 119498686cd2SShayne Chen rate.nss >>= 1; 119598686cd2SShayne Chen 119698686cd2SShayne Chen if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) 119798686cd2SShayne Chen stats->tx_nss[rate.nss - 1]++; 119898686cd2SShayne Chen if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) 119998686cd2SShayne Chen stats->tx_mcs[rate.mcs]++; 120098686cd2SShayne Chen 120198686cd2SShayne Chen mode = FIELD_GET(MT_TX_RATE_MODE, txrate); 120298686cd2SShayne Chen switch (mode) { 120398686cd2SShayne Chen case MT_PHY_TYPE_CCK: 120498686cd2SShayne Chen cck = true; 120598686cd2SShayne Chen fallthrough; 120698686cd2SShayne Chen case MT_PHY_TYPE_OFDM: 120798686cd2SShayne Chen mphy = mt76_dev_phy(mdev, wcid->phy_idx); 120898686cd2SShayne Chen 120998686cd2SShayne Chen if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) 121098686cd2SShayne Chen sband = &mphy->sband_5g.sband; 121198686cd2SShayne Chen else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) 121298686cd2SShayne Chen sband = &mphy->sband_6g.sband; 121398686cd2SShayne Chen else 121498686cd2SShayne Chen sband = &mphy->sband_2g.sband; 121598686cd2SShayne Chen 121698686cd2SShayne Chen rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, cck); 121798686cd2SShayne Chen rate.legacy = sband->bitrates[rate.mcs].bitrate; 121898686cd2SShayne Chen break; 121998686cd2SShayne Chen case MT_PHY_TYPE_HT: 122098686cd2SShayne Chen case MT_PHY_TYPE_HT_GF: 122198686cd2SShayne Chen if (rate.mcs > 31) 122298686cd2SShayne Chen goto out; 122398686cd2SShayne Chen 122498686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_MCS; 122598686cd2SShayne Chen if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) 122698686cd2SShayne Chen rate.flags |= RATE_INFO_FLAGS_SHORT_GI; 122798686cd2SShayne Chen break; 122898686cd2SShayne Chen case MT_PHY_TYPE_VHT: 122998686cd2SShayne Chen if (rate.mcs > 9) 123098686cd2SShayne Chen goto out; 123198686cd2SShayne Chen 123298686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_VHT_MCS; 123398686cd2SShayne Chen break; 123498686cd2SShayne Chen case MT_PHY_TYPE_HE_SU: 123598686cd2SShayne Chen case MT_PHY_TYPE_HE_EXT_SU: 123698686cd2SShayne Chen case MT_PHY_TYPE_HE_TB: 123798686cd2SShayne Chen case MT_PHY_TYPE_HE_MU: 123898686cd2SShayne Chen if (rate.mcs > 11) 123998686cd2SShayne Chen goto out; 124098686cd2SShayne Chen 124198686cd2SShayne Chen rate.he_gi = wcid->rate.he_gi; 124298686cd2SShayne Chen rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); 124398686cd2SShayne Chen rate.flags = RATE_INFO_FLAGS_HE_MCS; 124498686cd2SShayne Chen break; 124580f5a31dSShayne Chen case MT_PHY_TYPE_EHT_SU: 124680f5a31dSShayne Chen case MT_PHY_TYPE_EHT_TRIG: 124780f5a31dSShayne Chen case MT_PHY_TYPE_EHT_MU: 124880f5a31dSShayne Chen if (rate.mcs > 13) 124980f5a31dSShayne Chen goto out; 125080f5a31dSShayne Chen 125180f5a31dSShayne Chen rate.eht_gi = wcid->rate.eht_gi; 125280f5a31dSShayne Chen rate.flags = RATE_INFO_FLAGS_EHT_MCS; 125380f5a31dSShayne Chen break; 125498686cd2SShayne Chen default: 125598686cd2SShayne Chen goto out; 125698686cd2SShayne Chen } 125798686cd2SShayne Chen 125898686cd2SShayne Chen stats->tx_mode[mode]++; 125998686cd2SShayne Chen 126098686cd2SShayne Chen switch (FIELD_GET(MT_TXS0_BW, txs)) { 126180f5a31dSShayne Chen case IEEE80211_STA_RX_BW_320: 126280f5a31dSShayne Chen rate.bw = RATE_INFO_BW_320; 126380f5a31dSShayne Chen stats->tx_bw[4]++; 126480f5a31dSShayne Chen break; 126598686cd2SShayne Chen case IEEE80211_STA_RX_BW_160: 126698686cd2SShayne Chen rate.bw = RATE_INFO_BW_160; 126798686cd2SShayne Chen stats->tx_bw[3]++; 126898686cd2SShayne Chen break; 126998686cd2SShayne Chen case IEEE80211_STA_RX_BW_80: 127098686cd2SShayne Chen rate.bw = RATE_INFO_BW_80; 127198686cd2SShayne Chen stats->tx_bw[2]++; 127298686cd2SShayne Chen break; 127398686cd2SShayne Chen case IEEE80211_STA_RX_BW_40: 127498686cd2SShayne Chen rate.bw = RATE_INFO_BW_40; 127598686cd2SShayne Chen stats->tx_bw[1]++; 127698686cd2SShayne Chen break; 127798686cd2SShayne Chen default: 127898686cd2SShayne Chen rate.bw = RATE_INFO_BW_20; 127998686cd2SShayne Chen stats->tx_bw[0]++; 128098686cd2SShayne Chen break; 128198686cd2SShayne Chen } 128298686cd2SShayne Chen wcid->rate = rate; 128398686cd2SShayne Chen 128498686cd2SShayne Chen out: 128598686cd2SShayne Chen mt76_tx_status_skb_done(mdev, skb, &list); 128698686cd2SShayne Chen 128798686cd2SShayne Chen out_no_skb: 128898686cd2SShayne Chen mt76_tx_status_unlock(mdev, &list); 128998686cd2SShayne Chen 129098686cd2SShayne Chen return !!skb; 129198686cd2SShayne Chen } 129298686cd2SShayne Chen 129398686cd2SShayne Chen static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) 129498686cd2SShayne Chen { 129598686cd2SShayne Chen struct mt7996_sta *msta = NULL; 129698686cd2SShayne Chen struct mt76_wcid *wcid; 129798686cd2SShayne Chen __le32 *txs_data = data; 129898686cd2SShayne Chen u16 wcidx; 129998686cd2SShayne Chen u8 pid; 130098686cd2SShayne Chen 130198686cd2SShayne Chen if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) 130298686cd2SShayne Chen return; 130398686cd2SShayne Chen 130498686cd2SShayne Chen wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); 130598686cd2SShayne Chen pid = le32_get_bits(txs_data[3], MT_TXS3_PID); 130698686cd2SShayne Chen 130798686cd2SShayne Chen if (pid < MT_PACKET_ID_FIRST) 130898686cd2SShayne Chen return; 130998686cd2SShayne Chen 131043482540SShayne Chen if (wcidx >= mt7996_wtbl_size(dev)) 131198686cd2SShayne Chen return; 131298686cd2SShayne Chen 131398686cd2SShayne Chen rcu_read_lock(); 131498686cd2SShayne Chen 131598686cd2SShayne Chen wcid = rcu_dereference(dev->mt76.wcid[wcidx]); 131698686cd2SShayne Chen if (!wcid) 131798686cd2SShayne Chen goto out; 131898686cd2SShayne Chen 131998686cd2SShayne Chen msta = container_of(wcid, struct mt7996_sta, wcid); 132098686cd2SShayne Chen 1321d82e7c67SLorenzo Bianconi mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data); 132298686cd2SShayne Chen 132398686cd2SShayne Chen if (!wcid->sta) 132498686cd2SShayne Chen goto out; 132598686cd2SShayne Chen 1326ea0f3867SLorenzo Bianconi spin_lock_bh(&dev->mt76.sta_poll_lock); 1327e3b0311fSLorenzo Bianconi if (list_empty(&msta->wcid.poll_list)) 1328e3b0311fSLorenzo Bianconi list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); 1329ea0f3867SLorenzo Bianconi spin_unlock_bh(&dev->mt76.sta_poll_lock); 133098686cd2SShayne Chen 133198686cd2SShayne Chen out: 133298686cd2SShayne Chen rcu_read_unlock(); 133398686cd2SShayne Chen } 133498686cd2SShayne Chen 133598686cd2SShayne Chen bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len) 133698686cd2SShayne Chen { 133798686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 133898686cd2SShayne Chen __le32 *rxd = (__le32 *)data; 133998686cd2SShayne Chen __le32 *end = (__le32 *)&rxd[len / 4]; 134098686cd2SShayne Chen enum rx_pkt_type type; 134198686cd2SShayne Chen 134298686cd2SShayne Chen type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); 134398686cd2SShayne Chen if (type != PKT_TYPE_NORMAL) { 134498686cd2SShayne Chen u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK); 134598686cd2SShayne Chen 134698686cd2SShayne Chen if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) == 134798686cd2SShayne Chen MT_RXD0_SW_PKT_TYPE_FRAME)) 134898686cd2SShayne Chen return true; 134998686cd2SShayne Chen } 135098686cd2SShayne Chen 135198686cd2SShayne Chen switch (type) { 135298686cd2SShayne Chen case PKT_TYPE_TXRX_NOTIFY: 135398686cd2SShayne Chen mt7996_mac_tx_free(dev, data, len); 135498686cd2SShayne Chen return false; 135598686cd2SShayne Chen case PKT_TYPE_TXS: 135698686cd2SShayne Chen for (rxd += 4; rxd + 8 <= end; rxd += 8) 135798686cd2SShayne Chen mt7996_mac_add_txs(dev, rxd); 135898686cd2SShayne Chen return false; 135998686cd2SShayne Chen case PKT_TYPE_RX_FW_MONITOR: 136098686cd2SShayne Chen mt7996_debugfs_rx_fw_monitor(dev, data, len); 136198686cd2SShayne Chen return false; 136298686cd2SShayne Chen default: 136398686cd2SShayne Chen return true; 136498686cd2SShayne Chen } 136598686cd2SShayne Chen } 136698686cd2SShayne Chen 136798686cd2SShayne Chen void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, 136898686cd2SShayne Chen struct sk_buff *skb, u32 *info) 136998686cd2SShayne Chen { 137098686cd2SShayne Chen struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); 137198686cd2SShayne Chen __le32 *rxd = (__le32 *)skb->data; 137298686cd2SShayne Chen __le32 *end = (__le32 *)&skb->data[skb->len]; 137398686cd2SShayne Chen enum rx_pkt_type type; 137498686cd2SShayne Chen 137598686cd2SShayne Chen type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); 137698686cd2SShayne Chen if (type != PKT_TYPE_NORMAL) { 137798686cd2SShayne Chen u32 sw_type = le32_get_bits(rxd[0], MT_RXD0_SW_PKT_TYPE_MASK); 137898686cd2SShayne Chen 137998686cd2SShayne Chen if (unlikely((sw_type & MT_RXD0_SW_PKT_TYPE_MAP) == 138098686cd2SShayne Chen MT_RXD0_SW_PKT_TYPE_FRAME)) 138198686cd2SShayne Chen type = PKT_TYPE_NORMAL; 138298686cd2SShayne Chen } 138398686cd2SShayne Chen 138498686cd2SShayne Chen switch (type) { 138598686cd2SShayne Chen case PKT_TYPE_TXRX_NOTIFY: 138698686cd2SShayne Chen mt7996_mac_tx_free(dev, skb->data, skb->len); 138798686cd2SShayne Chen napi_consume_skb(skb, 1); 138898686cd2SShayne Chen break; 138998686cd2SShayne Chen case PKT_TYPE_RX_EVENT: 139098686cd2SShayne Chen mt7996_mcu_rx_event(dev, skb); 139198686cd2SShayne Chen break; 139298686cd2SShayne Chen case PKT_TYPE_TXS: 139398686cd2SShayne Chen for (rxd += 4; rxd + 8 <= end; rxd += 8) 139498686cd2SShayne Chen mt7996_mac_add_txs(dev, rxd); 139598686cd2SShayne Chen dev_kfree_skb(skb); 139698686cd2SShayne Chen break; 139798686cd2SShayne Chen case PKT_TYPE_RX_FW_MONITOR: 139898686cd2SShayne Chen mt7996_debugfs_rx_fw_monitor(dev, skb->data, skb->len); 139998686cd2SShayne Chen dev_kfree_skb(skb); 140098686cd2SShayne Chen break; 140198686cd2SShayne Chen case PKT_TYPE_NORMAL: 140298686cd2SShayne Chen if (!mt7996_mac_fill_rx(dev, skb)) { 140398686cd2SShayne Chen mt76_rx(&dev->mt76, q, skb); 140498686cd2SShayne Chen return; 140598686cd2SShayne Chen } 140698686cd2SShayne Chen fallthrough; 140798686cd2SShayne Chen default: 140898686cd2SShayne Chen dev_kfree_skb(skb); 140998686cd2SShayne Chen break; 141098686cd2SShayne Chen } 141198686cd2SShayne Chen } 141298686cd2SShayne Chen 141398686cd2SShayne Chen void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy) 141498686cd2SShayne Chen { 141598686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 141698686cd2SShayne Chen u32 reg = MT_WF_PHYRX_BAND_RX_CTRL1(phy->mt76->band_idx); 141798686cd2SShayne Chen 141898686cd2SShayne Chen mt76_clear(dev, reg, MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN); 141998686cd2SShayne Chen mt76_set(dev, reg, BIT(11) | BIT(9)); 142098686cd2SShayne Chen } 142198686cd2SShayne Chen 142298686cd2SShayne Chen void mt7996_mac_reset_counters(struct mt7996_phy *phy) 142398686cd2SShayne Chen { 142498686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 142598686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 142698686cd2SShayne Chen int i; 142798686cd2SShayne Chen 142898686cd2SShayne Chen for (i = 0; i < 16; i++) 142998686cd2SShayne Chen mt76_rr(dev, MT_TX_AGG_CNT(band_idx, i)); 143098686cd2SShayne Chen 143198686cd2SShayne Chen phy->mt76->survey_time = ktime_get_boottime(); 143298686cd2SShayne Chen 143398686cd2SShayne Chen memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats)); 143498686cd2SShayne Chen 143598686cd2SShayne Chen /* reset airtime counters */ 143698686cd2SShayne Chen mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band_idx), 143798686cd2SShayne Chen MT_WF_RMAC_MIB_RXTIME_CLR); 143898686cd2SShayne Chen 143998686cd2SShayne Chen mt7996_mcu_get_chan_mib_info(phy, true); 144098686cd2SShayne Chen } 144198686cd2SShayne Chen 144283a10ae2SPeter Chiu void mt7996_mac_set_coverage_class(struct mt7996_phy *phy) 144398686cd2SShayne Chen { 144498686cd2SShayne Chen s16 coverage_class = phy->coverage_class; 144598686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 144698686cd2SShayne Chen struct mt7996_phy *phy2 = mt7996_phy2(dev); 144798686cd2SShayne Chen struct mt7996_phy *phy3 = mt7996_phy3(dev); 144883a10ae2SPeter Chiu u32 reg_offset; 144998686cd2SShayne Chen u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | 145098686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); 145198686cd2SShayne Chen u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | 145298686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); 145398686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 145498686cd2SShayne Chen int offset; 145598686cd2SShayne Chen 145698686cd2SShayne Chen if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) 145798686cd2SShayne Chen return; 145898686cd2SShayne Chen 145998686cd2SShayne Chen if (phy2) 146098686cd2SShayne Chen coverage_class = max_t(s16, dev->phy.coverage_class, 146198686cd2SShayne Chen phy2->coverage_class); 146298686cd2SShayne Chen 146398686cd2SShayne Chen if (phy3) 146498686cd2SShayne Chen coverage_class = max_t(s16, coverage_class, 146598686cd2SShayne Chen phy3->coverage_class); 146698686cd2SShayne Chen 146798686cd2SShayne Chen offset = 3 * coverage_class; 146898686cd2SShayne Chen reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | 146998686cd2SShayne Chen FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); 147098686cd2SShayne Chen 147198686cd2SShayne Chen mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset); 147298686cd2SShayne Chen mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset); 147398686cd2SShayne Chen } 147498686cd2SShayne Chen 147598686cd2SShayne Chen void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band) 147698686cd2SShayne Chen { 147798686cd2SShayne Chen mt76_set(dev, MT_WF_PHYRX_CSD_BAND_RXTD12(band), 147898686cd2SShayne Chen MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY | 147998686cd2SShayne Chen MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR); 148098686cd2SShayne Chen 148198686cd2SShayne Chen mt76_set(dev, MT_WF_PHYRX_BAND_RX_CTRL1(band), 148298686cd2SShayne Chen FIELD_PREP(MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN, 0x5)); 148398686cd2SShayne Chen } 148498686cd2SShayne Chen 148598686cd2SShayne Chen static u8 148698686cd2SShayne Chen mt7996_phy_get_nf(struct mt7996_phy *phy, u8 band_idx) 148798686cd2SShayne Chen { 148898686cd2SShayne Chen static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; 148998686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 149098686cd2SShayne Chen u32 val, sum = 0, n = 0; 149198686cd2SShayne Chen int ant, i; 149298686cd2SShayne Chen 149398686cd2SShayne Chen for (ant = 0; ant < hweight8(phy->mt76->antenna_mask); ant++) { 149498686cd2SShayne Chen u32 reg = MT_WF_PHYRX_CSD_IRPI(band_idx, ant); 149598686cd2SShayne Chen 149698686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { 149798686cd2SShayne Chen val = mt76_rr(dev, reg); 149898686cd2SShayne Chen sum += val * nf_power[i]; 149998686cd2SShayne Chen n += val; 150098686cd2SShayne Chen } 150198686cd2SShayne Chen } 150298686cd2SShayne Chen 150398686cd2SShayne Chen return n ? sum / n : 0; 150498686cd2SShayne Chen } 150598686cd2SShayne Chen 150698686cd2SShayne Chen void mt7996_update_channel(struct mt76_phy *mphy) 150798686cd2SShayne Chen { 150898686cd2SShayne Chen struct mt7996_phy *phy = (struct mt7996_phy *)mphy->priv; 150998686cd2SShayne Chen struct mt76_channel_state *state = mphy->chan_state; 151098686cd2SShayne Chen int nf; 151198686cd2SShayne Chen 151298686cd2SShayne Chen mt7996_mcu_get_chan_mib_info(phy, false); 151398686cd2SShayne Chen 151498686cd2SShayne Chen nf = mt7996_phy_get_nf(phy, mphy->band_idx); 151598686cd2SShayne Chen if (!phy->noise) 151698686cd2SShayne Chen phy->noise = nf << 4; 151798686cd2SShayne Chen else if (nf) 151898686cd2SShayne Chen phy->noise += nf - (phy->noise >> 4); 151998686cd2SShayne Chen 152098686cd2SShayne Chen state->noise = -(phy->noise >> 4); 152198686cd2SShayne Chen } 152298686cd2SShayne Chen 152398686cd2SShayne Chen static bool 152498686cd2SShayne Chen mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state) 152598686cd2SShayne Chen { 152698686cd2SShayne Chen bool ret; 152798686cd2SShayne Chen 152898686cd2SShayne Chen ret = wait_event_timeout(dev->reset_wait, 152927015b6fSBo Jiao (READ_ONCE(dev->recovery.state) & state), 153098686cd2SShayne Chen MT7996_RESET_TIMEOUT); 153198686cd2SShayne Chen 153298686cd2SShayne Chen WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); 153398686cd2SShayne Chen return ret; 153498686cd2SShayne Chen } 153598686cd2SShayne Chen 153698686cd2SShayne Chen static void 153798686cd2SShayne Chen mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) 153898686cd2SShayne Chen { 153998686cd2SShayne Chen struct ieee80211_hw *hw = priv; 154098686cd2SShayne Chen 154198686cd2SShayne Chen switch (vif->type) { 154298686cd2SShayne Chen case NL80211_IFTYPE_MESH_POINT: 154398686cd2SShayne Chen case NL80211_IFTYPE_ADHOC: 154498686cd2SShayne Chen case NL80211_IFTYPE_AP: 154598686cd2SShayne Chen mt7996_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); 154698686cd2SShayne Chen break; 154798686cd2SShayne Chen default: 154898686cd2SShayne Chen break; 154998686cd2SShayne Chen } 155098686cd2SShayne Chen } 155198686cd2SShayne Chen 155298686cd2SShayne Chen static void 155398686cd2SShayne Chen mt7996_update_beacons(struct mt7996_dev *dev) 155498686cd2SShayne Chen { 155598686cd2SShayne Chen struct mt76_phy *phy2, *phy3; 155698686cd2SShayne Chen 155798686cd2SShayne Chen ieee80211_iterate_active_interfaces(dev->mt76.hw, 155898686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 155998686cd2SShayne Chen mt7996_update_vif_beacon, dev->mt76.hw); 156098686cd2SShayne Chen 156198686cd2SShayne Chen phy2 = dev->mt76.phys[MT_BAND1]; 156298686cd2SShayne Chen if (!phy2) 156398686cd2SShayne Chen return; 156498686cd2SShayne Chen 156598686cd2SShayne Chen ieee80211_iterate_active_interfaces(phy2->hw, 156698686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 156798686cd2SShayne Chen mt7996_update_vif_beacon, phy2->hw); 156898686cd2SShayne Chen 156998686cd2SShayne Chen phy3 = dev->mt76.phys[MT_BAND2]; 157098686cd2SShayne Chen if (!phy3) 157198686cd2SShayne Chen return; 157298686cd2SShayne Chen 157398686cd2SShayne Chen ieee80211_iterate_active_interfaces(phy3->hw, 157498686cd2SShayne Chen IEEE80211_IFACE_ITER_RESUME_ALL, 157598686cd2SShayne Chen mt7996_update_vif_beacon, phy3->hw); 157698686cd2SShayne Chen } 157798686cd2SShayne Chen 157898686cd2SShayne Chen void mt7996_tx_token_put(struct mt7996_dev *dev) 157998686cd2SShayne Chen { 158098686cd2SShayne Chen struct mt76_txwi_cache *txwi; 158198686cd2SShayne Chen int id; 158298686cd2SShayne Chen 158398686cd2SShayne Chen spin_lock_bh(&dev->mt76.token_lock); 158498686cd2SShayne Chen idr_for_each_entry(&dev->mt76.token, txwi, id) { 158598686cd2SShayne Chen mt7996_txwi_free(dev, txwi, NULL, NULL); 158698686cd2SShayne Chen dev->mt76.token_count--; 158798686cd2SShayne Chen } 158898686cd2SShayne Chen spin_unlock_bh(&dev->mt76.token_lock); 158998686cd2SShayne Chen idr_destroy(&dev->mt76.token); 159098686cd2SShayne Chen } 159198686cd2SShayne Chen 159227015b6fSBo Jiao static int 159327015b6fSBo Jiao mt7996_mac_restart(struct mt7996_dev *dev) 159427015b6fSBo Jiao { 159527015b6fSBo Jiao struct mt7996_phy *phy2, *phy3; 159627015b6fSBo Jiao struct mt76_dev *mdev = &dev->mt76; 159727015b6fSBo Jiao int i, ret; 159827015b6fSBo Jiao 159927015b6fSBo Jiao phy2 = mt7996_phy2(dev); 160027015b6fSBo Jiao phy3 = mt7996_phy3(dev); 160127015b6fSBo Jiao 160227015b6fSBo Jiao if (dev->hif2) { 160327015b6fSBo Jiao mt76_wr(dev, MT_INT1_MASK_CSR, 0x0); 160427015b6fSBo Jiao mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0); 160527015b6fSBo Jiao } 160627015b6fSBo Jiao 160727015b6fSBo Jiao if (dev_is_pci(mdev->dev)) { 160827015b6fSBo Jiao mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); 160927015b6fSBo Jiao if (dev->hif2) 161027015b6fSBo Jiao mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0); 161127015b6fSBo Jiao } 161227015b6fSBo Jiao 161327015b6fSBo Jiao set_bit(MT76_RESET, &dev->mphy.state); 161427015b6fSBo Jiao set_bit(MT76_MCU_RESET, &dev->mphy.state); 161527015b6fSBo Jiao wake_up(&dev->mt76.mcu.wait); 161627015b6fSBo Jiao if (phy2) { 161727015b6fSBo Jiao set_bit(MT76_RESET, &phy2->mt76->state); 161827015b6fSBo Jiao set_bit(MT76_MCU_RESET, &phy2->mt76->state); 161927015b6fSBo Jiao } 162027015b6fSBo Jiao if (phy3) { 162127015b6fSBo Jiao set_bit(MT76_RESET, &phy3->mt76->state); 162227015b6fSBo Jiao set_bit(MT76_MCU_RESET, &phy3->mt76->state); 162327015b6fSBo Jiao } 162427015b6fSBo Jiao 162527015b6fSBo Jiao /* lock/unlock all queues to ensure that no tx is pending */ 162627015b6fSBo Jiao mt76_txq_schedule_all(&dev->mphy); 162727015b6fSBo Jiao if (phy2) 162827015b6fSBo Jiao mt76_txq_schedule_all(phy2->mt76); 162927015b6fSBo Jiao if (phy3) 163027015b6fSBo Jiao mt76_txq_schedule_all(phy3->mt76); 163127015b6fSBo Jiao 163227015b6fSBo Jiao /* disable all tx/rx napi */ 163327015b6fSBo Jiao mt76_worker_disable(&dev->mt76.tx_worker); 163427015b6fSBo Jiao mt76_for_each_q_rx(mdev, i) { 163527015b6fSBo Jiao if (mdev->q_rx[i].ndesc) 163627015b6fSBo Jiao napi_disable(&dev->mt76.napi[i]); 163727015b6fSBo Jiao } 163827015b6fSBo Jiao napi_disable(&dev->mt76.tx_napi); 163927015b6fSBo Jiao 164027015b6fSBo Jiao /* token reinit */ 164127015b6fSBo Jiao mt7996_tx_token_put(dev); 164227015b6fSBo Jiao idr_init(&dev->mt76.token); 164327015b6fSBo Jiao 164427015b6fSBo Jiao mt7996_dma_reset(dev, true); 164527015b6fSBo Jiao 164627015b6fSBo Jiao local_bh_disable(); 164727015b6fSBo Jiao mt76_for_each_q_rx(mdev, i) { 164827015b6fSBo Jiao if (mdev->q_rx[i].ndesc) { 164927015b6fSBo Jiao napi_enable(&dev->mt76.napi[i]); 165027015b6fSBo Jiao napi_schedule(&dev->mt76.napi[i]); 165127015b6fSBo Jiao } 165227015b6fSBo Jiao } 165327015b6fSBo Jiao local_bh_enable(); 165427015b6fSBo Jiao clear_bit(MT76_MCU_RESET, &dev->mphy.state); 165527015b6fSBo Jiao clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 165627015b6fSBo Jiao 165727015b6fSBo Jiao mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); 165827015b6fSBo Jiao mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); 165927015b6fSBo Jiao if (dev->hif2) { 166027015b6fSBo Jiao mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask); 166127015b6fSBo Jiao mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0); 166227015b6fSBo Jiao } 166327015b6fSBo Jiao if (dev_is_pci(mdev->dev)) { 166427015b6fSBo Jiao mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 166527015b6fSBo Jiao if (dev->hif2) 166627015b6fSBo Jiao mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); 166727015b6fSBo Jiao } 166827015b6fSBo Jiao 166927015b6fSBo Jiao /* load firmware */ 167027015b6fSBo Jiao ret = mt7996_mcu_init_firmware(dev); 167127015b6fSBo Jiao if (ret) 167227015b6fSBo Jiao goto out; 167327015b6fSBo Jiao 167427015b6fSBo Jiao /* set the necessary init items */ 167527015b6fSBo Jiao ret = mt7996_mcu_set_eeprom(dev); 167627015b6fSBo Jiao if (ret) 167727015b6fSBo Jiao goto out; 167827015b6fSBo Jiao 167927015b6fSBo Jiao mt7996_mac_init(dev); 168027015b6fSBo Jiao mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband); 168127015b6fSBo Jiao mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband); 168227015b6fSBo Jiao mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband); 168327015b6fSBo Jiao ret = mt7996_txbf_init(dev); 168427015b6fSBo Jiao 168527015b6fSBo Jiao if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) { 168627015b6fSBo Jiao ret = mt7996_run(dev->mphy.hw); 168727015b6fSBo Jiao if (ret) 168827015b6fSBo Jiao goto out; 168927015b6fSBo Jiao } 169027015b6fSBo Jiao 169127015b6fSBo Jiao if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) { 169227015b6fSBo Jiao ret = mt7996_run(phy2->mt76->hw); 169327015b6fSBo Jiao if (ret) 169427015b6fSBo Jiao goto out; 169527015b6fSBo Jiao } 169627015b6fSBo Jiao 169727015b6fSBo Jiao if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) { 169827015b6fSBo Jiao ret = mt7996_run(phy3->mt76->hw); 169927015b6fSBo Jiao if (ret) 170027015b6fSBo Jiao goto out; 170127015b6fSBo Jiao } 170227015b6fSBo Jiao 170327015b6fSBo Jiao out: 170427015b6fSBo Jiao /* reset done */ 170527015b6fSBo Jiao clear_bit(MT76_RESET, &dev->mphy.state); 170627015b6fSBo Jiao if (phy2) 170727015b6fSBo Jiao clear_bit(MT76_RESET, &phy2->mt76->state); 170827015b6fSBo Jiao if (phy3) 170927015b6fSBo Jiao clear_bit(MT76_RESET, &phy3->mt76->state); 171027015b6fSBo Jiao 171127015b6fSBo Jiao local_bh_disable(); 171227015b6fSBo Jiao napi_enable(&dev->mt76.tx_napi); 171327015b6fSBo Jiao napi_schedule(&dev->mt76.tx_napi); 171427015b6fSBo Jiao local_bh_enable(); 171527015b6fSBo Jiao 171627015b6fSBo Jiao mt76_worker_enable(&dev->mt76.tx_worker); 171727015b6fSBo Jiao return ret; 171827015b6fSBo Jiao } 171927015b6fSBo Jiao 172027015b6fSBo Jiao static void 172127015b6fSBo Jiao mt7996_mac_full_reset(struct mt7996_dev *dev) 172227015b6fSBo Jiao { 172327015b6fSBo Jiao struct mt7996_phy *phy2, *phy3; 172427015b6fSBo Jiao int i; 172527015b6fSBo Jiao 172627015b6fSBo Jiao phy2 = mt7996_phy2(dev); 172727015b6fSBo Jiao phy3 = mt7996_phy3(dev); 172827015b6fSBo Jiao dev->recovery.hw_full_reset = true; 172927015b6fSBo Jiao 173027015b6fSBo Jiao wake_up(&dev->mt76.mcu.wait); 173127015b6fSBo Jiao ieee80211_stop_queues(mt76_hw(dev)); 173227015b6fSBo Jiao if (phy2) 173327015b6fSBo Jiao ieee80211_stop_queues(phy2->mt76->hw); 173427015b6fSBo Jiao if (phy3) 173527015b6fSBo Jiao ieee80211_stop_queues(phy3->mt76->hw); 173627015b6fSBo Jiao 173727015b6fSBo Jiao cancel_delayed_work_sync(&dev->mphy.mac_work); 173827015b6fSBo Jiao if (phy2) 173927015b6fSBo Jiao cancel_delayed_work_sync(&phy2->mt76->mac_work); 174027015b6fSBo Jiao if (phy3) 174127015b6fSBo Jiao cancel_delayed_work_sync(&phy3->mt76->mac_work); 174227015b6fSBo Jiao 174327015b6fSBo Jiao mutex_lock(&dev->mt76.mutex); 174427015b6fSBo Jiao for (i = 0; i < 10; i++) { 174527015b6fSBo Jiao if (!mt7996_mac_restart(dev)) 174627015b6fSBo Jiao break; 174727015b6fSBo Jiao } 174827015b6fSBo Jiao mutex_unlock(&dev->mt76.mutex); 174927015b6fSBo Jiao 175027015b6fSBo Jiao if (i == 10) 175127015b6fSBo Jiao dev_err(dev->mt76.dev, "chip full reset failed\n"); 175227015b6fSBo Jiao 175327015b6fSBo Jiao ieee80211_restart_hw(mt76_hw(dev)); 175427015b6fSBo Jiao if (phy2) 175527015b6fSBo Jiao ieee80211_restart_hw(phy2->mt76->hw); 175627015b6fSBo Jiao if (phy3) 175727015b6fSBo Jiao ieee80211_restart_hw(phy3->mt76->hw); 175827015b6fSBo Jiao 175927015b6fSBo Jiao ieee80211_wake_queues(mt76_hw(dev)); 176027015b6fSBo Jiao if (phy2) 176127015b6fSBo Jiao ieee80211_wake_queues(phy2->mt76->hw); 176227015b6fSBo Jiao if (phy3) 176327015b6fSBo Jiao ieee80211_wake_queues(phy3->mt76->hw); 176427015b6fSBo Jiao 176527015b6fSBo Jiao dev->recovery.hw_full_reset = false; 176627015b6fSBo Jiao ieee80211_queue_delayed_work(mt76_hw(dev), 176727015b6fSBo Jiao &dev->mphy.mac_work, 176827015b6fSBo Jiao MT7996_WATCHDOG_TIME); 176927015b6fSBo Jiao if (phy2) 177027015b6fSBo Jiao ieee80211_queue_delayed_work(phy2->mt76->hw, 177127015b6fSBo Jiao &phy2->mt76->mac_work, 177227015b6fSBo Jiao MT7996_WATCHDOG_TIME); 177327015b6fSBo Jiao if (phy3) 177427015b6fSBo Jiao ieee80211_queue_delayed_work(phy3->mt76->hw, 177527015b6fSBo Jiao &phy3->mt76->mac_work, 177627015b6fSBo Jiao MT7996_WATCHDOG_TIME); 177727015b6fSBo Jiao } 177827015b6fSBo Jiao 177998686cd2SShayne Chen void mt7996_mac_reset_work(struct work_struct *work) 178098686cd2SShayne Chen { 178198686cd2SShayne Chen struct mt7996_phy *phy2, *phy3; 178298686cd2SShayne Chen struct mt7996_dev *dev; 178398686cd2SShayne Chen int i; 178498686cd2SShayne Chen 178598686cd2SShayne Chen dev = container_of(work, struct mt7996_dev, reset_work); 178698686cd2SShayne Chen phy2 = mt7996_phy2(dev); 178798686cd2SShayne Chen phy3 = mt7996_phy3(dev); 178898686cd2SShayne Chen 178927015b6fSBo Jiao /* chip full reset */ 179027015b6fSBo Jiao if (dev->recovery.restart) { 179127015b6fSBo Jiao /* disable WA/WM WDT */ 179227015b6fSBo Jiao mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA, 179327015b6fSBo Jiao MT_MCU_CMD_WDT_MASK); 179427015b6fSBo Jiao 179527015b6fSBo Jiao if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT) 179627015b6fSBo Jiao dev->recovery.wa_reset_count++; 179727015b6fSBo Jiao else 179827015b6fSBo Jiao dev->recovery.wm_reset_count++; 179927015b6fSBo Jiao 180027015b6fSBo Jiao mt7996_mac_full_reset(dev); 180127015b6fSBo Jiao 180227015b6fSBo Jiao /* enable mcu irq */ 180327015b6fSBo Jiao mt7996_irq_enable(dev, MT_INT_MCU_CMD); 180427015b6fSBo Jiao mt7996_irq_disable(dev, 0); 180527015b6fSBo Jiao 180627015b6fSBo Jiao /* enable WA/WM WDT */ 180727015b6fSBo Jiao mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK); 180827015b6fSBo Jiao 180927015b6fSBo Jiao dev->recovery.state = MT_MCU_CMD_NORMAL_STATE; 181027015b6fSBo Jiao dev->recovery.restart = false; 181127015b6fSBo Jiao return; 181227015b6fSBo Jiao } 181327015b6fSBo Jiao 181427015b6fSBo Jiao if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) 181598686cd2SShayne Chen return; 181698686cd2SShayne Chen 181727015b6fSBo Jiao dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.", 181827015b6fSBo Jiao wiphy_name(dev->mt76.hw->wiphy)); 181998686cd2SShayne Chen ieee80211_stop_queues(mt76_hw(dev)); 182098686cd2SShayne Chen if (phy2) 182198686cd2SShayne Chen ieee80211_stop_queues(phy2->mt76->hw); 182298686cd2SShayne Chen if (phy3) 182398686cd2SShayne Chen ieee80211_stop_queues(phy3->mt76->hw); 182498686cd2SShayne Chen 182598686cd2SShayne Chen set_bit(MT76_RESET, &dev->mphy.state); 182698686cd2SShayne Chen set_bit(MT76_MCU_RESET, &dev->mphy.state); 182798686cd2SShayne Chen wake_up(&dev->mt76.mcu.wait); 182898686cd2SShayne Chen cancel_delayed_work_sync(&dev->mphy.mac_work); 182998686cd2SShayne Chen if (phy2) { 183098686cd2SShayne Chen set_bit(MT76_RESET, &phy2->mt76->state); 183198686cd2SShayne Chen cancel_delayed_work_sync(&phy2->mt76->mac_work); 183298686cd2SShayne Chen } 183398686cd2SShayne Chen if (phy3) { 183498686cd2SShayne Chen set_bit(MT76_RESET, &phy3->mt76->state); 183598686cd2SShayne Chen cancel_delayed_work_sync(&phy3->mt76->mac_work); 183698686cd2SShayne Chen } 183798686cd2SShayne Chen mt76_worker_disable(&dev->mt76.tx_worker); 183898686cd2SShayne Chen mt76_for_each_q_rx(&dev->mt76, i) 183998686cd2SShayne Chen napi_disable(&dev->mt76.napi[i]); 184098686cd2SShayne Chen napi_disable(&dev->mt76.tx_napi); 184198686cd2SShayne Chen 184298686cd2SShayne Chen mutex_lock(&dev->mt76.mutex); 184398686cd2SShayne Chen 184498686cd2SShayne Chen mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); 184598686cd2SShayne Chen 184698686cd2SShayne Chen if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { 184727015b6fSBo Jiao mt7996_dma_reset(dev, false); 184898686cd2SShayne Chen 184998686cd2SShayne Chen mt7996_tx_token_put(dev); 185098686cd2SShayne Chen idr_init(&dev->mt76.token); 185198686cd2SShayne Chen 185298686cd2SShayne Chen mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); 185398686cd2SShayne Chen mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); 185498686cd2SShayne Chen } 185598686cd2SShayne Chen 18568e8c09c7SBo Jiao mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); 18578e8c09c7SBo Jiao mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); 18588e8c09c7SBo Jiao 18598e8c09c7SBo Jiao /* enable DMA Tx/Tx and interrupt */ 18608e8c09c7SBo Jiao mt7996_dma_start(dev, false); 18618e8c09c7SBo Jiao 186298686cd2SShayne Chen clear_bit(MT76_MCU_RESET, &dev->mphy.state); 186398686cd2SShayne Chen clear_bit(MT76_RESET, &dev->mphy.state); 186498686cd2SShayne Chen if (phy2) 186598686cd2SShayne Chen clear_bit(MT76_RESET, &phy2->mt76->state); 186698686cd2SShayne Chen if (phy3) 186798686cd2SShayne Chen clear_bit(MT76_RESET, &phy3->mt76->state); 186898686cd2SShayne Chen 186998686cd2SShayne Chen local_bh_disable(); 187098686cd2SShayne Chen mt76_for_each_q_rx(&dev->mt76, i) { 187198686cd2SShayne Chen napi_enable(&dev->mt76.napi[i]); 187298686cd2SShayne Chen napi_schedule(&dev->mt76.napi[i]); 187398686cd2SShayne Chen } 187498686cd2SShayne Chen local_bh_enable(); 187598686cd2SShayne Chen 1876ec193b41SLorenzo Bianconi tasklet_schedule(&dev->mt76.irq_tasklet); 187798686cd2SShayne Chen 187898686cd2SShayne Chen mt76_worker_enable(&dev->mt76.tx_worker); 187998686cd2SShayne Chen 188098686cd2SShayne Chen local_bh_disable(); 188198686cd2SShayne Chen napi_enable(&dev->mt76.tx_napi); 188298686cd2SShayne Chen napi_schedule(&dev->mt76.tx_napi); 188398686cd2SShayne Chen local_bh_enable(); 188498686cd2SShayne Chen 188598686cd2SShayne Chen ieee80211_wake_queues(mt76_hw(dev)); 188698686cd2SShayne Chen if (phy2) 188798686cd2SShayne Chen ieee80211_wake_queues(phy2->mt76->hw); 188898686cd2SShayne Chen if (phy3) 188998686cd2SShayne Chen ieee80211_wake_queues(phy3->mt76->hw); 189098686cd2SShayne Chen 189198686cd2SShayne Chen mutex_unlock(&dev->mt76.mutex); 189298686cd2SShayne Chen 189398686cd2SShayne Chen mt7996_update_beacons(dev); 189498686cd2SShayne Chen 189598686cd2SShayne Chen ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, 189698686cd2SShayne Chen MT7996_WATCHDOG_TIME); 189798686cd2SShayne Chen if (phy2) 189898686cd2SShayne Chen ieee80211_queue_delayed_work(phy2->mt76->hw, 189998686cd2SShayne Chen &phy2->mt76->mac_work, 190098686cd2SShayne Chen MT7996_WATCHDOG_TIME); 190198686cd2SShayne Chen if (phy3) 190298686cd2SShayne Chen ieee80211_queue_delayed_work(phy3->mt76->hw, 190398686cd2SShayne Chen &phy3->mt76->mac_work, 190498686cd2SShayne Chen MT7996_WATCHDOG_TIME); 190527015b6fSBo Jiao dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.", 190627015b6fSBo Jiao wiphy_name(dev->mt76.hw->wiphy)); 190727015b6fSBo Jiao } 190827015b6fSBo Jiao 1909878161d5SRyder Lee /* firmware coredump */ 1910878161d5SRyder Lee void mt7996_mac_dump_work(struct work_struct *work) 1911878161d5SRyder Lee { 1912878161d5SRyder Lee const struct mt7996_mem_region *mem_region; 1913878161d5SRyder Lee struct mt7996_crash_data *crash_data; 1914878161d5SRyder Lee struct mt7996_dev *dev; 1915878161d5SRyder Lee struct mt7996_mem_hdr *hdr; 1916878161d5SRyder Lee size_t buf_len; 1917878161d5SRyder Lee int i; 1918878161d5SRyder Lee u32 num; 1919878161d5SRyder Lee u8 *buf; 1920878161d5SRyder Lee 1921878161d5SRyder Lee dev = container_of(work, struct mt7996_dev, dump_work); 1922878161d5SRyder Lee 1923878161d5SRyder Lee mutex_lock(&dev->dump_mutex); 1924878161d5SRyder Lee 1925878161d5SRyder Lee crash_data = mt7996_coredump_new(dev); 1926878161d5SRyder Lee if (!crash_data) { 1927878161d5SRyder Lee mutex_unlock(&dev->dump_mutex); 1928878161d5SRyder Lee goto skip_coredump; 1929878161d5SRyder Lee } 1930878161d5SRyder Lee 1931878161d5SRyder Lee mem_region = mt7996_coredump_get_mem_layout(dev, &num); 1932878161d5SRyder Lee if (!mem_region || !crash_data->memdump_buf_len) { 1933878161d5SRyder Lee mutex_unlock(&dev->dump_mutex); 1934878161d5SRyder Lee goto skip_memdump; 1935878161d5SRyder Lee } 1936878161d5SRyder Lee 1937878161d5SRyder Lee buf = crash_data->memdump_buf; 1938878161d5SRyder Lee buf_len = crash_data->memdump_buf_len; 1939878161d5SRyder Lee 1940878161d5SRyder Lee /* dumping memory content... */ 1941878161d5SRyder Lee memset(buf, 0, buf_len); 1942878161d5SRyder Lee for (i = 0; i < num; i++) { 1943878161d5SRyder Lee if (mem_region->len > buf_len) { 1944878161d5SRyder Lee dev_warn(dev->mt76.dev, "%s len %zu is too large\n", 1945878161d5SRyder Lee mem_region->name, mem_region->len); 1946878161d5SRyder Lee break; 1947878161d5SRyder Lee } 1948878161d5SRyder Lee 1949878161d5SRyder Lee /* reserve space for the header */ 1950878161d5SRyder Lee hdr = (void *)buf; 1951878161d5SRyder Lee buf += sizeof(*hdr); 1952878161d5SRyder Lee buf_len -= sizeof(*hdr); 1953878161d5SRyder Lee 1954878161d5SRyder Lee mt7996_memcpy_fromio(dev, buf, mem_region->start, 1955878161d5SRyder Lee mem_region->len); 1956878161d5SRyder Lee 1957878161d5SRyder Lee hdr->start = mem_region->start; 1958878161d5SRyder Lee hdr->len = mem_region->len; 1959878161d5SRyder Lee 1960878161d5SRyder Lee if (!mem_region->len) 1961878161d5SRyder Lee /* note: the header remains, just with zero length */ 1962878161d5SRyder Lee break; 1963878161d5SRyder Lee 1964878161d5SRyder Lee buf += mem_region->len; 1965878161d5SRyder Lee buf_len -= mem_region->len; 1966878161d5SRyder Lee 1967878161d5SRyder Lee mem_region++; 1968878161d5SRyder Lee } 1969878161d5SRyder Lee 1970878161d5SRyder Lee mutex_unlock(&dev->dump_mutex); 1971878161d5SRyder Lee 1972878161d5SRyder Lee skip_memdump: 1973878161d5SRyder Lee mt7996_coredump_submit(dev); 1974878161d5SRyder Lee skip_coredump: 1975878161d5SRyder Lee queue_work(dev->mt76.wq, &dev->reset_work); 1976878161d5SRyder Lee } 1977878161d5SRyder Lee 197827015b6fSBo Jiao void mt7996_reset(struct mt7996_dev *dev) 197927015b6fSBo Jiao { 198027015b6fSBo Jiao if (!dev->recovery.hw_init_done) 198127015b6fSBo Jiao return; 198227015b6fSBo Jiao 198327015b6fSBo Jiao if (dev->recovery.hw_full_reset) 198427015b6fSBo Jiao return; 198527015b6fSBo Jiao 198627015b6fSBo Jiao /* wm/wa exception: do full recovery */ 198727015b6fSBo Jiao if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) { 198827015b6fSBo Jiao dev->recovery.restart = true; 198927015b6fSBo Jiao dev_info(dev->mt76.dev, 199027015b6fSBo Jiao "%s indicated firmware crash, attempting recovery\n", 199127015b6fSBo Jiao wiphy_name(dev->mt76.hw->wiphy)); 199227015b6fSBo Jiao 199327015b6fSBo Jiao mt7996_irq_disable(dev, MT_INT_MCU_CMD); 1994878161d5SRyder Lee queue_work(dev->mt76.wq, &dev->dump_work); 199527015b6fSBo Jiao return; 199627015b6fSBo Jiao } 199727015b6fSBo Jiao 199827015b6fSBo Jiao queue_work(dev->mt76.wq, &dev->reset_work); 199927015b6fSBo Jiao wake_up(&dev->reset_wait); 200098686cd2SShayne Chen } 200198686cd2SShayne Chen 200298686cd2SShayne Chen void mt7996_mac_update_stats(struct mt7996_phy *phy) 200398686cd2SShayne Chen { 200498214484SLorenzo Bianconi struct mt76_mib_stats *mib = &phy->mib; 200598686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 200698686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 200798686cd2SShayne Chen u32 cnt; 200898686cd2SShayne Chen int i; 200998686cd2SShayne Chen 201098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR1(band_idx)); 201198686cd2SShayne Chen mib->fcs_err_cnt += cnt; 201298686cd2SShayne Chen 201398686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR33(band_idx)); 201498686cd2SShayne Chen mib->rx_fifo_full_cnt += cnt; 201598686cd2SShayne Chen 201698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR31(band_idx)); 201798686cd2SShayne Chen mib->rx_mpdu_cnt += cnt; 201898686cd2SShayne Chen 201998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR6(band_idx)); 202098686cd2SShayne Chen mib->channel_idle_cnt += FIELD_GET(MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK, cnt); 202198686cd2SShayne Chen 202298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RVSR0(band_idx)); 202398686cd2SShayne Chen mib->rx_vector_mismatch_cnt += cnt; 202498686cd2SShayne Chen 202598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR35(band_idx)); 202698686cd2SShayne Chen mib->rx_delimiter_fail_cnt += cnt; 202798686cd2SShayne Chen 202898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR36(band_idx)); 202998686cd2SShayne Chen mib->rx_len_mismatch_cnt += cnt; 203098686cd2SShayne Chen 203198686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR0(band_idx)); 203298686cd2SShayne Chen mib->tx_ampdu_cnt += cnt; 203398686cd2SShayne Chen 203498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR2(band_idx)); 203598686cd2SShayne Chen mib->tx_stop_q_empty_cnt += cnt; 203698686cd2SShayne Chen 203798686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR3(band_idx)); 203898686cd2SShayne Chen mib->tx_mpdu_attempts_cnt += cnt; 203998686cd2SShayne Chen 204098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR4(band_idx)); 204198686cd2SShayne Chen mib->tx_mpdu_success_cnt += cnt; 204298686cd2SShayne Chen 204398686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR27(band_idx)); 204498686cd2SShayne Chen mib->rx_ampdu_cnt += cnt; 204598686cd2SShayne Chen 204698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR28(band_idx)); 204798686cd2SShayne Chen mib->rx_ampdu_bytes_cnt += cnt; 204898686cd2SShayne Chen 204998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR29(band_idx)); 205098686cd2SShayne Chen mib->rx_ampdu_valid_subframe_cnt += cnt; 205198686cd2SShayne Chen 205298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RSCR30(band_idx)); 205398686cd2SShayne Chen mib->rx_ampdu_valid_subframe_bytes_cnt += cnt; 205498686cd2SShayne Chen 205598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR27(band_idx)); 205698686cd2SShayne Chen mib->tx_rwp_fail_cnt += FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT, cnt); 205798686cd2SShayne Chen 205898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_SDR28(band_idx)); 205998686cd2SShayne Chen mib->tx_rwp_need_cnt += FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT, cnt); 206098686cd2SShayne Chen 206198686cd2SShayne Chen cnt = mt76_rr(dev, MT_UMIB_RPDCR(band_idx)); 206298686cd2SShayne Chen mib->rx_pfdrop_cnt += cnt; 206398686cd2SShayne Chen 206498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_RVSR1(band_idx)); 206598686cd2SShayne Chen mib->rx_vec_queue_overflow_drop_cnt += cnt; 206698686cd2SShayne Chen 206798686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR1(band_idx)); 206898686cd2SShayne Chen mib->rx_ba_cnt += cnt; 206998686cd2SShayne Chen 207098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR0(band_idx)); 207198686cd2SShayne Chen mib->tx_bf_ebf_ppdu_cnt += cnt; 207298686cd2SShayne Chen 207398686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR1(band_idx)); 207498686cd2SShayne Chen mib->tx_bf_ibf_ppdu_cnt += cnt; 207598686cd2SShayne Chen 207698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR2(band_idx)); 207798686cd2SShayne Chen mib->tx_mu_bf_cnt += cnt; 207898686cd2SShayne Chen 207998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR5(band_idx)); 208098686cd2SShayne Chen mib->tx_mu_mpdu_cnt += cnt; 208198686cd2SShayne Chen 208298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR6(band_idx)); 208398686cd2SShayne Chen mib->tx_mu_acked_mpdu_cnt += cnt; 208498686cd2SShayne Chen 208598686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_TSCR7(band_idx)); 208698686cd2SShayne Chen mib->tx_su_acked_mpdu_cnt += cnt; 208798686cd2SShayne Chen 208898686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR3(band_idx)); 208998686cd2SShayne Chen mib->tx_bf_rx_fb_ht_cnt += cnt; 209098686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 209198686cd2SShayne Chen 209298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR4(band_idx)); 209398686cd2SShayne Chen mib->tx_bf_rx_fb_vht_cnt += cnt; 209498686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 209598686cd2SShayne Chen 209698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR5(band_idx)); 209798686cd2SShayne Chen mib->tx_bf_rx_fb_he_cnt += cnt; 209898686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 209998686cd2SShayne Chen 210098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR6(band_idx)); 210198686cd2SShayne Chen mib->tx_bf_rx_fb_eht_cnt += cnt; 210298686cd2SShayne Chen mib->tx_bf_rx_fb_all_cnt += cnt; 210398686cd2SShayne Chen 210498686cd2SShayne Chen cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(band_idx)); 210598686cd2SShayne Chen mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt); 210698686cd2SShayne Chen mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt); 210798686cd2SShayne Chen mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt); 210898686cd2SShayne Chen 210998686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR7(band_idx)); 211098686cd2SShayne Chen mib->tx_bf_fb_trig_cnt += cnt; 211198686cd2SShayne Chen 211298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BSCR17(band_idx)); 211398686cd2SShayne Chen mib->tx_bf_fb_cpl_cnt += cnt; 211498686cd2SShayne Chen 211598686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { 211698686cd2SShayne Chen cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); 211798686cd2SShayne Chen mib->tx_amsdu[i] += cnt; 211898686cd2SShayne Chen mib->tx_amsdu_cnt += cnt; 211998686cd2SShayne Chen } 212098686cd2SShayne Chen 212198686cd2SShayne Chen /* rts count */ 212298686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR5(band_idx)); 212398686cd2SShayne Chen mib->rts_cnt += cnt; 212498686cd2SShayne Chen 212598686cd2SShayne Chen /* rts retry count */ 212698686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR6(band_idx)); 212798686cd2SShayne Chen mib->rts_retries_cnt += cnt; 212898686cd2SShayne Chen 212998686cd2SShayne Chen /* ba miss count */ 213098686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BTSCR0(band_idx)); 213198686cd2SShayne Chen mib->ba_miss_cnt += cnt; 213298686cd2SShayne Chen 213398686cd2SShayne Chen /* ack fail count */ 213498686cd2SShayne Chen cnt = mt76_rr(dev, MT_MIB_BFTFCR(band_idx)); 213598686cd2SShayne Chen mib->ack_fail_cnt += cnt; 213698686cd2SShayne Chen 213798686cd2SShayne Chen for (i = 0; i < 16; i++) { 213898686cd2SShayne Chen cnt = mt76_rr(dev, MT_TX_AGG_CNT(band_idx, i)); 213998686cd2SShayne Chen phy->mt76->aggr_stats[i] += cnt; 214098686cd2SShayne Chen } 214198686cd2SShayne Chen } 214298686cd2SShayne Chen 214398686cd2SShayne Chen void mt7996_mac_sta_rc_work(struct work_struct *work) 214498686cd2SShayne Chen { 214598686cd2SShayne Chen struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work); 214698686cd2SShayne Chen struct ieee80211_sta *sta; 214798686cd2SShayne Chen struct ieee80211_vif *vif; 214898686cd2SShayne Chen struct mt7996_sta *msta; 214998686cd2SShayne Chen u32 changed; 215098686cd2SShayne Chen LIST_HEAD(list); 215198686cd2SShayne Chen 2152ea0f3867SLorenzo Bianconi spin_lock_bh(&dev->mt76.sta_poll_lock); 215398686cd2SShayne Chen list_splice_init(&dev->sta_rc_list, &list); 215498686cd2SShayne Chen 215598686cd2SShayne Chen while (!list_empty(&list)) { 215698686cd2SShayne Chen msta = list_first_entry(&list, struct mt7996_sta, rc_list); 215798686cd2SShayne Chen list_del_init(&msta->rc_list); 215898686cd2SShayne Chen changed = msta->changed; 215998686cd2SShayne Chen msta->changed = 0; 2160ea0f3867SLorenzo Bianconi spin_unlock_bh(&dev->mt76.sta_poll_lock); 216198686cd2SShayne Chen 216298686cd2SShayne Chen sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); 216398686cd2SShayne Chen vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); 216498686cd2SShayne Chen 216598686cd2SShayne Chen if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | 216698686cd2SShayne Chen IEEE80211_RC_NSS_CHANGED | 216798686cd2SShayne Chen IEEE80211_RC_BW_CHANGED)) 216898686cd2SShayne Chen mt7996_mcu_add_rate_ctrl(dev, vif, sta, true); 216998686cd2SShayne Chen 217098686cd2SShayne Chen /* TODO: smps change */ 217198686cd2SShayne Chen 2172ea0f3867SLorenzo Bianconi spin_lock_bh(&dev->mt76.sta_poll_lock); 217398686cd2SShayne Chen } 217498686cd2SShayne Chen 2175ea0f3867SLorenzo Bianconi spin_unlock_bh(&dev->mt76.sta_poll_lock); 217698686cd2SShayne Chen } 217798686cd2SShayne Chen 217898686cd2SShayne Chen void mt7996_mac_work(struct work_struct *work) 217998686cd2SShayne Chen { 218098686cd2SShayne Chen struct mt7996_phy *phy; 218198686cd2SShayne Chen struct mt76_phy *mphy; 218298686cd2SShayne Chen 218398686cd2SShayne Chen mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, 218498686cd2SShayne Chen mac_work.work); 218598686cd2SShayne Chen phy = mphy->priv; 218698686cd2SShayne Chen 218798686cd2SShayne Chen mutex_lock(&mphy->dev->mutex); 218898686cd2SShayne Chen 218998686cd2SShayne Chen mt76_update_survey(mphy); 219098686cd2SShayne Chen if (++mphy->mac_work_count == 5) { 219198686cd2SShayne Chen mphy->mac_work_count = 0; 219298686cd2SShayne Chen 219398686cd2SShayne Chen mt7996_mac_update_stats(phy); 219498686cd2SShayne Chen } 219598686cd2SShayne Chen 219698686cd2SShayne Chen mutex_unlock(&mphy->dev->mutex); 219798686cd2SShayne Chen 219898686cd2SShayne Chen mt76_tx_status_check(mphy->dev, false); 219998686cd2SShayne Chen 220098686cd2SShayne Chen ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, 220198686cd2SShayne Chen MT7996_WATCHDOG_TIME); 220298686cd2SShayne Chen } 220398686cd2SShayne Chen 220498686cd2SShayne Chen static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy) 220598686cd2SShayne Chen { 220698686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 220798686cd2SShayne Chen 220898686cd2SShayne Chen if (phy->rdd_state & BIT(0)) 220998686cd2SShayne Chen mt7996_mcu_rdd_cmd(dev, RDD_STOP, 0, 221098686cd2SShayne Chen MT_RX_SEL0, 0); 221198686cd2SShayne Chen if (phy->rdd_state & BIT(1)) 221298686cd2SShayne Chen mt7996_mcu_rdd_cmd(dev, RDD_STOP, 1, 221398686cd2SShayne Chen MT_RX_SEL0, 0); 221498686cd2SShayne Chen } 221598686cd2SShayne Chen 221698686cd2SShayne Chen static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int chain) 221798686cd2SShayne Chen { 221898686cd2SShayne Chen int err, region; 221998686cd2SShayne Chen 222098686cd2SShayne Chen switch (dev->mt76.region) { 222198686cd2SShayne Chen case NL80211_DFS_ETSI: 222298686cd2SShayne Chen region = 0; 222398686cd2SShayne Chen break; 222498686cd2SShayne Chen case NL80211_DFS_JP: 222598686cd2SShayne Chen region = 2; 222698686cd2SShayne Chen break; 222798686cd2SShayne Chen case NL80211_DFS_FCC: 222898686cd2SShayne Chen default: 222998686cd2SShayne Chen region = 1; 223098686cd2SShayne Chen break; 223198686cd2SShayne Chen } 223298686cd2SShayne Chen 223398686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_START, chain, 223498686cd2SShayne Chen MT_RX_SEL0, region); 223598686cd2SShayne Chen if (err < 0) 223698686cd2SShayne Chen return err; 223798686cd2SShayne Chen 223898686cd2SShayne Chen return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, chain, 223998686cd2SShayne Chen MT_RX_SEL0, 1); 224098686cd2SShayne Chen } 224198686cd2SShayne Chen 224298686cd2SShayne Chen static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy) 224398686cd2SShayne Chen { 224498686cd2SShayne Chen struct cfg80211_chan_def *chandef = &phy->mt76->chandef; 224598686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 224698686cd2SShayne Chen u8 band_idx = phy->mt76->band_idx; 224798686cd2SShayne Chen int err; 224898686cd2SShayne Chen 224998686cd2SShayne Chen /* start CAC */ 225098686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_START, band_idx, 225198686cd2SShayne Chen MT_RX_SEL0, 0); 225298686cd2SShayne Chen if (err < 0) 225398686cd2SShayne Chen return err; 225498686cd2SShayne Chen 225598686cd2SShayne Chen err = mt7996_dfs_start_rdd(dev, band_idx); 225698686cd2SShayne Chen if (err < 0) 225798686cd2SShayne Chen return err; 225898686cd2SShayne Chen 225998686cd2SShayne Chen phy->rdd_state |= BIT(band_idx); 226098686cd2SShayne Chen 226198686cd2SShayne Chen if (chandef->width == NL80211_CHAN_WIDTH_160 || 226298686cd2SShayne Chen chandef->width == NL80211_CHAN_WIDTH_80P80) { 226398686cd2SShayne Chen err = mt7996_dfs_start_rdd(dev, 1); 226498686cd2SShayne Chen if (err < 0) 226598686cd2SShayne Chen return err; 226698686cd2SShayne Chen 226798686cd2SShayne Chen phy->rdd_state |= BIT(1); 226898686cd2SShayne Chen } 226998686cd2SShayne Chen 227098686cd2SShayne Chen return 0; 227198686cd2SShayne Chen } 227298686cd2SShayne Chen 227398686cd2SShayne Chen static int 227498686cd2SShayne Chen mt7996_dfs_init_radar_specs(struct mt7996_phy *phy) 227598686cd2SShayne Chen { 227698686cd2SShayne Chen const struct mt7996_dfs_radar_spec *radar_specs; 227798686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 227898686cd2SShayne Chen int err, i; 227998686cd2SShayne Chen 228098686cd2SShayne Chen switch (dev->mt76.region) { 228198686cd2SShayne Chen case NL80211_DFS_FCC: 228298686cd2SShayne Chen radar_specs = &fcc_radar_specs; 228398686cd2SShayne Chen err = mt7996_mcu_set_fcc5_lpn(dev, 8); 228498686cd2SShayne Chen if (err < 0) 228598686cd2SShayne Chen return err; 228698686cd2SShayne Chen break; 228798686cd2SShayne Chen case NL80211_DFS_ETSI: 228898686cd2SShayne Chen radar_specs = &etsi_radar_specs; 228998686cd2SShayne Chen break; 229098686cd2SShayne Chen case NL80211_DFS_JP: 229198686cd2SShayne Chen radar_specs = &jp_radar_specs; 229298686cd2SShayne Chen break; 229398686cd2SShayne Chen default: 229498686cd2SShayne Chen return -EINVAL; 229598686cd2SShayne Chen } 229698686cd2SShayne Chen 229798686cd2SShayne Chen for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) { 229898686cd2SShayne Chen err = mt7996_mcu_set_radar_th(dev, i, 229998686cd2SShayne Chen &radar_specs->radar_pattern[i]); 230098686cd2SShayne Chen if (err < 0) 230198686cd2SShayne Chen return err; 230298686cd2SShayne Chen } 230398686cd2SShayne Chen 230498686cd2SShayne Chen return mt7996_mcu_set_pulse_th(dev, &radar_specs->pulse_th); 230598686cd2SShayne Chen } 230698686cd2SShayne Chen 230798686cd2SShayne Chen int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy) 230898686cd2SShayne Chen { 230998686cd2SShayne Chen struct mt7996_dev *dev = phy->dev; 231098686cd2SShayne Chen enum mt76_dfs_state dfs_state, prev_state; 231198686cd2SShayne Chen int err; 231298686cd2SShayne Chen 231398686cd2SShayne Chen prev_state = phy->mt76->dfs_state; 231498686cd2SShayne Chen dfs_state = mt76_phy_dfs_state(phy->mt76); 231598686cd2SShayne Chen 231698686cd2SShayne Chen if (prev_state == dfs_state) 231798686cd2SShayne Chen return 0; 231898686cd2SShayne Chen 231998686cd2SShayne Chen if (prev_state == MT_DFS_STATE_UNKNOWN) 232098686cd2SShayne Chen mt7996_dfs_stop_radar_detector(phy); 232198686cd2SShayne Chen 232298686cd2SShayne Chen if (dfs_state == MT_DFS_STATE_DISABLED) 232398686cd2SShayne Chen goto stop; 232498686cd2SShayne Chen 232598686cd2SShayne Chen if (prev_state <= MT_DFS_STATE_DISABLED) { 232698686cd2SShayne Chen err = mt7996_dfs_init_radar_specs(phy); 232798686cd2SShayne Chen if (err < 0) 232898686cd2SShayne Chen return err; 232998686cd2SShayne Chen 233098686cd2SShayne Chen err = mt7996_dfs_start_radar_detector(phy); 233198686cd2SShayne Chen if (err < 0) 233298686cd2SShayne Chen return err; 233398686cd2SShayne Chen 233498686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_CAC; 233598686cd2SShayne Chen } 233698686cd2SShayne Chen 233798686cd2SShayne Chen if (dfs_state == MT_DFS_STATE_CAC) 233898686cd2SShayne Chen return 0; 233998686cd2SShayne Chen 234098686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_END, 234198686cd2SShayne Chen phy->mt76->band_idx, MT_RX_SEL0, 0); 234298686cd2SShayne Chen if (err < 0) { 234398686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; 234498686cd2SShayne Chen return err; 234598686cd2SShayne Chen } 234698686cd2SShayne Chen 234798686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_ACTIVE; 234898686cd2SShayne Chen return 0; 234998686cd2SShayne Chen 235098686cd2SShayne Chen stop: 235198686cd2SShayne Chen err = mt7996_mcu_rdd_cmd(dev, RDD_NORMAL_START, 235298686cd2SShayne Chen phy->mt76->band_idx, MT_RX_SEL0, 0); 235398686cd2SShayne Chen if (err < 0) 235498686cd2SShayne Chen return err; 235598686cd2SShayne Chen 235698686cd2SShayne Chen mt7996_dfs_stop_radar_detector(phy); 235798686cd2SShayne Chen phy->mt76->dfs_state = MT_DFS_STATE_DISABLED; 235898686cd2SShayne Chen 235998686cd2SShayne Chen return 0; 236098686cd2SShayne Chen } 236198686cd2SShayne Chen 236298686cd2SShayne Chen static int 236398686cd2SShayne Chen mt7996_mac_twt_duration_align(int duration) 236498686cd2SShayne Chen { 236598686cd2SShayne Chen return duration << 8; 236698686cd2SShayne Chen } 236798686cd2SShayne Chen 236898686cd2SShayne Chen static u64 236998686cd2SShayne Chen mt7996_mac_twt_sched_list_add(struct mt7996_dev *dev, 237098686cd2SShayne Chen struct mt7996_twt_flow *flow) 237198686cd2SShayne Chen { 237298686cd2SShayne Chen struct mt7996_twt_flow *iter, *iter_next; 237398686cd2SShayne Chen u32 duration = flow->duration << 8; 237498686cd2SShayne Chen u64 start_tsf; 237598686cd2SShayne Chen 237698686cd2SShayne Chen iter = list_first_entry_or_null(&dev->twt_list, 237798686cd2SShayne Chen struct mt7996_twt_flow, list); 237898686cd2SShayne Chen if (!iter || !iter->sched || iter->start_tsf > duration) { 237998686cd2SShayne Chen /* add flow as first entry in the list */ 238098686cd2SShayne Chen list_add(&flow->list, &dev->twt_list); 238198686cd2SShayne Chen return 0; 238298686cd2SShayne Chen } 238398686cd2SShayne Chen 238498686cd2SShayne Chen list_for_each_entry_safe(iter, iter_next, &dev->twt_list, list) { 238598686cd2SShayne Chen start_tsf = iter->start_tsf + 238698686cd2SShayne Chen mt7996_mac_twt_duration_align(iter->duration); 238798686cd2SShayne Chen if (list_is_last(&iter->list, &dev->twt_list)) 238898686cd2SShayne Chen break; 238998686cd2SShayne Chen 239098686cd2SShayne Chen if (!iter_next->sched || 239198686cd2SShayne Chen iter_next->start_tsf > start_tsf + duration) { 239298686cd2SShayne Chen list_add(&flow->list, &iter->list); 239398686cd2SShayne Chen goto out; 239498686cd2SShayne Chen } 239598686cd2SShayne Chen } 239698686cd2SShayne Chen 239798686cd2SShayne Chen /* add flow as last entry in the list */ 239898686cd2SShayne Chen list_add_tail(&flow->list, &dev->twt_list); 239998686cd2SShayne Chen out: 240098686cd2SShayne Chen return start_tsf; 240198686cd2SShayne Chen } 240298686cd2SShayne Chen 240398686cd2SShayne Chen static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt) 240498686cd2SShayne Chen { 240598686cd2SShayne Chen struct ieee80211_twt_params *twt_agrt; 240698686cd2SShayne Chen u64 interval, duration; 240798686cd2SShayne Chen u16 mantissa; 240898686cd2SShayne Chen u8 exp; 240998686cd2SShayne Chen 241098686cd2SShayne Chen /* only individual agreement supported */ 241198686cd2SShayne Chen if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) 241298686cd2SShayne Chen return -EOPNOTSUPP; 241398686cd2SShayne Chen 241498686cd2SShayne Chen /* only 256us unit supported */ 241598686cd2SShayne Chen if (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) 241698686cd2SShayne Chen return -EOPNOTSUPP; 241798686cd2SShayne Chen 241898686cd2SShayne Chen twt_agrt = (struct ieee80211_twt_params *)twt->params; 241998686cd2SShayne Chen 242098686cd2SShayne Chen /* explicit agreement not supported */ 242198686cd2SShayne Chen if (!(twt_agrt->req_type & cpu_to_le16(IEEE80211_TWT_REQTYPE_IMPLICIT))) 242298686cd2SShayne Chen return -EOPNOTSUPP; 242398686cd2SShayne Chen 242498686cd2SShayne Chen exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, 242598686cd2SShayne Chen le16_to_cpu(twt_agrt->req_type)); 242698686cd2SShayne Chen mantissa = le16_to_cpu(twt_agrt->mantissa); 242798686cd2SShayne Chen duration = twt_agrt->min_twt_dur << 8; 242898686cd2SShayne Chen 242998686cd2SShayne Chen interval = (u64)mantissa << exp; 243098686cd2SShayne Chen if (interval < duration) 243198686cd2SShayne Chen return -EOPNOTSUPP; 243298686cd2SShayne Chen 243398686cd2SShayne Chen return 0; 243498686cd2SShayne Chen } 243598686cd2SShayne Chen 243698686cd2SShayne Chen void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw, 243798686cd2SShayne Chen struct ieee80211_sta *sta, 243898686cd2SShayne Chen struct ieee80211_twt_setup *twt) 243998686cd2SShayne Chen { 244098686cd2SShayne Chen enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT; 244198686cd2SShayne Chen struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; 244298686cd2SShayne Chen struct ieee80211_twt_params *twt_agrt = (void *)twt->params; 244398686cd2SShayne Chen u16 req_type = le16_to_cpu(twt_agrt->req_type); 244498686cd2SShayne Chen enum ieee80211_twt_setup_cmd sta_setup_cmd; 244598686cd2SShayne Chen struct mt7996_dev *dev = mt7996_hw_dev(hw); 244698686cd2SShayne Chen struct mt7996_twt_flow *flow; 244798686cd2SShayne Chen int flowid, table_id; 244898686cd2SShayne Chen u8 exp; 244998686cd2SShayne Chen 245098686cd2SShayne Chen if (mt7996_mac_check_twt_req(twt)) 245198686cd2SShayne Chen goto out; 245298686cd2SShayne Chen 245398686cd2SShayne Chen mutex_lock(&dev->mt76.mutex); 245498686cd2SShayne Chen 245598686cd2SShayne Chen if (dev->twt.n_agrt == MT7996_MAX_TWT_AGRT) 245698686cd2SShayne Chen goto unlock; 245798686cd2SShayne Chen 245898686cd2SShayne Chen if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) 245998686cd2SShayne Chen goto unlock; 246098686cd2SShayne Chen 246198686cd2SShayne Chen flowid = ffs(~msta->twt.flowid_mask) - 1; 246298686cd2SShayne Chen le16p_replace_bits(&twt_agrt->req_type, flowid, 246398686cd2SShayne Chen IEEE80211_TWT_REQTYPE_FLOWID); 246498686cd2SShayne Chen 246598686cd2SShayne Chen table_id = ffs(~dev->twt.table_mask) - 1; 246698686cd2SShayne Chen exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); 246798686cd2SShayne Chen sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type); 246898686cd2SShayne Chen 246998686cd2SShayne Chen flow = &msta->twt.flow[flowid]; 247098686cd2SShayne Chen memset(flow, 0, sizeof(*flow)); 247198686cd2SShayne Chen INIT_LIST_HEAD(&flow->list); 247298686cd2SShayne Chen flow->wcid = msta->wcid.idx; 247398686cd2SShayne Chen flow->table_id = table_id; 247498686cd2SShayne Chen flow->id = flowid; 247598686cd2SShayne Chen flow->duration = twt_agrt->min_twt_dur; 247698686cd2SShayne Chen flow->mantissa = twt_agrt->mantissa; 247798686cd2SShayne Chen flow->exp = exp; 247898686cd2SShayne Chen flow->protection = !!(req_type & IEEE80211_TWT_REQTYPE_PROTECTION); 247998686cd2SShayne Chen flow->flowtype = !!(req_type & IEEE80211_TWT_REQTYPE_FLOWTYPE); 248098686cd2SShayne Chen flow->trigger = !!(req_type & IEEE80211_TWT_REQTYPE_TRIGGER); 248198686cd2SShayne Chen 248298686cd2SShayne Chen if (sta_setup_cmd == TWT_SETUP_CMD_REQUEST || 248398686cd2SShayne Chen sta_setup_cmd == TWT_SETUP_CMD_SUGGEST) { 248498686cd2SShayne Chen u64 interval = (u64)le16_to_cpu(twt_agrt->mantissa) << exp; 248598686cd2SShayne Chen u64 flow_tsf, curr_tsf; 248698686cd2SShayne Chen u32 rem; 248798686cd2SShayne Chen 248898686cd2SShayne Chen flow->sched = true; 248998686cd2SShayne Chen flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow); 249098686cd2SShayne Chen curr_tsf = __mt7996_get_tsf(hw, msta->vif); 249198686cd2SShayne Chen div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem); 249298686cd2SShayne Chen flow_tsf = curr_tsf + interval - rem; 249398686cd2SShayne Chen twt_agrt->twt = cpu_to_le64(flow_tsf); 249498686cd2SShayne Chen } else { 249598686cd2SShayne Chen list_add_tail(&flow->list, &dev->twt_list); 249698686cd2SShayne Chen } 249798686cd2SShayne Chen flow->tsf = le64_to_cpu(twt_agrt->twt); 249898686cd2SShayne Chen 249998686cd2SShayne Chen if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD)) 250098686cd2SShayne Chen goto unlock; 250198686cd2SShayne Chen 250298686cd2SShayne Chen setup_cmd = TWT_SETUP_CMD_ACCEPT; 250398686cd2SShayne Chen dev->twt.table_mask |= BIT(table_id); 250498686cd2SShayne Chen msta->twt.flowid_mask |= BIT(flowid); 250598686cd2SShayne Chen dev->twt.n_agrt++; 250698686cd2SShayne Chen 250798686cd2SShayne Chen unlock: 250898686cd2SShayne Chen mutex_unlock(&dev->mt76.mutex); 250998686cd2SShayne Chen out: 251098686cd2SShayne Chen le16p_replace_bits(&twt_agrt->req_type, setup_cmd, 251198686cd2SShayne Chen IEEE80211_TWT_REQTYPE_SETUP_CMD); 251298686cd2SShayne Chen twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | 251398686cd2SShayne Chen (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); 251498686cd2SShayne Chen } 251598686cd2SShayne Chen 251698686cd2SShayne Chen void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev, 251798686cd2SShayne Chen struct mt7996_sta *msta, 251898686cd2SShayne Chen u8 flowid) 251998686cd2SShayne Chen { 252098686cd2SShayne Chen struct mt7996_twt_flow *flow; 252198686cd2SShayne Chen 252298686cd2SShayne Chen lockdep_assert_held(&dev->mt76.mutex); 252398686cd2SShayne Chen 252498686cd2SShayne Chen if (flowid >= ARRAY_SIZE(msta->twt.flow)) 252598686cd2SShayne Chen return; 252698686cd2SShayne Chen 252798686cd2SShayne Chen if (!(msta->twt.flowid_mask & BIT(flowid))) 252898686cd2SShayne Chen return; 252998686cd2SShayne Chen 253098686cd2SShayne Chen flow = &msta->twt.flow[flowid]; 253198686cd2SShayne Chen if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, 253298686cd2SShayne Chen MCU_TWT_AGRT_DELETE)) 253398686cd2SShayne Chen return; 253498686cd2SShayne Chen 253598686cd2SShayne Chen list_del_init(&flow->list); 253698686cd2SShayne Chen msta->twt.flowid_mask &= ~BIT(flowid); 253798686cd2SShayne Chen dev->twt.table_mask &= ~BIT(flow->table_id); 253898686cd2SShayne Chen dev->twt.n_agrt--; 253998686cd2SShayne Chen } 2540