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/platform_device.h>
66c92544dSBjoern A. Zeeb #include <linux/pci.h>
76c92544dSBjoern A. Zeeb #include <linux/module.h>
86c92544dSBjoern A. Zeeb #include "mt7915.h"
96c92544dSBjoern A. Zeeb #include "mcu.h"
106c92544dSBjoern A. Zeeb
mt7915_dev_running(struct mt7915_dev * dev)116c92544dSBjoern A. Zeeb static bool mt7915_dev_running(struct mt7915_dev *dev)
126c92544dSBjoern A. Zeeb {
136c92544dSBjoern A. Zeeb struct mt7915_phy *phy;
146c92544dSBjoern A. Zeeb
156c92544dSBjoern A. Zeeb if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))
166c92544dSBjoern A. Zeeb return true;
176c92544dSBjoern A. Zeeb
186c92544dSBjoern A. Zeeb phy = mt7915_ext_phy(dev);
196c92544dSBjoern A. Zeeb
206c92544dSBjoern A. Zeeb return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
216c92544dSBjoern A. Zeeb }
226c92544dSBjoern A. Zeeb
mt7915_run(struct ieee80211_hw * hw)23cbb3ec25SBjoern A. Zeeb int mt7915_run(struct ieee80211_hw *hw)
246c92544dSBjoern A. Zeeb {
256c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
266c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
276c92544dSBjoern A. Zeeb bool running;
286c92544dSBjoern A. Zeeb int ret;
296c92544dSBjoern A. Zeeb
306c92544dSBjoern A. Zeeb running = mt7915_dev_running(dev);
316c92544dSBjoern A. Zeeb
326c92544dSBjoern A. Zeeb if (!running) {
33cbb3ec25SBjoern A. Zeeb ret = mt76_connac_mcu_set_pm(&dev->mt76,
34cbb3ec25SBjoern A. Zeeb dev->phy.mt76->band_idx, 0);
356c92544dSBjoern A. Zeeb if (ret)
366c92544dSBjoern A. Zeeb goto out;
376c92544dSBjoern A. Zeeb
38cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_mac(dev, dev->phy.mt76->band_idx,
39cbb3ec25SBjoern A. Zeeb true, true);
406c92544dSBjoern A. Zeeb if (ret)
416c92544dSBjoern A. Zeeb goto out;
426c92544dSBjoern A. Zeeb
43cbb3ec25SBjoern A. Zeeb mt7915_mac_enable_nf(dev, dev->phy.mt76->band_idx);
446c92544dSBjoern A. Zeeb }
456c92544dSBjoern A. Zeeb
46cbb3ec25SBjoern A. Zeeb if (phy != &dev->phy) {
47cbb3ec25SBjoern A. Zeeb ret = mt76_connac_mcu_set_pm(&dev->mt76,
48cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx, 0);
496c92544dSBjoern A. Zeeb if (ret)
506c92544dSBjoern A. Zeeb goto out;
516c92544dSBjoern A. Zeeb
52cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_mac(dev, phy->mt76->band_idx,
53cbb3ec25SBjoern A. Zeeb true, true);
546c92544dSBjoern A. Zeeb if (ret)
556c92544dSBjoern A. Zeeb goto out;
566c92544dSBjoern A. Zeeb
57cbb3ec25SBjoern A. Zeeb mt7915_mac_enable_nf(dev, phy->mt76->band_idx);
586c92544dSBjoern A. Zeeb }
596c92544dSBjoern A. Zeeb
60cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_thermal_throttling(phy,
61cbb3ec25SBjoern A. Zeeb MT7915_THERMAL_THROTTLE_MAX);
62cbb3ec25SBjoern A. Zeeb
63cbb3ec25SBjoern A. Zeeb if (ret)
64cbb3ec25SBjoern A. Zeeb goto out;
65cbb3ec25SBjoern A. Zeeb
66cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_thermal_protect(phy);
67cbb3ec25SBjoern A. Zeeb
68cbb3ec25SBjoern A. Zeeb if (ret)
69cbb3ec25SBjoern A. Zeeb goto out;
70cbb3ec25SBjoern A. Zeeb
716c92544dSBjoern A. Zeeb ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b,
72cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx);
736c92544dSBjoern A. Zeeb if (ret)
746c92544dSBjoern A. Zeeb goto out;
756c92544dSBjoern A. Zeeb
766c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_sku_en(phy, true);
776c92544dSBjoern A. Zeeb if (ret)
786c92544dSBjoern A. Zeeb goto out;
796c92544dSBjoern A. Zeeb
806c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
816c92544dSBjoern A. Zeeb if (ret)
826c92544dSBjoern A. Zeeb goto out;
836c92544dSBjoern A. Zeeb
846c92544dSBjoern A. Zeeb set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
856c92544dSBjoern A. Zeeb
866c92544dSBjoern A. Zeeb if (!mt76_testmode_enabled(phy->mt76))
876c92544dSBjoern A. Zeeb ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
886c92544dSBjoern A. Zeeb MT7915_WATCHDOG_TIME);
896c92544dSBjoern A. Zeeb
906c92544dSBjoern A. Zeeb if (!running)
916c92544dSBjoern A. Zeeb mt7915_mac_reset_counters(phy);
926c92544dSBjoern A. Zeeb
936c92544dSBjoern A. Zeeb out:
94cbb3ec25SBjoern A. Zeeb return ret;
95cbb3ec25SBjoern A. Zeeb }
96cbb3ec25SBjoern A. Zeeb
mt7915_start(struct ieee80211_hw * hw)97cbb3ec25SBjoern A. Zeeb static int mt7915_start(struct ieee80211_hw *hw)
98cbb3ec25SBjoern A. Zeeb {
99cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
100cbb3ec25SBjoern A. Zeeb int ret;
101cbb3ec25SBjoern A. Zeeb
102cbb3ec25SBjoern A. Zeeb flush_work(&dev->init_work);
103cbb3ec25SBjoern A. Zeeb
104cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
105cbb3ec25SBjoern A. Zeeb ret = mt7915_run(hw);
1066c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
1076c92544dSBjoern A. Zeeb
1086c92544dSBjoern A. Zeeb return ret;
1096c92544dSBjoern A. Zeeb }
1106c92544dSBjoern A. Zeeb
mt7915_stop(struct ieee80211_hw * hw,bool suspend)111*8ba4d145SBjoern A. Zeeb static void mt7915_stop(struct ieee80211_hw *hw, bool suspend)
1126c92544dSBjoern A. Zeeb {
1136c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
1146c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
1156c92544dSBjoern A. Zeeb
1166c92544dSBjoern A. Zeeb cancel_delayed_work_sync(&phy->mt76->mac_work);
1176c92544dSBjoern A. Zeeb
1186c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
1196c92544dSBjoern A. Zeeb
1206c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, true);
1216c92544dSBjoern A. Zeeb
1226c92544dSBjoern A. Zeeb clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
1236c92544dSBjoern A. Zeeb
1246c92544dSBjoern A. Zeeb if (phy != &dev->phy) {
125cbb3ec25SBjoern A. Zeeb mt76_connac_mcu_set_pm(&dev->mt76, phy->mt76->band_idx, 1);
126cbb3ec25SBjoern A. Zeeb mt7915_mcu_set_mac(dev, phy->mt76->band_idx, false, false);
1276c92544dSBjoern A. Zeeb }
1286c92544dSBjoern A. Zeeb
1296c92544dSBjoern A. Zeeb if (!mt7915_dev_running(dev)) {
130cbb3ec25SBjoern A. Zeeb mt76_connac_mcu_set_pm(&dev->mt76, dev->phy.mt76->band_idx, 1);
131cbb3ec25SBjoern A. Zeeb mt7915_mcu_set_mac(dev, dev->phy.mt76->band_idx, false, false);
1326c92544dSBjoern A. Zeeb }
1336c92544dSBjoern A. Zeeb
1346c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
1356c92544dSBjoern A. Zeeb }
1366c92544dSBjoern A. Zeeb
get_free_idx(u32 mask,u8 start,u8 end)1376c92544dSBjoern A. Zeeb static inline int get_free_idx(u32 mask, u8 start, u8 end)
1386c92544dSBjoern A. Zeeb {
1396c92544dSBjoern A. Zeeb return ffs(~mask & GENMASK(end, start));
1406c92544dSBjoern A. Zeeb }
1416c92544dSBjoern A. Zeeb
get_omac_idx(enum nl80211_iftype type,u64 mask)1426c92544dSBjoern A. Zeeb static int get_omac_idx(enum nl80211_iftype type, u64 mask)
1436c92544dSBjoern A. Zeeb {
1446c92544dSBjoern A. Zeeb int i;
1456c92544dSBjoern A. Zeeb
1466c92544dSBjoern A. Zeeb switch (type) {
1476c92544dSBjoern A. Zeeb case NL80211_IFTYPE_MESH_POINT:
1486c92544dSBjoern A. Zeeb case NL80211_IFTYPE_ADHOC:
1496c92544dSBjoern A. Zeeb case NL80211_IFTYPE_STATION:
1506c92544dSBjoern A. Zeeb /* prefer hw bssid slot 1-3 */
1516c92544dSBjoern A. Zeeb i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3);
1526c92544dSBjoern A. Zeeb if (i)
1536c92544dSBjoern A. Zeeb return i - 1;
1546c92544dSBjoern A. Zeeb
1556c92544dSBjoern A. Zeeb if (type != NL80211_IFTYPE_STATION)
1566c92544dSBjoern A. Zeeb break;
1576c92544dSBjoern A. Zeeb
1586c92544dSBjoern A. Zeeb i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);
1596c92544dSBjoern A. Zeeb if (i)
1606c92544dSBjoern A. Zeeb return i - 1;
1616c92544dSBjoern A. Zeeb
1626c92544dSBjoern A. Zeeb if (~mask & BIT(HW_BSSID_0))
1636c92544dSBjoern A. Zeeb return HW_BSSID_0;
1646c92544dSBjoern A. Zeeb
1656c92544dSBjoern A. Zeeb break;
1666c92544dSBjoern A. Zeeb case NL80211_IFTYPE_MONITOR:
1676c92544dSBjoern A. Zeeb case NL80211_IFTYPE_AP:
1686c92544dSBjoern A. Zeeb /* ap uses hw bssid 0 and ext bssid */
1696c92544dSBjoern A. Zeeb if (~mask & BIT(HW_BSSID_0))
1706c92544dSBjoern A. Zeeb return HW_BSSID_0;
1716c92544dSBjoern A. Zeeb
1726c92544dSBjoern A. Zeeb i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);
1736c92544dSBjoern A. Zeeb if (i)
1746c92544dSBjoern A. Zeeb return i - 1;
1756c92544dSBjoern A. Zeeb
1766c92544dSBjoern A. Zeeb break;
1776c92544dSBjoern A. Zeeb default:
1786c92544dSBjoern A. Zeeb WARN_ON(1);
1796c92544dSBjoern A. Zeeb break;
1806c92544dSBjoern A. Zeeb }
1816c92544dSBjoern A. Zeeb
1826c92544dSBjoern A. Zeeb return -1;
1836c92544dSBjoern A. Zeeb }
1846c92544dSBjoern A. Zeeb
mt7915_init_bitrate_mask(struct ieee80211_vif * vif)1856c92544dSBjoern A. Zeeb static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
1866c92544dSBjoern A. Zeeb {
1876c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1886c92544dSBjoern A. Zeeb int i;
1896c92544dSBjoern A. Zeeb
1906c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {
1916c92544dSBjoern A. Zeeb mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;
1926c92544dSBjoern A. Zeeb mvif->bitrate_mask.control[i].he_gi = 0xff;
1936c92544dSBjoern A. Zeeb mvif->bitrate_mask.control[i].he_ltf = 0xff;
1946c92544dSBjoern A. Zeeb mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);
1956c92544dSBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff,
1966c92544dSBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].ht_mcs));
1976c92544dSBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff,
1986c92544dSBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].vht_mcs));
1996c92544dSBjoern A. Zeeb memset(mvif->bitrate_mask.control[i].he_mcs, 0xff,
2006c92544dSBjoern A. Zeeb sizeof(mvif->bitrate_mask.control[i].he_mcs));
2016c92544dSBjoern A. Zeeb }
2026c92544dSBjoern A. Zeeb }
2036c92544dSBjoern A. Zeeb
mt7915_add_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)2046c92544dSBjoern A. Zeeb static int mt7915_add_interface(struct ieee80211_hw *hw,
2056c92544dSBjoern A. Zeeb struct ieee80211_vif *vif)
2066c92544dSBjoern A. Zeeb {
2076c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
2086c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
2096c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
2106c92544dSBjoern A. Zeeb struct mt76_txq *mtxq;
2116c92544dSBjoern A. Zeeb bool ext_phy = phy != &dev->phy;
2126c92544dSBjoern A. Zeeb int idx, ret = 0;
2136c92544dSBjoern A. Zeeb
2146c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
2156c92544dSBjoern A. Zeeb
2166c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, true);
2176c92544dSBjoern A. Zeeb
2186c92544dSBjoern A. Zeeb if (vif->type == NL80211_IFTYPE_MONITOR &&
2196c92544dSBjoern A. Zeeb is_zero_ether_addr(vif->addr))
2206c92544dSBjoern A. Zeeb phy->monitor_vif = vif;
2216c92544dSBjoern A. Zeeb
2226c92544dSBjoern A. Zeeb mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);
2236c92544dSBjoern A. Zeeb if (mvif->mt76.idx >= (MT7915_MAX_INTERFACES << dev->dbdc_support)) {
2246c92544dSBjoern A. Zeeb ret = -ENOSPC;
2256c92544dSBjoern A. Zeeb goto out;
2266c92544dSBjoern A. Zeeb }
2276c92544dSBjoern A. Zeeb
2286c92544dSBjoern A. Zeeb idx = get_omac_idx(vif->type, phy->omac_mask);
2296c92544dSBjoern A. Zeeb if (idx < 0) {
2306c92544dSBjoern A. Zeeb ret = -ENOSPC;
2316c92544dSBjoern A. Zeeb goto out;
2326c92544dSBjoern A. Zeeb }
2336c92544dSBjoern A. Zeeb mvif->mt76.omac_idx = idx;
2346c92544dSBjoern A. Zeeb mvif->phy = phy;
235cbb3ec25SBjoern A. Zeeb mvif->mt76.band_idx = phy->mt76->band_idx;
236*8ba4d145SBjoern A. Zeeb mvif->mt76.wcid = &mvif->sta.wcid;
2376c92544dSBjoern A. Zeeb
2386c92544dSBjoern A. Zeeb mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;
2396c92544dSBjoern A. Zeeb if (ext_phy)
2406c92544dSBjoern A. Zeeb mvif->mt76.wmm_idx += 2;
2416c92544dSBjoern A. Zeeb
2426c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_dev_info(phy, vif, true);
2436c92544dSBjoern A. Zeeb if (ret)
2446c92544dSBjoern A. Zeeb goto out;
2456c92544dSBjoern A. Zeeb
2466c92544dSBjoern A. Zeeb dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
2476c92544dSBjoern A. Zeeb phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
2486c92544dSBjoern A. Zeeb
249*8ba4d145SBjoern A. Zeeb idx = mt76_wcid_alloc(dev->mt76.wcid_mask, mt7915_wtbl_size(dev));
250*8ba4d145SBjoern A. Zeeb if (idx < 0) {
251*8ba4d145SBjoern A. Zeeb ret = -ENOSPC;
252*8ba4d145SBjoern A. Zeeb goto out;
253*8ba4d145SBjoern A. Zeeb }
2546c92544dSBjoern A. Zeeb
2556c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&mvif->sta.rc_list);
2566c92544dSBjoern A. Zeeb mvif->sta.wcid.idx = idx;
2576c92544dSBjoern A. Zeeb mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
258*8ba4d145SBjoern A. Zeeb mt76_wcid_init(&mvif->sta.wcid, phy->mt76->band_idx);
2596c92544dSBjoern A. Zeeb
2606c92544dSBjoern A. Zeeb mt7915_mac_wtbl_update(dev, idx,
2616c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
2626c92544dSBjoern A. Zeeb
2636c92544dSBjoern A. Zeeb if (vif->txq) {
2646c92544dSBjoern A. Zeeb mtxq = (struct mt76_txq *)vif->txq->drv_priv;
2656c92544dSBjoern A. Zeeb mtxq->wcid = idx;
2666c92544dSBjoern A. Zeeb }
2676c92544dSBjoern A. Zeeb
2686c92544dSBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_AP &&
2696c92544dSBjoern A. Zeeb (!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3))
2706c92544dSBjoern A. Zeeb vif->offload_flags = 0;
2716c92544dSBjoern A. Zeeb vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
2726c92544dSBjoern A. Zeeb
2736c92544dSBjoern A. Zeeb mt7915_init_bitrate_mask(vif);
2746c92544dSBjoern A. Zeeb memset(&mvif->cap, -1, sizeof(mvif->cap));
2756c92544dSBjoern A. Zeeb
2766c92544dSBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, true);
277*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, true);
2786c92544dSBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
2796c92544dSBjoern A. Zeeb
2806c92544dSBjoern A. Zeeb out:
2816c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
2826c92544dSBjoern A. Zeeb
2836c92544dSBjoern A. Zeeb return ret;
2846c92544dSBjoern A. Zeeb }
2856c92544dSBjoern A. Zeeb
mt7915_remove_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)2866c92544dSBjoern A. Zeeb static void mt7915_remove_interface(struct ieee80211_hw *hw,
2876c92544dSBjoern A. Zeeb struct ieee80211_vif *vif)
2886c92544dSBjoern A. Zeeb {
2896c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
2906c92544dSBjoern A. Zeeb struct mt7915_sta *msta = &mvif->sta;
2916c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
2926c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
2936c92544dSBjoern A. Zeeb int idx = msta->wcid.idx;
2946c92544dSBjoern A. Zeeb
2956c92544dSBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, false);
296*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);
297*8ba4d145SBjoern A. Zeeb mt76_wcid_mask_clear(dev->mt76.wcid_mask, mvif->sta.wcid.idx);
2986c92544dSBjoern A. Zeeb
2996c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
3006c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, true);
3016c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
3026c92544dSBjoern A. Zeeb
3036c92544dSBjoern A. Zeeb if (vif == phy->monitor_vif)
3046c92544dSBjoern A. Zeeb phy->monitor_vif = NULL;
3056c92544dSBjoern A. Zeeb
3066c92544dSBjoern A. Zeeb mt7915_mcu_add_dev_info(phy, vif, false);
3076c92544dSBjoern A. Zeeb
3086c92544dSBjoern A. Zeeb rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
3096c92544dSBjoern A. Zeeb
3106c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
3116c92544dSBjoern A. Zeeb dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
3126c92544dSBjoern A. Zeeb phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
3136c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
3146c92544dSBjoern A. Zeeb
315cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock);
316cbb3ec25SBjoern A. Zeeb if (!list_empty(&msta->wcid.poll_list))
317cbb3ec25SBjoern A. Zeeb list_del_init(&msta->wcid.poll_list);
318cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
3196c92544dSBjoern A. Zeeb
320*8ba4d145SBjoern A. Zeeb mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
3216c92544dSBjoern A. Zeeb }
3226c92544dSBjoern A. Zeeb
mt7915_set_channel(struct mt76_phy * mphy)323*8ba4d145SBjoern A. Zeeb int mt7915_set_channel(struct mt76_phy *mphy)
3246c92544dSBjoern A. Zeeb {
325*8ba4d145SBjoern A. Zeeb struct mt7915_phy *phy = mphy->priv;
3266c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
3276c92544dSBjoern A. Zeeb int ret;
3286c92544dSBjoern A. Zeeb
329*8ba4d145SBjoern A. Zeeb if (dev->cal) {
3306c92544dSBjoern A. Zeeb ret = mt7915_mcu_apply_tx_dpd(phy);
3316c92544dSBjoern A. Zeeb if (ret)
3326c92544dSBjoern A. Zeeb goto out;
3336c92544dSBjoern A. Zeeb }
3346c92544dSBjoern A. Zeeb
3356c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
3366c92544dSBjoern A. Zeeb if (ret)
3376c92544dSBjoern A. Zeeb goto out;
3386c92544dSBjoern A. Zeeb
3396c92544dSBjoern A. Zeeb mt7915_mac_set_timing(phy);
3406c92544dSBjoern A. Zeeb ret = mt7915_dfs_init_radar_detector(phy);
3416c92544dSBjoern A. Zeeb mt7915_mac_cca_stats_reset(phy);
3426c92544dSBjoern A. Zeeb
3436c92544dSBjoern A. Zeeb mt7915_mac_reset_counters(phy);
3446c92544dSBjoern A. Zeeb phy->noise = 0;
3456c92544dSBjoern A. Zeeb
3466c92544dSBjoern A. Zeeb out:
3476c92544dSBjoern A. Zeeb if (!mt76_testmode_enabled(phy->mt76))
3486c92544dSBjoern A. Zeeb ieee80211_queue_delayed_work(phy->mt76->hw,
3496c92544dSBjoern A. Zeeb &phy->mt76->mac_work,
3506c92544dSBjoern A. Zeeb MT7915_WATCHDOG_TIME);
3516c92544dSBjoern A. Zeeb
3526c92544dSBjoern A. Zeeb return ret;
3536c92544dSBjoern A. Zeeb }
3546c92544dSBjoern A. Zeeb
mt7915_set_key(struct ieee80211_hw * hw,enum set_key_cmd cmd,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ieee80211_key_conf * key)3556c92544dSBjoern A. Zeeb static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3566c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, struct ieee80211_sta *sta,
3576c92544dSBjoern A. Zeeb struct ieee80211_key_conf *key)
3586c92544dSBjoern A. Zeeb {
3596c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
3606c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
3616c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
3626c92544dSBjoern A. Zeeb struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv :
3636c92544dSBjoern A. Zeeb &mvif->sta;
3646c92544dSBjoern A. Zeeb struct mt76_wcid *wcid = &msta->wcid;
3656c92544dSBjoern A. Zeeb u8 *wcid_keyidx = &wcid->hw_key_idx;
3666c92544dSBjoern A. Zeeb int idx = key->keyidx;
3676c92544dSBjoern A. Zeeb int err = 0;
3686c92544dSBjoern A. Zeeb
369*8ba4d145SBjoern A. Zeeb if (sta && !wcid->sta) {
370*8ba4d145SBjoern A. Zeeb if (cmd != SET_KEY)
371*8ba4d145SBjoern A. Zeeb return 0;
372*8ba4d145SBjoern A. Zeeb
373*8ba4d145SBjoern A. Zeeb return -EOPNOTSUPP;
374*8ba4d145SBjoern A. Zeeb }
375*8ba4d145SBjoern A. Zeeb
3766c92544dSBjoern A. Zeeb /* The hardware does not support per-STA RX GTK, fallback
3776c92544dSBjoern A. Zeeb * to software mode for these.
3786c92544dSBjoern A. Zeeb */
3796c92544dSBjoern A. Zeeb if ((vif->type == NL80211_IFTYPE_ADHOC ||
3806c92544dSBjoern A. Zeeb vif->type == NL80211_IFTYPE_MESH_POINT) &&
3816c92544dSBjoern A. Zeeb (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
3826c92544dSBjoern A. Zeeb key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
3836c92544dSBjoern A. Zeeb !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
3846c92544dSBjoern A. Zeeb return -EOPNOTSUPP;
3856c92544dSBjoern A. Zeeb
3866c92544dSBjoern A. Zeeb /* fall back to sw encryption for unsupported ciphers */
3876c92544dSBjoern A. Zeeb switch (key->cipher) {
3886c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_AES_CMAC:
3896c92544dSBjoern A. Zeeb wcid_keyidx = &wcid->hw_key_idx2;
3906c92544dSBjoern A. Zeeb key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
3916c92544dSBjoern A. Zeeb break;
3926c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_TKIP:
3936c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP:
3946c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_CCMP_256:
3956c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP:
3966c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_GCMP_256:
3976c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_SMS4:
3986c92544dSBjoern A. Zeeb break;
3996c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_WEP40:
4006c92544dSBjoern A. Zeeb case WLAN_CIPHER_SUITE_WEP104:
4016c92544dSBjoern A. Zeeb default:
4026c92544dSBjoern A. Zeeb return -EOPNOTSUPP;
4036c92544dSBjoern A. Zeeb }
4046c92544dSBjoern A. Zeeb
4056c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
4066c92544dSBjoern A. Zeeb
4076c92544dSBjoern A. Zeeb if (cmd == SET_KEY && !sta && !mvif->mt76.cipher) {
4086c92544dSBjoern A. Zeeb mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);
4096c92544dSBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, true);
4106c92544dSBjoern A. Zeeb }
4116c92544dSBjoern A. Zeeb
412cbb3ec25SBjoern A. Zeeb if (cmd == SET_KEY) {
4136c92544dSBjoern A. Zeeb *wcid_keyidx = idx;
414cbb3ec25SBjoern A. Zeeb } else {
415cbb3ec25SBjoern A. Zeeb if (idx == *wcid_keyidx)
4166c92544dSBjoern A. Zeeb *wcid_keyidx = -1;
4176c92544dSBjoern A. Zeeb goto out;
418cbb3ec25SBjoern A. Zeeb }
4196c92544dSBjoern A. Zeeb
420cbb3ec25SBjoern A. Zeeb mt76_wcid_key_setup(&dev->mt76, wcid, key);
4216c92544dSBjoern A. Zeeb err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
4226c92544dSBjoern A. Zeeb key, MCU_EXT_CMD(STA_REC_UPDATE),
4236c92544dSBjoern A. Zeeb &msta->wcid, cmd);
4246c92544dSBjoern A. Zeeb out:
4256c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
4266c92544dSBjoern A. Zeeb
4276c92544dSBjoern A. Zeeb return err;
4286c92544dSBjoern A. Zeeb }
4296c92544dSBjoern A. Zeeb
mt7915_set_sar_specs(struct ieee80211_hw * hw,const struct cfg80211_sar_specs * sar)4306c92544dSBjoern A. Zeeb static int mt7915_set_sar_specs(struct ieee80211_hw *hw,
4316c92544dSBjoern A. Zeeb const struct cfg80211_sar_specs *sar)
4326c92544dSBjoern A. Zeeb {
4336c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
4346c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
4356c92544dSBjoern A. Zeeb int err = -EINVAL;
4366c92544dSBjoern A. Zeeb
4376c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
4386c92544dSBjoern A. Zeeb if (!cfg80211_chandef_valid(&phy->mt76->chandef))
4396c92544dSBjoern A. Zeeb goto out;
4406c92544dSBjoern A. Zeeb
4416c92544dSBjoern A. Zeeb err = mt76_init_sar_power(hw, sar);
4426c92544dSBjoern A. Zeeb if (err)
4436c92544dSBjoern A. Zeeb goto out;
4446c92544dSBjoern A. Zeeb
4456c92544dSBjoern A. Zeeb err = mt7915_mcu_set_txpower_sku(phy);
4466c92544dSBjoern A. Zeeb out:
4476c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
4486c92544dSBjoern A. Zeeb
4496c92544dSBjoern A. Zeeb return err;
4506c92544dSBjoern A. Zeeb }
4516c92544dSBjoern A. Zeeb
mt7915_config(struct ieee80211_hw * hw,u32 changed)4526c92544dSBjoern A. Zeeb static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
4536c92544dSBjoern A. Zeeb {
4546c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
4556c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
4566c92544dSBjoern A. Zeeb int ret;
4576c92544dSBjoern A. Zeeb
4586c92544dSBjoern A. Zeeb if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
4596c92544dSBjoern A. Zeeb #ifdef CONFIG_NL80211_TESTMODE
4606c92544dSBjoern A. Zeeb if (phy->mt76->test.state != MT76_TM_STATE_OFF) {
4616c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
4626c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, false);
4636c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
4646c92544dSBjoern A. Zeeb }
4656c92544dSBjoern A. Zeeb #endif
466*8ba4d145SBjoern A. Zeeb ret = mt76_update_channel(phy->mt76);
4676c92544dSBjoern A. Zeeb if (ret)
4686c92544dSBjoern A. Zeeb return ret;
4696c92544dSBjoern A. Zeeb }
4706c92544dSBjoern A. Zeeb
471cbb3ec25SBjoern A. Zeeb if (changed & (IEEE80211_CONF_CHANGE_POWER |
472cbb3ec25SBjoern A. Zeeb IEEE80211_CONF_CHANGE_CHANNEL)) {
4736c92544dSBjoern A. Zeeb ret = mt7915_mcu_set_txpower_sku(phy);
4746c92544dSBjoern A. Zeeb if (ret)
4756c92544dSBjoern A. Zeeb return ret;
4766c92544dSBjoern A. Zeeb }
4776c92544dSBjoern A. Zeeb
4786c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
4796c92544dSBjoern A. Zeeb
4806c92544dSBjoern A. Zeeb if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
4816c92544dSBjoern A. Zeeb bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
482cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx;
483*8ba4d145SBjoern A. Zeeb u32 rxfilter = phy->rxfilter;
4846c92544dSBjoern A. Zeeb
485*8ba4d145SBjoern A. Zeeb if (!enabled) {
486*8ba4d145SBjoern A. Zeeb rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
487*8ba4d145SBjoern A. Zeeb dev->monitor_mask &= ~BIT(band);
488*8ba4d145SBjoern A. Zeeb } else {
489*8ba4d145SBjoern A. Zeeb rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
490*8ba4d145SBjoern A. Zeeb dev->monitor_mask |= BIT(band);
491*8ba4d145SBjoern A. Zeeb }
4926c92544dSBjoern A. Zeeb
4936c92544dSBjoern A. Zeeb mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN,
4946c92544dSBjoern A. Zeeb enabled);
495*8ba4d145SBjoern A. Zeeb mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_MDP_DCR0_RX_HDR_TRANS_EN,
496*8ba4d145SBjoern A. Zeeb !dev->monitor_mask);
4976c92544dSBjoern A. Zeeb mt76_testmode_reset(phy->mt76, true);
498*8ba4d145SBjoern A. Zeeb mt76_wr(dev, MT_WF_RFCR(band), rxfilter);
4996c92544dSBjoern A. Zeeb }
5006c92544dSBjoern A. Zeeb
5016c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
5026c92544dSBjoern A. Zeeb
5036c92544dSBjoern A. Zeeb return 0;
5046c92544dSBjoern A. Zeeb }
5056c92544dSBjoern A. Zeeb
5066c92544dSBjoern A. Zeeb static int
mt7915_conf_tx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,unsigned int link_id,u16 queue,const struct ieee80211_tx_queue_params * params)5076c92544dSBjoern A. Zeeb mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5086c92544dSBjoern A. Zeeb unsigned int link_id, u16 queue,
5096c92544dSBjoern A. Zeeb const struct ieee80211_tx_queue_params *params)
5106c92544dSBjoern A. Zeeb {
5116c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
5126c92544dSBjoern A. Zeeb
5136c92544dSBjoern A. Zeeb /* no need to update right away, we'll get BSS_CHANGED_QOS */
5146c92544dSBjoern A. Zeeb queue = mt76_connac_lmac_mapping(queue);
5156c92544dSBjoern A. Zeeb mvif->queue_params[queue] = *params;
5166c92544dSBjoern A. Zeeb
5176c92544dSBjoern A. Zeeb return 0;
5186c92544dSBjoern A. Zeeb }
5196c92544dSBjoern A. Zeeb
mt7915_configure_filter(struct ieee80211_hw * hw,unsigned int changed_flags,unsigned int * total_flags,u64 multicast)5206c92544dSBjoern A. Zeeb static void mt7915_configure_filter(struct ieee80211_hw *hw,
5216c92544dSBjoern A. Zeeb unsigned int changed_flags,
5226c92544dSBjoern A. Zeeb unsigned int *total_flags,
5236c92544dSBjoern A. Zeeb u64 multicast)
5246c92544dSBjoern A. Zeeb {
5256c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
5266c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
527cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx;
5286c92544dSBjoern A. Zeeb u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
5296c92544dSBjoern A. Zeeb MT_WF_RFCR1_DROP_BF_POLL |
5306c92544dSBjoern A. Zeeb MT_WF_RFCR1_DROP_BA |
5316c92544dSBjoern A. Zeeb MT_WF_RFCR1_DROP_CFEND |
5326c92544dSBjoern A. Zeeb MT_WF_RFCR1_DROP_CFACK;
533*8ba4d145SBjoern A. Zeeb u32 rxfilter;
5346c92544dSBjoern A. Zeeb u32 flags = 0;
5356c92544dSBjoern A. Zeeb
5366c92544dSBjoern A. Zeeb #define MT76_FILTER(_flag, _hw) do { \
5376c92544dSBjoern A. Zeeb flags |= *total_flags & FIF_##_flag; \
5386c92544dSBjoern A. Zeeb phy->rxfilter &= ~(_hw); \
5396c92544dSBjoern A. Zeeb phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \
5406c92544dSBjoern A. Zeeb } while (0)
5416c92544dSBjoern A. Zeeb
5426c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
5436c92544dSBjoern A. Zeeb
5446c92544dSBjoern A. Zeeb phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
5456c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_OTHER_BEACON |
5466c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_FRAME_REPORT |
5476c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_PROBEREQ |
5486c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_MCAST_FILTERED |
5496c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_MCAST |
5506c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_BCAST |
5516c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_DUPLICATE |
5526c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_A2_BSSID |
5536c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_UNWANTED_CTL |
5546c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_STBC_MULTI);
5556c92544dSBjoern A. Zeeb
5566c92544dSBjoern A. Zeeb MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
5576c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_A3_MAC |
5586c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_A3_BSSID);
5596c92544dSBjoern A. Zeeb
5606c92544dSBjoern A. Zeeb MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);
5616c92544dSBjoern A. Zeeb
5626c92544dSBjoern A. Zeeb MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |
5636c92544dSBjoern A. Zeeb MT_WF_RFCR_DROP_RTS |
564*8ba4d145SBjoern A. Zeeb MT_WF_RFCR_DROP_CTL_RSV);
5656c92544dSBjoern A. Zeeb
5666c92544dSBjoern A. Zeeb *total_flags = flags;
567*8ba4d145SBjoern A. Zeeb rxfilter = phy->rxfilter;
568*8ba4d145SBjoern A. Zeeb if (hw->conf.flags & IEEE80211_CONF_MONITOR)
569*8ba4d145SBjoern A. Zeeb rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
570*8ba4d145SBjoern A. Zeeb else
571*8ba4d145SBjoern A. Zeeb rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
572*8ba4d145SBjoern A. Zeeb mt76_wr(dev, MT_WF_RFCR(band), rxfilter);
5736c92544dSBjoern A. Zeeb
5746c92544dSBjoern A. Zeeb if (*total_flags & FIF_CONTROL)
5756c92544dSBjoern A. Zeeb mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags);
5766c92544dSBjoern A. Zeeb else
5776c92544dSBjoern A. Zeeb mt76_set(dev, MT_WF_RFCR1(band), ctl_flags);
5786c92544dSBjoern A. Zeeb
5796c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
5806c92544dSBjoern A. Zeeb }
5816c92544dSBjoern A. Zeeb
5826c92544dSBjoern A. Zeeb static void
mt7915_update_bss_color(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct cfg80211_he_bss_color * bss_color)5836c92544dSBjoern A. Zeeb mt7915_update_bss_color(struct ieee80211_hw *hw,
5846c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
5856c92544dSBjoern A. Zeeb struct cfg80211_he_bss_color *bss_color)
5866c92544dSBjoern A. Zeeb {
5876c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
5886c92544dSBjoern A. Zeeb
5896c92544dSBjoern A. Zeeb switch (vif->type) {
5906c92544dSBjoern A. Zeeb case NL80211_IFTYPE_AP: {
5916c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
5926c92544dSBjoern A. Zeeb
5936c92544dSBjoern A. Zeeb if (mvif->mt76.omac_idx > HW_BSSID_MAX)
5946c92544dSBjoern A. Zeeb return;
5956c92544dSBjoern A. Zeeb fallthrough;
5966c92544dSBjoern A. Zeeb }
5976c92544dSBjoern A. Zeeb case NL80211_IFTYPE_STATION:
5986c92544dSBjoern A. Zeeb mt7915_mcu_update_bss_color(dev, vif, bss_color);
5996c92544dSBjoern A. Zeeb break;
6006c92544dSBjoern A. Zeeb default:
6016c92544dSBjoern A. Zeeb break;
6026c92544dSBjoern A. Zeeb }
6036c92544dSBjoern A. Zeeb }
6046c92544dSBjoern A. Zeeb
mt7915_bss_info_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * info,u64 changed)6056c92544dSBjoern A. Zeeb static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
6066c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
6076c92544dSBjoern A. Zeeb struct ieee80211_bss_conf *info,
6086c92544dSBjoern A. Zeeb u64 changed)
6096c92544dSBjoern A. Zeeb {
6106c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
6116c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
612cbb3ec25SBjoern A. Zeeb int set_bss_info = -1, set_sta = -1;
6136c92544dSBjoern A. Zeeb
6146c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
6156c92544dSBjoern A. Zeeb
6166c92544dSBjoern A. Zeeb /*
6176c92544dSBjoern A. Zeeb * station mode uses BSSID to map the wlan entry to a peer,
6186c92544dSBjoern A. Zeeb * and then peer references bss_info_rfch to set bandwidth cap.
6196c92544dSBjoern A. Zeeb */
6206c92544dSBjoern A. Zeeb if (changed & BSS_CHANGED_BSSID &&
621cbb3ec25SBjoern A. Zeeb vif->type == NL80211_IFTYPE_STATION)
622cbb3ec25SBjoern A. Zeeb set_bss_info = set_sta = !is_zero_ether_addr(info->bssid);
623cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_ASSOC)
624cbb3ec25SBjoern A. Zeeb set_bss_info = vif->cfg.assoc;
625cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_BEACON_ENABLED &&
626*8ba4d145SBjoern A. Zeeb info->enable_beacon &&
627cbb3ec25SBjoern A. Zeeb vif->type != NL80211_IFTYPE_AP)
628*8ba4d145SBjoern A. Zeeb set_bss_info = set_sta = 1;
6296c92544dSBjoern A. Zeeb
630cbb3ec25SBjoern A. Zeeb if (set_bss_info == 1)
631cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, true);
632cbb3ec25SBjoern A. Zeeb if (set_sta == 1)
633*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);
6346c92544dSBjoern A. Zeeb
635cbb3ec25SBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_CTS_PROT)
636cbb3ec25SBjoern A. Zeeb mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot);
6376c92544dSBjoern A. Zeeb
6386c92544dSBjoern A. Zeeb if (changed & BSS_CHANGED_ERP_SLOT) {
639*8ba4d145SBjoern A. Zeeb int slottime = 9;
640*8ba4d145SBjoern A. Zeeb
641*8ba4d145SBjoern A. Zeeb if (phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ &&
642*8ba4d145SBjoern A. Zeeb !info->use_short_slot)
643*8ba4d145SBjoern A. Zeeb slottime = 20;
6446c92544dSBjoern A. Zeeb
6456c92544dSBjoern A. Zeeb if (slottime != phy->slottime) {
6466c92544dSBjoern A. Zeeb phy->slottime = slottime;
6476c92544dSBjoern A. Zeeb mt7915_mac_set_timing(phy);
6486c92544dSBjoern A. Zeeb }
6496c92544dSBjoern A. Zeeb }
6506c92544dSBjoern A. Zeeb
6516c92544dSBjoern A. Zeeb /* ensure that enable txcmd_mode after bss_info */
6526c92544dSBjoern A. Zeeb if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
6536c92544dSBjoern A. Zeeb mt7915_mcu_set_tx(dev, vif);
6546c92544dSBjoern A. Zeeb
6556c92544dSBjoern A. Zeeb if (changed & BSS_CHANGED_HE_OBSS_PD)
656cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_obss_spr(phy, vif, &info->he_obss_pd);
6576c92544dSBjoern A. Zeeb
6586c92544dSBjoern A. Zeeb if (changed & BSS_CHANGED_HE_BSS_COLOR)
6596c92544dSBjoern A. Zeeb mt7915_update_bss_color(hw, vif, &info->he_bss_color);
6606c92544dSBjoern A. Zeeb
6616c92544dSBjoern A. Zeeb if (changed & (BSS_CHANGED_BEACON |
662*8ba4d145SBjoern A. Zeeb BSS_CHANGED_BEACON_ENABLED))
6636c92544dSBjoern A. Zeeb mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);
6646c92544dSBjoern A. Zeeb
665*8ba4d145SBjoern A. Zeeb if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
666*8ba4d145SBjoern A. Zeeb BSS_CHANGED_FILS_DISCOVERY))
667*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_inband_discov(dev, vif, changed);
668*8ba4d145SBjoern A. Zeeb
669cbb3ec25SBjoern A. Zeeb if (set_bss_info == 0)
670cbb3ec25SBjoern A. Zeeb mt7915_mcu_add_bss_info(phy, vif, false);
671cbb3ec25SBjoern A. Zeeb if (set_sta == 0)
672*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);
673cbb3ec25SBjoern A. Zeeb
674cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
675cbb3ec25SBjoern A. Zeeb }
676cbb3ec25SBjoern A. Zeeb
677cbb3ec25SBjoern A. Zeeb static void
mt7915_vif_check_caps(struct mt7915_phy * phy,struct ieee80211_vif * vif)678cbb3ec25SBjoern A. Zeeb mt7915_vif_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif)
679cbb3ec25SBjoern A. Zeeb {
680cbb3ec25SBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
681cbb3ec25SBjoern A. Zeeb struct mt7915_vif_cap *vc = &mvif->cap;
682cbb3ec25SBjoern A. Zeeb
683cbb3ec25SBjoern A. Zeeb vc->ht_ldpc = vif->bss_conf.ht_ldpc;
684cbb3ec25SBjoern A. Zeeb vc->vht_ldpc = vif->bss_conf.vht_ldpc;
685cbb3ec25SBjoern A. Zeeb vc->vht_su_ebfer = vif->bss_conf.vht_su_beamformer;
686cbb3ec25SBjoern A. Zeeb vc->vht_su_ebfee = vif->bss_conf.vht_su_beamformee;
687cbb3ec25SBjoern A. Zeeb vc->vht_mu_ebfer = vif->bss_conf.vht_mu_beamformer;
688cbb3ec25SBjoern A. Zeeb vc->vht_mu_ebfee = vif->bss_conf.vht_mu_beamformee;
689cbb3ec25SBjoern A. Zeeb vc->he_ldpc = vif->bss_conf.he_ldpc;
690cbb3ec25SBjoern A. Zeeb vc->he_su_ebfer = vif->bss_conf.he_su_beamformer;
691cbb3ec25SBjoern A. Zeeb vc->he_su_ebfee = vif->bss_conf.he_su_beamformee;
692cbb3ec25SBjoern A. Zeeb vc->he_mu_ebfer = vif->bss_conf.he_mu_beamformer;
693cbb3ec25SBjoern A. Zeeb }
694cbb3ec25SBjoern A. Zeeb
695cbb3ec25SBjoern A. Zeeb static int
mt7915_start_ap(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * link_conf)696cbb3ec25SBjoern A. Zeeb mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
697cbb3ec25SBjoern A. Zeeb struct ieee80211_bss_conf *link_conf)
698cbb3ec25SBjoern A. Zeeb {
699cbb3ec25SBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
700cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
701cbb3ec25SBjoern A. Zeeb int err;
702cbb3ec25SBjoern A. Zeeb
703cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
704cbb3ec25SBjoern A. Zeeb
705cbb3ec25SBjoern A. Zeeb mt7915_vif_check_caps(phy, vif);
706cbb3ec25SBjoern A. Zeeb
707cbb3ec25SBjoern A. Zeeb err = mt7915_mcu_add_bss_info(phy, vif, true);
708cbb3ec25SBjoern A. Zeeb if (err)
709cbb3ec25SBjoern A. Zeeb goto out;
710*8ba4d145SBjoern A. Zeeb err = mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, false);
711cbb3ec25SBjoern A. Zeeb out:
712cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
713cbb3ec25SBjoern A. Zeeb
714cbb3ec25SBjoern A. Zeeb return err;
715cbb3ec25SBjoern A. Zeeb }
716cbb3ec25SBjoern A. Zeeb
717cbb3ec25SBjoern A. Zeeb static void
mt7915_stop_ap(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * link_conf)718cbb3ec25SBjoern A. Zeeb mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
719cbb3ec25SBjoern A. Zeeb struct ieee80211_bss_conf *link_conf)
720cbb3ec25SBjoern A. Zeeb {
721cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
722cbb3ec25SBjoern A. Zeeb
723cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
724*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_DISCONNECT, false);
7256c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
7266c92544dSBjoern A. Zeeb }
7276c92544dSBjoern A. Zeeb
7286c92544dSBjoern A. Zeeb static void
mt7915_channel_switch_beacon(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct cfg80211_chan_def * chandef)7296c92544dSBjoern A. Zeeb mt7915_channel_switch_beacon(struct ieee80211_hw *hw,
7306c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
7316c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef)
7326c92544dSBjoern A. Zeeb {
7336c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
7346c92544dSBjoern A. Zeeb
7356c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
7366c92544dSBjoern A. Zeeb mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON);
7376c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
7386c92544dSBjoern A. Zeeb }
7396c92544dSBjoern A. Zeeb
mt7915_mac_sta_add(struct mt76_dev * mdev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)7406c92544dSBjoern A. Zeeb int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
7416c92544dSBjoern A. Zeeb struct ieee80211_sta *sta)
7426c92544dSBjoern A. Zeeb {
7436c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
7446c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
7456c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
7466c92544dSBjoern A. Zeeb bool ext_phy = mvif->phy != &dev->phy;
747*8ba4d145SBjoern A. Zeeb int idx;
7486c92544dSBjoern A. Zeeb
7496c92544dSBjoern A. Zeeb idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
7506c92544dSBjoern A. Zeeb if (idx < 0)
7516c92544dSBjoern A. Zeeb return -ENOSPC;
7526c92544dSBjoern A. Zeeb
7536c92544dSBjoern A. Zeeb INIT_LIST_HEAD(&msta->rc_list);
754cbb3ec25SBjoern A. Zeeb INIT_LIST_HEAD(&msta->wcid.poll_list);
7556c92544dSBjoern A. Zeeb msta->vif = mvif;
756*8ba4d145SBjoern A. Zeeb msta->wcid.sta_disabled = 1;
7576c92544dSBjoern A. Zeeb msta->wcid.idx = idx;
7586c92544dSBjoern A. Zeeb msta->wcid.phy_idx = ext_phy;
7596c92544dSBjoern A. Zeeb msta->jiffies = jiffies;
7606c92544dSBjoern A. Zeeb
761cbb3ec25SBjoern A. Zeeb ewma_avg_signal_init(&msta->avg_ack_signal);
762cbb3ec25SBjoern A. Zeeb
7636c92544dSBjoern A. Zeeb mt7915_mac_wtbl_update(dev, idx,
7646c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
765*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, true);
7666c92544dSBjoern A. Zeeb
767*8ba4d145SBjoern A. Zeeb return 0;
768*8ba4d145SBjoern A. Zeeb }
769*8ba4d145SBjoern A. Zeeb
770*8ba4d145SBjoern A. Zeeb struct drop_sta_iter {
771*8ba4d145SBjoern A. Zeeb struct mt7915_dev *dev;
772*8ba4d145SBjoern A. Zeeb struct ieee80211_hw *hw;
773*8ba4d145SBjoern A. Zeeb struct ieee80211_vif *vif;
774*8ba4d145SBjoern A. Zeeb u8 sta_addr[ETH_ALEN];
775*8ba4d145SBjoern A. Zeeb };
776*8ba4d145SBjoern A. Zeeb
777*8ba4d145SBjoern A. Zeeb static void
__mt7915_drop_sta(void * ptr,u8 * mac,struct ieee80211_vif * vif)778*8ba4d145SBjoern A. Zeeb __mt7915_drop_sta(void *ptr, u8 *mac, struct ieee80211_vif *vif)
779*8ba4d145SBjoern A. Zeeb {
780*8ba4d145SBjoern A. Zeeb struct drop_sta_iter *data = ptr;
781*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta;
782*8ba4d145SBjoern A. Zeeb struct mt7915_sta *msta;
783*8ba4d145SBjoern A. Zeeb
784*8ba4d145SBjoern A. Zeeb if (vif == data->vif || vif->type != NL80211_IFTYPE_AP)
785*8ba4d145SBjoern A. Zeeb return;
786*8ba4d145SBjoern A. Zeeb
787*8ba4d145SBjoern A. Zeeb sta = ieee80211_find_sta_by_ifaddr(data->hw, data->sta_addr, mac);
788*8ba4d145SBjoern A. Zeeb if (!sta)
789*8ba4d145SBjoern A. Zeeb return;
790*8ba4d145SBjoern A. Zeeb
791*8ba4d145SBjoern A. Zeeb msta = (struct mt7915_sta *)sta->drv_priv;
792*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_sta(data->dev, vif, sta, CONN_STATE_DISCONNECT, false);
793*8ba4d145SBjoern A. Zeeb msta->wcid.sta_disabled = 1;
794*8ba4d145SBjoern A. Zeeb msta->wcid.sta = 0;
795*8ba4d145SBjoern A. Zeeb }
796*8ba4d145SBjoern A. Zeeb
797*8ba4d145SBjoern A. Zeeb static void
mt7915_drop_other_sta(struct mt7915_dev * dev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)798*8ba4d145SBjoern A. Zeeb mt7915_drop_other_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
799*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta)
800*8ba4d145SBjoern A. Zeeb {
801*8ba4d145SBjoern A. Zeeb struct mt76_phy *ext_phy = dev->mt76.phys[MT_BAND1];
802*8ba4d145SBjoern A. Zeeb struct drop_sta_iter data = {
803*8ba4d145SBjoern A. Zeeb .dev = dev,
804*8ba4d145SBjoern A. Zeeb .hw = dev->mphy.hw,
805*8ba4d145SBjoern A. Zeeb .vif = vif,
806*8ba4d145SBjoern A. Zeeb };
807*8ba4d145SBjoern A. Zeeb
808*8ba4d145SBjoern A. Zeeb if (vif->type != NL80211_IFTYPE_AP)
809*8ba4d145SBjoern A. Zeeb return;
810*8ba4d145SBjoern A. Zeeb
811*8ba4d145SBjoern A. Zeeb memcpy(data.sta_addr, sta->addr, ETH_ALEN);
812*8ba4d145SBjoern A. Zeeb ieee80211_iterate_active_interfaces(data.hw, 0, __mt7915_drop_sta, &data);
813*8ba4d145SBjoern A. Zeeb
814*8ba4d145SBjoern A. Zeeb if (!ext_phy)
815*8ba4d145SBjoern A. Zeeb return;
816*8ba4d145SBjoern A. Zeeb
817*8ba4d145SBjoern A. Zeeb data.hw = ext_phy->hw;
818*8ba4d145SBjoern A. Zeeb ieee80211_iterate_active_interfaces(data.hw, 0, __mt7915_drop_sta, &data);
819*8ba4d145SBjoern A. Zeeb }
820*8ba4d145SBjoern A. Zeeb
mt7915_mac_sta_event(struct mt76_dev * mdev,struct ieee80211_vif * vif,struct ieee80211_sta * sta,enum mt76_sta_event ev)821*8ba4d145SBjoern A. Zeeb int mt7915_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
822*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta, enum mt76_sta_event ev)
823*8ba4d145SBjoern A. Zeeb {
824*8ba4d145SBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
825*8ba4d145SBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
826*8ba4d145SBjoern A. Zeeb int i, ret;
827*8ba4d145SBjoern A. Zeeb u32 addr;
828*8ba4d145SBjoern A. Zeeb
829*8ba4d145SBjoern A. Zeeb switch (ev) {
830*8ba4d145SBjoern A. Zeeb case MT76_STA_EVENT_ASSOC:
831*8ba4d145SBjoern A. Zeeb ret = mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_CONNECT, true);
8326c92544dSBjoern A. Zeeb if (ret)
8336c92544dSBjoern A. Zeeb return ret;
8346c92544dSBjoern A. Zeeb
835*8ba4d145SBjoern A. Zeeb addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 30);
836*8ba4d145SBjoern A. Zeeb mt76_rmw_field(dev, addr, GENMASK(7, 0), 0xa0);
837*8ba4d145SBjoern A. Zeeb
838*8ba4d145SBjoern A. Zeeb ret = mt7915_mcu_add_rate_ctrl(dev, vif, sta, false);
839*8ba4d145SBjoern A. Zeeb if (ret)
840*8ba4d145SBjoern A. Zeeb return ret;
841*8ba4d145SBjoern A. Zeeb
842*8ba4d145SBjoern A. Zeeb msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
843*8ba4d145SBjoern A. Zeeb msta->wcid.sta = 1;
844*8ba4d145SBjoern A. Zeeb msta->wcid.sta_disabled = 0;
845*8ba4d145SBjoern A. Zeeb
846*8ba4d145SBjoern A. Zeeb return 0;
847*8ba4d145SBjoern A. Zeeb
848*8ba4d145SBjoern A. Zeeb case MT76_STA_EVENT_AUTHORIZE:
849*8ba4d145SBjoern A. Zeeb mt7915_drop_other_sta(dev, vif, sta);
850*8ba4d145SBjoern A. Zeeb return mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_PORT_SECURE, false);
851*8ba4d145SBjoern A. Zeeb
852*8ba4d145SBjoern A. Zeeb case MT76_STA_EVENT_DISASSOC:
853*8ba4d145SBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++)
854*8ba4d145SBjoern A. Zeeb mt7915_mac_twt_teardown_flow(dev, msta, i);
855*8ba4d145SBjoern A. Zeeb
856*8ba4d145SBjoern A. Zeeb mt7915_mcu_add_sta(dev, vif, sta, CONN_STATE_DISCONNECT, false);
857*8ba4d145SBjoern A. Zeeb msta->wcid.sta_disabled = 1;
858*8ba4d145SBjoern A. Zeeb msta->wcid.sta = 0;
859*8ba4d145SBjoern A. Zeeb return 0;
860*8ba4d145SBjoern A. Zeeb }
861*8ba4d145SBjoern A. Zeeb
862*8ba4d145SBjoern A. Zeeb return 0;
8636c92544dSBjoern A. Zeeb }
8646c92544dSBjoern A. Zeeb
mt7915_mac_sta_remove(struct mt76_dev * mdev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)8656c92544dSBjoern A. Zeeb void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
8666c92544dSBjoern A. Zeeb struct ieee80211_sta *sta)
8676c92544dSBjoern A. Zeeb {
8686c92544dSBjoern A. Zeeb struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
8696c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
8706c92544dSBjoern A. Zeeb
8716c92544dSBjoern A. Zeeb mt7915_mac_wtbl_update(dev, msta->wcid.idx,
8726c92544dSBjoern A. Zeeb MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
8736c92544dSBjoern A. Zeeb
874cbb3ec25SBjoern A. Zeeb spin_lock_bh(&mdev->sta_poll_lock);
875cbb3ec25SBjoern A. Zeeb if (!list_empty(&msta->wcid.poll_list))
876cbb3ec25SBjoern A. Zeeb list_del_init(&msta->wcid.poll_list);
8776c92544dSBjoern A. Zeeb if (!list_empty(&msta->rc_list))
8786c92544dSBjoern A. Zeeb list_del_init(&msta->rc_list);
879cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&mdev->sta_poll_lock);
8806c92544dSBjoern A. Zeeb }
8816c92544dSBjoern A. Zeeb
mt7915_tx(struct ieee80211_hw * hw,struct ieee80211_tx_control * control,struct sk_buff * skb)8826c92544dSBjoern A. Zeeb static void mt7915_tx(struct ieee80211_hw *hw,
8836c92544dSBjoern A. Zeeb struct ieee80211_tx_control *control,
8846c92544dSBjoern A. Zeeb struct sk_buff *skb)
8856c92544dSBjoern A. Zeeb {
8866c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
8876c92544dSBjoern A. Zeeb struct mt76_phy *mphy = hw->priv;
8886c92544dSBjoern A. Zeeb struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
8896c92544dSBjoern A. Zeeb struct ieee80211_vif *vif = info->control.vif;
8906c92544dSBjoern A. Zeeb struct mt76_wcid *wcid = &dev->mt76.global_wcid;
8916c92544dSBjoern A. Zeeb
8926c92544dSBjoern A. Zeeb if (control->sta) {
8936c92544dSBjoern A. Zeeb struct mt7915_sta *sta;
8946c92544dSBjoern A. Zeeb
8956c92544dSBjoern A. Zeeb sta = (struct mt7915_sta *)control->sta->drv_priv;
8966c92544dSBjoern A. Zeeb wcid = &sta->wcid;
8976c92544dSBjoern A. Zeeb }
8986c92544dSBjoern A. Zeeb
8996c92544dSBjoern A. Zeeb if (vif && !control->sta) {
9006c92544dSBjoern A. Zeeb struct mt7915_vif *mvif;
9016c92544dSBjoern A. Zeeb
9026c92544dSBjoern A. Zeeb mvif = (struct mt7915_vif *)vif->drv_priv;
9036c92544dSBjoern A. Zeeb wcid = &mvif->sta.wcid;
9046c92544dSBjoern A. Zeeb }
9056c92544dSBjoern A. Zeeb
9066c92544dSBjoern A. Zeeb mt76_tx(mphy, control->sta, wcid, skb);
9076c92544dSBjoern A. Zeeb }
9086c92544dSBjoern A. Zeeb
mt7915_set_rts_threshold(struct ieee80211_hw * hw,u32 val)9096c92544dSBjoern A. Zeeb static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
9106c92544dSBjoern A. Zeeb {
9116c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
9126c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
9136c92544dSBjoern A. Zeeb int ret;
9146c92544dSBjoern A. Zeeb
9156c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
916cbb3ec25SBjoern A. Zeeb ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, val,
917cbb3ec25SBjoern A. Zeeb phy->mt76->band_idx);
9186c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
9196c92544dSBjoern A. Zeeb
9206c92544dSBjoern A. Zeeb return ret;
9216c92544dSBjoern A. Zeeb }
9226c92544dSBjoern A. Zeeb
9236c92544dSBjoern A. Zeeb static int
mt7915_ampdu_action(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_ampdu_params * params)9246c92544dSBjoern A. Zeeb mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
9256c92544dSBjoern A. Zeeb struct ieee80211_ampdu_params *params)
9266c92544dSBjoern A. Zeeb {
9276c92544dSBjoern A. Zeeb enum ieee80211_ampdu_mlme_action action = params->action;
9286c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
9296c92544dSBjoern A. Zeeb struct ieee80211_sta *sta = params->sta;
9306c92544dSBjoern A. Zeeb struct ieee80211_txq *txq = sta->txq[params->tid];
9316c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
9326c92544dSBjoern A. Zeeb u16 tid = params->tid;
9336c92544dSBjoern A. Zeeb u16 ssn = params->ssn;
9346c92544dSBjoern A. Zeeb struct mt76_txq *mtxq;
9356c92544dSBjoern A. Zeeb int ret = 0;
9366c92544dSBjoern A. Zeeb
9376c92544dSBjoern A. Zeeb if (!txq)
9386c92544dSBjoern A. Zeeb return -EINVAL;
9396c92544dSBjoern A. Zeeb
9406c92544dSBjoern A. Zeeb mtxq = (struct mt76_txq *)txq->drv_priv;
9416c92544dSBjoern A. Zeeb
9426c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
9436c92544dSBjoern A. Zeeb switch (action) {
9446c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_RX_START:
9456c92544dSBjoern A. Zeeb mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
9466c92544dSBjoern A. Zeeb params->buf_size);
9476c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_rx_ba(dev, params, true);
9486c92544dSBjoern A. Zeeb break;
9496c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_RX_STOP:
9506c92544dSBjoern A. Zeeb mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
9516c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_rx_ba(dev, params, false);
9526c92544dSBjoern A. Zeeb break;
9536c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_OPERATIONAL:
9546c92544dSBjoern A. Zeeb mtxq->aggr = true;
9556c92544dSBjoern A. Zeeb mtxq->send_bar = false;
9566c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_tx_ba(dev, params, true);
9576c92544dSBjoern A. Zeeb break;
9586c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH:
9596c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
9606c92544dSBjoern A. Zeeb mtxq->aggr = false;
961cbb3ec25SBjoern A. Zeeb clear_bit(tid, &msta->wcid.ampdu_state);
9626c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_tx_ba(dev, params, false);
9636c92544dSBjoern A. Zeeb break;
9646c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_START:
965cbb3ec25SBjoern A. Zeeb set_bit(tid, &msta->wcid.ampdu_state);
9666c92544dSBjoern A. Zeeb ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
9676c92544dSBjoern A. Zeeb break;
9686c92544dSBjoern A. Zeeb case IEEE80211_AMPDU_TX_STOP_CONT:
9696c92544dSBjoern A. Zeeb mtxq->aggr = false;
970cbb3ec25SBjoern A. Zeeb clear_bit(tid, &msta->wcid.ampdu_state);
9716c92544dSBjoern A. Zeeb ret = mt7915_mcu_add_tx_ba(dev, params, false);
9726c92544dSBjoern A. Zeeb ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
9736c92544dSBjoern A. Zeeb break;
9746c92544dSBjoern A. Zeeb }
9756c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
9766c92544dSBjoern A. Zeeb
9776c92544dSBjoern A. Zeeb return ret;
9786c92544dSBjoern A. Zeeb }
9796c92544dSBjoern A. Zeeb
9806c92544dSBjoern A. Zeeb static int
mt7915_get_stats(struct ieee80211_hw * hw,struct ieee80211_low_level_stats * stats)9816c92544dSBjoern A. Zeeb mt7915_get_stats(struct ieee80211_hw *hw,
9826c92544dSBjoern A. Zeeb struct ieee80211_low_level_stats *stats)
9836c92544dSBjoern A. Zeeb {
9846c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
9856c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
986cbb3ec25SBjoern A. Zeeb struct mt76_mib_stats *mib = &phy->mib;
9876c92544dSBjoern A. Zeeb
9886c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
9896c92544dSBjoern A. Zeeb
9906c92544dSBjoern A. Zeeb stats->dot11RTSSuccessCount = mib->rts_cnt;
9916c92544dSBjoern A. Zeeb stats->dot11RTSFailureCount = mib->rts_retries_cnt;
9926c92544dSBjoern A. Zeeb stats->dot11FCSErrorCount = mib->fcs_err_cnt;
9936c92544dSBjoern A. Zeeb stats->dot11ACKFailureCount = mib->ack_fail_cnt;
9946c92544dSBjoern A. Zeeb
9956c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
9966c92544dSBjoern A. Zeeb
9976c92544dSBjoern A. Zeeb return 0;
9986c92544dSBjoern A. Zeeb }
9996c92544dSBjoern A. Zeeb
__mt7915_get_tsf(struct ieee80211_hw * hw,struct mt7915_vif * mvif)10006c92544dSBjoern A. Zeeb u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif)
10016c92544dSBjoern A. Zeeb {
10026c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
10036c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
1004cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx;
10056c92544dSBjoern A. Zeeb union {
10066c92544dSBjoern A. Zeeb u64 t64;
10076c92544dSBjoern A. Zeeb u32 t32[2];
10086c92544dSBjoern A. Zeeb } tsf;
10096c92544dSBjoern A. Zeeb u16 n;
10106c92544dSBjoern A. Zeeb
10116c92544dSBjoern A. Zeeb lockdep_assert_held(&dev->mt76.mutex);
10126c92544dSBjoern A. Zeeb
10136c92544dSBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
10146c92544dSBjoern A. Zeeb : mvif->mt76.omac_idx;
10156c92544dSBjoern A. Zeeb /* TSF software read */
10166c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76))
10176c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
10186c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_READ);
10196c92544dSBjoern A. Zeeb else
10206c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE,
10216c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_READ);
10226c92544dSBjoern A. Zeeb tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band));
10236c92544dSBjoern A. Zeeb tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band));
10246c92544dSBjoern A. Zeeb
10256c92544dSBjoern A. Zeeb return tsf.t64;
10266c92544dSBjoern A. Zeeb }
10276c92544dSBjoern A. Zeeb
10286c92544dSBjoern A. Zeeb static u64
mt7915_get_tsf(struct ieee80211_hw * hw,struct ieee80211_vif * vif)10296c92544dSBjoern A. Zeeb mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
10306c92544dSBjoern A. Zeeb {
10316c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
10326c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
10336c92544dSBjoern A. Zeeb u64 ret;
10346c92544dSBjoern A. Zeeb
10356c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
10366c92544dSBjoern A. Zeeb ret = __mt7915_get_tsf(hw, mvif);
10376c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
10386c92544dSBjoern A. Zeeb
10396c92544dSBjoern A. Zeeb return ret;
10406c92544dSBjoern A. Zeeb }
10416c92544dSBjoern A. Zeeb
10426c92544dSBjoern A. Zeeb static void
mt7915_set_tsf(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u64 timestamp)10436c92544dSBjoern A. Zeeb mt7915_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
10446c92544dSBjoern A. Zeeb u64 timestamp)
10456c92544dSBjoern A. Zeeb {
10466c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
10476c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
10486c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
1049cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx;
10506c92544dSBjoern A. Zeeb union {
10516c92544dSBjoern A. Zeeb u64 t64;
10526c92544dSBjoern A. Zeeb u32 t32[2];
10536c92544dSBjoern A. Zeeb } tsf = { .t64 = timestamp, };
10546c92544dSBjoern A. Zeeb u16 n;
10556c92544dSBjoern A. Zeeb
10566c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
10576c92544dSBjoern A. Zeeb
10586c92544dSBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
10596c92544dSBjoern A. Zeeb : mvif->mt76.omac_idx;
10606c92544dSBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
10616c92544dSBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
10626c92544dSBjoern A. Zeeb /* TSF software overwrite */
10636c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76))
10646c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
10656c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_WRITE);
10666c92544dSBjoern A. Zeeb else
10676c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE,
10686c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_WRITE);
10696c92544dSBjoern A. Zeeb
10706c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
10716c92544dSBjoern A. Zeeb }
10726c92544dSBjoern A. Zeeb
10736c92544dSBjoern A. Zeeb static void
mt7915_offset_tsf(struct ieee80211_hw * hw,struct ieee80211_vif * vif,s64 timestamp)10746c92544dSBjoern A. Zeeb mt7915_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
10756c92544dSBjoern A. Zeeb s64 timestamp)
10766c92544dSBjoern A. Zeeb {
10776c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
10786c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
10796c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
1080cbb3ec25SBjoern A. Zeeb bool band = phy->mt76->band_idx;
10816c92544dSBjoern A. Zeeb union {
10826c92544dSBjoern A. Zeeb u64 t64;
10836c92544dSBjoern A. Zeeb u32 t32[2];
10846c92544dSBjoern A. Zeeb } tsf = { .t64 = timestamp, };
10856c92544dSBjoern A. Zeeb u16 n;
10866c92544dSBjoern A. Zeeb
10876c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
10886c92544dSBjoern A. Zeeb
10896c92544dSBjoern A. Zeeb n = mvif->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
10906c92544dSBjoern A. Zeeb : mvif->mt76.omac_idx;
10916c92544dSBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
10926c92544dSBjoern A. Zeeb mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
10936c92544dSBjoern A. Zeeb /* TSF software adjust*/
10946c92544dSBjoern A. Zeeb if (is_mt7915(&dev->mt76))
10956c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
10966c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_ADJUST);
10976c92544dSBjoern A. Zeeb else
10986c92544dSBjoern A. Zeeb mt76_rmw(dev, MT_LPON_TCR_MT7916(band, n), MT_LPON_TCR_SW_MODE,
10996c92544dSBjoern A. Zeeb MT_LPON_TCR_SW_ADJUST);
11006c92544dSBjoern A. Zeeb
11016c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
11026c92544dSBjoern A. Zeeb }
11036c92544dSBjoern A. Zeeb
11046c92544dSBjoern A. Zeeb static void
mt7915_set_coverage_class(struct ieee80211_hw * hw,s16 coverage_class)11056c92544dSBjoern A. Zeeb mt7915_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
11066c92544dSBjoern A. Zeeb {
11076c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
11086c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
11096c92544dSBjoern A. Zeeb
11106c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
11116c92544dSBjoern A. Zeeb phy->coverage_class = max_t(s16, coverage_class, 0);
11126c92544dSBjoern A. Zeeb mt7915_mac_set_timing(phy);
11136c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
11146c92544dSBjoern A. Zeeb }
11156c92544dSBjoern A. Zeeb
11166c92544dSBjoern A. Zeeb static int
mt7915_set_antenna(struct ieee80211_hw * hw,u32 tx_ant,u32 rx_ant)11176c92544dSBjoern A. Zeeb mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
11186c92544dSBjoern A. Zeeb {
11196c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
11206c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
11216c92544dSBjoern A. Zeeb int max_nss = hweight8(hw->wiphy->available_antennas_tx);
1122cbb3ec25SBjoern A. Zeeb u8 chainshift = dev->chainshift;
1123cbb3ec25SBjoern A. Zeeb u8 band = phy->mt76->band_idx;
11246c92544dSBjoern A. Zeeb
11256c92544dSBjoern A. Zeeb if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss)
11266c92544dSBjoern A. Zeeb return -EINVAL;
11276c92544dSBjoern A. Zeeb
11286c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
11296c92544dSBjoern A. Zeeb
11306c92544dSBjoern A. Zeeb phy->mt76->antenna_mask = tx_ant;
11316c92544dSBjoern A. Zeeb
1132*8ba4d145SBjoern A. Zeeb /* handle a variant of mt7916/mt7981 which has 3T3R but nss2 on 5 GHz band */
1133*8ba4d145SBjoern A. Zeeb if ((is_mt7916(&dev->mt76) || is_mt7981(&dev->mt76)) &&
1134*8ba4d145SBjoern A. Zeeb band && hweight8(tx_ant) == max_nss)
1135cbb3ec25SBjoern A. Zeeb phy->mt76->chainmask = (dev->chainmask >> chainshift) << chainshift;
1136cbb3ec25SBjoern A. Zeeb else
1137cbb3ec25SBjoern A. Zeeb phy->mt76->chainmask = tx_ant << (chainshift * band);
11386c92544dSBjoern A. Zeeb
11396c92544dSBjoern A. Zeeb mt76_set_stream_caps(phy->mt76, true);
11406c92544dSBjoern A. Zeeb mt7915_set_stream_vht_txbf_caps(phy);
11416c92544dSBjoern A. Zeeb mt7915_set_stream_he_caps(phy);
11426c92544dSBjoern A. Zeeb
11436c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
11446c92544dSBjoern A. Zeeb
11456c92544dSBjoern A. Zeeb return 0;
11466c92544dSBjoern A. Zeeb }
11476c92544dSBjoern A. Zeeb
mt7915_sta_statistics(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct station_info * sinfo)11486c92544dSBjoern A. Zeeb static void mt7915_sta_statistics(struct ieee80211_hw *hw,
11496c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
11506c92544dSBjoern A. Zeeb struct ieee80211_sta *sta,
11516c92544dSBjoern A. Zeeb struct station_info *sinfo)
11526c92544dSBjoern A. Zeeb {
11536c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
11546c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
11556c92544dSBjoern A. Zeeb struct rate_info *txrate = &msta->wcid.rate;
11566c92544dSBjoern A. Zeeb struct rate_info rxrate = {};
11576c92544dSBjoern A. Zeeb
1158*8ba4d145SBjoern A. Zeeb if (!mt7915_mcu_get_rx_rate(phy, vif, sta, &rxrate)) {
11596c92544dSBjoern A. Zeeb sinfo->rxrate = rxrate;
11606c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
11616c92544dSBjoern A. Zeeb }
11626c92544dSBjoern A. Zeeb
1163cbb3ec25SBjoern A. Zeeb if (txrate->legacy || txrate->flags) {
11646c92544dSBjoern A. Zeeb if (txrate->legacy) {
11656c92544dSBjoern A. Zeeb sinfo->txrate.legacy = txrate->legacy;
11666c92544dSBjoern A. Zeeb } else {
11676c92544dSBjoern A. Zeeb sinfo->txrate.mcs = txrate->mcs;
11686c92544dSBjoern A. Zeeb sinfo->txrate.nss = txrate->nss;
11696c92544dSBjoern A. Zeeb sinfo->txrate.bw = txrate->bw;
11706c92544dSBjoern A. Zeeb sinfo->txrate.he_gi = txrate->he_gi;
11716c92544dSBjoern A. Zeeb sinfo->txrate.he_dcm = txrate->he_dcm;
11726c92544dSBjoern A. Zeeb sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
11736c92544dSBjoern A. Zeeb }
11746c92544dSBjoern A. Zeeb sinfo->txrate.flags = txrate->flags;
11756c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
1176cbb3ec25SBjoern A. Zeeb }
11776c92544dSBjoern A. Zeeb
11786c92544dSBjoern A. Zeeb /* offloading flows bypass networking stack, so driver counts and
11796c92544dSBjoern A. Zeeb * reports sta statistics via NL80211_STA_INFO when WED is active.
11806c92544dSBjoern A. Zeeb */
11816c92544dSBjoern A. Zeeb if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
11826c92544dSBjoern A. Zeeb sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
11836c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
11846c92544dSBjoern A. Zeeb
1185cbb3ec25SBjoern A. Zeeb if (!mt7915_mcu_wed_wa_tx_stats(phy->dev, msta->wcid.idx)) {
11866c92544dSBjoern A. Zeeb sinfo->tx_packets = msta->wcid.stats.tx_packets;
11876c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
1188cbb3ec25SBjoern A. Zeeb }
1189cbb3ec25SBjoern A. Zeeb
1190cbb3ec25SBjoern A. Zeeb if (mtk_wed_get_rx_capa(&phy->dev->mt76.mmio.wed)) {
1191cbb3ec25SBjoern A. Zeeb sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
1192cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
1193cbb3ec25SBjoern A. Zeeb
1194cbb3ec25SBjoern A. Zeeb sinfo->rx_packets = msta->wcid.stats.rx_packets;
1195cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
1196cbb3ec25SBjoern A. Zeeb }
1197cbb3ec25SBjoern A. Zeeb }
11986c92544dSBjoern A. Zeeb
11996c92544dSBjoern A. Zeeb sinfo->tx_failed = msta->wcid.stats.tx_failed;
12006c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
12016c92544dSBjoern A. Zeeb
12026c92544dSBjoern A. Zeeb sinfo->tx_retries = msta->wcid.stats.tx_retries;
12036c92544dSBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
1204cbb3ec25SBjoern A. Zeeb
1205cbb3ec25SBjoern A. Zeeb sinfo->ack_signal = (s8)msta->ack_signal;
1206cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
1207cbb3ec25SBjoern A. Zeeb
1208cbb3ec25SBjoern A. Zeeb sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
1209cbb3ec25SBjoern A. Zeeb sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
12106c92544dSBjoern A. Zeeb }
12116c92544dSBjoern A. Zeeb
mt7915_sta_rc_work(void * data,struct ieee80211_sta * sta)12126c92544dSBjoern A. Zeeb static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
12136c92544dSBjoern A. Zeeb {
12146c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
12156c92544dSBjoern A. Zeeb struct mt7915_dev *dev = msta->vif->phy->dev;
12166c92544dSBjoern A. Zeeb u32 *changed = data;
12176c92544dSBjoern A. Zeeb
1218cbb3ec25SBjoern A. Zeeb spin_lock_bh(&dev->mt76.sta_poll_lock);
12196c92544dSBjoern A. Zeeb msta->changed |= *changed;
12206c92544dSBjoern A. Zeeb if (list_empty(&msta->rc_list))
12216c92544dSBjoern A. Zeeb list_add_tail(&msta->rc_list, &dev->sta_rc_list);
1222cbb3ec25SBjoern A. Zeeb spin_unlock_bh(&dev->mt76.sta_poll_lock);
12236c92544dSBjoern A. Zeeb }
12246c92544dSBjoern A. Zeeb
mt7915_sta_rc_update(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_link_sta * link_sta,u32 changed)12256c92544dSBjoern A. Zeeb static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
12266c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
1227*8ba4d145SBjoern A. Zeeb struct ieee80211_link_sta *link_sta,
12286c92544dSBjoern A. Zeeb u32 changed)
12296c92544dSBjoern A. Zeeb {
1230*8ba4d145SBjoern A. Zeeb struct ieee80211_sta *sta = link_sta->sta;
12316c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
12326c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
1233*8ba4d145SBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
1234*8ba4d145SBjoern A. Zeeb
1235*8ba4d145SBjoern A. Zeeb if (!msta->wcid.sta)
1236*8ba4d145SBjoern A. Zeeb return;
12376c92544dSBjoern A. Zeeb
12386c92544dSBjoern A. Zeeb mt7915_sta_rc_work(&changed, sta);
12396c92544dSBjoern A. Zeeb ieee80211_queue_work(hw, &dev->rc_work);
12406c92544dSBjoern A. Zeeb }
12416c92544dSBjoern A. Zeeb
12426c92544dSBjoern A. Zeeb static int
mt7915_set_bitrate_mask(struct ieee80211_hw * hw,struct ieee80211_vif * vif,const struct cfg80211_bitrate_mask * mask)12436c92544dSBjoern A. Zeeb mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
12446c92544dSBjoern A. Zeeb const struct cfg80211_bitrate_mask *mask)
12456c92544dSBjoern A. Zeeb {
12466c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
12476c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
12486c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
12496c92544dSBjoern A. Zeeb u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
12506c92544dSBjoern A. Zeeb
12516c92544dSBjoern A. Zeeb mvif->bitrate_mask = *mask;
12526c92544dSBjoern A. Zeeb
12536c92544dSBjoern A. Zeeb /* if multiple rates across different preambles are given we can
12546c92544dSBjoern A. Zeeb * reconfigure this info with all peers using sta_rec command with
12556c92544dSBjoern A. Zeeb * the below exception cases.
12566c92544dSBjoern A. Zeeb * - single rate : if a rate is passed along with different preambles,
12576c92544dSBjoern A. Zeeb * we select the highest one as fixed rate. i.e VHT MCS for VHT peers.
12586c92544dSBjoern A. Zeeb * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT
12596c92544dSBjoern A. Zeeb * then multiple MCS setting (MCS 4,5,6) is not supported.
12606c92544dSBjoern A. Zeeb */
12616c92544dSBjoern A. Zeeb ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed);
12626c92544dSBjoern A. Zeeb ieee80211_queue_work(hw, &dev->rc_work);
12636c92544dSBjoern A. Zeeb
12646c92544dSBjoern A. Zeeb return 0;
12656c92544dSBjoern A. Zeeb }
12666c92544dSBjoern A. Zeeb
mt7915_sta_set_4addr(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enabled)12676c92544dSBjoern A. Zeeb static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
12686c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
12696c92544dSBjoern A. Zeeb struct ieee80211_sta *sta,
12706c92544dSBjoern A. Zeeb bool enabled)
12716c92544dSBjoern A. Zeeb {
12726c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
12736c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
12746c92544dSBjoern A. Zeeb
12756c92544dSBjoern A. Zeeb if (enabled)
12766c92544dSBjoern A. Zeeb set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
12776c92544dSBjoern A. Zeeb else
12786c92544dSBjoern A. Zeeb clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
12796c92544dSBjoern A. Zeeb
1280*8ba4d145SBjoern A. Zeeb if (!msta->wcid.sta)
1281*8ba4d145SBjoern A. Zeeb return;
1282*8ba4d145SBjoern A. Zeeb
12836c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
12846c92544dSBjoern A. Zeeb }
12856c92544dSBjoern A. Zeeb
mt7915_sta_set_decap_offload(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,bool enabled)12866c92544dSBjoern A. Zeeb static void mt7915_sta_set_decap_offload(struct ieee80211_hw *hw,
12876c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
12886c92544dSBjoern A. Zeeb struct ieee80211_sta *sta,
12896c92544dSBjoern A. Zeeb bool enabled)
12906c92544dSBjoern A. Zeeb {
12916c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
12926c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
12936c92544dSBjoern A. Zeeb
12946c92544dSBjoern A. Zeeb if (enabled)
12956c92544dSBjoern A. Zeeb set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
12966c92544dSBjoern A. Zeeb else
12976c92544dSBjoern A. Zeeb clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
12986c92544dSBjoern A. Zeeb
1299*8ba4d145SBjoern A. Zeeb if (!msta->wcid.sta)
1300*8ba4d145SBjoern A. Zeeb return;
1301*8ba4d145SBjoern A. Zeeb
13026c92544dSBjoern A. Zeeb mt76_connac_mcu_wtbl_update_hdr_trans(&dev->mt76, vif, sta);
13036c92544dSBjoern A. Zeeb }
13046c92544dSBjoern A. Zeeb
mt7915_sta_set_txpwr(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)1305cbb3ec25SBjoern A. Zeeb static int mt7915_sta_set_txpwr(struct ieee80211_hw *hw,
1306cbb3ec25SBjoern A. Zeeb struct ieee80211_vif *vif,
1307cbb3ec25SBjoern A. Zeeb struct ieee80211_sta *sta)
1308cbb3ec25SBjoern A. Zeeb {
1309cbb3ec25SBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
1310cbb3ec25SBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
1311cbb3ec25SBjoern A. Zeeb s16 txpower = sta->deflink.txpwr.power;
1312cbb3ec25SBjoern A. Zeeb int ret;
1313cbb3ec25SBjoern A. Zeeb
1314cbb3ec25SBjoern A. Zeeb if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC)
1315cbb3ec25SBjoern A. Zeeb txpower = 0;
1316cbb3ec25SBjoern A. Zeeb
1317cbb3ec25SBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
1318cbb3ec25SBjoern A. Zeeb
1319cbb3ec25SBjoern A. Zeeb /* NOTE: temporarily use 0 as minimum limit, which is a
1320cbb3ec25SBjoern A. Zeeb * global setting and will be applied to all stations.
1321cbb3ec25SBjoern A. Zeeb */
1322cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_txpower_frame_min(phy, 0);
1323cbb3ec25SBjoern A. Zeeb if (ret)
1324cbb3ec25SBjoern A. Zeeb goto out;
1325cbb3ec25SBjoern A. Zeeb
1326cbb3ec25SBjoern A. Zeeb /* This only applies to data frames while pushing traffic,
1327cbb3ec25SBjoern A. Zeeb * whereas the management frames or other packets that are
1328cbb3ec25SBjoern A. Zeeb * using fixed rate can be configured via TxD.
1329cbb3ec25SBjoern A. Zeeb */
1330cbb3ec25SBjoern A. Zeeb ret = mt7915_mcu_set_txpower_frame(phy, vif, sta, txpower);
1331cbb3ec25SBjoern A. Zeeb
1332cbb3ec25SBjoern A. Zeeb out:
1333cbb3ec25SBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
1334cbb3ec25SBjoern A. Zeeb
1335cbb3ec25SBjoern A. Zeeb return ret;
1336cbb3ec25SBjoern A. Zeeb }
1337cbb3ec25SBjoern A. Zeeb
13386c92544dSBjoern A. Zeeb static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = {
13396c92544dSBjoern A. Zeeb "tx_ampdu_cnt",
13406c92544dSBjoern A. Zeeb "tx_stop_q_empty_cnt",
13416c92544dSBjoern A. Zeeb "tx_mpdu_attempts",
13426c92544dSBjoern A. Zeeb "tx_mpdu_success",
13436c92544dSBjoern A. Zeeb "tx_rwp_fail_cnt",
13446c92544dSBjoern A. Zeeb "tx_rwp_need_cnt",
13456c92544dSBjoern A. Zeeb "tx_pkt_ebf_cnt",
13466c92544dSBjoern A. Zeeb "tx_pkt_ibf_cnt",
13476c92544dSBjoern A. Zeeb "tx_ampdu_len:0-1",
13486c92544dSBjoern A. Zeeb "tx_ampdu_len:2-10",
13496c92544dSBjoern A. Zeeb "tx_ampdu_len:11-19",
13506c92544dSBjoern A. Zeeb "tx_ampdu_len:20-28",
13516c92544dSBjoern A. Zeeb "tx_ampdu_len:29-37",
13526c92544dSBjoern A. Zeeb "tx_ampdu_len:38-46",
13536c92544dSBjoern A. Zeeb "tx_ampdu_len:47-55",
13546c92544dSBjoern A. Zeeb "tx_ampdu_len:56-79",
13556c92544dSBjoern A. Zeeb "tx_ampdu_len:80-103",
13566c92544dSBjoern A. Zeeb "tx_ampdu_len:104-127",
13576c92544dSBjoern A. Zeeb "tx_ampdu_len:128-151",
13586c92544dSBjoern A. Zeeb "tx_ampdu_len:152-175",
13596c92544dSBjoern A. Zeeb "tx_ampdu_len:176-199",
13606c92544dSBjoern A. Zeeb "tx_ampdu_len:200-223",
13616c92544dSBjoern A. Zeeb "tx_ampdu_len:224-247",
13626c92544dSBjoern A. Zeeb "ba_miss_count",
13636c92544dSBjoern A. Zeeb "tx_beamformer_ppdu_iBF",
13646c92544dSBjoern A. Zeeb "tx_beamformer_ppdu_eBF",
13656c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_all",
13666c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_he",
13676c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_vht",
13686c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_ht",
13696c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_bw", /* zero based idx: 20, 40, 80, 160 */
13706c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_nc",
13716c92544dSBjoern A. Zeeb "tx_beamformer_rx_feedback_nr",
13726c92544dSBjoern A. Zeeb "tx_beamformee_ok_feedback_pkts",
13736c92544dSBjoern A. Zeeb "tx_beamformee_feedback_trig",
13746c92544dSBjoern A. Zeeb "tx_mu_beamforming",
13756c92544dSBjoern A. Zeeb "tx_mu_mpdu",
13766c92544dSBjoern A. Zeeb "tx_mu_successful_mpdu",
13776c92544dSBjoern A. Zeeb "tx_su_successful_mpdu",
13786c92544dSBjoern A. Zeeb "tx_msdu_pack_1",
13796c92544dSBjoern A. Zeeb "tx_msdu_pack_2",
13806c92544dSBjoern A. Zeeb "tx_msdu_pack_3",
13816c92544dSBjoern A. Zeeb "tx_msdu_pack_4",
13826c92544dSBjoern A. Zeeb "tx_msdu_pack_5",
13836c92544dSBjoern A. Zeeb "tx_msdu_pack_6",
13846c92544dSBjoern A. Zeeb "tx_msdu_pack_7",
13856c92544dSBjoern A. Zeeb "tx_msdu_pack_8",
13866c92544dSBjoern A. Zeeb
13876c92544dSBjoern A. Zeeb /* rx counters */
13886c92544dSBjoern A. Zeeb "rx_fifo_full_cnt",
13896c92544dSBjoern A. Zeeb "rx_mpdu_cnt",
13906c92544dSBjoern A. Zeeb "channel_idle_cnt",
13916c92544dSBjoern A. Zeeb "primary_cca_busy_time",
13926c92544dSBjoern A. Zeeb "secondary_cca_busy_time",
13936c92544dSBjoern A. Zeeb "primary_energy_detect_time",
13946c92544dSBjoern A. Zeeb "cck_mdrdy_time",
13956c92544dSBjoern A. Zeeb "ofdm_mdrdy_time",
13966c92544dSBjoern A. Zeeb "green_mdrdy_time",
13976c92544dSBjoern A. Zeeb "rx_vector_mismatch_cnt",
13986c92544dSBjoern A. Zeeb "rx_delimiter_fail_cnt",
13996c92544dSBjoern A. Zeeb "rx_mrdy_cnt",
14006c92544dSBjoern A. Zeeb "rx_len_mismatch_cnt",
14016c92544dSBjoern A. Zeeb "rx_ampdu_cnt",
14026c92544dSBjoern A. Zeeb "rx_ampdu_bytes_cnt",
14036c92544dSBjoern A. Zeeb "rx_ampdu_valid_subframe_cnt",
14046c92544dSBjoern A. Zeeb "rx_ampdu_valid_subframe_b_cnt",
14056c92544dSBjoern A. Zeeb "rx_pfdrop_cnt",
14066c92544dSBjoern A. Zeeb "rx_vec_queue_overflow_drop_cnt",
14076c92544dSBjoern A. Zeeb "rx_ba_cnt",
14086c92544dSBjoern A. Zeeb
1409cbb3ec25SBjoern A. Zeeb /* muru mu-mimo and ofdma related stats */
1410cbb3ec25SBjoern A. Zeeb "dl_cck_cnt",
1411cbb3ec25SBjoern A. Zeeb "dl_ofdm_cnt",
1412cbb3ec25SBjoern A. Zeeb "dl_htmix_cnt",
1413cbb3ec25SBjoern A. Zeeb "dl_htgf_cnt",
1414cbb3ec25SBjoern A. Zeeb "dl_vht_su_cnt",
1415cbb3ec25SBjoern A. Zeeb "dl_vht_2mu_cnt",
1416cbb3ec25SBjoern A. Zeeb "dl_vht_3mu_cnt",
1417cbb3ec25SBjoern A. Zeeb "dl_vht_4mu_cnt",
1418cbb3ec25SBjoern A. Zeeb "dl_he_su_cnt",
1419cbb3ec25SBjoern A. Zeeb "dl_he_ext_su_cnt",
1420cbb3ec25SBjoern A. Zeeb "dl_he_2ru_cnt",
1421cbb3ec25SBjoern A. Zeeb "dl_he_2mu_cnt",
1422cbb3ec25SBjoern A. Zeeb "dl_he_3ru_cnt",
1423cbb3ec25SBjoern A. Zeeb "dl_he_3mu_cnt",
1424cbb3ec25SBjoern A. Zeeb "dl_he_4ru_cnt",
1425cbb3ec25SBjoern A. Zeeb "dl_he_4mu_cnt",
1426cbb3ec25SBjoern A. Zeeb "dl_he_5to8ru_cnt",
1427cbb3ec25SBjoern A. Zeeb "dl_he_9to16ru_cnt",
1428cbb3ec25SBjoern A. Zeeb "dl_he_gtr16ru_cnt",
1429cbb3ec25SBjoern A. Zeeb
1430cbb3ec25SBjoern A. Zeeb "ul_hetrig_su_cnt",
1431cbb3ec25SBjoern A. Zeeb "ul_hetrig_2ru_cnt",
1432cbb3ec25SBjoern A. Zeeb "ul_hetrig_3ru_cnt",
1433cbb3ec25SBjoern A. Zeeb "ul_hetrig_4ru_cnt",
1434cbb3ec25SBjoern A. Zeeb "ul_hetrig_5to8ru_cnt",
1435cbb3ec25SBjoern A. Zeeb "ul_hetrig_9to16ru_cnt",
1436cbb3ec25SBjoern A. Zeeb "ul_hetrig_gtr16ru_cnt",
1437cbb3ec25SBjoern A. Zeeb "ul_hetrig_2mu_cnt",
1438cbb3ec25SBjoern A. Zeeb "ul_hetrig_3mu_cnt",
1439cbb3ec25SBjoern A. Zeeb "ul_hetrig_4mu_cnt",
1440cbb3ec25SBjoern A. Zeeb
14416c92544dSBjoern A. Zeeb /* per vif counters */
14426c92544dSBjoern A. Zeeb "v_tx_mode_cck",
14436c92544dSBjoern A. Zeeb "v_tx_mode_ofdm",
14446c92544dSBjoern A. Zeeb "v_tx_mode_ht",
14456c92544dSBjoern A. Zeeb "v_tx_mode_ht_gf",
14466c92544dSBjoern A. Zeeb "v_tx_mode_vht",
14476c92544dSBjoern A. Zeeb "v_tx_mode_he_su",
14486c92544dSBjoern A. Zeeb "v_tx_mode_he_ext_su",
14496c92544dSBjoern A. Zeeb "v_tx_mode_he_tb",
14506c92544dSBjoern A. Zeeb "v_tx_mode_he_mu",
14516c92544dSBjoern A. Zeeb "v_tx_bw_20",
14526c92544dSBjoern A. Zeeb "v_tx_bw_40",
14536c92544dSBjoern A. Zeeb "v_tx_bw_80",
14546c92544dSBjoern A. Zeeb "v_tx_bw_160",
14556c92544dSBjoern A. Zeeb "v_tx_mcs_0",
14566c92544dSBjoern A. Zeeb "v_tx_mcs_1",
14576c92544dSBjoern A. Zeeb "v_tx_mcs_2",
14586c92544dSBjoern A. Zeeb "v_tx_mcs_3",
14596c92544dSBjoern A. Zeeb "v_tx_mcs_4",
14606c92544dSBjoern A. Zeeb "v_tx_mcs_5",
14616c92544dSBjoern A. Zeeb "v_tx_mcs_6",
14626c92544dSBjoern A. Zeeb "v_tx_mcs_7",
14636c92544dSBjoern A. Zeeb "v_tx_mcs_8",
14646c92544dSBjoern A. Zeeb "v_tx_mcs_9",
14656c92544dSBjoern A. Zeeb "v_tx_mcs_10",
14666c92544dSBjoern A. Zeeb "v_tx_mcs_11",
1467cbb3ec25SBjoern A. Zeeb "v_tx_nss_1",
1468cbb3ec25SBjoern A. Zeeb "v_tx_nss_2",
1469cbb3ec25SBjoern A. Zeeb "v_tx_nss_3",
1470cbb3ec25SBjoern A. Zeeb "v_tx_nss_4",
14716c92544dSBjoern A. Zeeb };
14726c92544dSBjoern A. Zeeb
14736c92544dSBjoern A. Zeeb #define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats)
14746c92544dSBjoern A. Zeeb
14756c92544dSBjoern A. Zeeb /* Ethtool related API */
14766c92544dSBjoern A. Zeeb static
mt7915_get_et_strings(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u32 sset,u8 * data)14776c92544dSBjoern A. Zeeb void mt7915_get_et_strings(struct ieee80211_hw *hw,
14786c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
14796c92544dSBjoern A. Zeeb u32 sset, u8 *data)
14806c92544dSBjoern A. Zeeb {
1481cbb3ec25SBjoern A. Zeeb if (sset != ETH_SS_STATS)
1482cbb3ec25SBjoern A. Zeeb return;
1483cbb3ec25SBjoern A. Zeeb
1484*8ba4d145SBjoern A. Zeeb memcpy(data, mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));
1485cbb3ec25SBjoern A. Zeeb data += sizeof(mt7915_gstrings_stats);
1486cbb3ec25SBjoern A. Zeeb page_pool_ethtool_stats_get_strings(data);
14876c92544dSBjoern A. Zeeb }
14886c92544dSBjoern A. Zeeb
14896c92544dSBjoern A. Zeeb static
mt7915_get_et_sset_count(struct ieee80211_hw * hw,struct ieee80211_vif * vif,int sset)14906c92544dSBjoern A. Zeeb int mt7915_get_et_sset_count(struct ieee80211_hw *hw,
14916c92544dSBjoern A. Zeeb struct ieee80211_vif *vif, int sset)
14926c92544dSBjoern A. Zeeb {
1493cbb3ec25SBjoern A. Zeeb if (sset != ETH_SS_STATS)
14946c92544dSBjoern A. Zeeb return 0;
1495cbb3ec25SBjoern A. Zeeb
1496cbb3ec25SBjoern A. Zeeb return MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count();
14976c92544dSBjoern A. Zeeb }
14986c92544dSBjoern A. Zeeb
mt7915_ethtool_worker(void * wi_data,struct ieee80211_sta * sta)14996c92544dSBjoern A. Zeeb static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
15006c92544dSBjoern A. Zeeb {
15016c92544dSBjoern A. Zeeb struct mt76_ethtool_worker_info *wi = wi_data;
15026c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
15036c92544dSBjoern A. Zeeb
15046c92544dSBjoern A. Zeeb if (msta->vif->mt76.idx != wi->idx)
15056c92544dSBjoern A. Zeeb return;
15066c92544dSBjoern A. Zeeb
1507cbb3ec25SBjoern A. Zeeb mt76_ethtool_worker(wi, &msta->wcid.stats, false);
15086c92544dSBjoern A. Zeeb }
15096c92544dSBjoern A. Zeeb
15106c92544dSBjoern A. Zeeb static
mt7915_get_et_stats(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ethtool_stats * stats,u64 * data)15116c92544dSBjoern A. Zeeb void mt7915_get_et_stats(struct ieee80211_hw *hw,
15126c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
15136c92544dSBjoern A. Zeeb struct ethtool_stats *stats, u64 *data)
15146c92544dSBjoern A. Zeeb {
15156c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
15166c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
15176c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
1518cbb3ec25SBjoern A. Zeeb struct mt76_mib_stats *mib = &phy->mib;
15196c92544dSBjoern A. Zeeb struct mt76_ethtool_worker_info wi = {
15206c92544dSBjoern A. Zeeb .data = data,
15216c92544dSBjoern A. Zeeb .idx = mvif->mt76.idx,
15226c92544dSBjoern A. Zeeb };
15236c92544dSBjoern A. Zeeb /* See mt7915_ampdu_stat_read_phy, etc */
1524cbb3ec25SBjoern A. Zeeb int i, ei = 0, stats_size;
15256c92544dSBjoern A. Zeeb
15266c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
15276c92544dSBjoern A. Zeeb
15286c92544dSBjoern A. Zeeb mt7915_mac_update_stats(phy);
15296c92544dSBjoern A. Zeeb
15306c92544dSBjoern A. Zeeb data[ei++] = mib->tx_ampdu_cnt;
15316c92544dSBjoern A. Zeeb data[ei++] = mib->tx_stop_q_empty_cnt;
15326c92544dSBjoern A. Zeeb data[ei++] = mib->tx_mpdu_attempts_cnt;
15336c92544dSBjoern A. Zeeb data[ei++] = mib->tx_mpdu_success_cnt;
15346c92544dSBjoern A. Zeeb data[ei++] = mib->tx_rwp_fail_cnt;
15356c92544dSBjoern A. Zeeb data[ei++] = mib->tx_rwp_need_cnt;
15366c92544dSBjoern A. Zeeb data[ei++] = mib->tx_pkt_ebf_cnt;
15376c92544dSBjoern A. Zeeb data[ei++] = mib->tx_pkt_ibf_cnt;
15386c92544dSBjoern A. Zeeb
15396c92544dSBjoern A. Zeeb /* Tx ampdu stat */
15406c92544dSBjoern A. Zeeb for (i = 0; i < 15 /*ARRAY_SIZE(bound)*/; i++)
1541cbb3ec25SBjoern A. Zeeb data[ei++] = phy->mt76->aggr_stats[i];
15426c92544dSBjoern A. Zeeb
15436c92544dSBjoern A. Zeeb data[ei++] = phy->mib.ba_miss_cnt;
15446c92544dSBjoern A. Zeeb
15456c92544dSBjoern A. Zeeb /* Tx Beamformer monitor */
15466c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_ibf_ppdu_cnt;
15476c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_ebf_ppdu_cnt;
15486c92544dSBjoern A. Zeeb
15496c92544dSBjoern A. Zeeb /* Tx Beamformer Rx feedback monitor */
15506c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_all_cnt;
15516c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_he_cnt;
15526c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_vht_cnt;
15536c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_ht_cnt;
15546c92544dSBjoern A. Zeeb
15556c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_bw;
15566c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_nc_cnt;
15576c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_rx_fb_nr_cnt;
15586c92544dSBjoern A. Zeeb
15596c92544dSBjoern A. Zeeb /* Tx Beamformee Rx NDPA & Tx feedback report */
15606c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_fb_cpl_cnt;
15616c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_fb_trig_cnt;
15626c92544dSBjoern A. Zeeb
15636c92544dSBjoern A. Zeeb /* Tx SU & MU counters */
15646c92544dSBjoern A. Zeeb data[ei++] = mib->tx_bf_cnt;
15656c92544dSBjoern A. Zeeb data[ei++] = mib->tx_mu_mpdu_cnt;
15666c92544dSBjoern A. Zeeb data[ei++] = mib->tx_mu_acked_mpdu_cnt;
15676c92544dSBjoern A. Zeeb data[ei++] = mib->tx_su_acked_mpdu_cnt;
15686c92544dSBjoern A. Zeeb
15696c92544dSBjoern A. Zeeb /* Tx amsdu info (pack-count histogram) */
15706c92544dSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++)
15716c92544dSBjoern A. Zeeb data[ei++] = mib->tx_amsdu[i];
15726c92544dSBjoern A. Zeeb
15736c92544dSBjoern A. Zeeb /* rx counters */
15746c92544dSBjoern A. Zeeb data[ei++] = mib->rx_fifo_full_cnt;
15756c92544dSBjoern A. Zeeb data[ei++] = mib->rx_mpdu_cnt;
15766c92544dSBjoern A. Zeeb data[ei++] = mib->channel_idle_cnt;
15776c92544dSBjoern A. Zeeb data[ei++] = mib->primary_cca_busy_time;
15786c92544dSBjoern A. Zeeb data[ei++] = mib->secondary_cca_busy_time;
15796c92544dSBjoern A. Zeeb data[ei++] = mib->primary_energy_detect_time;
15806c92544dSBjoern A. Zeeb data[ei++] = mib->cck_mdrdy_time;
15816c92544dSBjoern A. Zeeb data[ei++] = mib->ofdm_mdrdy_time;
15826c92544dSBjoern A. Zeeb data[ei++] = mib->green_mdrdy_time;
15836c92544dSBjoern A. Zeeb data[ei++] = mib->rx_vector_mismatch_cnt;
15846c92544dSBjoern A. Zeeb data[ei++] = mib->rx_delimiter_fail_cnt;
15856c92544dSBjoern A. Zeeb data[ei++] = mib->rx_mrdy_cnt;
15866c92544dSBjoern A. Zeeb data[ei++] = mib->rx_len_mismatch_cnt;
15876c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ampdu_cnt;
15886c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ampdu_bytes_cnt;
15896c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ampdu_valid_subframe_cnt;
15906c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ampdu_valid_subframe_bytes_cnt;
15916c92544dSBjoern A. Zeeb data[ei++] = mib->rx_pfdrop_cnt;
15926c92544dSBjoern A. Zeeb data[ei++] = mib->rx_vec_queue_overflow_drop_cnt;
15936c92544dSBjoern A. Zeeb data[ei++] = mib->rx_ba_cnt;
15946c92544dSBjoern A. Zeeb
1595cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_cck_cnt;
1596cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_ofdm_cnt;
1597cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_htmix_cnt;
1598cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_htgf_cnt;
1599cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_vht_su_cnt;
1600cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_vht_2mu_cnt;
1601cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_vht_3mu_cnt;
1602cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_vht_4mu_cnt;
1603cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_su_cnt;
1604cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_ext_su_cnt;
1605cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_2ru_cnt;
1606cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_2mu_cnt;
1607cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_3ru_cnt;
1608cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_3mu_cnt;
1609cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_4ru_cnt;
1610cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_4mu_cnt;
1611cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_5to8ru_cnt;
1612cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_9to16ru_cnt;
1613cbb3ec25SBjoern A. Zeeb data[ei++] = mib->dl_he_gtr16ru_cnt;
1614cbb3ec25SBjoern A. Zeeb
1615cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_su_cnt;
1616cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_2ru_cnt;
1617cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_3ru_cnt;
1618cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_4ru_cnt;
1619cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_5to8ru_cnt;
1620cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_9to16ru_cnt;
1621cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_gtr16ru_cnt;
1622cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_2mu_cnt;
1623cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_3mu_cnt;
1624cbb3ec25SBjoern A. Zeeb data[ei++] = mib->ul_hetrig_4mu_cnt;
1625cbb3ec25SBjoern A. Zeeb
16266c92544dSBjoern A. Zeeb /* Add values for all stations owned by this vif */
16276c92544dSBjoern A. Zeeb wi.initial_stat_idx = ei;
16286c92544dSBjoern A. Zeeb ieee80211_iterate_stations_atomic(hw, mt7915_ethtool_worker, &wi);
16296c92544dSBjoern A. Zeeb
16306c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
16316c92544dSBjoern A. Zeeb
16326c92544dSBjoern A. Zeeb if (wi.sta_count == 0)
16336c92544dSBjoern A. Zeeb return;
16346c92544dSBjoern A. Zeeb
16356c92544dSBjoern A. Zeeb ei += wi.worker_stat_count;
1636cbb3ec25SBjoern A. Zeeb
1637cbb3ec25SBjoern A. Zeeb mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei);
1638cbb3ec25SBjoern A. Zeeb
1639cbb3ec25SBjoern A. Zeeb stats_size = MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count();
1640cbb3ec25SBjoern A. Zeeb if (ei != stats_size)
1641cbb3ec25SBjoern A. Zeeb dev_err(dev->mt76.dev, "ei: %d size: %d", ei, stats_size);
16426c92544dSBjoern A. Zeeb }
16436c92544dSBjoern A. Zeeb
16446c92544dSBjoern A. Zeeb static void
mt7915_twt_teardown_request(struct ieee80211_hw * hw,struct ieee80211_sta * sta,u8 flowid)16456c92544dSBjoern A. Zeeb mt7915_twt_teardown_request(struct ieee80211_hw *hw,
16466c92544dSBjoern A. Zeeb struct ieee80211_sta *sta,
16476c92544dSBjoern A. Zeeb u8 flowid)
16486c92544dSBjoern A. Zeeb {
16496c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
16506c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
16516c92544dSBjoern A. Zeeb
16526c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
16536c92544dSBjoern A. Zeeb mt7915_mac_twt_teardown_flow(dev, msta, flowid);
16546c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
16556c92544dSBjoern A. Zeeb }
16566c92544dSBjoern A. Zeeb
16576c92544dSBjoern A. Zeeb static int
mt7915_set_frag_threshold(struct ieee80211_hw * hw,u32 val)1658*8ba4d145SBjoern A. Zeeb mt7915_set_frag_threshold(struct ieee80211_hw *hw, u32 val)
1659*8ba4d145SBjoern A. Zeeb {
1660*8ba4d145SBjoern A. Zeeb return 0;
1661*8ba4d145SBjoern A. Zeeb }
1662*8ba4d145SBjoern A. Zeeb
1663*8ba4d145SBjoern A. Zeeb static int
mt7915_set_radar_background(struct ieee80211_hw * hw,struct cfg80211_chan_def * chandef)16646c92544dSBjoern A. Zeeb mt7915_set_radar_background(struct ieee80211_hw *hw,
16656c92544dSBjoern A. Zeeb struct cfg80211_chan_def *chandef)
16666c92544dSBjoern A. Zeeb {
16676c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
16686c92544dSBjoern A. Zeeb struct mt7915_dev *dev = phy->dev;
16696c92544dSBjoern A. Zeeb int ret = -EINVAL;
16706c92544dSBjoern A. Zeeb bool running;
16716c92544dSBjoern A. Zeeb
16726c92544dSBjoern A. Zeeb mutex_lock(&dev->mt76.mutex);
16736c92544dSBjoern A. Zeeb
16746c92544dSBjoern A. Zeeb if (dev->mt76.region == NL80211_DFS_UNSET)
16756c92544dSBjoern A. Zeeb goto out;
16766c92544dSBjoern A. Zeeb
16776c92544dSBjoern A. Zeeb if (dev->rdd2_phy && dev->rdd2_phy != phy) {
16786c92544dSBjoern A. Zeeb /* rdd2 is already locked */
16796c92544dSBjoern A. Zeeb ret = -EBUSY;
16806c92544dSBjoern A. Zeeb goto out;
16816c92544dSBjoern A. Zeeb }
16826c92544dSBjoern A. Zeeb
16836c92544dSBjoern A. Zeeb /* rdd2 already configured on a radar channel */
16846c92544dSBjoern A. Zeeb running = dev->rdd2_phy &&
16856c92544dSBjoern A. Zeeb cfg80211_chandef_valid(&dev->rdd2_chandef) &&
16866c92544dSBjoern A. Zeeb !!(dev->rdd2_chandef.chan->flags & IEEE80211_CHAN_RADAR);
16876c92544dSBjoern A. Zeeb
16886c92544dSBjoern A. Zeeb if (!chandef || running ||
16896c92544dSBjoern A. Zeeb !(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {
16906c92544dSBjoern A. Zeeb ret = mt7915_mcu_rdd_background_enable(phy, NULL);
16916c92544dSBjoern A. Zeeb if (ret)
16926c92544dSBjoern A. Zeeb goto out;
16936c92544dSBjoern A. Zeeb
16946c92544dSBjoern A. Zeeb if (!running)
16956c92544dSBjoern A. Zeeb goto update_phy;
16966c92544dSBjoern A. Zeeb }
16976c92544dSBjoern A. Zeeb
16986c92544dSBjoern A. Zeeb ret = mt7915_mcu_rdd_background_enable(phy, chandef);
16996c92544dSBjoern A. Zeeb if (ret)
17006c92544dSBjoern A. Zeeb goto out;
17016c92544dSBjoern A. Zeeb
17026c92544dSBjoern A. Zeeb update_phy:
17036c92544dSBjoern A. Zeeb dev->rdd2_phy = chandef ? phy : NULL;
17046c92544dSBjoern A. Zeeb if (chandef)
17056c92544dSBjoern A. Zeeb dev->rdd2_chandef = *chandef;
17066c92544dSBjoern A. Zeeb out:
17076c92544dSBjoern A. Zeeb mutex_unlock(&dev->mt76.mutex);
17086c92544dSBjoern A. Zeeb
17096c92544dSBjoern A. Zeeb return ret;
17106c92544dSBjoern A. Zeeb }
17116c92544dSBjoern A. Zeeb
17126c92544dSBjoern A. Zeeb #ifdef CONFIG_NET_MEDIATEK_SOC_WED
17136c92544dSBjoern A. Zeeb static int
mt7915_net_fill_forward_path(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct net_device_path_ctx * ctx,struct net_device_path * path)17146c92544dSBjoern A. Zeeb mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
17156c92544dSBjoern A. Zeeb struct ieee80211_vif *vif,
17166c92544dSBjoern A. Zeeb struct ieee80211_sta *sta,
17176c92544dSBjoern A. Zeeb struct net_device_path_ctx *ctx,
17186c92544dSBjoern A. Zeeb struct net_device_path *path)
17196c92544dSBjoern A. Zeeb {
17206c92544dSBjoern A. Zeeb struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
17216c92544dSBjoern A. Zeeb struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
17226c92544dSBjoern A. Zeeb struct mt7915_dev *dev = mt7915_hw_dev(hw);
17236c92544dSBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
17246c92544dSBjoern A. Zeeb struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
17256c92544dSBjoern A. Zeeb
17266c92544dSBjoern A. Zeeb if (!mtk_wed_device_active(wed))
17276c92544dSBjoern A. Zeeb return -ENODEV;
17286c92544dSBjoern A. Zeeb
17296c92544dSBjoern A. Zeeb if (msta->wcid.idx > 0xff)
17306c92544dSBjoern A. Zeeb return -EIO;
17316c92544dSBjoern A. Zeeb
17326c92544dSBjoern A. Zeeb path->type = DEV_PATH_MTK_WDMA;
17336c92544dSBjoern A. Zeeb path->dev = ctx->dev;
17346c92544dSBjoern A. Zeeb path->mtk_wdma.wdma_idx = wed->wdma_idx;
17356c92544dSBjoern A. Zeeb path->mtk_wdma.bss = mvif->mt76.idx;
1736cbb3ec25SBjoern A. Zeeb path->mtk_wdma.wcid = is_mt7915(&dev->mt76) ? msta->wcid.idx : 0x3ff;
17376c92544dSBjoern A. Zeeb path->mtk_wdma.queue = phy != &dev->phy;
17386c92544dSBjoern A. Zeeb
17396c92544dSBjoern A. Zeeb ctx->dev = NULL;
17406c92544dSBjoern A. Zeeb
17416c92544dSBjoern A. Zeeb return 0;
17426c92544dSBjoern A. Zeeb }
17436c92544dSBjoern A. Zeeb #endif
17446c92544dSBjoern A. Zeeb
1745*8ba4d145SBjoern A. Zeeb static void
mt7915_reconfig_complete(struct ieee80211_hw * hw,enum ieee80211_reconfig_type reconfig_type)1746*8ba4d145SBjoern A. Zeeb mt7915_reconfig_complete(struct ieee80211_hw *hw,
1747*8ba4d145SBjoern A. Zeeb enum ieee80211_reconfig_type reconfig_type)
1748*8ba4d145SBjoern A. Zeeb {
1749*8ba4d145SBjoern A. Zeeb struct mt7915_phy *phy = mt7915_hw_phy(hw);
1750*8ba4d145SBjoern A. Zeeb
1751*8ba4d145SBjoern A. Zeeb ieee80211_wake_queues(hw);
1752*8ba4d145SBjoern A. Zeeb ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
1753*8ba4d145SBjoern A. Zeeb MT7915_WATCHDOG_TIME);
1754*8ba4d145SBjoern A. Zeeb }
1755*8ba4d145SBjoern A. Zeeb
17566c92544dSBjoern A. Zeeb const struct ieee80211_ops mt7915_ops = {
1757*8ba4d145SBjoern A. Zeeb .add_chanctx = ieee80211_emulate_add_chanctx,
1758*8ba4d145SBjoern A. Zeeb .remove_chanctx = ieee80211_emulate_remove_chanctx,
1759*8ba4d145SBjoern A. Zeeb .change_chanctx = ieee80211_emulate_change_chanctx,
1760*8ba4d145SBjoern A. Zeeb .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
17616c92544dSBjoern A. Zeeb .tx = mt7915_tx,
17626c92544dSBjoern A. Zeeb .start = mt7915_start,
17636c92544dSBjoern A. Zeeb .stop = mt7915_stop,
17646c92544dSBjoern A. Zeeb .add_interface = mt7915_add_interface,
17656c92544dSBjoern A. Zeeb .remove_interface = mt7915_remove_interface,
17666c92544dSBjoern A. Zeeb .config = mt7915_config,
17676c92544dSBjoern A. Zeeb .conf_tx = mt7915_conf_tx,
17686c92544dSBjoern A. Zeeb .configure_filter = mt7915_configure_filter,
17696c92544dSBjoern A. Zeeb .bss_info_changed = mt7915_bss_info_changed,
1770cbb3ec25SBjoern A. Zeeb .start_ap = mt7915_start_ap,
1771cbb3ec25SBjoern A. Zeeb .stop_ap = mt7915_stop_ap,
1772*8ba4d145SBjoern A. Zeeb .sta_state = mt76_sta_state,
17736c92544dSBjoern A. Zeeb .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
1774*8ba4d145SBjoern A. Zeeb .link_sta_rc_update = mt7915_sta_rc_update,
17756c92544dSBjoern A. Zeeb .set_key = mt7915_set_key,
17766c92544dSBjoern A. Zeeb .ampdu_action = mt7915_ampdu_action,
17776c92544dSBjoern A. Zeeb .set_rts_threshold = mt7915_set_rts_threshold,
17786c92544dSBjoern A. Zeeb .wake_tx_queue = mt76_wake_tx_queue,
17796c92544dSBjoern A. Zeeb .sw_scan_start = mt76_sw_scan,
17806c92544dSBjoern A. Zeeb .sw_scan_complete = mt76_sw_scan_complete,
17816c92544dSBjoern A. Zeeb .release_buffered_frames = mt76_release_buffered_frames,
17826c92544dSBjoern A. Zeeb .get_txpower = mt76_get_txpower,
17836c92544dSBjoern A. Zeeb .set_sar_specs = mt7915_set_sar_specs,
17846c92544dSBjoern A. Zeeb .channel_switch_beacon = mt7915_channel_switch_beacon,
17856c92544dSBjoern A. Zeeb .get_stats = mt7915_get_stats,
17866c92544dSBjoern A. Zeeb .get_et_sset_count = mt7915_get_et_sset_count,
17876c92544dSBjoern A. Zeeb .get_et_stats = mt7915_get_et_stats,
17886c92544dSBjoern A. Zeeb .get_et_strings = mt7915_get_et_strings,
17896c92544dSBjoern A. Zeeb .get_tsf = mt7915_get_tsf,
17906c92544dSBjoern A. Zeeb .set_tsf = mt7915_set_tsf,
17916c92544dSBjoern A. Zeeb .offset_tsf = mt7915_offset_tsf,
17926c92544dSBjoern A. Zeeb .get_survey = mt76_get_survey,
17936c92544dSBjoern A. Zeeb .get_antenna = mt76_get_antenna,
17946c92544dSBjoern A. Zeeb .set_antenna = mt7915_set_antenna,
17956c92544dSBjoern A. Zeeb .set_bitrate_mask = mt7915_set_bitrate_mask,
17966c92544dSBjoern A. Zeeb .set_coverage_class = mt7915_set_coverage_class,
17976c92544dSBjoern A. Zeeb .sta_statistics = mt7915_sta_statistics,
1798cbb3ec25SBjoern A. Zeeb .sta_set_txpwr = mt7915_sta_set_txpwr,
17996c92544dSBjoern A. Zeeb .sta_set_4addr = mt7915_sta_set_4addr,
18006c92544dSBjoern A. Zeeb .sta_set_decap_offload = mt7915_sta_set_decap_offload,
18016c92544dSBjoern A. Zeeb .add_twt_setup = mt7915_mac_add_twt_setup,
18026c92544dSBjoern A. Zeeb .twt_teardown_request = mt7915_twt_teardown_request,
1803*8ba4d145SBjoern A. Zeeb .set_frag_threshold = mt7915_set_frag_threshold,
18046c92544dSBjoern A. Zeeb CFG80211_TESTMODE_CMD(mt76_testmode_cmd)
18056c92544dSBjoern A. Zeeb CFG80211_TESTMODE_DUMP(mt76_testmode_dump)
18066c92544dSBjoern A. Zeeb #ifdef CONFIG_MAC80211_DEBUGFS
18076c92544dSBjoern A. Zeeb .sta_add_debugfs = mt7915_sta_add_debugfs,
18086c92544dSBjoern A. Zeeb #endif
18096c92544dSBjoern A. Zeeb .set_radar_background = mt7915_set_radar_background,
18106c92544dSBjoern A. Zeeb #ifdef CONFIG_NET_MEDIATEK_SOC_WED
18116c92544dSBjoern A. Zeeb .net_fill_forward_path = mt7915_net_fill_forward_path,
1812*8ba4d145SBjoern A. Zeeb .net_setup_tc = mt76_wed_net_setup_tc,
18136c92544dSBjoern A. Zeeb #endif
1814*8ba4d145SBjoern A. Zeeb .reconfig_complete = mt7915_reconfig_complete,
18156c92544dSBjoern A. Zeeb };
1816