16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC 26c92544dSBjoern A. Zeeb /* Copyright (C) 2020 MediaTek Inc. */ 36c92544dSBjoern A. Zeeb 46c92544dSBjoern A. Zeeb #include <linux/etherdevice.h> 56c92544dSBjoern A. Zeeb #include <linux/timekeeping.h> 66c92544dSBjoern A. Zeeb #if defined(__FreeBSD__) 76c92544dSBjoern A. Zeeb #include <linux/delay.h> 86c92544dSBjoern A. Zeeb #include <linux/math64.h> 96c92544dSBjoern A. Zeeb #endif 10*cbb3ec25SBjoern A. Zeeb #include "coredump.h" 116c92544dSBjoern A. Zeeb #include "mt7915.h" 126c92544dSBjoern A. Zeeb #include "../dma.h" 136c92544dSBjoern A. Zeeb #include "mac.h" 146c92544dSBjoern A. Zeeb #include "mcu.h" 156c92544dSBjoern A. Zeeb 16*cbb3ec25SBjoern A. Zeeb #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2) 176c92544dSBjoern A. Zeeb 186c92544dSBjoern A. Zeeb static const struct mt7915_dfs_radar_spec etsi_radar_specs = { 196c92544dSBjoern A. Zeeb .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 206c92544dSBjoern A. Zeeb .radar_pattern = { 216c92544dSBjoern A. Zeeb [5] = { 1, 0, 6, 32, 28, 0, 990, 5010, 17, 1, 1 }, 226c92544dSBjoern A. Zeeb [6] = { 1, 0, 9, 32, 28, 0, 615, 5010, 27, 1, 1 }, 236c92544dSBjoern A. Zeeb [7] = { 1, 0, 15, 32, 28, 0, 240, 445, 27, 1, 1 }, 246c92544dSBjoern A. Zeeb [8] = { 1, 0, 12, 32, 28, 0, 240, 510, 42, 1, 1 }, 256c92544dSBjoern A. Zeeb [9] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 12, 32, 28, { }, 126 }, 266c92544dSBjoern A. Zeeb [10] = { 1, 1, 0, 0, 0, 0, 2490, 3343, 14, 0, 0, 15, 32, 24, { }, 126 }, 276c92544dSBjoern A. Zeeb [11] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 18, 32, 28, { }, 54 }, 286c92544dSBjoern A. Zeeb [12] = { 1, 1, 0, 0, 0, 0, 823, 2510, 14, 0, 0, 27, 32, 24, { }, 54 }, 296c92544dSBjoern A. Zeeb }, 306c92544dSBjoern A. Zeeb }; 316c92544dSBjoern A. Zeeb 326c92544dSBjoern A. Zeeb static const struct mt7915_dfs_radar_spec fcc_radar_specs = { 336c92544dSBjoern A. Zeeb .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 346c92544dSBjoern A. Zeeb .radar_pattern = { 356c92544dSBjoern A. Zeeb [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, 366c92544dSBjoern A. Zeeb [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, 376c92544dSBjoern A. Zeeb [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, 386c92544dSBjoern A. Zeeb [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, 396c92544dSBjoern A. Zeeb [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, 406c92544dSBjoern A. Zeeb }, 416c92544dSBjoern A. Zeeb }; 426c92544dSBjoern A. Zeeb 436c92544dSBjoern A. Zeeb static const struct mt7915_dfs_radar_spec jp_radar_specs = { 446c92544dSBjoern A. Zeeb .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, 456c92544dSBjoern A. Zeeb .radar_pattern = { 466c92544dSBjoern A. Zeeb [0] = { 1, 0, 8, 32, 28, 0, 508, 3076, 13, 1, 1 }, 476c92544dSBjoern A. Zeeb [1] = { 1, 0, 12, 32, 28, 0, 140, 240, 17, 1, 1 }, 486c92544dSBjoern A. Zeeb [2] = { 1, 0, 8, 32, 28, 0, 190, 510, 22, 1, 1 }, 496c92544dSBjoern A. Zeeb [3] = { 1, 0, 6, 32, 28, 0, 190, 510, 32, 1, 1 }, 506c92544dSBjoern A. Zeeb [4] = { 1, 0, 9, 255, 28, 0, 323, 343, 13, 1, 32 }, 516c92544dSBjoern A. Zeeb [13] = { 1, 0, 7, 32, 28, 0, 3836, 3856, 14, 1, 1 }, 526c92544dSBjoern A. Zeeb [14] = { 1, 0, 6, 32, 28, 0, 615, 5010, 110, 1, 1 }, 536c92544dSBjoern A. Zeeb [15] = { 1, 1, 0, 0, 0, 0, 15, 5010, 110, 0, 0, 12, 32, 28 }, 546c92544dSBjoern A. Zeeb }, 556c92544dSBjoern A. Zeeb }; 566c92544dSBjoern A. Zeeb 576c92544dSBjoern A. Zeeb static struct mt76_wcid *mt7915_rx_get_wcid(struct mt7915_dev *dev, 586c92544dSBjoern A. Zeeb u16 idx, bool unicast) 596c92544dSBjoern A. Zeeb { 606c92544dSBjoern A. Zeeb struct mt7915_sta *sta; 616c92544dSBjoern A. Zeeb struct mt76_wcid *wcid; 626c92544dSBjoern A. Zeeb 636c92544dSBjoern A. Zeeb if (idx >= ARRAY_SIZE(dev->mt76.wcid)) 646c92544dSBjoern A. Zeeb return NULL; 656c92544dSBjoern A. Zeeb 666c92544dSBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[idx]); 676c92544dSBjoern A. Zeeb if (unicast || !wcid) 686c92544dSBjoern A. Zeeb return wcid; 696c92544dSBjoern A. Zeeb 706c92544dSBjoern A. Zeeb if (!wcid->sta) 716c92544dSBjoern A. Zeeb return NULL; 726c92544dSBjoern A. Zeeb 736c92544dSBjoern A. Zeeb sta = container_of(wcid, struct mt7915_sta, wcid); 746c92544dSBjoern A. Zeeb if (!sta->vif) 756c92544dSBjoern A. Zeeb return NULL; 766c92544dSBjoern A. Zeeb 776c92544dSBjoern A. Zeeb return &sta->vif->sta.wcid; 786c92544dSBjoern A. Zeeb } 796c92544dSBjoern A. Zeeb 806c92544dSBjoern A. Zeeb bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask) 816c92544dSBjoern A. Zeeb { 826c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, 836c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); 846c92544dSBjoern A. Zeeb 856c92544dSBjoern A. Zeeb return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 866c92544dSBjoern A. Zeeb 0, 5000); 876c92544dSBjoern A. Zeeb } 886c92544dSBjoern A. Zeeb 896c92544dSBjoern A. Zeeb u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw) 906c92544dSBjoern A. Zeeb { 916c92544dSBjoern A. Zeeb mt76_wr(dev, MT_WTBLON_TOP_WDUCR, 926c92544dSBjoern A. Zeeb FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7))); 936c92544dSBjoern A. Zeeb 946c92544dSBjoern A. Zeeb return MT_WTBL_LMAC_OFFS(wcid, dw); 956c92544dSBjoern A. Zeeb } 966c92544dSBjoern A. Zeeb 976c92544dSBjoern A. Zeeb static void mt7915_mac_sta_poll(struct mt7915_dev *dev) 986c92544dSBjoern A. Zeeb { 996c92544dSBjoern A. Zeeb static const u8 ac_to_tid[] = { 1006c92544dSBjoern A. Zeeb [IEEE80211_AC_BE] = 0, 1016c92544dSBjoern A. Zeeb [IEEE80211_AC_BK] = 1, 1026c92544dSBjoern A. Zeeb [IEEE80211_AC_VI] = 4, 1036c92544dSBjoern A. Zeeb [IEEE80211_AC_VO] = 6 1046c92544dSBjoern A. Zeeb }; 1056c92544dSBjoern A. Zeeb struct ieee80211_sta *sta; 1066c92544dSBjoern A. Zeeb struct mt7915_sta *msta; 1076c92544dSBjoern A. Zeeb struct rate_info *rate; 1086c92544dSBjoern A. Zeeb u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; 1096c92544dSBjoern A. Zeeb #if defined(__linux__) 1106c92544dSBjoern A. Zeeb LIST_HEAD(sta_poll_list); 1116c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__) 1126c92544dSBjoern A. Zeeb LINUX_LIST_HEAD(sta_poll_list); 1136c92544dSBjoern A. Zeeb #endif 1146c92544dSBjoern A. Zeeb int i; 1156c92544dSBjoern A. Zeeb 116*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 117*cbb3ec25SBjoern A. Zeeb list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); 118*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 1196c92544dSBjoern A. Zeeb 1206c92544dSBjoern A. Zeeb rcu_read_lock(); 1216c92544dSBjoern A. Zeeb 1226c92544dSBjoern A. Zeeb while (true) { 1236c92544dSBjoern A. Zeeb bool clear = false; 1246c92544dSBjoern A. Zeeb u32 addr, val; 1256c92544dSBjoern A. Zeeb u16 idx; 126*cbb3ec25SBjoern A. Zeeb s8 rssi[4]; 1276c92544dSBjoern A. Zeeb u8 bw; 1286c92544dSBjoern A. Zeeb 129*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 1306c92544dSBjoern A. Zeeb if (list_empty(&sta_poll_list)) { 131*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 1326c92544dSBjoern A. Zeeb break; 1336c92544dSBjoern A. Zeeb } 1346c92544dSBjoern A. Zeeb msta = list_first_entry(&sta_poll_list, 135*cbb3ec25SBjoern A. Zeeb struct mt7915_sta, wcid.poll_list); 136*cbb3ec25SBjoern A. Zeeb list_del_init(&msta->wcid.poll_list); 137*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 1386c92544dSBjoern A. Zeeb 1396c92544dSBjoern A. Zeeb idx = msta->wcid.idx; 140*cbb3ec25SBjoern A. Zeeb 141*cbb3ec25SBjoern A. Zeeb /* refresh peer's airtime reporting */ 1426c92544dSBjoern A. Zeeb addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 20); 1436c92544dSBjoern A. Zeeb 1446c92544dSBjoern A. Zeeb for (i = 0; i < IEEE80211_NUM_ACS; i++) { 1456c92544dSBjoern A. Zeeb u32 tx_last = msta->airtime_ac[i]; 1466c92544dSBjoern A. Zeeb u32 rx_last = msta->airtime_ac[i + 4]; 1476c92544dSBjoern A. Zeeb 1486c92544dSBjoern A. Zeeb msta->airtime_ac[i] = mt76_rr(dev, addr); 1496c92544dSBjoern A. Zeeb msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4); 1506c92544dSBjoern A. Zeeb 1516c92544dSBjoern A. Zeeb tx_time[i] = msta->airtime_ac[i] - tx_last; 1526c92544dSBjoern A. Zeeb rx_time[i] = msta->airtime_ac[i + 4] - rx_last; 1536c92544dSBjoern A. Zeeb 1546c92544dSBjoern A. Zeeb if ((tx_last | rx_last) & BIT(30)) 1556c92544dSBjoern A. Zeeb clear = true; 1566c92544dSBjoern A. Zeeb 1576c92544dSBjoern A. Zeeb addr += 8; 1586c92544dSBjoern A. Zeeb } 1596c92544dSBjoern A. Zeeb 1606c92544dSBjoern A. Zeeb if (clear) { 1616c92544dSBjoern A. Zeeb mt7915_mac_wtbl_update(dev, idx, 1626c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 1636c92544dSBjoern A. Zeeb memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); 1646c92544dSBjoern A. Zeeb } 1656c92544dSBjoern A. Zeeb 1666c92544dSBjoern A. Zeeb if (!msta->wcid.sta) 1676c92544dSBjoern A. Zeeb continue; 1686c92544dSBjoern A. Zeeb 1696c92544dSBjoern A. Zeeb sta = container_of((void *)msta, struct ieee80211_sta, 1706c92544dSBjoern A. Zeeb drv_priv); 1716c92544dSBjoern A. Zeeb for (i = 0; i < IEEE80211_NUM_ACS; i++) { 172*cbb3ec25SBjoern A. Zeeb u8 queue = mt76_connac_lmac_mapping(i); 173*cbb3ec25SBjoern A. Zeeb u32 tx_cur = tx_time[queue]; 174*cbb3ec25SBjoern A. Zeeb u32 rx_cur = rx_time[queue]; 1756c92544dSBjoern A. Zeeb u8 tid = ac_to_tid[i]; 1766c92544dSBjoern A. Zeeb 1776c92544dSBjoern A. Zeeb if (!tx_cur && !rx_cur) 1786c92544dSBjoern A. Zeeb continue; 1796c92544dSBjoern A. Zeeb 1806c92544dSBjoern A. Zeeb ieee80211_sta_register_airtime(sta, tid, tx_cur, 1816c92544dSBjoern A. Zeeb rx_cur); 1826c92544dSBjoern A. Zeeb } 1836c92544dSBjoern A. Zeeb 1846c92544dSBjoern A. Zeeb /* 1856c92544dSBjoern A. Zeeb * We don't support reading GI info from txs packets. 1866c92544dSBjoern A. Zeeb * For accurate tx status reporting and AQL improvement, 1876c92544dSBjoern A. Zeeb * we need to make sure that flags match so polling GI 1886c92544dSBjoern A. Zeeb * from per-sta counters directly. 1896c92544dSBjoern A. Zeeb */ 1906c92544dSBjoern A. Zeeb rate = &msta->wcid.rate; 1916c92544dSBjoern A. Zeeb addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 7); 1926c92544dSBjoern A. Zeeb val = mt76_rr(dev, addr); 1936c92544dSBjoern A. Zeeb 1946c92544dSBjoern A. Zeeb switch (rate->bw) { 1956c92544dSBjoern A. Zeeb case RATE_INFO_BW_160: 1966c92544dSBjoern A. Zeeb bw = IEEE80211_STA_RX_BW_160; 1976c92544dSBjoern A. Zeeb break; 1986c92544dSBjoern A. Zeeb case RATE_INFO_BW_80: 1996c92544dSBjoern A. Zeeb bw = IEEE80211_STA_RX_BW_80; 2006c92544dSBjoern A. Zeeb break; 2016c92544dSBjoern A. Zeeb case RATE_INFO_BW_40: 2026c92544dSBjoern A. Zeeb bw = IEEE80211_STA_RX_BW_40; 2036c92544dSBjoern A. Zeeb break; 2046c92544dSBjoern A. Zeeb default: 2056c92544dSBjoern A. Zeeb bw = IEEE80211_STA_RX_BW_20; 2066c92544dSBjoern A. Zeeb break; 2076c92544dSBjoern A. Zeeb } 2086c92544dSBjoern A. Zeeb 2096c92544dSBjoern A. Zeeb if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { 2106c92544dSBjoern A. Zeeb u8 offs = 24 + 2 * bw; 2116c92544dSBjoern A. Zeeb 2126c92544dSBjoern A. Zeeb rate->he_gi = (val & (0x3 << offs)) >> offs; 2136c92544dSBjoern A. Zeeb } else if (rate->flags & 2146c92544dSBjoern A. Zeeb (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) { 2156c92544dSBjoern A. Zeeb if (val & BIT(12 + bw)) 2166c92544dSBjoern A. Zeeb rate->flags |= RATE_INFO_FLAGS_SHORT_GI; 2176c92544dSBjoern A. Zeeb else 2186c92544dSBjoern A. Zeeb rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI; 2196c92544dSBjoern A. Zeeb } 220*cbb3ec25SBjoern A. Zeeb 221*cbb3ec25SBjoern A. Zeeb /* get signal strength of resp frames (CTS/BA/ACK) */ 222*cbb3ec25SBjoern A. Zeeb addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 30); 223*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, addr); 224*cbb3ec25SBjoern A. Zeeb 225*cbb3ec25SBjoern A. Zeeb rssi[0] = to_rssi(GENMASK(7, 0), val); 226*cbb3ec25SBjoern A. Zeeb rssi[1] = to_rssi(GENMASK(15, 8), val); 227*cbb3ec25SBjoern A. Zeeb rssi[2] = to_rssi(GENMASK(23, 16), val); 228*cbb3ec25SBjoern A. Zeeb rssi[3] = to_rssi(GENMASK(31, 14), val); 229*cbb3ec25SBjoern A. Zeeb 230*cbb3ec25SBjoern A. Zeeb msta->ack_signal = 231*cbb3ec25SBjoern A. Zeeb mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); 232*cbb3ec25SBjoern A. Zeeb 233*cbb3ec25SBjoern A. Zeeb ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); 2346c92544dSBjoern A. Zeeb } 2356c92544dSBjoern A. Zeeb 2366c92544dSBjoern A. Zeeb rcu_read_unlock(); 2376c92544dSBjoern A. Zeeb } 2386c92544dSBjoern A. Zeeb 239*cbb3ec25SBjoern A. Zeeb void mt7915_mac_enable_rtscts(struct mt7915_dev *dev, 240*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif, bool enable) 241*cbb3ec25SBjoern A. Zeeb { 242*cbb3ec25SBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 243*cbb3ec25SBjoern A. Zeeb u32 addr; 244*cbb3ec25SBjoern A. Zeeb 245*cbb3ec25SBjoern A. Zeeb addr = mt7915_mac_wtbl_lmac_addr(dev, mvif->sta.wcid.idx, 5); 246*cbb3ec25SBjoern A. Zeeb if (enable) 247*cbb3ec25SBjoern A. Zeeb mt76_set(dev, addr, BIT(5)); 248*cbb3ec25SBjoern A. Zeeb else 249*cbb3ec25SBjoern A. Zeeb mt76_clear(dev, addr, BIT(5)); 250*cbb3ec25SBjoern A. Zeeb } 251*cbb3ec25SBjoern A. Zeeb 252*cbb3ec25SBjoern A. Zeeb static void 253*cbb3ec25SBjoern A. Zeeb mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q, 254*cbb3ec25SBjoern A. Zeeb struct mt7915_sta *msta, struct sk_buff *skb, 255*cbb3ec25SBjoern A. Zeeb u32 info) 256*cbb3ec25SBjoern A. Zeeb { 257*cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif; 258*cbb3ec25SBjoern A. Zeeb struct wireless_dev *wdev; 259*cbb3ec25SBjoern A. Zeeb 260*cbb3ec25SBjoern A. Zeeb if (!msta || !msta->vif) 261*cbb3ec25SBjoern A. Zeeb return; 262*cbb3ec25SBjoern A. Zeeb 263*cbb3ec25SBjoern A. Zeeb if (!mt76_queue_is_wed_rx(q)) 264*cbb3ec25SBjoern A. Zeeb return; 265*cbb3ec25SBjoern A. Zeeb 266*cbb3ec25SBjoern A. Zeeb if (!(info & MT_DMA_INFO_PPE_VLD)) 267*cbb3ec25SBjoern A. Zeeb return; 268*cbb3ec25SBjoern A. Zeeb 269*cbb3ec25SBjoern A. Zeeb vif = container_of((void *)msta->vif, struct ieee80211_vif, 270*cbb3ec25SBjoern A. Zeeb drv_priv); 271*cbb3ec25SBjoern A. Zeeb wdev = ieee80211_vif_to_wdev(vif); 272*cbb3ec25SBjoern A. Zeeb skb->dev = wdev->netdev; 273*cbb3ec25SBjoern A. Zeeb 274*cbb3ec25SBjoern A. Zeeb mtk_wed_device_ppe_check(&dev->mt76.mmio.wed, skb, 275*cbb3ec25SBjoern A. Zeeb FIELD_GET(MT_DMA_PPE_CPU_REASON, info), 276*cbb3ec25SBjoern A. Zeeb FIELD_GET(MT_DMA_PPE_ENTRY, info)); 277*cbb3ec25SBjoern A. Zeeb } 278*cbb3ec25SBjoern A. Zeeb 2796c92544dSBjoern A. Zeeb static int 280*cbb3ec25SBjoern A. Zeeb mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, 281*cbb3ec25SBjoern A. Zeeb enum mt76_rxq_id q, u32 *info) 2826c92544dSBjoern A. Zeeb { 2836c92544dSBjoern A. Zeeb struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 2846c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->mt76.phy; 2856c92544dSBjoern A. Zeeb struct mt7915_phy *phy = &dev->phy; 2866c92544dSBjoern A. Zeeb struct ieee80211_supported_band *sband; 2876c92544dSBjoern A. Zeeb __le32 *rxd = (__le32 *)skb->data; 2886c92544dSBjoern A. Zeeb __le32 *rxv = NULL; 2896c92544dSBjoern A. Zeeb u32 rxd0 = le32_to_cpu(rxd[0]); 2906c92544dSBjoern A. Zeeb u32 rxd1 = le32_to_cpu(rxd[1]); 2916c92544dSBjoern A. Zeeb u32 rxd2 = le32_to_cpu(rxd[2]); 2926c92544dSBjoern A. Zeeb u32 rxd3 = le32_to_cpu(rxd[3]); 2936c92544dSBjoern A. Zeeb u32 rxd4 = le32_to_cpu(rxd[4]); 2946c92544dSBjoern A. Zeeb u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; 2956c92544dSBjoern A. Zeeb bool unicast, insert_ccmp_hdr = false; 2966c92544dSBjoern A. Zeeb u8 remove_pad, amsdu_info; 2976c92544dSBjoern A. Zeeb u8 mode = 0, qos_ctl = 0; 2986c92544dSBjoern A. Zeeb struct mt7915_sta *msta = NULL; 2996c92544dSBjoern A. Zeeb u32 csum_status = *(u32 *)skb->cb; 3006c92544dSBjoern A. Zeeb bool hdr_trans; 3016c92544dSBjoern A. Zeeb u16 hdr_gap; 3026c92544dSBjoern A. Zeeb u16 seq_ctrl = 0; 3036c92544dSBjoern A. Zeeb __le16 fc = 0; 3046c92544dSBjoern A. Zeeb int idx; 3056c92544dSBjoern A. Zeeb 3066c92544dSBjoern A. Zeeb memset(status, 0, sizeof(*status)); 3076c92544dSBjoern A. Zeeb 308*cbb3ec25SBjoern A. Zeeb if ((rxd1 & MT_RXD1_NORMAL_BAND_IDX) && !phy->mt76->band_idx) { 3096c92544dSBjoern A. Zeeb mphy = dev->mt76.phys[MT_BAND1]; 3106c92544dSBjoern A. Zeeb if (!mphy) 3116c92544dSBjoern A. Zeeb return -EINVAL; 3126c92544dSBjoern A. Zeeb 3136c92544dSBjoern A. Zeeb phy = mphy->priv; 3146c92544dSBjoern A. Zeeb status->phy_idx = 1; 3156c92544dSBjoern A. Zeeb } 3166c92544dSBjoern A. Zeeb 3176c92544dSBjoern A. Zeeb if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) 3186c92544dSBjoern A. Zeeb return -EINVAL; 3196c92544dSBjoern A. Zeeb 3206c92544dSBjoern A. Zeeb if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) 3216c92544dSBjoern A. Zeeb return -EINVAL; 3226c92544dSBjoern A. Zeeb 3236c92544dSBjoern A. Zeeb hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; 3246c92544dSBjoern A. Zeeb if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) 3256c92544dSBjoern A. Zeeb return -EINVAL; 3266c92544dSBjoern A. Zeeb 3276c92544dSBjoern A. Zeeb /* ICV error or CCMP/BIP/WPI MIC error */ 3286c92544dSBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) 3296c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_ONLY_MONITOR; 3306c92544dSBjoern A. Zeeb 3316c92544dSBjoern A. Zeeb unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; 3326c92544dSBjoern A. Zeeb idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); 3336c92544dSBjoern A. Zeeb status->wcid = mt7915_rx_get_wcid(dev, idx, unicast); 3346c92544dSBjoern A. Zeeb 3356c92544dSBjoern A. Zeeb if (status->wcid) { 3366c92544dSBjoern A. Zeeb msta = container_of(status->wcid, struct mt7915_sta, wcid); 337*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 338*cbb3ec25SBjoern A. Zeeb if (list_empty(&msta->wcid.poll_list)) 339*cbb3ec25SBjoern A. Zeeb list_add_tail(&msta->wcid.poll_list, 340*cbb3ec25SBjoern A. Zeeb &dev->mt76.sta_poll_list); 341*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 3426c92544dSBjoern A. Zeeb } 3436c92544dSBjoern A. Zeeb 3446c92544dSBjoern A. Zeeb status->freq = mphy->chandef.chan->center_freq; 3456c92544dSBjoern A. Zeeb status->band = mphy->chandef.chan->band; 3466c92544dSBjoern A. Zeeb if (status->band == NL80211_BAND_5GHZ) 3476c92544dSBjoern A. Zeeb sband = &mphy->sband_5g.sband; 3486c92544dSBjoern A. Zeeb else if (status->band == NL80211_BAND_6GHZ) 3496c92544dSBjoern A. Zeeb sband = &mphy->sband_6g.sband; 3506c92544dSBjoern A. Zeeb else 3516c92544dSBjoern A. Zeeb sband = &mphy->sband_2g.sband; 3526c92544dSBjoern A. Zeeb 3536c92544dSBjoern A. Zeeb if (!sband->channels) 3546c92544dSBjoern A. Zeeb return -EINVAL; 3556c92544dSBjoern A. Zeeb 3566c92544dSBjoern A. Zeeb if ((rxd0 & csum_mask) == csum_mask && 3576c92544dSBjoern A. Zeeb !(csum_status & (BIT(0) | BIT(2) | BIT(3)))) 3586c92544dSBjoern A. Zeeb skb->ip_summed = CHECKSUM_UNNECESSARY; 3596c92544dSBjoern A. Zeeb 3606c92544dSBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_FCS_ERR) 3616c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_FAILED_FCS_CRC; 3626c92544dSBjoern A. Zeeb 3636c92544dSBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_TKIP_MIC_ERR) 3646c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_MMIC_ERROR; 3656c92544dSBjoern A. Zeeb 3666c92544dSBjoern A. Zeeb if (FIELD_GET(MT_RXD1_NORMAL_SEC_MODE, rxd1) != 0 && 3676c92544dSBjoern A. Zeeb !(rxd1 & (MT_RXD1_NORMAL_CLM | MT_RXD1_NORMAL_CM))) { 3686c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_DECRYPTED; 3696c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_IV_STRIPPED; 3706c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; 3716c92544dSBjoern A. Zeeb } 3726c92544dSBjoern A. Zeeb 3736c92544dSBjoern A. Zeeb remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); 3746c92544dSBjoern A. Zeeb 3756c92544dSBjoern A. Zeeb if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) 3766c92544dSBjoern A. Zeeb return -EINVAL; 3776c92544dSBjoern A. Zeeb 3786c92544dSBjoern A. Zeeb rxd += 6; 3796c92544dSBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { 3806c92544dSBjoern A. Zeeb u32 v0 = le32_to_cpu(rxd[0]); 3816c92544dSBjoern A. Zeeb u32 v2 = le32_to_cpu(rxd[2]); 3826c92544dSBjoern A. Zeeb 3836c92544dSBjoern A. Zeeb fc = cpu_to_le16(FIELD_GET(MT_RXD6_FRAME_CONTROL, v0)); 3846c92544dSBjoern A. Zeeb qos_ctl = FIELD_GET(MT_RXD8_QOS_CTL, v2); 3856c92544dSBjoern A. Zeeb seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, v2); 3866c92544dSBjoern A. Zeeb 3876c92544dSBjoern A. Zeeb rxd += 4; 3886c92544dSBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len) 3896c92544dSBjoern A. Zeeb return -EINVAL; 3906c92544dSBjoern A. Zeeb } 3916c92544dSBjoern A. Zeeb 3926c92544dSBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_1) { 3936c92544dSBjoern A. Zeeb u8 *data = (u8 *)rxd; 3946c92544dSBjoern A. Zeeb 3956c92544dSBjoern A. Zeeb if (status->flag & RX_FLAG_DECRYPTED) { 3966c92544dSBjoern A. Zeeb switch (FIELD_GET(MT_RXD1_NORMAL_SEC_MODE, rxd1)) { 3976c92544dSBjoern A. Zeeb case MT_CIPHER_AES_CCMP: 3986c92544dSBjoern A. Zeeb case MT_CIPHER_CCMP_CCX: 3996c92544dSBjoern A. Zeeb case MT_CIPHER_CCMP_256: 4006c92544dSBjoern A. Zeeb insert_ccmp_hdr = 4016c92544dSBjoern A. Zeeb FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); 4026c92544dSBjoern A. Zeeb fallthrough; 4036c92544dSBjoern A. Zeeb case MT_CIPHER_TKIP: 4046c92544dSBjoern A. Zeeb case MT_CIPHER_TKIP_NO_MIC: 4056c92544dSBjoern A. Zeeb case MT_CIPHER_GCMP: 4066c92544dSBjoern A. Zeeb case MT_CIPHER_GCMP_256: 4076c92544dSBjoern A. Zeeb status->iv[0] = data[5]; 4086c92544dSBjoern A. Zeeb status->iv[1] = data[4]; 4096c92544dSBjoern A. Zeeb status->iv[2] = data[3]; 4106c92544dSBjoern A. Zeeb status->iv[3] = data[2]; 4116c92544dSBjoern A. Zeeb status->iv[4] = data[1]; 4126c92544dSBjoern A. Zeeb status->iv[5] = data[0]; 4136c92544dSBjoern A. Zeeb break; 4146c92544dSBjoern A. Zeeb default: 4156c92544dSBjoern A. Zeeb break; 4166c92544dSBjoern A. Zeeb } 4176c92544dSBjoern A. Zeeb } 4186c92544dSBjoern A. Zeeb rxd += 4; 4196c92544dSBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len) 4206c92544dSBjoern A. Zeeb return -EINVAL; 4216c92544dSBjoern A. Zeeb } 4226c92544dSBjoern A. Zeeb 4236c92544dSBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { 4246c92544dSBjoern A. Zeeb status->timestamp = le32_to_cpu(rxd[0]); 4256c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_MACTIME_START; 4266c92544dSBjoern A. Zeeb 4276c92544dSBjoern A. Zeeb if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { 4286c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_AMPDU_DETAILS; 4296c92544dSBjoern A. Zeeb 4306c92544dSBjoern A. Zeeb /* all subframes of an A-MPDU have the same timestamp */ 4316c92544dSBjoern A. Zeeb if (phy->rx_ampdu_ts != status->timestamp) { 4326c92544dSBjoern A. Zeeb if (!++phy->ampdu_ref) 4336c92544dSBjoern A. Zeeb phy->ampdu_ref++; 4346c92544dSBjoern A. Zeeb } 4356c92544dSBjoern A. Zeeb phy->rx_ampdu_ts = status->timestamp; 4366c92544dSBjoern A. Zeeb 4376c92544dSBjoern A. Zeeb status->ampdu_ref = phy->ampdu_ref; 4386c92544dSBjoern A. Zeeb } 4396c92544dSBjoern A. Zeeb 4406c92544dSBjoern A. Zeeb rxd += 2; 4416c92544dSBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len) 4426c92544dSBjoern A. Zeeb return -EINVAL; 4436c92544dSBjoern A. Zeeb } 4446c92544dSBjoern A. Zeeb 4456c92544dSBjoern A. Zeeb /* RXD Group 3 - P-RXV */ 4466c92544dSBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { 4476c92544dSBjoern A. Zeeb u32 v0, v1; 4486c92544dSBjoern A. Zeeb int ret; 4496c92544dSBjoern A. Zeeb 4506c92544dSBjoern A. Zeeb rxv = rxd; 4516c92544dSBjoern A. Zeeb rxd += 2; 4526c92544dSBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len) 4536c92544dSBjoern A. Zeeb return -EINVAL; 4546c92544dSBjoern A. Zeeb 4556c92544dSBjoern A. Zeeb v0 = le32_to_cpu(rxv[0]); 4566c92544dSBjoern A. Zeeb v1 = le32_to_cpu(rxv[1]); 4576c92544dSBjoern A. Zeeb 4586c92544dSBjoern A. Zeeb if (v0 & MT_PRXV_HT_AD_CODE) 4596c92544dSBjoern A. Zeeb status->enc_flags |= RX_ENC_FLAG_LDPC; 4606c92544dSBjoern A. Zeeb 4616c92544dSBjoern A. Zeeb status->chains = mphy->antenna_mask; 4626c92544dSBjoern A. Zeeb status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v1); 4636c92544dSBjoern A. Zeeb status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1); 4646c92544dSBjoern A. Zeeb status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1); 4656c92544dSBjoern A. Zeeb status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1); 4666c92544dSBjoern A. Zeeb 4676c92544dSBjoern A. Zeeb /* RXD Group 5 - C-RXV */ 4686c92544dSBjoern A. Zeeb if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { 4696c92544dSBjoern A. Zeeb rxd += 18; 4706c92544dSBjoern A. Zeeb if ((u8 *)rxd - skb->data >= skb->len) 4716c92544dSBjoern A. Zeeb return -EINVAL; 4726c92544dSBjoern A. Zeeb } 4736c92544dSBjoern A. Zeeb 4746c92544dSBjoern A. Zeeb if (!is_mt7915(&dev->mt76) || (rxd1 & MT_RXD1_NORMAL_GROUP_5)) { 4756c92544dSBjoern A. Zeeb ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status, 4766c92544dSBjoern A. Zeeb sband, rxv, &mode); 4776c92544dSBjoern A. Zeeb if (ret < 0) 4786c92544dSBjoern A. Zeeb return ret; 4796c92544dSBjoern A. Zeeb } 4806c92544dSBjoern A. Zeeb } 4816c92544dSBjoern A. Zeeb 4826c92544dSBjoern A. Zeeb amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); 4836c92544dSBjoern A. Zeeb status->amsdu = !!amsdu_info; 4846c92544dSBjoern A. Zeeb if (status->amsdu) { 4856c92544dSBjoern A. Zeeb status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; 4866c92544dSBjoern A. Zeeb status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; 4876c92544dSBjoern A. Zeeb } 4886c92544dSBjoern A. Zeeb 4896c92544dSBjoern A. Zeeb hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad; 4906c92544dSBjoern A. Zeeb if (hdr_trans && ieee80211_has_morefrags(fc)) { 4916c92544dSBjoern A. Zeeb struct ieee80211_vif *vif; 4926c92544dSBjoern A. Zeeb int err; 4936c92544dSBjoern A. Zeeb 4946c92544dSBjoern A. Zeeb if (!msta || !msta->vif) 4956c92544dSBjoern A. Zeeb return -EINVAL; 4966c92544dSBjoern A. Zeeb 4976c92544dSBjoern A. Zeeb vif = container_of((void *)msta->vif, struct ieee80211_vif, 4986c92544dSBjoern A. Zeeb drv_priv); 4996c92544dSBjoern A. Zeeb err = mt76_connac2_reverse_frag0_hdr_trans(vif, skb, hdr_gap); 5006c92544dSBjoern A. Zeeb if (err) 5016c92544dSBjoern A. Zeeb return err; 5026c92544dSBjoern A. Zeeb 5036c92544dSBjoern A. Zeeb hdr_trans = false; 5046c92544dSBjoern A. Zeeb } else { 5056c92544dSBjoern A. Zeeb int pad_start = 0; 5066c92544dSBjoern A. Zeeb 5076c92544dSBjoern A. Zeeb skb_pull(skb, hdr_gap); 5086c92544dSBjoern A. Zeeb if (!hdr_trans && status->amsdu) { 5096c92544dSBjoern A. Zeeb pad_start = ieee80211_get_hdrlen_from_skb(skb); 5106c92544dSBjoern A. Zeeb } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { 5116c92544dSBjoern A. Zeeb /* 5126c92544dSBjoern A. Zeeb * When header translation failure is indicated, 5136c92544dSBjoern A. Zeeb * the hardware will insert an extra 2-byte field 5146c92544dSBjoern A. Zeeb * containing the data length after the protocol 5156c92544dSBjoern A. Zeeb * type field. This happens either when the LLC-SNAP 5166c92544dSBjoern A. Zeeb * pattern did not match, or if a VLAN header was 5176c92544dSBjoern A. Zeeb * detected. 5186c92544dSBjoern A. Zeeb */ 5196c92544dSBjoern A. Zeeb pad_start = 12; 5206c92544dSBjoern A. Zeeb if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) 5216c92544dSBjoern A. Zeeb pad_start += 4; 5226c92544dSBjoern A. Zeeb else 5236c92544dSBjoern A. Zeeb pad_start = 0; 5246c92544dSBjoern A. Zeeb } 5256c92544dSBjoern A. Zeeb 5266c92544dSBjoern A. Zeeb if (pad_start) { 5276c92544dSBjoern A. Zeeb memmove(skb->data + 2, skb->data, pad_start); 5286c92544dSBjoern A. Zeeb skb_pull(skb, 2); 5296c92544dSBjoern A. Zeeb } 5306c92544dSBjoern A. Zeeb } 5316c92544dSBjoern A. Zeeb 5326c92544dSBjoern A. Zeeb if (!hdr_trans) { 5336c92544dSBjoern A. Zeeb struct ieee80211_hdr *hdr; 5346c92544dSBjoern A. Zeeb 5356c92544dSBjoern A. Zeeb if (insert_ccmp_hdr) { 5366c92544dSBjoern A. Zeeb u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); 5376c92544dSBjoern A. Zeeb 5386c92544dSBjoern A. Zeeb mt76_insert_ccmp_hdr(skb, key_id); 5396c92544dSBjoern A. Zeeb } 5406c92544dSBjoern A. Zeeb 5416c92544dSBjoern A. Zeeb hdr = mt76_skb_get_hdr(skb); 5426c92544dSBjoern A. Zeeb fc = hdr->frame_control; 5436c92544dSBjoern A. Zeeb if (ieee80211_is_data_qos(fc)) { 5446c92544dSBjoern A. Zeeb seq_ctrl = le16_to_cpu(hdr->seq_ctrl); 5456c92544dSBjoern A. Zeeb qos_ctl = *ieee80211_get_qos_ctl(hdr); 5466c92544dSBjoern A. Zeeb } 5476c92544dSBjoern A. Zeeb } else { 5486c92544dSBjoern A. Zeeb status->flag |= RX_FLAG_8023; 549*cbb3ec25SBjoern A. Zeeb mt7915_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb, 550*cbb3ec25SBjoern A. Zeeb *info); 5516c92544dSBjoern A. Zeeb } 5526c92544dSBjoern A. Zeeb 5536c92544dSBjoern A. Zeeb if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) 5546c92544dSBjoern A. Zeeb mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv, mode); 5556c92544dSBjoern A. Zeeb 5566c92544dSBjoern A. Zeeb if (!status->wcid || !ieee80211_is_data_qos(fc)) 5576c92544dSBjoern A. Zeeb return 0; 5586c92544dSBjoern A. Zeeb 5596c92544dSBjoern A. Zeeb status->aggr = unicast && 5606c92544dSBjoern A. Zeeb !ieee80211_is_qos_nullfunc(fc); 5616c92544dSBjoern A. Zeeb status->qos_ctl = qos_ctl; 5626c92544dSBjoern A. Zeeb status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); 5636c92544dSBjoern A. Zeeb 5646c92544dSBjoern A. Zeeb return 0; 5656c92544dSBjoern A. Zeeb } 5666c92544dSBjoern A. Zeeb 5676c92544dSBjoern A. Zeeb static void 5686c92544dSBjoern A. Zeeb mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb) 5696c92544dSBjoern A. Zeeb { 5706c92544dSBjoern A. Zeeb #ifdef CONFIG_NL80211_TESTMODE 5716c92544dSBjoern A. Zeeb struct mt7915_phy *phy = &dev->phy; 5726c92544dSBjoern A. Zeeb __le32 *rxd = (__le32 *)skb->data; 5736c92544dSBjoern A. Zeeb __le32 *rxv_hdr = rxd + 2; 5746c92544dSBjoern A. Zeeb __le32 *rxv = rxd + 4; 5756c92544dSBjoern A. Zeeb u32 rcpi, ib_rssi, wb_rssi, v20, v21; 5766c92544dSBjoern A. Zeeb u8 band_idx; 5776c92544dSBjoern A. Zeeb s32 foe; 5786c92544dSBjoern A. Zeeb u8 snr; 5796c92544dSBjoern A. Zeeb int i; 5806c92544dSBjoern A. Zeeb 5816c92544dSBjoern A. Zeeb band_idx = le32_get_bits(rxv_hdr[1], MT_RXV_HDR_BAND_IDX); 582*cbb3ec25SBjoern A. Zeeb if (band_idx && !phy->mt76->band_idx) { 5836c92544dSBjoern A. Zeeb phy = mt7915_ext_phy(dev); 5846c92544dSBjoern A. Zeeb if (!phy) 5856c92544dSBjoern A. Zeeb goto out; 5866c92544dSBjoern A. Zeeb } 5876c92544dSBjoern A. Zeeb 5886c92544dSBjoern A. Zeeb rcpi = le32_to_cpu(rxv[6]); 5896c92544dSBjoern A. Zeeb ib_rssi = le32_to_cpu(rxv[7]); 5906c92544dSBjoern A. Zeeb wb_rssi = le32_to_cpu(rxv[8]) >> 5; 5916c92544dSBjoern A. Zeeb 5926c92544dSBjoern A. Zeeb for (i = 0; i < 4; i++, rcpi >>= 8, ib_rssi >>= 8, wb_rssi >>= 9) { 5936c92544dSBjoern A. Zeeb if (i == 3) 5946c92544dSBjoern A. Zeeb wb_rssi = le32_to_cpu(rxv[9]); 5956c92544dSBjoern A. Zeeb 5966c92544dSBjoern A. Zeeb phy->test.last_rcpi[i] = rcpi & 0xff; 5976c92544dSBjoern A. Zeeb phy->test.last_ib_rssi[i] = ib_rssi & 0xff; 5986c92544dSBjoern A. Zeeb phy->test.last_wb_rssi[i] = wb_rssi & 0xff; 5996c92544dSBjoern A. Zeeb } 6006c92544dSBjoern A. Zeeb 6016c92544dSBjoern A. Zeeb v20 = le32_to_cpu(rxv[20]); 6026c92544dSBjoern A. Zeeb v21 = le32_to_cpu(rxv[21]); 6036c92544dSBjoern A. Zeeb 6046c92544dSBjoern A. Zeeb foe = FIELD_GET(MT_CRXV_FOE_LO, v20) | 6056c92544dSBjoern A. Zeeb (FIELD_GET(MT_CRXV_FOE_HI, v21) << MT_CRXV_FOE_SHIFT); 6066c92544dSBjoern A. Zeeb 6076c92544dSBjoern A. Zeeb snr = FIELD_GET(MT_CRXV_SNR, v20) - 16; 6086c92544dSBjoern A. Zeeb 6096c92544dSBjoern A. Zeeb phy->test.last_freq_offset = foe; 6106c92544dSBjoern A. Zeeb phy->test.last_snr = snr; 6116c92544dSBjoern A. Zeeb out: 6126c92544dSBjoern A. Zeeb #endif 6136c92544dSBjoern A. Zeeb dev_kfree_skb(skb); 6146c92544dSBjoern A. Zeeb } 6156c92544dSBjoern A. Zeeb 6166c92544dSBjoern A. Zeeb static void 6176c92544dSBjoern A. Zeeb mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi, 6186c92544dSBjoern A. Zeeb struct sk_buff *skb) 6196c92544dSBjoern A. Zeeb { 6206c92544dSBjoern A. Zeeb #ifdef CONFIG_NL80211_TESTMODE 6216c92544dSBjoern A. Zeeb struct mt76_testmode_data *td = &phy->mt76->test; 6226c92544dSBjoern A. Zeeb const struct ieee80211_rate *r; 6236c92544dSBjoern A. Zeeb u8 bw, mode, nss = td->tx_rate_nss; 6246c92544dSBjoern A. Zeeb u8 rate_idx = td->tx_rate_idx; 6256c92544dSBjoern A. Zeeb u16 rateval = 0; 6266c92544dSBjoern A. Zeeb u32 val; 6276c92544dSBjoern A. Zeeb bool cck = false; 6286c92544dSBjoern A. Zeeb int band; 6296c92544dSBjoern A. Zeeb 6306c92544dSBjoern A. Zeeb if (skb != phy->mt76->test.tx_skb) 6316c92544dSBjoern A. Zeeb return; 6326c92544dSBjoern A. Zeeb 6336c92544dSBjoern A. Zeeb switch (td->tx_rate_mode) { 6346c92544dSBjoern A. Zeeb case MT76_TM_TX_MODE_HT: 6356c92544dSBjoern A. Zeeb nss = 1 + (rate_idx >> 3); 6366c92544dSBjoern A. Zeeb mode = MT_PHY_TYPE_HT; 6376c92544dSBjoern A. Zeeb break; 6386c92544dSBjoern A. Zeeb case MT76_TM_TX_MODE_VHT: 6396c92544dSBjoern A. Zeeb mode = MT_PHY_TYPE_VHT; 6406c92544dSBjoern A. Zeeb break; 6416c92544dSBjoern A. Zeeb case MT76_TM_TX_MODE_HE_SU: 6426c92544dSBjoern A. Zeeb mode = MT_PHY_TYPE_HE_SU; 6436c92544dSBjoern A. Zeeb break; 6446c92544dSBjoern A. Zeeb case MT76_TM_TX_MODE_HE_EXT_SU: 6456c92544dSBjoern A. Zeeb mode = MT_PHY_TYPE_HE_EXT_SU; 6466c92544dSBjoern A. Zeeb break; 6476c92544dSBjoern A. Zeeb case MT76_TM_TX_MODE_HE_TB: 6486c92544dSBjoern A. Zeeb mode = MT_PHY_TYPE_HE_TB; 6496c92544dSBjoern A. Zeeb break; 6506c92544dSBjoern A. Zeeb case MT76_TM_TX_MODE_HE_MU: 6516c92544dSBjoern A. Zeeb mode = MT_PHY_TYPE_HE_MU; 6526c92544dSBjoern A. Zeeb break; 6536c92544dSBjoern A. Zeeb case MT76_TM_TX_MODE_CCK: 6546c92544dSBjoern A. Zeeb cck = true; 6556c92544dSBjoern A. Zeeb fallthrough; 6566c92544dSBjoern A. Zeeb case MT76_TM_TX_MODE_OFDM: 6576c92544dSBjoern A. Zeeb band = phy->mt76->chandef.chan->band; 6586c92544dSBjoern A. Zeeb if (band == NL80211_BAND_2GHZ && !cck) 6596c92544dSBjoern A. Zeeb rate_idx += 4; 6606c92544dSBjoern A. Zeeb 6616c92544dSBjoern A. Zeeb r = &phy->mt76->hw->wiphy->bands[band]->bitrates[rate_idx]; 6626c92544dSBjoern A. Zeeb val = cck ? r->hw_value_short : r->hw_value; 6636c92544dSBjoern A. Zeeb 6646c92544dSBjoern A. Zeeb mode = val >> 8; 6656c92544dSBjoern A. Zeeb rate_idx = val & 0xff; 6666c92544dSBjoern A. Zeeb break; 6676c92544dSBjoern A. Zeeb default: 6686c92544dSBjoern A. Zeeb mode = MT_PHY_TYPE_OFDM; 6696c92544dSBjoern A. Zeeb break; 6706c92544dSBjoern A. Zeeb } 6716c92544dSBjoern A. Zeeb 6726c92544dSBjoern A. Zeeb switch (phy->mt76->chandef.width) { 6736c92544dSBjoern A. Zeeb case NL80211_CHAN_WIDTH_40: 6746c92544dSBjoern A. Zeeb bw = 1; 6756c92544dSBjoern A. Zeeb break; 6766c92544dSBjoern A. Zeeb case NL80211_CHAN_WIDTH_80: 6776c92544dSBjoern A. Zeeb bw = 2; 6786c92544dSBjoern A. Zeeb break; 6796c92544dSBjoern A. Zeeb case NL80211_CHAN_WIDTH_80P80: 6806c92544dSBjoern A. Zeeb case NL80211_CHAN_WIDTH_160: 6816c92544dSBjoern A. Zeeb bw = 3; 6826c92544dSBjoern A. Zeeb break; 6836c92544dSBjoern A. Zeeb default: 6846c92544dSBjoern A. Zeeb bw = 0; 6856c92544dSBjoern A. Zeeb break; 6866c92544dSBjoern A. Zeeb } 6876c92544dSBjoern A. Zeeb 6886c92544dSBjoern A. Zeeb if (td->tx_rate_stbc && nss == 1) { 6896c92544dSBjoern A. Zeeb nss++; 6906c92544dSBjoern A. Zeeb rateval |= MT_TX_RATE_STBC; 6916c92544dSBjoern A. Zeeb } 6926c92544dSBjoern A. Zeeb 6936c92544dSBjoern A. Zeeb rateval |= FIELD_PREP(MT_TX_RATE_IDX, rate_idx) | 6946c92544dSBjoern A. Zeeb FIELD_PREP(MT_TX_RATE_MODE, mode) | 6956c92544dSBjoern A. Zeeb FIELD_PREP(MT_TX_RATE_NSS, nss - 1); 6966c92544dSBjoern A. Zeeb 6976c92544dSBjoern A. Zeeb txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); 6986c92544dSBjoern A. Zeeb 6996c92544dSBjoern A. Zeeb le32p_replace_bits(&txwi[3], 1, MT_TXD3_REM_TX_COUNT); 7006c92544dSBjoern A. Zeeb if (td->tx_rate_mode < MT76_TM_TX_MODE_HT) 7016c92544dSBjoern A. Zeeb txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); 7026c92544dSBjoern A. Zeeb 7036c92544dSBjoern A. Zeeb val = MT_TXD6_FIXED_BW | 7046c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD6_BW, bw) | 7056c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD6_TX_RATE, rateval) | 7066c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD6_SGI, td->tx_rate_sgi); 7076c92544dSBjoern A. Zeeb 7086c92544dSBjoern A. Zeeb /* for HE_SU/HE_EXT_SU PPDU 7096c92544dSBjoern A. Zeeb * - 1x, 2x, 4x LTF + 0.8us GI 7106c92544dSBjoern A. Zeeb * - 2x LTF + 1.6us GI, 4x LTF + 3.2us GI 7116c92544dSBjoern A. Zeeb * for HE_MU PPDU 7126c92544dSBjoern A. Zeeb * - 2x, 4x LTF + 0.8us GI 7136c92544dSBjoern A. Zeeb * - 2x LTF + 1.6us GI, 4x LTF + 3.2us GI 7146c92544dSBjoern A. Zeeb * for HE_TB PPDU 7156c92544dSBjoern A. Zeeb * - 1x, 2x LTF + 1.6us GI 7166c92544dSBjoern A. Zeeb * - 4x LTF + 3.2us GI 7176c92544dSBjoern A. Zeeb */ 7186c92544dSBjoern A. Zeeb if (mode >= MT_PHY_TYPE_HE_SU) 7196c92544dSBjoern A. Zeeb val |= FIELD_PREP(MT_TXD6_HELTF, td->tx_ltf); 7206c92544dSBjoern A. Zeeb 7216c92544dSBjoern A. Zeeb if (td->tx_rate_ldpc || (bw > 0 && mode >= MT_PHY_TYPE_HE_SU)) 7226c92544dSBjoern A. Zeeb val |= MT_TXD6_LDPC; 7236c92544dSBjoern A. Zeeb 7246c92544dSBjoern A. Zeeb txwi[3] &= ~cpu_to_le32(MT_TXD3_SN_VALID); 7256c92544dSBjoern A. Zeeb txwi[6] |= cpu_to_le32(val); 7266c92544dSBjoern A. Zeeb txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, 7276c92544dSBjoern A. Zeeb phy->test.spe_idx)); 7286c92544dSBjoern A. Zeeb #endif 7296c92544dSBjoern A. Zeeb } 7306c92544dSBjoern A. Zeeb 7316c92544dSBjoern A. Zeeb void mt7915_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, 7326c92544dSBjoern A. Zeeb struct sk_buff *skb, struct mt76_wcid *wcid, int pid, 7336c92544dSBjoern A. Zeeb struct ieee80211_key_conf *key, 7346c92544dSBjoern A. Zeeb enum mt76_txq_id qid, u32 changed) 7356c92544dSBjoern A. Zeeb { 7366c92544dSBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 7376c92544dSBjoern A. Zeeb u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; 7386c92544dSBjoern A. Zeeb struct mt76_phy *mphy = &dev->phy; 7396c92544dSBjoern A. Zeeb 7406c92544dSBjoern A. Zeeb if (phy_idx && dev->phys[MT_BAND1]) 7416c92544dSBjoern A. Zeeb mphy = dev->phys[MT_BAND1]; 7426c92544dSBjoern A. Zeeb 7436c92544dSBjoern A. Zeeb mt76_connac2_mac_write_txwi(dev, txwi, skb, wcid, key, pid, qid, changed); 7446c92544dSBjoern A. Zeeb 7456c92544dSBjoern A. Zeeb if (mt76_testmode_enabled(mphy)) 7466c92544dSBjoern A. Zeeb mt7915_mac_write_txwi_tm(mphy->priv, txwi, skb); 7476c92544dSBjoern A. Zeeb } 7486c92544dSBjoern A. Zeeb 7496c92544dSBjoern A. Zeeb int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 7506c92544dSBjoern A. Zeeb enum mt76_txq_id qid, struct mt76_wcid *wcid, 7516c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, 7526c92544dSBjoern A. Zeeb struct mt76_tx_info *tx_info) 7536c92544dSBjoern A. Zeeb { 7546c92544dSBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; 7556c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); 7566c92544dSBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); 7576c92544dSBjoern A. Zeeb struct ieee80211_key_conf *key = info->control.hw_key; 7586c92544dSBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif; 7596c92544dSBjoern A. Zeeb struct mt76_connac_fw_txp *txp; 7606c92544dSBjoern A. Zeeb struct mt76_txwi_cache *t; 7616c92544dSBjoern A. Zeeb int id, i, nbuf = tx_info->nbuf - 1; 7626c92544dSBjoern A. Zeeb u8 *txwi = (u8 *)txwi_ptr; 7636c92544dSBjoern A. Zeeb int pid; 7646c92544dSBjoern A. Zeeb 7656c92544dSBjoern A. Zeeb if (unlikely(tx_info->skb->len <= ETH_HLEN)) 7666c92544dSBjoern A. Zeeb return -EINVAL; 7676c92544dSBjoern A. Zeeb 7686c92544dSBjoern A. Zeeb if (!wcid) 7696c92544dSBjoern A. Zeeb wcid = &dev->mt76.global_wcid; 7706c92544dSBjoern A. Zeeb 7716c92544dSBjoern A. Zeeb if (sta) { 7726c92544dSBjoern A. Zeeb struct mt7915_sta *msta; 7736c92544dSBjoern A. Zeeb 7746c92544dSBjoern A. Zeeb msta = (struct mt7915_sta *)sta->drv_priv; 7756c92544dSBjoern A. Zeeb 7766c92544dSBjoern A. Zeeb if (time_after(jiffies, msta->jiffies + HZ / 4)) { 7776c92544dSBjoern A. Zeeb info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 7786c92544dSBjoern A. Zeeb msta->jiffies = jiffies; 7796c92544dSBjoern A. Zeeb } 7806c92544dSBjoern A. Zeeb } 7816c92544dSBjoern A. Zeeb 7826c92544dSBjoern A. Zeeb t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); 7836c92544dSBjoern A. Zeeb t->skb = tx_info->skb; 7846c92544dSBjoern A. Zeeb 7856c92544dSBjoern A. Zeeb id = mt76_token_consume(mdev, &t); 7866c92544dSBjoern A. Zeeb if (id < 0) 7876c92544dSBjoern A. Zeeb return id; 7886c92544dSBjoern A. Zeeb 7896c92544dSBjoern A. Zeeb pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); 7906c92544dSBjoern A. Zeeb mt7915_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, pid, key, 7916c92544dSBjoern A. Zeeb qid, 0); 7926c92544dSBjoern A. Zeeb 7936c92544dSBjoern A. Zeeb txp = (struct mt76_connac_fw_txp *)(txwi + MT_TXD_SIZE); 7946c92544dSBjoern A. Zeeb for (i = 0; i < nbuf; i++) { 7956c92544dSBjoern A. Zeeb txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); 7966c92544dSBjoern A. Zeeb txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len); 7976c92544dSBjoern A. Zeeb } 7986c92544dSBjoern A. Zeeb txp->nbuf = nbuf; 7996c92544dSBjoern A. Zeeb 8006c92544dSBjoern A. Zeeb txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD | MT_CT_INFO_FROM_HOST); 8016c92544dSBjoern A. Zeeb 8026c92544dSBjoern A. Zeeb if (!key) 8036c92544dSBjoern A. Zeeb txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); 8046c92544dSBjoern A. Zeeb 8056c92544dSBjoern A. Zeeb if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && 8066c92544dSBjoern A. Zeeb ieee80211_is_mgmt(hdr->frame_control)) 8076c92544dSBjoern A. Zeeb txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); 8086c92544dSBjoern A. Zeeb 8096c92544dSBjoern A. Zeeb if (vif) { 8106c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; 8116c92544dSBjoern A. Zeeb 8126c92544dSBjoern A. Zeeb txp->bss_idx = mvif->mt76.idx; 8136c92544dSBjoern A. Zeeb } 8146c92544dSBjoern A. Zeeb 8156c92544dSBjoern A. Zeeb txp->token = cpu_to_le16(id); 8166c92544dSBjoern A. Zeeb if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) 8176c92544dSBjoern A. Zeeb txp->rept_wds_wcid = cpu_to_le16(wcid->idx); 8186c92544dSBjoern A. Zeeb else 8196c92544dSBjoern A. Zeeb txp->rept_wds_wcid = cpu_to_le16(0x3ff); 8206c92544dSBjoern A. Zeeb tx_info->skb = DMA_DUMMY_DATA; 8216c92544dSBjoern A. Zeeb 8226c92544dSBjoern A. Zeeb /* pass partial skb header to fw */ 8236c92544dSBjoern A. Zeeb tx_info->buf[1].len = MT_CT_PARSE_LEN; 8246c92544dSBjoern A. Zeeb tx_info->buf[1].skip_unmap = true; 8256c92544dSBjoern A. Zeeb tx_info->nbuf = MT_CT_DMA_BUF_NUM; 8266c92544dSBjoern A. Zeeb 8276c92544dSBjoern A. Zeeb return 0; 8286c92544dSBjoern A. Zeeb } 8296c92544dSBjoern A. Zeeb 8306c92544dSBjoern A. Zeeb u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id) 8316c92544dSBjoern A. Zeeb { 8326c92544dSBjoern A. Zeeb #if defined(__linux__) 8336c92544dSBjoern A. Zeeb struct mt76_connac_fw_txp *txp = ptr + MT_TXD_SIZE; 8346c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__) 8356c92544dSBjoern A. Zeeb struct mt76_connac_fw_txp *txp = (void *)((u8 *)ptr + MT_TXD_SIZE); 8366c92544dSBjoern A. Zeeb #endif 8376c92544dSBjoern A. Zeeb __le32 *txwi = ptr; 8386c92544dSBjoern A. Zeeb u32 val; 8396c92544dSBjoern A. Zeeb 8406c92544dSBjoern A. Zeeb memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp)); 8416c92544dSBjoern A. Zeeb 8426c92544dSBjoern A. Zeeb val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) | 8436c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT); 8446c92544dSBjoern A. Zeeb txwi[0] = cpu_to_le32(val); 8456c92544dSBjoern A. Zeeb 8466c92544dSBjoern A. Zeeb val = MT_TXD1_LONG_FORMAT | 8476c92544dSBjoern A. Zeeb FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3); 8486c92544dSBjoern A. Zeeb txwi[1] = cpu_to_le32(val); 8496c92544dSBjoern A. Zeeb 8506c92544dSBjoern A. Zeeb txp->token = cpu_to_le16(token_id); 8516c92544dSBjoern A. Zeeb txp->nbuf = 1; 8526c92544dSBjoern A. Zeeb txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp)); 8536c92544dSBjoern A. Zeeb 8546c92544dSBjoern A. Zeeb return MT_TXD_SIZE + sizeof(*txp); 8556c92544dSBjoern A. Zeeb } 8566c92544dSBjoern A. Zeeb 8576c92544dSBjoern A. Zeeb static void 8586c92544dSBjoern A. Zeeb mt7915_mac_tx_free_prepare(struct mt7915_dev *dev) 8596c92544dSBjoern A. Zeeb { 8606c92544dSBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76; 8616c92544dSBjoern A. Zeeb struct mt76_phy *mphy_ext = mdev->phys[MT_BAND1]; 8626c92544dSBjoern A. Zeeb 8636c92544dSBjoern A. Zeeb /* clean DMA queues and unmap buffers first */ 8646c92544dSBjoern A. Zeeb mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false); 8656c92544dSBjoern A. Zeeb mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false); 8666c92544dSBjoern A. Zeeb if (mphy_ext) { 8676c92544dSBjoern A. Zeeb mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false); 8686c92544dSBjoern A. Zeeb mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false); 8696c92544dSBjoern A. Zeeb } 8706c92544dSBjoern A. Zeeb } 8716c92544dSBjoern A. Zeeb 8726c92544dSBjoern A. Zeeb static void 8736c92544dSBjoern A. Zeeb mt7915_mac_tx_free_done(struct mt7915_dev *dev, 8746c92544dSBjoern A. Zeeb struct list_head *free_list, bool wake) 8756c92544dSBjoern A. Zeeb { 8766c92544dSBjoern A. Zeeb struct sk_buff *skb, *tmp; 8776c92544dSBjoern A. Zeeb 8786c92544dSBjoern A. Zeeb mt7915_mac_sta_poll(dev); 8796c92544dSBjoern A. Zeeb 8806c92544dSBjoern A. Zeeb if (wake) 8816c92544dSBjoern A. Zeeb mt76_set_tx_blocked(&dev->mt76, false); 8826c92544dSBjoern A. Zeeb 8836c92544dSBjoern A. Zeeb mt76_worker_schedule(&dev->mt76.tx_worker); 8846c92544dSBjoern A. Zeeb 8856c92544dSBjoern A. Zeeb list_for_each_entry_safe(skb, tmp, free_list, list) { 8866c92544dSBjoern A. Zeeb skb_list_del_init(skb); 8876c92544dSBjoern A. Zeeb napi_consume_skb(skb, 1); 8886c92544dSBjoern A. Zeeb } 8896c92544dSBjoern A. Zeeb } 8906c92544dSBjoern A. Zeeb 8916c92544dSBjoern A. Zeeb static void 8926c92544dSBjoern A. Zeeb mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) 8936c92544dSBjoern A. Zeeb { 8946c92544dSBjoern A. Zeeb struct mt76_connac_tx_free *free = data; 8956c92544dSBjoern A. Zeeb #if defined(__linux__) 8966c92544dSBjoern A. Zeeb __le32 *tx_info = (__le32 *)(data + sizeof(*free)); 8976c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__) 8986c92544dSBjoern A. Zeeb __le32 *tx_info = (__le32 *)((u8 *)data + sizeof(*free)); 8996c92544dSBjoern A. Zeeb #endif 9006c92544dSBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76; 9016c92544dSBjoern A. Zeeb struct mt76_txwi_cache *txwi; 9026c92544dSBjoern A. Zeeb struct ieee80211_sta *sta = NULL; 903*cbb3ec25SBjoern A. Zeeb struct mt76_wcid *wcid = NULL; 9046c92544dSBjoern A. Zeeb #if defined(__linux__) 9056c92544dSBjoern A. Zeeb LIST_HEAD(free_list); 9066c92544dSBjoern A. Zeeb void *end = data + len; 9076c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__) 9086c92544dSBjoern A. Zeeb LINUX_LIST_HEAD(free_list); 9096c92544dSBjoern A. Zeeb void *end = (u8 *)data + len; 9106c92544dSBjoern A. Zeeb #endif 9116c92544dSBjoern A. Zeeb bool v3, wake = false; 9126c92544dSBjoern A. Zeeb u16 total, count = 0; 9136c92544dSBjoern A. Zeeb u32 txd = le32_to_cpu(free->txd); 9146c92544dSBjoern A. Zeeb __le32 *cur_info; 9156c92544dSBjoern A. Zeeb 9166c92544dSBjoern A. Zeeb mt7915_mac_tx_free_prepare(dev); 9176c92544dSBjoern A. Zeeb 9186c92544dSBjoern A. Zeeb total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT); 9196c92544dSBjoern A. Zeeb v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4); 9206c92544dSBjoern A. Zeeb 9216c92544dSBjoern A. Zeeb for (cur_info = tx_info; count < total; cur_info++) { 922*cbb3ec25SBjoern A. Zeeb u32 msdu, info; 9236c92544dSBjoern A. Zeeb u8 i; 9246c92544dSBjoern A. Zeeb 925*cbb3ec25SBjoern A. Zeeb if (WARN_ON_ONCE((void *)cur_info >= end)) 926*cbb3ec25SBjoern A. Zeeb return; 927*cbb3ec25SBjoern A. Zeeb 9286c92544dSBjoern A. Zeeb /* 9296c92544dSBjoern A. Zeeb * 1'b1: new wcid pair. 9306c92544dSBjoern A. Zeeb * 1'b0: msdu_id with the same 'wcid pair' as above. 9316c92544dSBjoern A. Zeeb */ 932*cbb3ec25SBjoern A. Zeeb info = le32_to_cpu(*cur_info); 9336c92544dSBjoern A. Zeeb if (info & MT_TX_FREE_PAIR) { 9346c92544dSBjoern A. Zeeb struct mt7915_sta *msta; 9356c92544dSBjoern A. Zeeb u16 idx; 9366c92544dSBjoern A. Zeeb 9376c92544dSBjoern A. Zeeb idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); 9386c92544dSBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[idx]); 9396c92544dSBjoern A. Zeeb sta = wcid_to_sta(wcid); 9406c92544dSBjoern A. Zeeb if (!sta) 9416c92544dSBjoern A. Zeeb continue; 9426c92544dSBjoern A. Zeeb 9436c92544dSBjoern A. Zeeb msta = container_of(wcid, struct mt7915_sta, wcid); 944*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&mdev->sta_poll_lock); 945*cbb3ec25SBjoern A. Zeeb if (list_empty(&msta->wcid.poll_list)) 946*cbb3ec25SBjoern A. Zeeb list_add_tail(&msta->wcid.poll_list, 947*cbb3ec25SBjoern A. Zeeb &mdev->sta_poll_list); 948*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&mdev->sta_poll_lock); 9496c92544dSBjoern A. Zeeb continue; 9506c92544dSBjoern A. Zeeb } 9516c92544dSBjoern A. Zeeb 952*cbb3ec25SBjoern A. Zeeb if (!mtk_wed_device_active(&mdev->mmio.wed) && wcid) { 953*cbb3ec25SBjoern A. Zeeb u32 tx_retries = 0, tx_failed = 0; 954*cbb3ec25SBjoern A. Zeeb 955*cbb3ec25SBjoern A. Zeeb if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3)) { 956*cbb3ec25SBjoern A. Zeeb tx_retries = 957*cbb3ec25SBjoern A. Zeeb FIELD_GET(MT_TX_FREE_COUNT_V3, info) - 1; 958*cbb3ec25SBjoern A. Zeeb tx_failed = tx_retries + 959*cbb3ec25SBjoern A. Zeeb !!FIELD_GET(MT_TX_FREE_STAT_V3, info); 960*cbb3ec25SBjoern A. Zeeb } else if (!v3 && (info & MT_TX_FREE_MPDU_HEADER)) { 961*cbb3ec25SBjoern A. Zeeb tx_retries = 962*cbb3ec25SBjoern A. Zeeb FIELD_GET(MT_TX_FREE_COUNT, info) - 1; 963*cbb3ec25SBjoern A. Zeeb tx_failed = tx_retries + 964*cbb3ec25SBjoern A. Zeeb !!FIELD_GET(MT_TX_FREE_STAT, info); 965*cbb3ec25SBjoern A. Zeeb } 966*cbb3ec25SBjoern A. Zeeb wcid->stats.tx_retries += tx_retries; 967*cbb3ec25SBjoern A. Zeeb wcid->stats.tx_failed += tx_failed; 968*cbb3ec25SBjoern A. Zeeb } 969*cbb3ec25SBjoern A. Zeeb 970*cbb3ec25SBjoern A. Zeeb if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3)) 9716c92544dSBjoern A. Zeeb continue; 9726c92544dSBjoern A. Zeeb 9736c92544dSBjoern A. Zeeb for (i = 0; i < 1 + v3; i++) { 9746c92544dSBjoern A. Zeeb if (v3) { 9756c92544dSBjoern A. Zeeb msdu = (info >> (15 * i)) & MT_TX_FREE_MSDU_ID_V3; 9766c92544dSBjoern A. Zeeb if (msdu == MT_TX_FREE_MSDU_ID_V3) 9776c92544dSBjoern A. Zeeb continue; 9786c92544dSBjoern A. Zeeb } else { 9796c92544dSBjoern A. Zeeb msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); 9806c92544dSBjoern A. Zeeb } 9816c92544dSBjoern A. Zeeb count++; 9826c92544dSBjoern A. Zeeb txwi = mt76_token_release(mdev, msdu, &wake); 9836c92544dSBjoern A. Zeeb if (!txwi) 9846c92544dSBjoern A. Zeeb continue; 9856c92544dSBjoern A. Zeeb 986*cbb3ec25SBjoern A. Zeeb mt76_connac2_txwi_free(mdev, txwi, sta, &free_list); 9876c92544dSBjoern A. Zeeb } 9886c92544dSBjoern A. Zeeb } 9896c92544dSBjoern A. Zeeb 9906c92544dSBjoern A. Zeeb mt7915_mac_tx_free_done(dev, &free_list, wake); 9916c92544dSBjoern A. Zeeb } 9926c92544dSBjoern A. Zeeb 9936c92544dSBjoern A. Zeeb static void 9946c92544dSBjoern A. Zeeb mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len) 9956c92544dSBjoern A. Zeeb { 9966c92544dSBjoern A. Zeeb struct mt76_connac_tx_free *free = data; 9976c92544dSBjoern A. Zeeb #if defined(__linux__) 9986c92544dSBjoern A. Zeeb __le16 *info = (__le16 *)(data + sizeof(*free)); 9996c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__) 10006c92544dSBjoern A. Zeeb __le16 *info = (__le16 *)((u8 *)data + sizeof(*free)); 10016c92544dSBjoern A. Zeeb #endif 10026c92544dSBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76; 10036c92544dSBjoern A. Zeeb #if defined(__linux__) 10046c92544dSBjoern A. Zeeb void *end = data + len; 10056c92544dSBjoern A. Zeeb LIST_HEAD(free_list); 10066c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__) 10076c92544dSBjoern A. Zeeb void *end = (u8 *)data + len; 10086c92544dSBjoern A. Zeeb LINUX_LIST_HEAD(free_list); 10096c92544dSBjoern A. Zeeb #endif 10106c92544dSBjoern A. Zeeb bool wake = false; 10116c92544dSBjoern A. Zeeb u8 i, count; 10126c92544dSBjoern A. Zeeb 10136c92544dSBjoern A. Zeeb mt7915_mac_tx_free_prepare(dev); 10146c92544dSBjoern A. Zeeb 10156c92544dSBjoern A. Zeeb count = FIELD_GET(MT_TX_FREE_MSDU_CNT_V0, le16_to_cpu(free->ctrl)); 10166c92544dSBjoern A. Zeeb if (WARN_ON_ONCE((void *)&info[count] > end)) 10176c92544dSBjoern A. Zeeb return; 10186c92544dSBjoern A. Zeeb 10196c92544dSBjoern A. Zeeb for (i = 0; i < count; i++) { 10206c92544dSBjoern A. Zeeb struct mt76_txwi_cache *txwi; 10216c92544dSBjoern A. Zeeb u16 msdu = le16_to_cpu(info[i]); 10226c92544dSBjoern A. Zeeb 10236c92544dSBjoern A. Zeeb txwi = mt76_token_release(mdev, msdu, &wake); 10246c92544dSBjoern A. Zeeb if (!txwi) 10256c92544dSBjoern A. Zeeb continue; 10266c92544dSBjoern A. Zeeb 1027*cbb3ec25SBjoern A. Zeeb mt76_connac2_txwi_free(mdev, txwi, NULL, &free_list); 10286c92544dSBjoern A. Zeeb } 10296c92544dSBjoern A. Zeeb 10306c92544dSBjoern A. Zeeb mt7915_mac_tx_free_done(dev, &free_list, wake); 10316c92544dSBjoern A. Zeeb } 10326c92544dSBjoern A. Zeeb 10336c92544dSBjoern A. Zeeb static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) 10346c92544dSBjoern A. Zeeb { 10356c92544dSBjoern A. Zeeb struct mt7915_sta *msta = NULL; 10366c92544dSBjoern A. Zeeb struct mt76_wcid *wcid; 10376c92544dSBjoern A. Zeeb __le32 *txs_data = data; 10386c92544dSBjoern A. Zeeb u16 wcidx; 10396c92544dSBjoern A. Zeeb u8 pid; 10406c92544dSBjoern A. Zeeb 10416c92544dSBjoern A. Zeeb wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); 10426c92544dSBjoern A. Zeeb pid = le32_get_bits(txs_data[3], MT_TXS3_PID); 10436c92544dSBjoern A. Zeeb 10446c92544dSBjoern A. Zeeb if (pid < MT_PACKET_ID_WED) 10456c92544dSBjoern A. Zeeb return; 10466c92544dSBjoern A. Zeeb 10476c92544dSBjoern A. Zeeb if (wcidx >= mt7915_wtbl_size(dev)) 10486c92544dSBjoern A. Zeeb return; 10496c92544dSBjoern A. Zeeb 10506c92544dSBjoern A. Zeeb rcu_read_lock(); 10516c92544dSBjoern A. Zeeb 10526c92544dSBjoern A. Zeeb wcid = rcu_dereference(dev->mt76.wcid[wcidx]); 10536c92544dSBjoern A. Zeeb if (!wcid) 10546c92544dSBjoern A. Zeeb goto out; 10556c92544dSBjoern A. Zeeb 10566c92544dSBjoern A. Zeeb msta = container_of(wcid, struct mt7915_sta, wcid); 10576c92544dSBjoern A. Zeeb 10586c92544dSBjoern A. Zeeb if (pid == MT_PACKET_ID_WED) 10596c92544dSBjoern A. Zeeb mt76_connac2_mac_fill_txs(&dev->mt76, wcid, txs_data); 10606c92544dSBjoern A. Zeeb else 10616c92544dSBjoern A. Zeeb mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data); 10626c92544dSBjoern A. Zeeb 10636c92544dSBjoern A. Zeeb if (!wcid->sta) 10646c92544dSBjoern A. Zeeb goto out; 10656c92544dSBjoern A. Zeeb 1066*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 1067*cbb3ec25SBjoern A. Zeeb if (list_empty(&msta->wcid.poll_list)) 1068*cbb3ec25SBjoern A. Zeeb list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); 1069*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 10706c92544dSBjoern A. Zeeb 10716c92544dSBjoern A. Zeeb out: 10726c92544dSBjoern A. Zeeb rcu_read_unlock(); 10736c92544dSBjoern A. Zeeb } 10746c92544dSBjoern A. Zeeb 10756c92544dSBjoern A. Zeeb bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len) 10766c92544dSBjoern A. Zeeb { 10776c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); 10786c92544dSBjoern A. Zeeb __le32 *rxd = (__le32 *)data; 10796c92544dSBjoern A. Zeeb __le32 *end = (__le32 *)&rxd[len / 4]; 10806c92544dSBjoern A. Zeeb enum rx_pkt_type type; 10816c92544dSBjoern A. Zeeb 10826c92544dSBjoern A. Zeeb type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); 10836c92544dSBjoern A. Zeeb 10846c92544dSBjoern A. Zeeb switch (type) { 10856c92544dSBjoern A. Zeeb case PKT_TYPE_TXRX_NOTIFY: 10866c92544dSBjoern A. Zeeb mt7915_mac_tx_free(dev, data, len); 10876c92544dSBjoern A. Zeeb return false; 10886c92544dSBjoern A. Zeeb case PKT_TYPE_TXRX_NOTIFY_V0: 10896c92544dSBjoern A. Zeeb mt7915_mac_tx_free_v0(dev, data, len); 10906c92544dSBjoern A. Zeeb return false; 10916c92544dSBjoern A. Zeeb case PKT_TYPE_TXS: 10926c92544dSBjoern A. Zeeb for (rxd += 2; rxd + 8 <= end; rxd += 8) 10936c92544dSBjoern A. Zeeb mt7915_mac_add_txs(dev, rxd); 10946c92544dSBjoern A. Zeeb return false; 10956c92544dSBjoern A. Zeeb case PKT_TYPE_RX_FW_MONITOR: 10966c92544dSBjoern A. Zeeb #if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS) 10976c92544dSBjoern A. Zeeb mt7915_debugfs_rx_fw_monitor(dev, data, len); 10986c92544dSBjoern A. Zeeb #endif 10996c92544dSBjoern A. Zeeb return false; 11006c92544dSBjoern A. Zeeb default: 11016c92544dSBjoern A. Zeeb return true; 11026c92544dSBjoern A. Zeeb } 11036c92544dSBjoern A. Zeeb } 11046c92544dSBjoern A. Zeeb 11056c92544dSBjoern A. Zeeb void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, 1106*cbb3ec25SBjoern A. Zeeb struct sk_buff *skb, u32 *info) 11076c92544dSBjoern A. Zeeb { 11086c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); 11096c92544dSBjoern A. Zeeb __le32 *rxd = (__le32 *)skb->data; 11106c92544dSBjoern A. Zeeb __le32 *end = (__le32 *)&skb->data[skb->len]; 11116c92544dSBjoern A. Zeeb enum rx_pkt_type type; 11126c92544dSBjoern A. Zeeb 11136c92544dSBjoern A. Zeeb type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE); 11146c92544dSBjoern A. Zeeb 11156c92544dSBjoern A. Zeeb switch (type) { 11166c92544dSBjoern A. Zeeb case PKT_TYPE_TXRX_NOTIFY: 11176c92544dSBjoern A. Zeeb mt7915_mac_tx_free(dev, skb->data, skb->len); 11186c92544dSBjoern A. Zeeb napi_consume_skb(skb, 1); 11196c92544dSBjoern A. Zeeb break; 11206c92544dSBjoern A. Zeeb case PKT_TYPE_TXRX_NOTIFY_V0: 11216c92544dSBjoern A. Zeeb mt7915_mac_tx_free_v0(dev, skb->data, skb->len); 11226c92544dSBjoern A. Zeeb napi_consume_skb(skb, 1); 11236c92544dSBjoern A. Zeeb break; 11246c92544dSBjoern A. Zeeb case PKT_TYPE_RX_EVENT: 11256c92544dSBjoern A. Zeeb mt7915_mcu_rx_event(dev, skb); 11266c92544dSBjoern A. Zeeb break; 11276c92544dSBjoern A. Zeeb case PKT_TYPE_TXRXV: 11286c92544dSBjoern A. Zeeb mt7915_mac_fill_rx_vector(dev, skb); 11296c92544dSBjoern A. Zeeb break; 11306c92544dSBjoern A. Zeeb case PKT_TYPE_TXS: 11316c92544dSBjoern A. Zeeb for (rxd += 2; rxd + 8 <= end; rxd += 8) 11326c92544dSBjoern A. Zeeb mt7915_mac_add_txs(dev, rxd); 11336c92544dSBjoern A. Zeeb dev_kfree_skb(skb); 11346c92544dSBjoern A. Zeeb break; 11356c92544dSBjoern A. Zeeb case PKT_TYPE_RX_FW_MONITOR: 11366c92544dSBjoern A. Zeeb #if !defined(__FreeBSD__) || defined(CONFIG_MT7915_DEBUGFS) 11376c92544dSBjoern A. Zeeb mt7915_debugfs_rx_fw_monitor(dev, skb->data, skb->len); 11386c92544dSBjoern A. Zeeb #endif 11396c92544dSBjoern A. Zeeb dev_kfree_skb(skb); 11406c92544dSBjoern A. Zeeb break; 11416c92544dSBjoern A. Zeeb case PKT_TYPE_NORMAL: 1142*cbb3ec25SBjoern A. Zeeb if (!mt7915_mac_fill_rx(dev, skb, q, info)) { 11436c92544dSBjoern A. Zeeb mt76_rx(&dev->mt76, q, skb); 11446c92544dSBjoern A. Zeeb return; 11456c92544dSBjoern A. Zeeb } 11466c92544dSBjoern A. Zeeb fallthrough; 11476c92544dSBjoern A. Zeeb default: 11486c92544dSBjoern A. Zeeb dev_kfree_skb(skb); 11496c92544dSBjoern A. Zeeb break; 11506c92544dSBjoern A. Zeeb } 11516c92544dSBjoern A. Zeeb } 11526c92544dSBjoern A. Zeeb 11536c92544dSBjoern A. Zeeb void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy) 11546c92544dSBjoern A. Zeeb { 11556c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 1156*cbb3ec25SBjoern A. Zeeb u32 reg = MT_WF_PHY_RX_CTRL1(phy->mt76->band_idx); 11576c92544dSBjoern A. Zeeb 11586c92544dSBjoern A. Zeeb mt76_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN); 11596c92544dSBjoern A. Zeeb mt76_set(dev, reg, BIT(11) | BIT(9)); 11606c92544dSBjoern A. Zeeb } 11616c92544dSBjoern A. Zeeb 11626c92544dSBjoern A. Zeeb void mt7915_mac_reset_counters(struct mt7915_phy *phy) 11636c92544dSBjoern A. Zeeb { 11646c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 11656c92544dSBjoern A. Zeeb int i; 11666c92544dSBjoern A. Zeeb 11676c92544dSBjoern A. Zeeb for (i = 0; i < 4; i++) { 1168*cbb3ec25SBjoern A. Zeeb mt76_rr(dev, MT_TX_AGG_CNT(phy->mt76->band_idx, i)); 1169*cbb3ec25SBjoern A. Zeeb mt76_rr(dev, MT_TX_AGG_CNT2(phy->mt76->band_idx, i)); 11706c92544dSBjoern A. Zeeb } 11716c92544dSBjoern A. Zeeb 11726c92544dSBjoern A. Zeeb phy->mt76->survey_time = ktime_get_boottime(); 1173*cbb3ec25SBjoern A. Zeeb memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats)); 11746c92544dSBjoern A. Zeeb 11756c92544dSBjoern A. Zeeb /* reset airtime counters */ 1176*cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(phy->mt76->band_idx), 11776c92544dSBjoern A. Zeeb MT_WF_RMAC_MIB_RXTIME_CLR); 11786c92544dSBjoern A. Zeeb 11796c92544dSBjoern A. Zeeb mt7915_mcu_get_chan_mib_info(phy, true); 11806c92544dSBjoern A. Zeeb } 11816c92544dSBjoern A. Zeeb 11826c92544dSBjoern A. Zeeb void mt7915_mac_set_timing(struct mt7915_phy *phy) 11836c92544dSBjoern A. Zeeb { 11846c92544dSBjoern A. Zeeb s16 coverage_class = phy->coverage_class; 11856c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 11866c92544dSBjoern A. Zeeb struct mt7915_phy *ext_phy = mt7915_ext_phy(dev); 11876c92544dSBjoern A. Zeeb u32 val, reg_offset; 11886c92544dSBjoern A. Zeeb u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | 11896c92544dSBjoern A. Zeeb FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); 11906c92544dSBjoern A. Zeeb u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | 11916c92544dSBjoern A. Zeeb FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); 1192*cbb3ec25SBjoern A. Zeeb u8 band = phy->mt76->band_idx; 1193*cbb3ec25SBjoern A. Zeeb int eifs_ofdm = 360, sifs = 10, offset; 11946c92544dSBjoern A. Zeeb bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); 11956c92544dSBjoern A. Zeeb 11966c92544dSBjoern A. Zeeb if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) 11976c92544dSBjoern A. Zeeb return; 11986c92544dSBjoern A. Zeeb 11996c92544dSBjoern A. Zeeb if (ext_phy) 12006c92544dSBjoern A. Zeeb coverage_class = max_t(s16, dev->phy.coverage_class, 12016c92544dSBjoern A. Zeeb ext_phy->coverage_class); 12026c92544dSBjoern A. Zeeb 1203*cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_ARB_SCR(band), 12046c92544dSBjoern A. Zeeb MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 12056c92544dSBjoern A. Zeeb udelay(1); 12066c92544dSBjoern A. Zeeb 12076c92544dSBjoern A. Zeeb offset = 3 * coverage_class; 12086c92544dSBjoern A. Zeeb reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | 12096c92544dSBjoern A. Zeeb FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); 12106c92544dSBjoern A. Zeeb 1211*cbb3ec25SBjoern A. Zeeb if (!is_mt7915(&dev->mt76)) { 1212*cbb3ec25SBjoern A. Zeeb if (!a_band) { 1213*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_TMAC_ICR1(band), 12146c92544dSBjoern A. Zeeb FIELD_PREP(MT_IFS_EIFS_CCK, 314)); 1215*cbb3ec25SBjoern A. Zeeb eifs_ofdm = 78; 1216*cbb3ec25SBjoern A. Zeeb } else { 1217*cbb3ec25SBjoern A. Zeeb eifs_ofdm = 84; 1218*cbb3ec25SBjoern A. Zeeb } 1219*cbb3ec25SBjoern A. Zeeb } else if (a_band) { 1220*cbb3ec25SBjoern A. Zeeb sifs = 16; 1221*cbb3ec25SBjoern A. Zeeb } 1222*cbb3ec25SBjoern A. Zeeb 1223*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_TMAC_CDTR(band), cck + reg_offset); 1224*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_TMAC_ODTR(band), ofdm + reg_offset); 1225*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_TMAC_ICR0(band), 1226*cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_IFS_EIFS_OFDM, eifs_ofdm) | 1227*cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_IFS_RIFS, 2) | 1228*cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_IFS_SIFS, sifs) | 1229*cbb3ec25SBjoern A. Zeeb FIELD_PREP(MT_IFS_SLOT, phy->slottime)); 12306c92544dSBjoern A. Zeeb 12316c92544dSBjoern A. Zeeb if (phy->slottime < 20 || a_band) 12326c92544dSBjoern A. Zeeb val = MT7915_CFEND_RATE_DEFAULT; 12336c92544dSBjoern A. Zeeb else 12346c92544dSBjoern A. Zeeb val = MT7915_CFEND_RATE_11B; 12356c92544dSBjoern A. Zeeb 1236*cbb3ec25SBjoern A. Zeeb mt76_rmw_field(dev, MT_AGG_ACR0(band), MT_AGG_ACR_CFEND_RATE, val); 1237*cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_ARB_SCR(band), 12386c92544dSBjoern A. Zeeb MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 12396c92544dSBjoern A. Zeeb } 12406c92544dSBjoern A. Zeeb 1241*cbb3ec25SBjoern A. Zeeb void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool band) 12426c92544dSBjoern A. Zeeb { 12436c92544dSBjoern A. Zeeb u32 reg; 12446c92544dSBjoern A. Zeeb 1245*cbb3ec25SBjoern A. Zeeb reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_RXTD12(band) : 1246*cbb3ec25SBjoern A. Zeeb MT_WF_PHY_RXTD12_MT7916(band); 12476c92544dSBjoern A. Zeeb mt76_set(dev, reg, 12486c92544dSBjoern A. Zeeb MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY | 12496c92544dSBjoern A. Zeeb MT_WF_PHY_RXTD12_IRPI_SW_CLR); 12506c92544dSBjoern A. Zeeb 1251*cbb3ec25SBjoern A. Zeeb reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_RX_CTRL1(band) : 1252*cbb3ec25SBjoern A. Zeeb MT_WF_PHY_RX_CTRL1_MT7916(band); 12536c92544dSBjoern A. Zeeb mt76_set(dev, reg, FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); 12546c92544dSBjoern A. Zeeb } 12556c92544dSBjoern A. Zeeb 12566c92544dSBjoern A. Zeeb static u8 12576c92544dSBjoern A. Zeeb mt7915_phy_get_nf(struct mt7915_phy *phy, int idx) 12586c92544dSBjoern A. Zeeb { 12596c92544dSBjoern A. Zeeb static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; 12606c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 12616c92544dSBjoern A. Zeeb u32 val, sum = 0, n = 0; 12626c92544dSBjoern A. Zeeb int nss, i; 12636c92544dSBjoern A. Zeeb 12646c92544dSBjoern A. Zeeb for (nss = 0; nss < hweight8(phy->mt76->chainmask); nss++) { 12656c92544dSBjoern A. Zeeb u32 reg = is_mt7915(&dev->mt76) ? 12666c92544dSBjoern A. Zeeb MT_WF_IRPI_NSS(0, nss + (idx << dev->dbdc_support)) : 12676c92544dSBjoern A. Zeeb MT_WF_IRPI_NSS_MT7916(idx, nss); 12686c92544dSBjoern A. Zeeb 12696c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { 12706c92544dSBjoern A. Zeeb val = mt76_rr(dev, reg); 12716c92544dSBjoern A. Zeeb sum += val * nf_power[i]; 12726c92544dSBjoern A. Zeeb n += val; 12736c92544dSBjoern A. Zeeb } 12746c92544dSBjoern A. Zeeb } 12756c92544dSBjoern A. Zeeb 12766c92544dSBjoern A. Zeeb if (!n) 12776c92544dSBjoern A. Zeeb return 0; 12786c92544dSBjoern A. Zeeb 12796c92544dSBjoern A. Zeeb return sum / n; 12806c92544dSBjoern A. Zeeb } 12816c92544dSBjoern A. Zeeb 12826c92544dSBjoern A. Zeeb void mt7915_update_channel(struct mt76_phy *mphy) 12836c92544dSBjoern A. Zeeb { 12846c92544dSBjoern A. Zeeb struct mt7915_phy *phy = (struct mt7915_phy *)mphy->priv; 12856c92544dSBjoern A. Zeeb struct mt76_channel_state *state = mphy->chan_state; 12866c92544dSBjoern A. Zeeb int nf; 12876c92544dSBjoern A. Zeeb 12886c92544dSBjoern A. Zeeb mt7915_mcu_get_chan_mib_info(phy, false); 12896c92544dSBjoern A. Zeeb 1290*cbb3ec25SBjoern A. Zeeb nf = mt7915_phy_get_nf(phy, phy->mt76->band_idx); 12916c92544dSBjoern A. Zeeb if (!phy->noise) 12926c92544dSBjoern A. Zeeb phy->noise = nf << 4; 12936c92544dSBjoern A. Zeeb else if (nf) 12946c92544dSBjoern A. Zeeb phy->noise += nf - (phy->noise >> 4); 12956c92544dSBjoern A. Zeeb 12966c92544dSBjoern A. Zeeb state->noise = -(phy->noise >> 4); 12976c92544dSBjoern A. Zeeb } 12986c92544dSBjoern A. Zeeb 12996c92544dSBjoern A. Zeeb static bool 13006c92544dSBjoern A. Zeeb mt7915_wait_reset_state(struct mt7915_dev *dev, u32 state) 13016c92544dSBjoern A. Zeeb { 13026c92544dSBjoern A. Zeeb bool ret; 13036c92544dSBjoern A. Zeeb 13046c92544dSBjoern A. Zeeb ret = wait_event_timeout(dev->reset_wait, 1305*cbb3ec25SBjoern A. Zeeb (READ_ONCE(dev->recovery.state) & state), 13066c92544dSBjoern A. Zeeb MT7915_RESET_TIMEOUT); 13076c92544dSBjoern A. Zeeb 13086c92544dSBjoern A. Zeeb WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); 13096c92544dSBjoern A. Zeeb return ret; 13106c92544dSBjoern A. Zeeb } 13116c92544dSBjoern A. Zeeb 13126c92544dSBjoern A. Zeeb static void 13136c92544dSBjoern A. Zeeb mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) 13146c92544dSBjoern A. Zeeb { 13156c92544dSBjoern A. Zeeb struct ieee80211_hw *hw = priv; 13166c92544dSBjoern A. Zeeb 13176c92544dSBjoern A. Zeeb switch (vif->type) { 13186c92544dSBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT: 13196c92544dSBjoern A. Zeeb case NL80211_IFTYPE_ADHOC: 13206c92544dSBjoern A. Zeeb case NL80211_IFTYPE_AP: 13216c92544dSBjoern A. Zeeb mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon, 13226c92544dSBjoern A. Zeeb BSS_CHANGED_BEACON_ENABLED); 13236c92544dSBjoern A. Zeeb break; 13246c92544dSBjoern A. Zeeb default: 13256c92544dSBjoern A. Zeeb break; 13266c92544dSBjoern A. Zeeb } 13276c92544dSBjoern A. Zeeb } 13286c92544dSBjoern A. Zeeb 13296c92544dSBjoern A. Zeeb static void 13306c92544dSBjoern A. Zeeb mt7915_update_beacons(struct mt7915_dev *dev) 13316c92544dSBjoern A. Zeeb { 13326c92544dSBjoern A. Zeeb struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1]; 13336c92544dSBjoern A. Zeeb 13346c92544dSBjoern A. Zeeb ieee80211_iterate_active_interfaces(dev->mt76.hw, 13356c92544dSBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL, 13366c92544dSBjoern A. Zeeb mt7915_update_vif_beacon, dev->mt76.hw); 13376c92544dSBjoern A. Zeeb 13386c92544dSBjoern A. Zeeb if (!mphy_ext) 13396c92544dSBjoern A. Zeeb return; 13406c92544dSBjoern A. Zeeb 13416c92544dSBjoern A. Zeeb ieee80211_iterate_active_interfaces(mphy_ext->hw, 13426c92544dSBjoern A. Zeeb IEEE80211_IFACE_ITER_RESUME_ALL, 13436c92544dSBjoern A. Zeeb mt7915_update_vif_beacon, mphy_ext->hw); 13446c92544dSBjoern A. Zeeb } 13456c92544dSBjoern A. Zeeb 1346*cbb3ec25SBjoern A. Zeeb static int 1347*cbb3ec25SBjoern A. Zeeb mt7915_mac_restart(struct mt7915_dev *dev) 13486c92544dSBjoern A. Zeeb { 1349*cbb3ec25SBjoern A. Zeeb struct mt7915_phy *phy2; 1350*cbb3ec25SBjoern A. Zeeb struct mt76_phy *ext_phy; 1351*cbb3ec25SBjoern A. Zeeb struct mt76_dev *mdev = &dev->mt76; 1352*cbb3ec25SBjoern A. Zeeb int i, ret; 1353*cbb3ec25SBjoern A. Zeeb 1354*cbb3ec25SBjoern A. Zeeb ext_phy = dev->mt76.phys[MT_BAND1]; 1355*cbb3ec25SBjoern A. Zeeb phy2 = ext_phy ? ext_phy->priv : NULL; 1356*cbb3ec25SBjoern A. Zeeb 1357*cbb3ec25SBjoern A. Zeeb if (dev->hif2) { 1358*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT1_MASK_CSR, 0x0); 1359*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0); 1360*cbb3ec25SBjoern A. Zeeb } 1361*cbb3ec25SBjoern A. Zeeb 1362*cbb3ec25SBjoern A. Zeeb if (dev_is_pci(mdev->dev)) { 1363*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); 1364*cbb3ec25SBjoern A. Zeeb if (dev->hif2) { 1365*cbb3ec25SBjoern A. Zeeb if (is_mt7915(mdev)) 1366*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0); 1367*cbb3ec25SBjoern A. Zeeb else 1368*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0x0); 1369*cbb3ec25SBjoern A. Zeeb } 1370*cbb3ec25SBjoern A. Zeeb } 1371*cbb3ec25SBjoern A. Zeeb 1372*cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &dev->mphy.state); 1373*cbb3ec25SBjoern A. Zeeb set_bit(MT76_MCU_RESET, &dev->mphy.state); 1374*cbb3ec25SBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait); 1375*cbb3ec25SBjoern A. Zeeb if (ext_phy) { 1376*cbb3ec25SBjoern A. Zeeb set_bit(MT76_RESET, &ext_phy->state); 1377*cbb3ec25SBjoern A. Zeeb set_bit(MT76_MCU_RESET, &ext_phy->state); 1378*cbb3ec25SBjoern A. Zeeb } 1379*cbb3ec25SBjoern A. Zeeb 1380*cbb3ec25SBjoern A. Zeeb /* lock/unlock all queues to ensure that no tx is pending */ 1381*cbb3ec25SBjoern A. Zeeb mt76_txq_schedule_all(&dev->mphy); 1382*cbb3ec25SBjoern A. Zeeb if (ext_phy) 1383*cbb3ec25SBjoern A. Zeeb mt76_txq_schedule_all(ext_phy); 1384*cbb3ec25SBjoern A. Zeeb 1385*cbb3ec25SBjoern A. Zeeb /* disable all tx/rx napi */ 1386*cbb3ec25SBjoern A. Zeeb mt76_worker_disable(&dev->mt76.tx_worker); 1387*cbb3ec25SBjoern A. Zeeb mt76_for_each_q_rx(mdev, i) { 1388*cbb3ec25SBjoern A. Zeeb if (mdev->q_rx[i].ndesc) 1389*cbb3ec25SBjoern A. Zeeb napi_disable(&dev->mt76.napi[i]); 1390*cbb3ec25SBjoern A. Zeeb } 1391*cbb3ec25SBjoern A. Zeeb napi_disable(&dev->mt76.tx_napi); 1392*cbb3ec25SBjoern A. Zeeb 1393*cbb3ec25SBjoern A. Zeeb /* token reinit */ 1394*cbb3ec25SBjoern A. Zeeb mt76_connac2_tx_token_put(&dev->mt76); 1395*cbb3ec25SBjoern A. Zeeb idr_init(&dev->mt76.token); 1396*cbb3ec25SBjoern A. Zeeb 1397*cbb3ec25SBjoern A. Zeeb mt7915_dma_reset(dev, true); 1398*cbb3ec25SBjoern A. Zeeb 1399*cbb3ec25SBjoern A. Zeeb local_bh_disable(); 1400*cbb3ec25SBjoern A. Zeeb mt76_for_each_q_rx(mdev, i) { 1401*cbb3ec25SBjoern A. Zeeb if (mdev->q_rx[i].ndesc) { 1402*cbb3ec25SBjoern A. Zeeb napi_enable(&dev->mt76.napi[i]); 1403*cbb3ec25SBjoern A. Zeeb napi_schedule(&dev->mt76.napi[i]); 1404*cbb3ec25SBjoern A. Zeeb } 1405*cbb3ec25SBjoern A. Zeeb } 1406*cbb3ec25SBjoern A. Zeeb local_bh_enable(); 1407*cbb3ec25SBjoern A. Zeeb clear_bit(MT76_MCU_RESET, &dev->mphy.state); 1408*cbb3ec25SBjoern A. Zeeb clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 1409*cbb3ec25SBjoern A. Zeeb 1410*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); 1411*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); 1412*cbb3ec25SBjoern A. Zeeb 1413*cbb3ec25SBjoern A. Zeeb if (dev->hif2) { 1414*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask); 1415*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0); 1416*cbb3ec25SBjoern A. Zeeb } 1417*cbb3ec25SBjoern A. Zeeb if (dev_is_pci(mdev->dev)) { 1418*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); 1419*cbb3ec25SBjoern A. Zeeb if (dev->hif2) { 1420*cbb3ec25SBjoern A. Zeeb if (is_mt7915(mdev)) 1421*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); 1422*cbb3ec25SBjoern A. Zeeb else 1423*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff); 1424*cbb3ec25SBjoern A. Zeeb } 1425*cbb3ec25SBjoern A. Zeeb } 1426*cbb3ec25SBjoern A. Zeeb 1427*cbb3ec25SBjoern A. Zeeb /* load firmware */ 1428*cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_init_firmware(dev); 1429*cbb3ec25SBjoern A. Zeeb if (ret) 1430*cbb3ec25SBjoern A. Zeeb goto out; 1431*cbb3ec25SBjoern A. Zeeb 1432*cbb3ec25SBjoern A. Zeeb /* set the necessary init items */ 1433*cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_eeprom(dev); 1434*cbb3ec25SBjoern A. Zeeb if (ret) 1435*cbb3ec25SBjoern A. Zeeb goto out; 1436*cbb3ec25SBjoern A. Zeeb 1437*cbb3ec25SBjoern A. Zeeb mt7915_mac_init(dev); 1438*cbb3ec25SBjoern A. Zeeb mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband); 1439*cbb3ec25SBjoern A. Zeeb mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband); 1440*cbb3ec25SBjoern A. Zeeb ret = mt7915_txbf_init(dev); 1441*cbb3ec25SBjoern A. Zeeb 1442*cbb3ec25SBjoern A. Zeeb if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) { 1443*cbb3ec25SBjoern A. Zeeb ret = mt7915_run(dev->mphy.hw); 1444*cbb3ec25SBjoern A. Zeeb if (ret) 1445*cbb3ec25SBjoern A. Zeeb goto out; 1446*cbb3ec25SBjoern A. Zeeb } 1447*cbb3ec25SBjoern A. Zeeb 1448*cbb3ec25SBjoern A. Zeeb if (ext_phy && test_bit(MT76_STATE_RUNNING, &ext_phy->state)) { 1449*cbb3ec25SBjoern A. Zeeb ret = mt7915_run(ext_phy->hw); 1450*cbb3ec25SBjoern A. Zeeb if (ret) 1451*cbb3ec25SBjoern A. Zeeb goto out; 1452*cbb3ec25SBjoern A. Zeeb } 1453*cbb3ec25SBjoern A. Zeeb 1454*cbb3ec25SBjoern A. Zeeb out: 1455*cbb3ec25SBjoern A. Zeeb /* reset done */ 1456*cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &dev->mphy.state); 1457*cbb3ec25SBjoern A. Zeeb if (phy2) 1458*cbb3ec25SBjoern A. Zeeb clear_bit(MT76_RESET, &phy2->mt76->state); 1459*cbb3ec25SBjoern A. Zeeb 1460*cbb3ec25SBjoern A. Zeeb local_bh_disable(); 1461*cbb3ec25SBjoern A. Zeeb napi_enable(&dev->mt76.tx_napi); 1462*cbb3ec25SBjoern A. Zeeb napi_schedule(&dev->mt76.tx_napi); 1463*cbb3ec25SBjoern A. Zeeb local_bh_enable(); 1464*cbb3ec25SBjoern A. Zeeb 1465*cbb3ec25SBjoern A. Zeeb mt76_worker_enable(&dev->mt76.tx_worker); 1466*cbb3ec25SBjoern A. Zeeb 1467*cbb3ec25SBjoern A. Zeeb return ret; 1468*cbb3ec25SBjoern A. Zeeb } 1469*cbb3ec25SBjoern A. Zeeb 1470*cbb3ec25SBjoern A. Zeeb static void 1471*cbb3ec25SBjoern A. Zeeb mt7915_mac_full_reset(struct mt7915_dev *dev) 1472*cbb3ec25SBjoern A. Zeeb { 1473*cbb3ec25SBjoern A. Zeeb struct mt76_phy *ext_phy; 14746c92544dSBjoern A. Zeeb int i; 14756c92544dSBjoern A. Zeeb 1476*cbb3ec25SBjoern A. Zeeb ext_phy = dev->mt76.phys[MT_BAND1]; 14776c92544dSBjoern A. Zeeb 1478*cbb3ec25SBjoern A. Zeeb dev->recovery.hw_full_reset = true; 14796c92544dSBjoern A. Zeeb 1480*cbb3ec25SBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait); 1481*cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(mt76_hw(dev)); 1482*cbb3ec25SBjoern A. Zeeb if (ext_phy) 1483*cbb3ec25SBjoern A. Zeeb ieee80211_stop_queues(ext_phy->hw); 1484*cbb3ec25SBjoern A. Zeeb 1485*cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&dev->mphy.mac_work); 1486*cbb3ec25SBjoern A. Zeeb if (ext_phy) 1487*cbb3ec25SBjoern A. Zeeb cancel_delayed_work_sync(&ext_phy->mac_work); 1488*cbb3ec25SBjoern A. Zeeb 1489*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 1490*cbb3ec25SBjoern A. Zeeb for (i = 0; i < 10; i++) { 1491*cbb3ec25SBjoern A. Zeeb if (!mt7915_mac_restart(dev)) 1492*cbb3ec25SBjoern A. Zeeb break; 14936c92544dSBjoern A. Zeeb } 1494*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 14956c92544dSBjoern A. Zeeb 1496*cbb3ec25SBjoern A. Zeeb if (i == 10) 1497*cbb3ec25SBjoern A. Zeeb dev_err(dev->mt76.dev, "chip full reset failed\n"); 14986c92544dSBjoern A. Zeeb 1499*cbb3ec25SBjoern A. Zeeb ieee80211_restart_hw(mt76_hw(dev)); 1500*cbb3ec25SBjoern A. Zeeb if (ext_phy) 1501*cbb3ec25SBjoern A. Zeeb ieee80211_restart_hw(ext_phy->hw); 15026c92544dSBjoern A. Zeeb 1503*cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(mt76_hw(dev)); 1504*cbb3ec25SBjoern A. Zeeb if (ext_phy) 1505*cbb3ec25SBjoern A. Zeeb ieee80211_wake_queues(ext_phy->hw); 15066c92544dSBjoern A. Zeeb 1507*cbb3ec25SBjoern A. Zeeb dev->recovery.hw_full_reset = false; 1508*cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, 1509*cbb3ec25SBjoern A. Zeeb MT7915_WATCHDOG_TIME); 1510*cbb3ec25SBjoern A. Zeeb if (ext_phy) 1511*cbb3ec25SBjoern A. Zeeb ieee80211_queue_delayed_work(ext_phy->hw, 1512*cbb3ec25SBjoern A. Zeeb &ext_phy->mac_work, 1513*cbb3ec25SBjoern A. Zeeb MT7915_WATCHDOG_TIME); 15146c92544dSBjoern A. Zeeb } 15156c92544dSBjoern A. Zeeb 15166c92544dSBjoern A. Zeeb /* system error recovery */ 15176c92544dSBjoern A. Zeeb void mt7915_mac_reset_work(struct work_struct *work) 15186c92544dSBjoern A. Zeeb { 15196c92544dSBjoern A. Zeeb struct mt7915_phy *phy2; 15206c92544dSBjoern A. Zeeb struct mt76_phy *ext_phy; 15216c92544dSBjoern A. Zeeb struct mt7915_dev *dev; 15226c92544dSBjoern A. Zeeb int i; 15236c92544dSBjoern A. Zeeb 15246c92544dSBjoern A. Zeeb dev = container_of(work, struct mt7915_dev, reset_work); 15256c92544dSBjoern A. Zeeb ext_phy = dev->mt76.phys[MT_BAND1]; 15266c92544dSBjoern A. Zeeb phy2 = ext_phy ? ext_phy->priv : NULL; 15276c92544dSBjoern A. Zeeb 1528*cbb3ec25SBjoern A. Zeeb /* chip full reset */ 1529*cbb3ec25SBjoern A. Zeeb if (dev->recovery.restart) { 1530*cbb3ec25SBjoern A. Zeeb /* disable WA/WM WDT */ 1531*cbb3ec25SBjoern A. Zeeb mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA, 1532*cbb3ec25SBjoern A. Zeeb MT_MCU_CMD_WDT_MASK); 1533*cbb3ec25SBjoern A. Zeeb 1534*cbb3ec25SBjoern A. Zeeb if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT) 1535*cbb3ec25SBjoern A. Zeeb dev->recovery.wa_reset_count++; 1536*cbb3ec25SBjoern A. Zeeb else 1537*cbb3ec25SBjoern A. Zeeb dev->recovery.wm_reset_count++; 1538*cbb3ec25SBjoern A. Zeeb 1539*cbb3ec25SBjoern A. Zeeb mt7915_mac_full_reset(dev); 1540*cbb3ec25SBjoern A. Zeeb 1541*cbb3ec25SBjoern A. Zeeb /* enable mcu irq */ 1542*cbb3ec25SBjoern A. Zeeb mt7915_irq_enable(dev, MT_INT_MCU_CMD); 1543*cbb3ec25SBjoern A. Zeeb mt7915_irq_disable(dev, 0); 1544*cbb3ec25SBjoern A. Zeeb 1545*cbb3ec25SBjoern A. Zeeb /* enable WA/WM WDT */ 1546*cbb3ec25SBjoern A. Zeeb mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK); 1547*cbb3ec25SBjoern A. Zeeb 1548*cbb3ec25SBjoern A. Zeeb dev->recovery.state = MT_MCU_CMD_NORMAL_STATE; 1549*cbb3ec25SBjoern A. Zeeb dev->recovery.restart = false; 15506c92544dSBjoern A. Zeeb return; 1551*cbb3ec25SBjoern A. Zeeb } 1552*cbb3ec25SBjoern A. Zeeb 1553*cbb3ec25SBjoern A. Zeeb /* chip partial reset */ 1554*cbb3ec25SBjoern A. Zeeb if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) 1555*cbb3ec25SBjoern A. Zeeb return; 1556*cbb3ec25SBjoern A. Zeeb 1557*cbb3ec25SBjoern A. Zeeb if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { 1558*cbb3ec25SBjoern A. Zeeb mtk_wed_device_stop(&dev->mt76.mmio.wed); 1559*cbb3ec25SBjoern A. Zeeb if (!is_mt798x(&dev->mt76)) 1560*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_INT_WED_MASK_CSR, 0); 1561*cbb3ec25SBjoern A. Zeeb } 15626c92544dSBjoern A. Zeeb 15636c92544dSBjoern A. Zeeb ieee80211_stop_queues(mt76_hw(dev)); 15646c92544dSBjoern A. Zeeb if (ext_phy) 15656c92544dSBjoern A. Zeeb ieee80211_stop_queues(ext_phy->hw); 15666c92544dSBjoern A. Zeeb 15676c92544dSBjoern A. Zeeb set_bit(MT76_RESET, &dev->mphy.state); 15686c92544dSBjoern A. Zeeb set_bit(MT76_MCU_RESET, &dev->mphy.state); 15696c92544dSBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait); 15706c92544dSBjoern A. Zeeb cancel_delayed_work_sync(&dev->mphy.mac_work); 15716c92544dSBjoern A. Zeeb if (phy2) { 15726c92544dSBjoern A. Zeeb set_bit(MT76_RESET, &phy2->mt76->state); 15736c92544dSBjoern A. Zeeb cancel_delayed_work_sync(&phy2->mt76->mac_work); 15746c92544dSBjoern A. Zeeb } 15756c92544dSBjoern A. Zeeb mt76_worker_disable(&dev->mt76.tx_worker); 15766c92544dSBjoern A. Zeeb mt76_for_each_q_rx(&dev->mt76, i) 15776c92544dSBjoern A. Zeeb napi_disable(&dev->mt76.napi[i]); 15786c92544dSBjoern A. Zeeb napi_disable(&dev->mt76.tx_napi); 15796c92544dSBjoern A. Zeeb 15806c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 15816c92544dSBjoern A. Zeeb 15826c92544dSBjoern A. Zeeb mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); 15836c92544dSBjoern A. Zeeb 15846c92544dSBjoern A. Zeeb if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { 1585*cbb3ec25SBjoern A. Zeeb mt7915_dma_reset(dev, false); 15866c92544dSBjoern A. Zeeb 1587*cbb3ec25SBjoern A. Zeeb mt76_connac2_tx_token_put(&dev->mt76); 15886c92544dSBjoern A. Zeeb idr_init(&dev->mt76.token); 15896c92544dSBjoern A. Zeeb 15906c92544dSBjoern A. Zeeb mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); 15916c92544dSBjoern A. Zeeb mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); 15926c92544dSBjoern A. Zeeb } 15936c92544dSBjoern A. Zeeb 1594*cbb3ec25SBjoern A. Zeeb mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); 1595*cbb3ec25SBjoern A. Zeeb mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); 1596*cbb3ec25SBjoern A. Zeeb 1597*cbb3ec25SBjoern A. Zeeb /* enable DMA Tx/Rx and interrupt */ 1598*cbb3ec25SBjoern A. Zeeb mt7915_dma_start(dev, false, false); 1599*cbb3ec25SBjoern A. Zeeb 16006c92544dSBjoern A. Zeeb clear_bit(MT76_MCU_RESET, &dev->mphy.state); 16016c92544dSBjoern A. Zeeb clear_bit(MT76_RESET, &dev->mphy.state); 16026c92544dSBjoern A. Zeeb if (phy2) 16036c92544dSBjoern A. Zeeb clear_bit(MT76_RESET, &phy2->mt76->state); 16046c92544dSBjoern A. Zeeb 16056c92544dSBjoern A. Zeeb local_bh_disable(); 16066c92544dSBjoern A. Zeeb mt76_for_each_q_rx(&dev->mt76, i) { 16076c92544dSBjoern A. Zeeb napi_enable(&dev->mt76.napi[i]); 16086c92544dSBjoern A. Zeeb napi_schedule(&dev->mt76.napi[i]); 16096c92544dSBjoern A. Zeeb } 16106c92544dSBjoern A. Zeeb local_bh_enable(); 16116c92544dSBjoern A. Zeeb 1612*cbb3ec25SBjoern A. Zeeb tasklet_schedule(&dev->mt76.irq_tasklet); 16136c92544dSBjoern A. Zeeb 16146c92544dSBjoern A. Zeeb mt76_worker_enable(&dev->mt76.tx_worker); 16156c92544dSBjoern A. Zeeb 16166c92544dSBjoern A. Zeeb local_bh_disable(); 16176c92544dSBjoern A. Zeeb napi_enable(&dev->mt76.tx_napi); 16186c92544dSBjoern A. Zeeb napi_schedule(&dev->mt76.tx_napi); 16196c92544dSBjoern A. Zeeb local_bh_enable(); 16206c92544dSBjoern A. Zeeb 16216c92544dSBjoern A. Zeeb ieee80211_wake_queues(mt76_hw(dev)); 16226c92544dSBjoern A. Zeeb if (ext_phy) 16236c92544dSBjoern A. Zeeb ieee80211_wake_queues(ext_phy->hw); 16246c92544dSBjoern A. Zeeb 16256c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 16266c92544dSBjoern A. Zeeb 16276c92544dSBjoern A. Zeeb mt7915_update_beacons(dev); 16286c92544dSBjoern A. Zeeb 16296c92544dSBjoern A. Zeeb ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, 16306c92544dSBjoern A. Zeeb MT7915_WATCHDOG_TIME); 16316c92544dSBjoern A. Zeeb if (phy2) 16326c92544dSBjoern A. Zeeb ieee80211_queue_delayed_work(ext_phy->hw, 16336c92544dSBjoern A. Zeeb &phy2->mt76->mac_work, 16346c92544dSBjoern A. Zeeb MT7915_WATCHDOG_TIME); 16356c92544dSBjoern A. Zeeb } 16366c92544dSBjoern A. Zeeb 1637*cbb3ec25SBjoern A. Zeeb /* firmware coredump */ 1638*cbb3ec25SBjoern A. Zeeb void mt7915_mac_dump_work(struct work_struct *work) 1639*cbb3ec25SBjoern A. Zeeb { 1640*cbb3ec25SBjoern A. Zeeb const struct mt7915_mem_region *mem_region; 1641*cbb3ec25SBjoern A. Zeeb struct mt7915_crash_data *crash_data; 1642*cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev; 1643*cbb3ec25SBjoern A. Zeeb struct mt7915_mem_hdr *hdr; 1644*cbb3ec25SBjoern A. Zeeb size_t buf_len; 1645*cbb3ec25SBjoern A. Zeeb int i; 1646*cbb3ec25SBjoern A. Zeeb u32 num; 1647*cbb3ec25SBjoern A. Zeeb u8 *buf; 1648*cbb3ec25SBjoern A. Zeeb 1649*cbb3ec25SBjoern A. Zeeb dev = container_of(work, struct mt7915_dev, dump_work); 1650*cbb3ec25SBjoern A. Zeeb 1651*cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->dump_mutex); 1652*cbb3ec25SBjoern A. Zeeb 1653*cbb3ec25SBjoern A. Zeeb crash_data = mt7915_coredump_new(dev); 1654*cbb3ec25SBjoern A. Zeeb if (!crash_data) { 1655*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->dump_mutex); 1656*cbb3ec25SBjoern A. Zeeb goto skip_coredump; 1657*cbb3ec25SBjoern A. Zeeb } 1658*cbb3ec25SBjoern A. Zeeb 1659*cbb3ec25SBjoern A. Zeeb mem_region = mt7915_coredump_get_mem_layout(dev, &num); 1660*cbb3ec25SBjoern A. Zeeb if (!mem_region || !crash_data->memdump_buf_len) { 1661*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->dump_mutex); 1662*cbb3ec25SBjoern A. Zeeb goto skip_memdump; 1663*cbb3ec25SBjoern A. Zeeb } 1664*cbb3ec25SBjoern A. Zeeb 1665*cbb3ec25SBjoern A. Zeeb buf = crash_data->memdump_buf; 1666*cbb3ec25SBjoern A. Zeeb buf_len = crash_data->memdump_buf_len; 1667*cbb3ec25SBjoern A. Zeeb 1668*cbb3ec25SBjoern A. Zeeb /* dumping memory content... */ 1669*cbb3ec25SBjoern A. Zeeb memset(buf, 0, buf_len); 1670*cbb3ec25SBjoern A. Zeeb for (i = 0; i < num; i++) { 1671*cbb3ec25SBjoern A. Zeeb if (mem_region->len > buf_len) { 1672*cbb3ec25SBjoern A. Zeeb dev_warn(dev->mt76.dev, "%s len %lu is too large\n", 1673*cbb3ec25SBjoern A. Zeeb mem_region->name, 1674*cbb3ec25SBjoern A. Zeeb (unsigned long)mem_region->len); 1675*cbb3ec25SBjoern A. Zeeb break; 1676*cbb3ec25SBjoern A. Zeeb } 1677*cbb3ec25SBjoern A. Zeeb 1678*cbb3ec25SBjoern A. Zeeb /* reserve space for the header */ 1679*cbb3ec25SBjoern A. Zeeb hdr = (void *)buf; 1680*cbb3ec25SBjoern A. Zeeb buf += sizeof(*hdr); 1681*cbb3ec25SBjoern A. Zeeb buf_len -= sizeof(*hdr); 1682*cbb3ec25SBjoern A. Zeeb 1683*cbb3ec25SBjoern A. Zeeb mt7915_memcpy_fromio(dev, buf, mem_region->start, 1684*cbb3ec25SBjoern A. Zeeb mem_region->len); 1685*cbb3ec25SBjoern A. Zeeb 1686*cbb3ec25SBjoern A. Zeeb hdr->start = mem_region->start; 1687*cbb3ec25SBjoern A. Zeeb hdr->len = mem_region->len; 1688*cbb3ec25SBjoern A. Zeeb 1689*cbb3ec25SBjoern A. Zeeb if (!mem_region->len) 1690*cbb3ec25SBjoern A. Zeeb /* note: the header remains, just with zero length */ 1691*cbb3ec25SBjoern A. Zeeb break; 1692*cbb3ec25SBjoern A. Zeeb 1693*cbb3ec25SBjoern A. Zeeb buf += mem_region->len; 1694*cbb3ec25SBjoern A. Zeeb buf_len -= mem_region->len; 1695*cbb3ec25SBjoern A. Zeeb 1696*cbb3ec25SBjoern A. Zeeb mem_region++; 1697*cbb3ec25SBjoern A. Zeeb } 1698*cbb3ec25SBjoern A. Zeeb 1699*cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->dump_mutex); 1700*cbb3ec25SBjoern A. Zeeb 1701*cbb3ec25SBjoern A. Zeeb skip_memdump: 1702*cbb3ec25SBjoern A. Zeeb mt7915_coredump_submit(dev); 1703*cbb3ec25SBjoern A. Zeeb skip_coredump: 1704*cbb3ec25SBjoern A. Zeeb queue_work(dev->mt76.wq, &dev->reset_work); 1705*cbb3ec25SBjoern A. Zeeb } 1706*cbb3ec25SBjoern A. Zeeb 1707*cbb3ec25SBjoern A. Zeeb void mt7915_reset(struct mt7915_dev *dev) 1708*cbb3ec25SBjoern A. Zeeb { 1709*cbb3ec25SBjoern A. Zeeb if (!dev->recovery.hw_init_done) 1710*cbb3ec25SBjoern A. Zeeb return; 1711*cbb3ec25SBjoern A. Zeeb 1712*cbb3ec25SBjoern A. Zeeb if (dev->recovery.hw_full_reset) 1713*cbb3ec25SBjoern A. Zeeb return; 1714*cbb3ec25SBjoern A. Zeeb 1715*cbb3ec25SBjoern A. Zeeb /* wm/wa exception: do full recovery */ 1716*cbb3ec25SBjoern A. Zeeb if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) { 1717*cbb3ec25SBjoern A. Zeeb dev->recovery.restart = true; 1718*cbb3ec25SBjoern A. Zeeb dev_info(dev->mt76.dev, 1719*cbb3ec25SBjoern A. Zeeb "%s indicated firmware crash, attempting recovery\n", 1720*cbb3ec25SBjoern A. Zeeb wiphy_name(dev->mt76.hw->wiphy)); 1721*cbb3ec25SBjoern A. Zeeb 1722*cbb3ec25SBjoern A. Zeeb mt7915_irq_disable(dev, MT_INT_MCU_CMD); 1723*cbb3ec25SBjoern A. Zeeb queue_work(dev->mt76.wq, &dev->dump_work); 1724*cbb3ec25SBjoern A. Zeeb return; 1725*cbb3ec25SBjoern A. Zeeb } 1726*cbb3ec25SBjoern A. Zeeb 1727*cbb3ec25SBjoern A. Zeeb queue_work(dev->mt76.wq, &dev->reset_work); 1728*cbb3ec25SBjoern A. Zeeb wake_up(&dev->reset_wait); 1729*cbb3ec25SBjoern A. Zeeb } 1730*cbb3ec25SBjoern A. Zeeb 17316c92544dSBjoern A. Zeeb void mt7915_mac_update_stats(struct mt7915_phy *phy) 17326c92544dSBjoern A. Zeeb { 1733*cbb3ec25SBjoern A. Zeeb struct mt76_mib_stats *mib = &phy->mib; 17346c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 1735*cbb3ec25SBjoern A. Zeeb int i, aggr0 = 0, aggr1, cnt; 1736*cbb3ec25SBjoern A. Zeeb u8 band = phy->mt76->band_idx; 17376c92544dSBjoern A. Zeeb u32 val; 17386c92544dSBjoern A. Zeeb 1739*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR3(band)); 17406c92544dSBjoern A. Zeeb mib->fcs_err_cnt += is_mt7915(&dev->mt76) ? 17416c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK, cnt) : 17426c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK_MT7916, cnt); 17436c92544dSBjoern A. Zeeb 1744*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR4(band)); 17456c92544dSBjoern A. Zeeb mib->rx_fifo_full_cnt += FIELD_GET(MT_MIB_SDR4_RX_FIFO_FULL_MASK, cnt); 17466c92544dSBjoern A. Zeeb 1747*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR5(band)); 17486c92544dSBjoern A. Zeeb mib->rx_mpdu_cnt += cnt; 17496c92544dSBjoern A. Zeeb 1750*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR6(band)); 17516c92544dSBjoern A. Zeeb mib->channel_idle_cnt += FIELD_GET(MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK, cnt); 17526c92544dSBjoern A. Zeeb 1753*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR7(band)); 17546c92544dSBjoern A. Zeeb mib->rx_vector_mismatch_cnt += 17556c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR7_RX_VECTOR_MISMATCH_CNT_MASK, cnt); 17566c92544dSBjoern A. Zeeb 1757*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR8(band)); 17586c92544dSBjoern A. Zeeb mib->rx_delimiter_fail_cnt += 17596c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR8_RX_DELIMITER_FAIL_CNT_MASK, cnt); 17606c92544dSBjoern A. Zeeb 1761*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR10(band)); 17626c92544dSBjoern A. Zeeb mib->rx_mrdy_cnt += is_mt7915(&dev->mt76) ? 17636c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR10_MRDY_COUNT_MASK, cnt) : 17646c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR10_MRDY_COUNT_MASK_MT7916, cnt); 17656c92544dSBjoern A. Zeeb 1766*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR11(band)); 17676c92544dSBjoern A. Zeeb mib->rx_len_mismatch_cnt += 17686c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR11_RX_LEN_MISMATCH_CNT_MASK, cnt); 17696c92544dSBjoern A. Zeeb 1770*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR12(band)); 17716c92544dSBjoern A. Zeeb mib->tx_ampdu_cnt += cnt; 17726c92544dSBjoern A. Zeeb 1773*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR13(band)); 17746c92544dSBjoern A. Zeeb mib->tx_stop_q_empty_cnt += 17756c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR13_TX_STOP_Q_EMPTY_CNT_MASK, cnt); 17766c92544dSBjoern A. Zeeb 1777*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR14(band)); 17786c92544dSBjoern A. Zeeb mib->tx_mpdu_attempts_cnt += is_mt7915(&dev->mt76) ? 17796c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK, cnt) : 17806c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR14_TX_MPDU_ATTEMPTS_CNT_MASK_MT7916, cnt); 17816c92544dSBjoern A. Zeeb 1782*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR15(band)); 17836c92544dSBjoern A. Zeeb mib->tx_mpdu_success_cnt += is_mt7915(&dev->mt76) ? 17846c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK, cnt) : 17856c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR15_TX_MPDU_SUCCESS_CNT_MASK_MT7916, cnt); 17866c92544dSBjoern A. Zeeb 1787*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR16(band)); 17886c92544dSBjoern A. Zeeb mib->primary_cca_busy_time += 17896c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR16_PRIMARY_CCA_BUSY_TIME_MASK, cnt); 17906c92544dSBjoern A. Zeeb 1791*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR17(band)); 17926c92544dSBjoern A. Zeeb mib->secondary_cca_busy_time += 17936c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR17_SECONDARY_CCA_BUSY_TIME_MASK, cnt); 17946c92544dSBjoern A. Zeeb 1795*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR18(band)); 17966c92544dSBjoern A. Zeeb mib->primary_energy_detect_time += 17976c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR18_PRIMARY_ENERGY_DETECT_TIME_MASK, cnt); 17986c92544dSBjoern A. Zeeb 1799*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR19(band)); 18006c92544dSBjoern A. Zeeb mib->cck_mdrdy_time += FIELD_GET(MT_MIB_SDR19_CCK_MDRDY_TIME_MASK, cnt); 18016c92544dSBjoern A. Zeeb 1802*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR20(band)); 18036c92544dSBjoern A. Zeeb mib->ofdm_mdrdy_time += 18046c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR20_OFDM_VHT_MDRDY_TIME_MASK, cnt); 18056c92544dSBjoern A. Zeeb 1806*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR21(band)); 18076c92544dSBjoern A. Zeeb mib->green_mdrdy_time += 18086c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR21_GREEN_MDRDY_TIME_MASK, cnt); 18096c92544dSBjoern A. Zeeb 1810*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR22(band)); 18116c92544dSBjoern A. Zeeb mib->rx_ampdu_cnt += cnt; 18126c92544dSBjoern A. Zeeb 1813*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR23(band)); 18146c92544dSBjoern A. Zeeb mib->rx_ampdu_bytes_cnt += cnt; 18156c92544dSBjoern A. Zeeb 1816*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR24(band)); 18176c92544dSBjoern A. Zeeb mib->rx_ampdu_valid_subframe_cnt += is_mt7915(&dev->mt76) ? 18186c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK, cnt) : 18196c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR24_RX_AMPDU_SF_CNT_MASK_MT7916, cnt); 18206c92544dSBjoern A. Zeeb 1821*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR25(band)); 18226c92544dSBjoern A. Zeeb mib->rx_ampdu_valid_subframe_bytes_cnt += cnt; 18236c92544dSBjoern A. Zeeb 1824*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR27(band)); 18256c92544dSBjoern A. Zeeb mib->tx_rwp_fail_cnt += 18266c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR27_TX_RWP_FAIL_CNT_MASK, cnt); 18276c92544dSBjoern A. Zeeb 1828*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR28(band)); 18296c92544dSBjoern A. Zeeb mib->tx_rwp_need_cnt += 18306c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR28_TX_RWP_NEED_CNT_MASK, cnt); 18316c92544dSBjoern A. Zeeb 1832*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR29(band)); 18336c92544dSBjoern A. Zeeb mib->rx_pfdrop_cnt += is_mt7915(&dev->mt76) ? 18346c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR29_RX_PFDROP_CNT_MASK, cnt) : 18356c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR29_RX_PFDROP_CNT_MASK_MT7916, cnt); 18366c92544dSBjoern A. Zeeb 1837*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDRVEC(band)); 18386c92544dSBjoern A. Zeeb mib->rx_vec_queue_overflow_drop_cnt += is_mt7915(&dev->mt76) ? 18396c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK, cnt) : 18406c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_SDR30_RX_VEC_QUEUE_OVERFLOW_DROP_CNT_MASK_MT7916, cnt); 18416c92544dSBjoern A. Zeeb 1842*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR31(band)); 18436c92544dSBjoern A. Zeeb mib->rx_ba_cnt += cnt; 18446c92544dSBjoern A. Zeeb 1845*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDRMUBF(band)); 18466c92544dSBjoern A. Zeeb mib->tx_bf_cnt += FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt); 18476c92544dSBjoern A. Zeeb 1848*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_DR8(band)); 18496c92544dSBjoern A. Zeeb mib->tx_mu_mpdu_cnt += cnt; 18506c92544dSBjoern A. Zeeb 1851*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_DR9(band)); 18526c92544dSBjoern A. Zeeb mib->tx_mu_acked_mpdu_cnt += cnt; 18536c92544dSBjoern A. Zeeb 1854*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_DR11(band)); 18556c92544dSBjoern A. Zeeb mib->tx_su_acked_mpdu_cnt += cnt; 18566c92544dSBjoern A. Zeeb 1857*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_ETBF_PAR_RPT0(band)); 18586c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_PAR_RPT0_FB_BW, cnt); 18596c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NC, cnt); 18606c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NR, cnt); 18616c92544dSBjoern A. Zeeb 18626c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { 18636c92544dSBjoern A. Zeeb cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); 18646c92544dSBjoern A. Zeeb mib->tx_amsdu[i] += cnt; 18656c92544dSBjoern A. Zeeb mib->tx_amsdu_cnt += cnt; 18666c92544dSBjoern A. Zeeb } 18676c92544dSBjoern A. Zeeb 18686c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76)) { 1869*cbb3ec25SBjoern A. Zeeb for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) { 1870*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_MIB_MB_SDR1(band, (i << 4))); 18716c92544dSBjoern A. Zeeb mib->ba_miss_cnt += 18726c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); 18736c92544dSBjoern A. Zeeb mib->ack_fail_cnt += 18746c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); 18756c92544dSBjoern A. Zeeb 1876*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_MIB_MB_SDR0(band, (i << 4))); 18776c92544dSBjoern A. Zeeb mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); 18786c92544dSBjoern A. Zeeb mib->rts_retries_cnt += 18796c92544dSBjoern A. Zeeb FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); 18806c92544dSBjoern A. Zeeb 1881*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_TX_AGG_CNT(band, i)); 1882*cbb3ec25SBjoern A. Zeeb phy->mt76->aggr_stats[aggr0++] += val & 0xffff; 1883*cbb3ec25SBjoern A. Zeeb phy->mt76->aggr_stats[aggr0++] += val >> 16; 18846c92544dSBjoern A. Zeeb 1885*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_TX_AGG_CNT2(band, i)); 1886*cbb3ec25SBjoern A. Zeeb phy->mt76->aggr_stats[aggr1++] += val & 0xffff; 1887*cbb3ec25SBjoern A. Zeeb phy->mt76->aggr_stats[aggr1++] += val >> 16; 18886c92544dSBjoern A. Zeeb } 18896c92544dSBjoern A. Zeeb 1890*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR32(band)); 18916c92544dSBjoern A. Zeeb mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); 18926c92544dSBjoern A. Zeeb 1893*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR33(band)); 18946c92544dSBjoern A. Zeeb mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR33_TX_PKT_IBF_CNT, cnt); 18956c92544dSBjoern A. Zeeb 1896*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(band)); 18976c92544dSBjoern A. Zeeb mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt); 18986c92544dSBjoern A. Zeeb mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt); 18996c92544dSBjoern A. Zeeb 1900*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(band)); 19016c92544dSBjoern A. Zeeb mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt); 19026c92544dSBjoern A. Zeeb mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt); 19036c92544dSBjoern A. Zeeb 1904*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(band)); 19056c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt); 19066c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt); 19076c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt); 19086c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt); 19096c92544dSBjoern A. Zeeb } else { 19106c92544dSBjoern A. Zeeb for (i = 0; i < 2; i++) { 19116c92544dSBjoern A. Zeeb /* rts count */ 1912*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_MIB_MB_SDR0(band, (i << 2))); 19136c92544dSBjoern A. Zeeb mib->rts_cnt += FIELD_GET(GENMASK(15, 0), val); 19146c92544dSBjoern A. Zeeb mib->rts_cnt += FIELD_GET(GENMASK(31, 16), val); 19156c92544dSBjoern A. Zeeb 19166c92544dSBjoern A. Zeeb /* rts retry count */ 1917*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_MIB_MB_SDR1(band, (i << 2))); 19186c92544dSBjoern A. Zeeb mib->rts_retries_cnt += FIELD_GET(GENMASK(15, 0), val); 19196c92544dSBjoern A. Zeeb mib->rts_retries_cnt += FIELD_GET(GENMASK(31, 16), val); 19206c92544dSBjoern A. Zeeb 19216c92544dSBjoern A. Zeeb /* ba miss count */ 1922*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_MIB_MB_SDR2(band, (i << 2))); 19236c92544dSBjoern A. Zeeb mib->ba_miss_cnt += FIELD_GET(GENMASK(15, 0), val); 19246c92544dSBjoern A. Zeeb mib->ba_miss_cnt += FIELD_GET(GENMASK(31, 16), val); 19256c92544dSBjoern A. Zeeb 19266c92544dSBjoern A. Zeeb /* ack fail count */ 1927*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_MIB_MB_BFTF(band, (i << 2))); 19286c92544dSBjoern A. Zeeb mib->ack_fail_cnt += FIELD_GET(GENMASK(15, 0), val); 19296c92544dSBjoern A. Zeeb mib->ack_fail_cnt += FIELD_GET(GENMASK(31, 16), val); 19306c92544dSBjoern A. Zeeb } 19316c92544dSBjoern A. Zeeb 19326c92544dSBjoern A. Zeeb for (i = 0; i < 8; i++) { 1933*cbb3ec25SBjoern A. Zeeb val = mt76_rr(dev, MT_TX_AGG_CNT(band, i)); 1934*cbb3ec25SBjoern A. Zeeb phy->mt76->aggr_stats[aggr0++] += FIELD_GET(GENMASK(15, 0), val); 1935*cbb3ec25SBjoern A. Zeeb phy->mt76->aggr_stats[aggr0++] += FIELD_GET(GENMASK(31, 16), val); 19366c92544dSBjoern A. Zeeb } 19376c92544dSBjoern A. Zeeb 1938*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_SDR32(band)); 19396c92544dSBjoern A. Zeeb mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt); 19406c92544dSBjoern A. Zeeb mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt); 19416c92544dSBjoern A. Zeeb mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); 19426c92544dSBjoern A. Zeeb mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt); 19436c92544dSBjoern A. Zeeb 1944*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BFCR7(band)); 19456c92544dSBjoern A. Zeeb mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_MIB_BFCR7_BFEE_TX_FB_CPL, cnt); 19466c92544dSBjoern A. Zeeb 1947*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BFCR2(band)); 19486c92544dSBjoern A. Zeeb mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_MIB_BFCR2_BFEE_TX_FB_TRIG, cnt); 19496c92544dSBjoern A. Zeeb 1950*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BFCR0(band)); 19516c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt); 19526c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt); 19536c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt); 19546c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt); 19556c92544dSBjoern A. Zeeb 1956*cbb3ec25SBjoern A. Zeeb cnt = mt76_rr(dev, MT_MIB_BFCR1(band)); 19576c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt); 19586c92544dSBjoern A. Zeeb mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt); 19596c92544dSBjoern A. Zeeb } 19606c92544dSBjoern A. Zeeb } 19616c92544dSBjoern A. Zeeb 19626c92544dSBjoern A. Zeeb static void mt7915_mac_severe_check(struct mt7915_phy *phy) 19636c92544dSBjoern A. Zeeb { 19646c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 19656c92544dSBjoern A. Zeeb u32 trb; 19666c92544dSBjoern A. Zeeb 19676c92544dSBjoern A. Zeeb if (!phy->omac_mask) 19686c92544dSBjoern A. Zeeb return; 19696c92544dSBjoern A. Zeeb 19706c92544dSBjoern A. Zeeb /* In rare cases, TRB pointers might be out of sync leads to RMAC 19716c92544dSBjoern A. Zeeb * stopping Rx, so check status periodically to see if TRB hardware 19726c92544dSBjoern A. Zeeb * requires minimal recovery. 19736c92544dSBjoern A. Zeeb */ 1974*cbb3ec25SBjoern A. Zeeb trb = mt76_rr(dev, MT_TRB_RXPSR0(phy->mt76->band_idx)); 19756c92544dSBjoern A. Zeeb 19766c92544dSBjoern A. Zeeb if ((FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, trb) != 19776c92544dSBjoern A. Zeeb FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, trb)) && 19786c92544dSBjoern A. Zeeb (FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, phy->trb_ts) != 19796c92544dSBjoern A. Zeeb FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, phy->trb_ts)) && 19806c92544dSBjoern A. Zeeb trb == phy->trb_ts) 19816c92544dSBjoern A. Zeeb mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L3_RX_ABORT, 1982*cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx); 19836c92544dSBjoern A. Zeeb 19846c92544dSBjoern A. Zeeb phy->trb_ts = trb; 19856c92544dSBjoern A. Zeeb } 19866c92544dSBjoern A. Zeeb 19876c92544dSBjoern A. Zeeb void mt7915_mac_sta_rc_work(struct work_struct *work) 19886c92544dSBjoern A. Zeeb { 19896c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work); 19906c92544dSBjoern A. Zeeb struct ieee80211_sta *sta; 19916c92544dSBjoern A. Zeeb struct ieee80211_vif *vif; 19926c92544dSBjoern A. Zeeb struct mt7915_sta *msta; 19936c92544dSBjoern A. Zeeb u32 changed; 19946c92544dSBjoern A. Zeeb #if defined(__linux__) 19956c92544dSBjoern A. Zeeb LIST_HEAD(list); 19966c92544dSBjoern A. Zeeb #elif defined(__FreeBSD__) 19976c92544dSBjoern A. Zeeb LINUX_LIST_HEAD(list); 19986c92544dSBjoern A. Zeeb #endif 19996c92544dSBjoern A. Zeeb 2000*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 20016c92544dSBjoern A. Zeeb list_splice_init(&dev->sta_rc_list, &list); 20026c92544dSBjoern A. Zeeb 20036c92544dSBjoern A. Zeeb while (!list_empty(&list)) { 20046c92544dSBjoern A. Zeeb msta = list_first_entry(&list, struct mt7915_sta, rc_list); 20056c92544dSBjoern A. Zeeb list_del_init(&msta->rc_list); 20066c92544dSBjoern A. Zeeb changed = msta->changed; 20076c92544dSBjoern A. Zeeb msta->changed = 0; 2008*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 20096c92544dSBjoern A. Zeeb 20106c92544dSBjoern A. Zeeb sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); 20116c92544dSBjoern A. Zeeb vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); 20126c92544dSBjoern A. Zeeb 20136c92544dSBjoern A. Zeeb if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | 20146c92544dSBjoern A. Zeeb IEEE80211_RC_NSS_CHANGED | 20156c92544dSBjoern A. Zeeb IEEE80211_RC_BW_CHANGED)) 20166c92544dSBjoern A. Zeeb mt7915_mcu_add_rate_ctrl(dev, vif, sta, true); 20176c92544dSBjoern A. Zeeb 20186c92544dSBjoern A. Zeeb if (changed & IEEE80211_RC_SMPS_CHANGED) 20196c92544dSBjoern A. Zeeb mt7915_mcu_add_smps(dev, vif, sta); 20206c92544dSBjoern A. Zeeb 2021*cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock); 20226c92544dSBjoern A. Zeeb } 20236c92544dSBjoern A. Zeeb 2024*cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock); 20256c92544dSBjoern A. Zeeb } 20266c92544dSBjoern A. Zeeb 20276c92544dSBjoern A. Zeeb void mt7915_mac_work(struct work_struct *work) 20286c92544dSBjoern A. Zeeb { 20296c92544dSBjoern A. Zeeb struct mt7915_phy *phy; 20306c92544dSBjoern A. Zeeb struct mt76_phy *mphy; 20316c92544dSBjoern A. Zeeb 20326c92544dSBjoern A. Zeeb mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, 20336c92544dSBjoern A. Zeeb mac_work.work); 20346c92544dSBjoern A. Zeeb phy = mphy->priv; 20356c92544dSBjoern A. Zeeb 20366c92544dSBjoern A. Zeeb mutex_lock(&mphy->dev->mutex); 20376c92544dSBjoern A. Zeeb 20386c92544dSBjoern A. Zeeb mt76_update_survey(mphy); 20396c92544dSBjoern A. Zeeb if (++mphy->mac_work_count == 5) { 20406c92544dSBjoern A. Zeeb mphy->mac_work_count = 0; 20416c92544dSBjoern A. Zeeb 20426c92544dSBjoern A. Zeeb mt7915_mac_update_stats(phy); 20436c92544dSBjoern A. Zeeb mt7915_mac_severe_check(phy); 2044*cbb3ec25SBjoern A. Zeeb 2045*cbb3ec25SBjoern A. Zeeb if (phy->dev->muru_debug) 2046*cbb3ec25SBjoern A. Zeeb mt7915_mcu_muru_debug_get(phy); 20476c92544dSBjoern A. Zeeb } 20486c92544dSBjoern A. Zeeb 20496c92544dSBjoern A. Zeeb mutex_unlock(&mphy->dev->mutex); 20506c92544dSBjoern A. Zeeb 20516c92544dSBjoern A. Zeeb mt76_tx_status_check(mphy->dev, false); 20526c92544dSBjoern A. Zeeb 20536c92544dSBjoern A. Zeeb ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, 20546c92544dSBjoern A. Zeeb MT7915_WATCHDOG_TIME); 20556c92544dSBjoern A. Zeeb } 20566c92544dSBjoern A. Zeeb 20576c92544dSBjoern A. Zeeb static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy) 20586c92544dSBjoern A. Zeeb { 20596c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 20606c92544dSBjoern A. Zeeb 20616c92544dSBjoern A. Zeeb if (phy->rdd_state & BIT(0)) 20626c92544dSBjoern A. Zeeb mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 0, 20636c92544dSBjoern A. Zeeb MT_RX_SEL0, 0); 20646c92544dSBjoern A. Zeeb if (phy->rdd_state & BIT(1)) 20656c92544dSBjoern A. Zeeb mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 1, 20666c92544dSBjoern A. Zeeb MT_RX_SEL0, 0); 20676c92544dSBjoern A. Zeeb } 20686c92544dSBjoern A. Zeeb 20696c92544dSBjoern A. Zeeb static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain) 20706c92544dSBjoern A. Zeeb { 20716c92544dSBjoern A. Zeeb int err, region; 20726c92544dSBjoern A. Zeeb 20736c92544dSBjoern A. Zeeb switch (dev->mt76.region) { 20746c92544dSBjoern A. Zeeb case NL80211_DFS_ETSI: 20756c92544dSBjoern A. Zeeb region = 0; 20766c92544dSBjoern A. Zeeb break; 20776c92544dSBjoern A. Zeeb case NL80211_DFS_JP: 20786c92544dSBjoern A. Zeeb region = 2; 20796c92544dSBjoern A. Zeeb break; 20806c92544dSBjoern A. Zeeb case NL80211_DFS_FCC: 20816c92544dSBjoern A. Zeeb default: 20826c92544dSBjoern A. Zeeb region = 1; 20836c92544dSBjoern A. Zeeb break; 20846c92544dSBjoern A. Zeeb } 20856c92544dSBjoern A. Zeeb 20866c92544dSBjoern A. Zeeb err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain, 20876c92544dSBjoern A. Zeeb MT_RX_SEL0, region); 20886c92544dSBjoern A. Zeeb if (err < 0) 20896c92544dSBjoern A. Zeeb return err; 20906c92544dSBjoern A. Zeeb 2091*cbb3ec25SBjoern A. Zeeb if (is_mt7915(&dev->mt76)) { 2092*cbb3ec25SBjoern A. Zeeb err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, chain, 2093*cbb3ec25SBjoern A. Zeeb 0, dev->dbdc_support ? 2 : 0); 2094*cbb3ec25SBjoern A. Zeeb if (err < 0) 2095*cbb3ec25SBjoern A. Zeeb return err; 2096*cbb3ec25SBjoern A. Zeeb } 2097*cbb3ec25SBjoern A. Zeeb 20986c92544dSBjoern A. Zeeb return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, chain, 20996c92544dSBjoern A. Zeeb MT_RX_SEL0, 1); 21006c92544dSBjoern A. Zeeb } 21016c92544dSBjoern A. Zeeb 21026c92544dSBjoern A. Zeeb static int mt7915_dfs_start_radar_detector(struct mt7915_phy *phy) 21036c92544dSBjoern A. Zeeb { 21046c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef = &phy->mt76->chandef; 21056c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 21066c92544dSBjoern A. Zeeb int err; 21076c92544dSBjoern A. Zeeb 21086c92544dSBjoern A. Zeeb /* start CAC */ 2109*cbb3ec25SBjoern A. Zeeb err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, 2110*cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx, MT_RX_SEL0, 0); 21116c92544dSBjoern A. Zeeb if (err < 0) 21126c92544dSBjoern A. Zeeb return err; 21136c92544dSBjoern A. Zeeb 2114*cbb3ec25SBjoern A. Zeeb err = mt7915_dfs_start_rdd(dev, phy->mt76->band_idx); 21156c92544dSBjoern A. Zeeb if (err < 0) 21166c92544dSBjoern A. Zeeb return err; 21176c92544dSBjoern A. Zeeb 2118*cbb3ec25SBjoern A. Zeeb phy->rdd_state |= BIT(phy->mt76->band_idx); 21196c92544dSBjoern A. Zeeb 21206c92544dSBjoern A. Zeeb if (!is_mt7915(&dev->mt76)) 21216c92544dSBjoern A. Zeeb return 0; 21226c92544dSBjoern A. Zeeb 21236c92544dSBjoern A. Zeeb if (chandef->width == NL80211_CHAN_WIDTH_160 || 21246c92544dSBjoern A. Zeeb chandef->width == NL80211_CHAN_WIDTH_80P80) { 21256c92544dSBjoern A. Zeeb err = mt7915_dfs_start_rdd(dev, 1); 21266c92544dSBjoern A. Zeeb if (err < 0) 21276c92544dSBjoern A. Zeeb return err; 21286c92544dSBjoern A. Zeeb 21296c92544dSBjoern A. Zeeb phy->rdd_state |= BIT(1); 21306c92544dSBjoern A. Zeeb } 21316c92544dSBjoern A. Zeeb 21326c92544dSBjoern A. Zeeb return 0; 21336c92544dSBjoern A. Zeeb } 21346c92544dSBjoern A. Zeeb 21356c92544dSBjoern A. Zeeb static int 21366c92544dSBjoern A. Zeeb mt7915_dfs_init_radar_specs(struct mt7915_phy *phy) 21376c92544dSBjoern A. Zeeb { 21386c92544dSBjoern A. Zeeb const struct mt7915_dfs_radar_spec *radar_specs; 21396c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 21406c92544dSBjoern A. Zeeb int err, i; 21416c92544dSBjoern A. Zeeb 21426c92544dSBjoern A. Zeeb switch (dev->mt76.region) { 21436c92544dSBjoern A. Zeeb case NL80211_DFS_FCC: 21446c92544dSBjoern A. Zeeb radar_specs = &fcc_radar_specs; 21456c92544dSBjoern A. Zeeb err = mt7915_mcu_set_fcc5_lpn(dev, 8); 21466c92544dSBjoern A. Zeeb if (err < 0) 21476c92544dSBjoern A. Zeeb return err; 21486c92544dSBjoern A. Zeeb break; 21496c92544dSBjoern A. Zeeb case NL80211_DFS_ETSI: 21506c92544dSBjoern A. Zeeb radar_specs = &etsi_radar_specs; 21516c92544dSBjoern A. Zeeb break; 21526c92544dSBjoern A. Zeeb case NL80211_DFS_JP: 21536c92544dSBjoern A. Zeeb radar_specs = &jp_radar_specs; 21546c92544dSBjoern A. Zeeb break; 21556c92544dSBjoern A. Zeeb default: 21566c92544dSBjoern A. Zeeb return -EINVAL; 21576c92544dSBjoern A. Zeeb } 21586c92544dSBjoern A. Zeeb 21596c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) { 21606c92544dSBjoern A. Zeeb err = mt7915_mcu_set_radar_th(dev, i, 21616c92544dSBjoern A. Zeeb &radar_specs->radar_pattern[i]); 21626c92544dSBjoern A. Zeeb if (err < 0) 21636c92544dSBjoern A. Zeeb return err; 21646c92544dSBjoern A. Zeeb } 21656c92544dSBjoern A. Zeeb 21666c92544dSBjoern A. Zeeb return mt7915_mcu_set_pulse_th(dev, &radar_specs->pulse_th); 21676c92544dSBjoern A. Zeeb } 21686c92544dSBjoern A. Zeeb 21696c92544dSBjoern A. Zeeb int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy) 21706c92544dSBjoern A. Zeeb { 21716c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev; 21726c92544dSBjoern A. Zeeb enum mt76_dfs_state dfs_state, prev_state; 21736c92544dSBjoern A. Zeeb int err; 21746c92544dSBjoern A. Zeeb 21756c92544dSBjoern A. Zeeb prev_state = phy->mt76->dfs_state; 21766c92544dSBjoern A. Zeeb dfs_state = mt76_phy_dfs_state(phy->mt76); 21776c92544dSBjoern A. Zeeb 21786c92544dSBjoern A. Zeeb if (prev_state == dfs_state) 21796c92544dSBjoern A. Zeeb return 0; 21806c92544dSBjoern A. Zeeb 21816c92544dSBjoern A. Zeeb if (prev_state == MT_DFS_STATE_UNKNOWN) 21826c92544dSBjoern A. Zeeb mt7915_dfs_stop_radar_detector(phy); 21836c92544dSBjoern A. Zeeb 21846c92544dSBjoern A. Zeeb if (dfs_state == MT_DFS_STATE_DISABLED) 21856c92544dSBjoern A. Zeeb goto stop; 21866c92544dSBjoern A. Zeeb 21876c92544dSBjoern A. Zeeb if (prev_state <= MT_DFS_STATE_DISABLED) { 21886c92544dSBjoern A. Zeeb err = mt7915_dfs_init_radar_specs(phy); 21896c92544dSBjoern A. Zeeb if (err < 0) 21906c92544dSBjoern A. Zeeb return err; 21916c92544dSBjoern A. Zeeb 21926c92544dSBjoern A. Zeeb err = mt7915_dfs_start_radar_detector(phy); 21936c92544dSBjoern A. Zeeb if (err < 0) 21946c92544dSBjoern A. Zeeb return err; 21956c92544dSBjoern A. Zeeb 21966c92544dSBjoern A. Zeeb phy->mt76->dfs_state = MT_DFS_STATE_CAC; 21976c92544dSBjoern A. Zeeb } 21986c92544dSBjoern A. Zeeb 21996c92544dSBjoern A. Zeeb if (dfs_state == MT_DFS_STATE_CAC) 22006c92544dSBjoern A. Zeeb return 0; 22016c92544dSBjoern A. Zeeb 22026c92544dSBjoern A. Zeeb err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END, 2203*cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx, MT_RX_SEL0, 0); 22046c92544dSBjoern A. Zeeb if (err < 0) { 22056c92544dSBjoern A. Zeeb phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN; 22066c92544dSBjoern A. Zeeb return err; 22076c92544dSBjoern A. Zeeb } 22086c92544dSBjoern A. Zeeb 22096c92544dSBjoern A. Zeeb phy->mt76->dfs_state = MT_DFS_STATE_ACTIVE; 22106c92544dSBjoern A. Zeeb return 0; 22116c92544dSBjoern A. Zeeb 22126c92544dSBjoern A. Zeeb stop: 22136c92544dSBjoern A. Zeeb err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, 2214*cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx, MT_RX_SEL0, 0); 22156c92544dSBjoern A. Zeeb if (err < 0) 22166c92544dSBjoern A. Zeeb return err; 22176c92544dSBjoern A. Zeeb 2218*cbb3ec25SBjoern A. Zeeb if (is_mt7915(&dev->mt76)) { 2219*cbb3ec25SBjoern A. Zeeb err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, 2220*cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx, 0, 2221*cbb3ec25SBjoern A. Zeeb dev->dbdc_support ? 2 : 0); 2222*cbb3ec25SBjoern A. Zeeb if (err < 0) 2223*cbb3ec25SBjoern A. Zeeb return err; 2224*cbb3ec25SBjoern A. Zeeb } 2225*cbb3ec25SBjoern A. Zeeb 22266c92544dSBjoern A. Zeeb mt7915_dfs_stop_radar_detector(phy); 22276c92544dSBjoern A. Zeeb phy->mt76->dfs_state = MT_DFS_STATE_DISABLED; 22286c92544dSBjoern A. Zeeb 22296c92544dSBjoern A. Zeeb return 0; 22306c92544dSBjoern A. Zeeb } 22316c92544dSBjoern A. Zeeb 22326c92544dSBjoern A. Zeeb static int 22336c92544dSBjoern A. Zeeb mt7915_mac_twt_duration_align(int duration) 22346c92544dSBjoern A. Zeeb { 22356c92544dSBjoern A. Zeeb return duration << 8; 22366c92544dSBjoern A. Zeeb } 22376c92544dSBjoern A. Zeeb 22386c92544dSBjoern A. Zeeb static u64 22396c92544dSBjoern A. Zeeb mt7915_mac_twt_sched_list_add(struct mt7915_dev *dev, 22406c92544dSBjoern A. Zeeb struct mt7915_twt_flow *flow) 22416c92544dSBjoern A. Zeeb { 22426c92544dSBjoern A. Zeeb struct mt7915_twt_flow *iter, *iter_next; 22436c92544dSBjoern A. Zeeb u32 duration = flow->duration << 8; 22446c92544dSBjoern A. Zeeb u64 start_tsf; 22456c92544dSBjoern A. Zeeb 22466c92544dSBjoern A. Zeeb iter = list_first_entry_or_null(&dev->twt_list, 22476c92544dSBjoern A. Zeeb struct mt7915_twt_flow, list); 22486c92544dSBjoern A. Zeeb if (!iter || !iter->sched || iter->start_tsf > duration) { 22496c92544dSBjoern A. Zeeb /* add flow as first entry in the list */ 22506c92544dSBjoern A. Zeeb list_add(&flow->list, &dev->twt_list); 22516c92544dSBjoern A. Zeeb return 0; 22526c92544dSBjoern A. Zeeb } 22536c92544dSBjoern A. Zeeb 22546c92544dSBjoern A. Zeeb list_for_each_entry_safe(iter, iter_next, &dev->twt_list, list) { 22556c92544dSBjoern A. Zeeb start_tsf = iter->start_tsf + 22566c92544dSBjoern A. Zeeb mt7915_mac_twt_duration_align(iter->duration); 22576c92544dSBjoern A. Zeeb if (list_is_last(&iter->list, &dev->twt_list)) 22586c92544dSBjoern A. Zeeb break; 22596c92544dSBjoern A. Zeeb 22606c92544dSBjoern A. Zeeb if (!iter_next->sched || 22616c92544dSBjoern A. Zeeb iter_next->start_tsf > start_tsf + duration) { 22626c92544dSBjoern A. Zeeb list_add(&flow->list, &iter->list); 22636c92544dSBjoern A. Zeeb goto out; 22646c92544dSBjoern A. Zeeb } 22656c92544dSBjoern A. Zeeb } 22666c92544dSBjoern A. Zeeb 22676c92544dSBjoern A. Zeeb /* add flow as last entry in the list */ 22686c92544dSBjoern A. Zeeb list_add_tail(&flow->list, &dev->twt_list); 22696c92544dSBjoern A. Zeeb out: 22706c92544dSBjoern A. Zeeb return start_tsf; 22716c92544dSBjoern A. Zeeb } 22726c92544dSBjoern A. Zeeb 22736c92544dSBjoern A. Zeeb static int mt7915_mac_check_twt_req(struct ieee80211_twt_setup *twt) 22746c92544dSBjoern A. Zeeb { 22756c92544dSBjoern A. Zeeb struct ieee80211_twt_params *twt_agrt; 22766c92544dSBjoern A. Zeeb u64 interval, duration; 22776c92544dSBjoern A. Zeeb u16 mantissa; 22786c92544dSBjoern A. Zeeb u8 exp; 22796c92544dSBjoern A. Zeeb 22806c92544dSBjoern A. Zeeb /* only individual agreement supported */ 22816c92544dSBjoern A. Zeeb if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) 22826c92544dSBjoern A. Zeeb return -EOPNOTSUPP; 22836c92544dSBjoern A. Zeeb 22846c92544dSBjoern A. Zeeb /* only 256us unit supported */ 22856c92544dSBjoern A. Zeeb if (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) 22866c92544dSBjoern A. Zeeb return -EOPNOTSUPP; 22876c92544dSBjoern A. Zeeb 22886c92544dSBjoern A. Zeeb twt_agrt = (struct ieee80211_twt_params *)twt->params; 22896c92544dSBjoern A. Zeeb 22906c92544dSBjoern A. Zeeb /* explicit agreement not supported */ 22916c92544dSBjoern A. Zeeb if (!(twt_agrt->req_type & cpu_to_le16(IEEE80211_TWT_REQTYPE_IMPLICIT))) 22926c92544dSBjoern A. Zeeb return -EOPNOTSUPP; 22936c92544dSBjoern A. Zeeb 22946c92544dSBjoern A. Zeeb exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, 22956c92544dSBjoern A. Zeeb le16_to_cpu(twt_agrt->req_type)); 22966c92544dSBjoern A. Zeeb mantissa = le16_to_cpu(twt_agrt->mantissa); 22976c92544dSBjoern A. Zeeb duration = twt_agrt->min_twt_dur << 8; 22986c92544dSBjoern A. Zeeb 22996c92544dSBjoern A. Zeeb interval = (u64)mantissa << exp; 23006c92544dSBjoern A. Zeeb if (interval < duration) 23016c92544dSBjoern A. Zeeb return -EOPNOTSUPP; 23026c92544dSBjoern A. Zeeb 23036c92544dSBjoern A. Zeeb return 0; 23046c92544dSBjoern A. Zeeb } 23056c92544dSBjoern A. Zeeb 23066c92544dSBjoern A. Zeeb static bool 23076c92544dSBjoern A. Zeeb mt7915_mac_twt_param_equal(struct mt7915_sta *msta, 23086c92544dSBjoern A. Zeeb struct ieee80211_twt_params *twt_agrt) 23096c92544dSBjoern A. Zeeb { 23106c92544dSBjoern A. Zeeb u16 type = le16_to_cpu(twt_agrt->req_type); 23116c92544dSBjoern A. Zeeb u8 exp; 23126c92544dSBjoern A. Zeeb int i; 23136c92544dSBjoern A. Zeeb 23146c92544dSBjoern A. Zeeb exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type); 23156c92544dSBjoern A. Zeeb for (i = 0; i < MT7915_MAX_STA_TWT_AGRT; i++) { 23166c92544dSBjoern A. Zeeb struct mt7915_twt_flow *f; 23176c92544dSBjoern A. Zeeb 23186c92544dSBjoern A. Zeeb if (!(msta->twt.flowid_mask & BIT(i))) 23196c92544dSBjoern A. Zeeb continue; 23206c92544dSBjoern A. Zeeb 23216c92544dSBjoern A. Zeeb f = &msta->twt.flow[i]; 23226c92544dSBjoern A. Zeeb if (f->duration == twt_agrt->min_twt_dur && 23236c92544dSBjoern A. Zeeb f->mantissa == twt_agrt->mantissa && 23246c92544dSBjoern A. Zeeb f->exp == exp && 23256c92544dSBjoern A. Zeeb f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) && 23266c92544dSBjoern A. Zeeb f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) && 23276c92544dSBjoern A. Zeeb f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER)) 23286c92544dSBjoern A. Zeeb return true; 23296c92544dSBjoern A. Zeeb } 23306c92544dSBjoern A. Zeeb 23316c92544dSBjoern A. Zeeb return false; 23326c92544dSBjoern A. Zeeb } 23336c92544dSBjoern A. Zeeb 23346c92544dSBjoern A. Zeeb void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, 23356c92544dSBjoern A. Zeeb struct ieee80211_sta *sta, 23366c92544dSBjoern A. Zeeb struct ieee80211_twt_setup *twt) 23376c92544dSBjoern A. Zeeb { 23386c92544dSBjoern A. Zeeb enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT; 23396c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; 23406c92544dSBjoern A. Zeeb struct ieee80211_twt_params *twt_agrt = (void *)twt->params; 23416c92544dSBjoern A. Zeeb u16 req_type = le16_to_cpu(twt_agrt->req_type); 23426c92544dSBjoern A. Zeeb enum ieee80211_twt_setup_cmd sta_setup_cmd; 23436c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw); 23446c92544dSBjoern A. Zeeb struct mt7915_twt_flow *flow; 23456c92544dSBjoern A. Zeeb int flowid, table_id; 23466c92544dSBjoern A. Zeeb u8 exp; 23476c92544dSBjoern A. Zeeb 23486c92544dSBjoern A. Zeeb if (mt7915_mac_check_twt_req(twt)) 23496c92544dSBjoern A. Zeeb goto out; 23506c92544dSBjoern A. Zeeb 23516c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex); 23526c92544dSBjoern A. Zeeb 23536c92544dSBjoern A. Zeeb if (dev->twt.n_agrt == MT7915_MAX_TWT_AGRT) 23546c92544dSBjoern A. Zeeb goto unlock; 23556c92544dSBjoern A. Zeeb 23566c92544dSBjoern A. Zeeb if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow)) 23576c92544dSBjoern A. Zeeb goto unlock; 23586c92544dSBjoern A. Zeeb 23596c92544dSBjoern A. Zeeb if (twt_agrt->min_twt_dur < MT7915_MIN_TWT_DUR) { 23606c92544dSBjoern A. Zeeb setup_cmd = TWT_SETUP_CMD_DICTATE; 23616c92544dSBjoern A. Zeeb twt_agrt->min_twt_dur = MT7915_MIN_TWT_DUR; 23626c92544dSBjoern A. Zeeb goto unlock; 23636c92544dSBjoern A. Zeeb } 23646c92544dSBjoern A. Zeeb 23656c92544dSBjoern A. Zeeb flowid = ffs(~msta->twt.flowid_mask) - 1; 23666c92544dSBjoern A. Zeeb twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID); 23676c92544dSBjoern A. Zeeb twt_agrt->req_type |= le16_encode_bits(flowid, 23686c92544dSBjoern A. Zeeb IEEE80211_TWT_REQTYPE_FLOWID); 23696c92544dSBjoern A. Zeeb 23706c92544dSBjoern A. Zeeb table_id = ffs(~dev->twt.table_mask) - 1; 23716c92544dSBjoern A. Zeeb exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); 23726c92544dSBjoern A. Zeeb sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type); 23736c92544dSBjoern A. Zeeb 23746c92544dSBjoern A. Zeeb if (mt7915_mac_twt_param_equal(msta, twt_agrt)) 23756c92544dSBjoern A. Zeeb goto unlock; 23766c92544dSBjoern A. Zeeb 23776c92544dSBjoern A. Zeeb flow = &msta->twt.flow[flowid]; 23786c92544dSBjoern A. Zeeb memset(flow, 0, sizeof(*flow)); 23796c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&flow->list); 23806c92544dSBjoern A. Zeeb flow->wcid = msta->wcid.idx; 23816c92544dSBjoern A. Zeeb flow->table_id = table_id; 23826c92544dSBjoern A. Zeeb flow->id = flowid; 23836c92544dSBjoern A. Zeeb flow->duration = twt_agrt->min_twt_dur; 23846c92544dSBjoern A. Zeeb flow->mantissa = twt_agrt->mantissa; 23856c92544dSBjoern A. Zeeb flow->exp = exp; 23866c92544dSBjoern A. Zeeb flow->protection = !!(req_type & IEEE80211_TWT_REQTYPE_PROTECTION); 23876c92544dSBjoern A. Zeeb flow->flowtype = !!(req_type & IEEE80211_TWT_REQTYPE_FLOWTYPE); 23886c92544dSBjoern A. Zeeb flow->trigger = !!(req_type & IEEE80211_TWT_REQTYPE_TRIGGER); 23896c92544dSBjoern A. Zeeb 23906c92544dSBjoern A. Zeeb if (sta_setup_cmd == TWT_SETUP_CMD_REQUEST || 23916c92544dSBjoern A. Zeeb sta_setup_cmd == TWT_SETUP_CMD_SUGGEST) { 23926c92544dSBjoern A. Zeeb u64 interval = (u64)le16_to_cpu(twt_agrt->mantissa) << exp; 23936c92544dSBjoern A. Zeeb u64 flow_tsf, curr_tsf; 23946c92544dSBjoern A. Zeeb u32 rem; 23956c92544dSBjoern A. Zeeb 23966c92544dSBjoern A. Zeeb flow->sched = true; 23976c92544dSBjoern A. Zeeb flow->start_tsf = mt7915_mac_twt_sched_list_add(dev, flow); 23986c92544dSBjoern A. Zeeb curr_tsf = __mt7915_get_tsf(hw, msta->vif); 23996c92544dSBjoern A. Zeeb div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem); 24006c92544dSBjoern A. Zeeb flow_tsf = curr_tsf + interval - rem; 24016c92544dSBjoern A. Zeeb twt_agrt->twt = cpu_to_le64(flow_tsf); 24026c92544dSBjoern A. Zeeb } else { 24036c92544dSBjoern A. Zeeb list_add_tail(&flow->list, &dev->twt_list); 24046c92544dSBjoern A. Zeeb } 24056c92544dSBjoern A. Zeeb flow->tsf = le64_to_cpu(twt_agrt->twt); 24066c92544dSBjoern A. Zeeb 24076c92544dSBjoern A. Zeeb if (mt7915_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD)) 24086c92544dSBjoern A. Zeeb goto unlock; 24096c92544dSBjoern A. Zeeb 24106c92544dSBjoern A. Zeeb setup_cmd = TWT_SETUP_CMD_ACCEPT; 24116c92544dSBjoern A. Zeeb dev->twt.table_mask |= BIT(table_id); 24126c92544dSBjoern A. Zeeb msta->twt.flowid_mask |= BIT(flowid); 24136c92544dSBjoern A. Zeeb dev->twt.n_agrt++; 24146c92544dSBjoern A. Zeeb 24156c92544dSBjoern A. Zeeb unlock: 24166c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex); 24176c92544dSBjoern A. Zeeb out: 24186c92544dSBjoern A. Zeeb twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD); 24196c92544dSBjoern A. Zeeb twt_agrt->req_type |= 24206c92544dSBjoern A. Zeeb le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD); 24216c92544dSBjoern A. Zeeb twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | 24226c92544dSBjoern A. Zeeb (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); 24236c92544dSBjoern A. Zeeb } 24246c92544dSBjoern A. Zeeb 24256c92544dSBjoern A. Zeeb void mt7915_mac_twt_teardown_flow(struct mt7915_dev *dev, 24266c92544dSBjoern A. Zeeb struct mt7915_sta *msta, 24276c92544dSBjoern A. Zeeb u8 flowid) 24286c92544dSBjoern A. Zeeb { 24296c92544dSBjoern A. Zeeb struct mt7915_twt_flow *flow; 24306c92544dSBjoern A. Zeeb 24316c92544dSBjoern A. Zeeb lockdep_assert_held(&dev->mt76.mutex); 24326c92544dSBjoern A. Zeeb 24336c92544dSBjoern A. Zeeb if (flowid >= ARRAY_SIZE(msta->twt.flow)) 24346c92544dSBjoern A. Zeeb return; 24356c92544dSBjoern A. Zeeb 24366c92544dSBjoern A. Zeeb if (!(msta->twt.flowid_mask & BIT(flowid))) 24376c92544dSBjoern A. Zeeb return; 24386c92544dSBjoern A. Zeeb 24396c92544dSBjoern A. Zeeb flow = &msta->twt.flow[flowid]; 24406c92544dSBjoern A. Zeeb if (mt7915_mcu_twt_agrt_update(dev, msta->vif, flow, 24416c92544dSBjoern A. Zeeb MCU_TWT_AGRT_DELETE)) 24426c92544dSBjoern A. Zeeb return; 24436c92544dSBjoern A. Zeeb 24446c92544dSBjoern A. Zeeb list_del_init(&flow->list); 24456c92544dSBjoern A. Zeeb msta->twt.flowid_mask &= ~BIT(flowid); 24466c92544dSBjoern A. Zeeb dev->twt.table_mask &= ~BIT(flow->table_id); 24476c92544dSBjoern A. Zeeb dev->twt.n_agrt--; 24486c92544dSBjoern A. Zeeb } 2449