diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..7c5116bb96 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "submodules/awg-openwrt"] + path = submodules/awg-openwrt + url = https://github.com/Slava-Shchipunov/awg-openwrt.git diff --git a/package/amneziawg-tools b/package/amneziawg-tools new file mode 120000 index 0000000000..4191345adb --- /dev/null +++ b/package/amneziawg-tools @@ -0,0 +1 @@ +../submodules/awg-openwrt/amneziawg-tools \ No newline at end of file diff --git a/package/kernel/lantiq/ltq-adsl-mei/src/drv_mei_cpe.c b/package/kernel/lantiq/ltq-adsl-mei/src/drv_mei_cpe.c index cce0999396..383283a06e 100644 --- a/package/kernel/lantiq/ltq-adsl-mei/src/drv_mei_cpe.c +++ b/package/kernel/lantiq/ltq-adsl-mei/src/drv_mei_cpe.c @@ -1186,7 +1186,7 @@ makeCMV (u8 opcode, u8 group, u16 address, u16 index, int size, u16 * data, u16 CMVMSG[2] = address; CMVMSG[3] = index; if (opcode == H2D_CMV_WRITE) - memcpy (CMVMSG + 4, data, size * 2); + memcpy (CMVMSG + 4, data, min_t(int, size, MSG_LENGTH - 4) * 2); return; } diff --git a/package/kernel/mac80211/patches/subsys/390-mac80211-defer-ap-side-ft-key-upload.patch b/package/kernel/mac80211/patches/subsys/390-mac80211-defer-ap-side-ft-key-upload.patch new file mode 100644 index 0000000000..8d8baa8816 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/390-mac80211-defer-ap-side-ft-key-upload.patch @@ -0,0 +1,192 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: AndreaCovelli +Date: Thu, 30 Apr 2026 03:30:00 +0200 +Subject: [PATCH] mac80211: defer AP-side FT key upload until station association + +AP-side Fast Transition can derive and hand over the pairwise PTK while the +peer already has a station entry but before mac80211 marks it associated. + +Today `ieee80211_add_key()` rejects that with `-ENOENT`, which bubbles up +to hostapd as: + + nl80211: kernel reports: key addition failed + +On OpenWrt APs this is the log line commonly seen during 802.11r roaming. +It is mostly harmless under WPA2 because userspace retries once the STA is +associated, but under WPA3/PMF the timing window is much tighter and the +same rejection can break the roam. + +Accept AP-side pairwise keys as soon as the station entry exists, keep them +in mac80211, skip the initial hardware upload while the station is still +pre-association, upload it to the driver once the station is associated, +and keep the later AUTHORIZED transition as an extra retry point. +This preserves the original intent behind the old ASSOC gate while removing +the FT race that still exists before the AUTH flag is raised on AP-side +roams. + +Signed-off-by: AndreaCovelli +--- + net/mac80211/cfg.c | 24 +++++++++++++-------- + net/mac80211/key.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ + net/mac80211/key.h | 1 + + net/mac80211/sta_info.c | 4 ++++ + 4 files changed, 82 insertions(+), 9 deletions(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -655,18 +655,24 @@ static int ieee80211_add_key(struct wiph + key->conf.flags |= IEEE80211_KEY_FLAG_NO_AUTO_TX; + + if (mac_addr) { ++ bool defer_pairwise_ap; ++ + sta = sta_info_get_bss(sdata, mac_addr); ++ defer_pairwise_ap = ++ pairwise && ++ (sdata->vif.type == NL80211_IFTYPE_AP || ++ sdata->vif.type == NL80211_IFTYPE_AP_VLAN); + /* +- * The ASSOC test makes sure the driver is ready to +- * receive the key. When wpa_supplicant has roamed +- * using FT, it attempts to set the key before +- * association has completed, this rejects that attempt +- * so it will set the key again after association. +- * +- * TODO: accept the key if we have a station entry and +- * add it to the device after the station. ++ * Fast transition on the AP side can derive and hand over a ++ * pairwise PTK before mac80211 marks the station associated. ++ * Accept only AP-side pairwise keys before ASSOC; keep the ++ * original ASSOC gate for everything else. The deferred ++ * upload path will push the key to hardware once the STA ++ * reaches ASSOC. + */ +- if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { ++ if (!sta || ++ (!test_sta_flag(sta, WLAN_STA_ASSOC) && ++ !defer_pairwise_ap)) { + ieee80211_key_free_unused(key); + return -ENOENT; + } +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -122,6 +122,7 @@ static int ieee80211_key_enable_hw_accel + struct ieee80211_sub_if_data *sdata = key->sdata; + struct sta_info *sta; + int ret = -EOPNOTSUPP; ++ bool pairwise_ap; + + might_sleep(); + lockdep_assert_wiphy(key->local->hw.wiphy); +@@ -148,6 +149,9 @@ static int ieee80211_key_enable_hw_accel + goto out_unsupported; + + sta = key->sta; ++ pairwise_ap = sta && (key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE) && ++ (sdata->vif.type == NL80211_IFTYPE_AP || ++ sdata->vif.type == NL80211_IFTYPE_AP_VLAN); + + /* + * If this is a per-STA GTK, check if it +@@ -157,6 +161,16 @@ static int ieee80211_key_enable_hw_accel + !ieee80211_hw_check(&key->local->hw, SUPPORTS_PER_STA_GTK)) + goto out_unsupported; + ++ /* AP-side FT can install a pairwise key before association completes. ++ * Keep it in software until the STA reaches ASSOC so drivers do not ++ * see the same premature key upload that cfg.c used to reject. ++ * Use ret=1 to validate the cipher without failing SW_CRYPTO_CONTROL. ++ */ ++ if (pairwise_ap && !test_sta_flag(sta, WLAN_STA_ASSOC)) { ++ ret = 1; ++ goto out_unsupported; ++ } ++ + if (sta && !sta->uploaded) + goto out_unsupported; + +@@ -994,6 +1008,54 @@ void ieee80211_reenable_keys(struct ieee + } + } + ++static void ieee80211_upload_keys_for_sta(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta) ++{ ++ struct ieee80211_key *key; ++ ++ /* Walk the interface key list rather than sta->ptk[] so we retry ++ * any key objects bound to this STA, not just the pairwise PTK slots. ++ */ ++ list_for_each_entry(key, &sdata->key_list, list) { ++ if (key->sta != sta) ++ continue; ++ if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ++ continue; ++ ieee80211_key_enable_hw_accel(key); ++ } ++} ++ ++void ieee80211_upload_deferred_ap_sta_keys(struct sta_info *sta) ++{ ++ struct ieee80211_sub_if_data *sdata = sta->sdata; ++ struct ieee80211_sub_if_data *master; ++ struct ieee80211_sub_if_data *vlan; ++ ++ lockdep_assert_wiphy(sdata->local->hw.wiphy); ++ ++ if (sdata->vif.type != NL80211_IFTYPE_AP && ++ sdata->vif.type != NL80211_IFTYPE_AP_VLAN) ++ return; ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->bss) ++ return; ++ ++ ieee80211_upload_keys_for_sta(sdata, sta); ++ ++ switch (sdata->vif.type) { ++ case NL80211_IFTYPE_AP: ++ list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) ++ ieee80211_upload_keys_for_sta(vlan, sta); ++ break; ++ case NL80211_IFTYPE_AP_VLAN: ++ master = container_of(sdata->bss, struct ieee80211_sub_if_data, ++ u.ap); ++ ieee80211_upload_keys_for_sta(master, sta); ++ break; ++ default: ++ break; ++ } ++} ++ + static void + ieee80211_key_iter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -164,6 +164,7 @@ void ieee80211_free_keys(struct ieee8021 + bool force_synchronize); + void ieee80211_free_sta_keys(struct ieee80211_local *local, + struct sta_info *sta); ++void ieee80211_upload_deferred_ap_sta_keys(struct sta_info *sta); + void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata); + int ieee80211_key_switch_links(struct ieee80211_sub_if_data *sdata, + unsigned long del_links_mask, +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -1419,6 +1419,8 @@ static int _sta_info_move_state(struct s + if (!sta->sta.support_p2p_ps) + ieee80211_recalc_p2p_go_ps_allowed(sta->sdata); + } ++ /* Primary retry for AP key uploads deferred until ASSOC. */ ++ ieee80211_upload_deferred_ap_sta_keys(sta); + } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { + ieee80211_vif_dec_num_mcast(sta->sdata); + clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); +@@ -1450,6 +1452,8 @@ static int _sta_info_move_state(struct s + set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); + ieee80211_check_fast_xmit(sta); + ieee80211_check_fast_rx(sta); ++ /* Extra retry if the ASSOC-time AP key upload was too early. */ ++ ieee80211_upload_deferred_ap_sta_keys(sta); + } + if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN || + sta->sdata->vif.type == NL80211_IFTYPE_AP) diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index c2e3a199fc..98d3f64cd6 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2026-03-21 -PKG_SOURCE_VERSION:=018f60316d4dd6b4e741874eda40e2dfaa29df3b -PKG_MIRROR_HASH:=54a8125453a6fe04c89cf5335bdf0ea16c409361e1e5a79fb339d67cee26df0e +PKG_SOURCE_DATE:=2026-06-09 +PKG_SOURCE_VERSION:=72d8dc8574430210e782857c3f50ceddf355432c +PKG_MIRROR_HASH:=36d263dc212c45de62d74dd2823834cd0c6734e3d6bb0242ff8e3ca26fa8be39 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 diff --git a/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch b/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch deleted file mode 100644 index 705104cc4b..0000000000 --- a/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch +++ /dev/null @@ -1,33 +0,0 @@ -From a95e567eb0e06d460dee234f9c845fbfb215ab11 Mon Sep 17 00:00:00 2001 -From: Mieczyslaw Nalewaj -Date: Thu, 29 Jan 2026 16:36:25 +0100 -Subject: [PATCH] wifi: mt76: use hrtimer_setup() in mt76x02u beacon init - -Replace the two-step hrtimer initialization pattern with a single -consolidated call to hrtimer_setup(). -The legacy approach of calling hrtimer_init() followed by manual -assignment to timer.function is deprecated. The new hrtimer_setup() -helper atomically initializes the timer and assigns the callback -function in one operation, eliminating the race-prone intermediate -state where the timer is initialized but lacks a handler. - -Signed-off-by: Mieczyslaw Nalewaj ---- - mt76x02_usb_core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/mt76x02_usb_core.c b/mt76x02_usb_core.c -index c94c2f661..3a28a8cc1 100644 ---- a/mt76x02_usb_core.c -+++ b/mt76x02_usb_core.c -@@ -264,8 +264,8 @@ void mt76x02u_init_beacon_config(struct mt76x02_dev *dev) - }; - dev->beacon_ops = &beacon_ops; - -- hrtimer_init(&dev->pre_tbtt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -- dev->pre_tbtt_timer.function = mt76x02u_pre_tbtt_interrupt; -+ hrtimer_setup(&dev->pre_tbtt_timer, mt76x02u_pre_tbtt_interrupt, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); - INIT_WORK(&dev->pre_tbtt_work, mt76x02u_pre_tbtt_work); - - mt76x02_init_beacon_config(dev); diff --git a/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch b/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch deleted file mode 100644 index 243d4efee8..0000000000 --- a/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Mieczyslaw Nalewaj -Date: Thu, 2 Apr 2026 19:01:10 +0200 -Subject: Subject: [PATCH] mt76: pass LED define via ccflags-y - -Replace the deprecated EXTRA_CFLAGS with ccflags-y so that -the -DCONFIG_MT76_LEDS define is applied correctly by the kernel -build system. EXTRA_CFLAGS is no longer honored by recent -kbuilds[1]; ccflags-y is the supported variable and works -on kernels 6.12 and 6.18. - -1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.18.20&id=f77bf01425b11947eeb3b5b54685212c302741b8 - -Signed-off-by: Mieczyslaw Nalewaj ---- - Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/Makefile -+++ b/Makefile -@@ -1,5 +1,5 @@ - # SPDX-License-Identifier: BSD-3-Clause-Clear --EXTRA_CFLAGS += -Werror -DCONFIG_MT76_LEDS -+ccflags-y += -Werror -DCONFIG_MT76_LEDS - obj-m := mt76.o - obj-$(CONFIG_MT76_USB) += mt76-usb.o - obj-$(CONFIG_MT76_SDIO) += mt76-sdio.o diff --git a/package/kernel/mt76/patches/005-fixup-mt76-pass-LED-define-via-ccflags-y.patch b/package/kernel/mt76/patches/005-fixup-mt76-pass-LED-define-via-ccflags-y.patch new file mode 100644 index 0000000000..644b89aae2 --- /dev/null +++ b/package/kernel/mt76/patches/005-fixup-mt76-pass-LED-define-via-ccflags-y.patch @@ -0,0 +1,50 @@ +From 869992ff86570df629e56c611fca048e42ce1eb2 Mon Sep 17 00:00:00 2001 +From: Rany Hany +Date: Wed, 3 Jun 2026 15:51:00 +0000 +Subject: [PATCH] fixup! mt76: pass LED define via ccflags-y + +Signed-off-by: Rany Hany +--- + mt7603/Makefile | 2 +- + mt7615/Makefile | 2 +- + mt7915/Makefile | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/mt7603/Makefile b/mt7603/Makefile +index 57d28591..5e7ab30f 100644 +--- a/mt7603/Makefile ++++ b/mt7603/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: BSD-3-Clause-Clear +-EXTRA_CFLAGS += -Werror -DCONFIG_MT76_LEDS ++ccflags-y += -Werror -DCONFIG_MT76_LEDS + obj-m += mt7603e.o + + mt7603e-y := \ +diff --git a/mt7615/Makefile b/mt7615/Makefile +index 9274c006..8b8eff3f 100644 +--- a/mt7615/Makefile ++++ b/mt7615/Makefile +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: BSD-3-Clause-Clear + +-EXTRA_CFLAGS += -DCONFIG_MT76_LEDS ++ccflags-y += -DCONFIG_MT76_LEDS + obj-$(CONFIG_MT7615_COMMON) += mt7615-common.o + obj-$(CONFIG_MT7615E) += mt7615e.o + obj-$(CONFIG_MT7663_USB_SDIO_COMMON) += mt7663-usb-sdio-common.o +diff --git a/mt7915/Makefile b/mt7915/Makefile +index 6b0058ca..7ea5b05c 100644 +--- a/mt7915/Makefile ++++ b/mt7915/Makefile +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: BSD-3-Clause-Clear + +-EXTRA_CFLAGS += -DCONFIG_MT76_LEDS ++ccflags-y += -DCONFIG_MT76_LEDS + obj-$(CONFIG_MT7915E) += mt7915e.o + + mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ +-- +2.52.0 + diff --git a/package/kernel/mt76/patches/010-mt7915-detect-and-purge-stuck-PLE-queues.patch b/package/kernel/mt76/patches/010-mt7915-detect-and-purge-stuck-PLE-queues.patch new file mode 100644 index 0000000000..5656adbfeb --- /dev/null +++ b/package/kernel/mt76/patches/010-mt7915-detect-and-purge-stuck-PLE-queues.patch @@ -0,0 +1,299 @@ +From e3706f4706c7388c96011883062bf1d362f6b208 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sat, 15 Nov 2025 14:36:38 +0100 +Subject: [PATCH] mt7915: detect and purge stuck PLE queues + +When stations leave the area of service while there are transmissions +pending inside the hardware, these queues can become stuck. + +This results in missing TXRX free / TXS events to the host. Also the +throughput of other connected stations substantially decreases and +latency massively increases. + +Periodically poll the queue state of connected station from hardware and +purge queues detected as stuck. + +Signed-off-by: David Bauer +--- + mt7915/debugfs.c | 2 + + mt7915/init.c | 1 + + mt7915/mac.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/mmio.c | 4 ++ + mt7915/mt7915.h | 15 ++++++ + mt7915/regs.h | 22 +++++++++ + 6 files changed, 162 insertions(+) + +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -860,9 +860,11 @@ mt7915_sta_hw_queue_read(void *data, str + if (val & BIT(offs)) + continue; + ++ mutex_lock(&dev->qctrl_mutex); + mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta->wcid.idx); + qlen = mt76_get_field(dev, MT_FL_Q3_CTRL, + GENMASK(11, 0)); ++ mutex_unlock(&dev->qctrl_mutex); + seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n", + sta->addr, msta->wcid.idx, + msta->vif->mt76.wmm_idx, ac, qlen); +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -1237,6 +1237,7 @@ int mt7915_register_device(struct mt7915 + INIT_WORK(&dev->reset_work, mt7915_mac_reset_work); + INIT_WORK(&dev->dump_work, mt7915_mac_dump_work); + mutex_init(&dev->dump_mutex); ++ mutex_init(&dev->qctrl_mutex); + + dev->dbdc_support = mt7915_band_config(dev); + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1983,10 +1983,116 @@ void mt7915_mac_sta_rc_work(struct work_ + spin_unlock_bh(&dev->mt76.sta_poll_lock); + } + ++static void ++mt7915_sta_read_hw_queue(struct ieee80211_sta *sta, ++ u8 ac, u16 *head, u16 *tail, u16 *qlen) ++{ ++ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; ++ struct mt7915_dev *dev = msta->vif->phy->dev; ++ u32 q0_ctrl, q2_ctrl, q3_ctrl; ++ ++ q0_ctrl = MT_FL_Q0_CTRL_EXECUTE | BIT(11) | FIELD_PREP(MT_FL_Q0_CTRL_SRC_QID, ac); ++ ++ mutex_lock(&dev->qctrl_mutex); ++ mt76_wr(dev, MT_FL_Q0_CTRL, q0_ctrl | msta->wcid.idx); ++ q2_ctrl = mt76_rr(dev, MT_FL_Q2_CTRL); ++ q3_ctrl = mt76_rr(dev, MT_FL_Q3_CTRL); ++ mutex_unlock(&dev->qctrl_mutex); ++ ++ *head = FIELD_GET(MT_FL_Q2_CTRL_HFID, q2_ctrl); ++ *tail = FIELD_GET(MT_FL_Q2_CTRL_TFID, q2_ctrl); ++ *qlen = FIELD_GET(MT_FL_Q3_CTRL_PKT_NUM, q3_ctrl); ++} ++ ++static void mt7915_purge_ac(struct ieee80211_sta *sta, int ac, int fid_start, int fid_end) ++{ ++ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; ++ struct mt7915_dev *dev = msta->vif->phy->dev; ++ u32 deq_ctrl[3]; ++ ++ deq_ctrl[0] = MT_PLE_DEQ_0_EXECUTE | BIT(11); ++ deq_ctrl[0] |= FIELD_PREP(MT_PLE_DEQ_0_DEQ_SRC_WCID, msta->wcid.idx); ++ deq_ctrl[0] |= FIELD_PREP(MT_PLE_DEQ_0_SRC_QID, ac); ++ deq_ctrl[0] |= FIELD_PREP(MT_PLE_DEQ_0_DEQ_SUB_TYPE, 0x2); ++ deq_ctrl[0] |= FIELD_PREP(MT_PLE_DEQ_0_ENQ_SUB_TYPE, 0x1); ++ deq_ctrl[0] |= MT_PLE_DEQ_0_ENQ_VALID; ++ ++ deq_ctrl[1] = FIELD_PREP(MT_PLE_DEQ_1_FID_START, fid_start); ++ deq_ctrl[1] |= FIELD_PREP(MT_PLE_DEQ_1_FID_END, fid_end); ++ ++ deq_ctrl[2] = FIELD_PREP(MT_PLE_DEQ_2_DST_QID, 0x1f); ++ ++ mt76_wr(dev, MT_PLE_DEQ(1), deq_ctrl[1]); ++ mt76_wr(dev, MT_PLE_DEQ(2), deq_ctrl[2]); ++ mt76_wr(dev, MT_PLE_DEQ(0), deq_ctrl[0]); ++} ++ ++static int ++mt7915_sta_purge_hw_queue(struct ieee80211_sta *sta, u8 ac) ++{ ++ u16 head_frame_id, tail_frame_id, q_len; ++ int i = MT7915_PLE_PURGE_MAX_ITER; ++ ++ do { ++ mt7915_sta_read_hw_queue(sta, ac, &head_frame_id, ++ &tail_frame_id, &q_len); ++ ++ if (q_len == 0) ++ break; ++ ++ mt7915_purge_ac(sta, ac, head_frame_id, head_frame_id); ++ } while (--i > 0); ++ ++ return MT7915_PLE_PURGE_MAX_ITER - i; ++} ++ ++static void ++mt7915_sta_check_hw_queues(void *data, struct ieee80211_sta *sta) ++{ ++ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; ++ struct mt7915_dev *dev = msta->vif->phy->dev; ++ struct mt7915_hw_queue_state *hwq; ++ bool *purged = data; ++ ++ u16 head_frame_id, tail_frame_id, q_len; ++ u32 q_empty; ++ u8 ac; ++ ++ for (ac = 0; ac < 4; ac++) { ++ hwq = &msta->hwq_state[ac]; ++ ++ /* Check if STA has frames pending. */ ++ q_empty = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, msta->wcid.idx >> 5)); ++ if (q_empty & BIT(msta->wcid.idx & GENMASK(4, 0))) { ++ /* Queue empty */ ++ hwq->head = 0xFFF; ++ hwq->last_update = jiffies; ++ continue; ++ } ++ ++ /* Check hardware queue state */ ++ mt7915_sta_read_hw_queue(sta, ac, &head_frame_id, &tail_frame_id, &q_len); ++ if (hwq->head != head_frame_id) { ++ /* Queue moved, update */ ++ hwq->last_update = jiffies; ++ hwq->head = head_frame_id; ++ continue; ++ } ++ ++ /* Begin purge after queue detected stuck for QUEUE_TIMEOUT */ ++ if (time_is_after_jiffies(hwq->last_update + MT7915_PLE_QUEUE_TIMEOUT)) ++ continue; ++ ++ mt7915_sta_purge_hw_queue(sta, ac); ++ *purged = true; ++ } ++} ++ + void mt7915_mac_work(struct work_struct *work) + { + struct mt7915_phy *phy; + struct mt76_phy *mphy; ++ bool purged = false; + + mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, + mac_work.work); +@@ -2009,6 +2115,18 @@ void mt7915_mac_work(struct work_struct + + mt76_tx_status_check(mphy->dev, false); + ++ if (++phy->stuck_queue_check >= 5) { ++ /* Lock MCU Lock to avoid command timeouts */ ++ mutex_lock(&mphy->dev->mcu.mutex); ++ ieee80211_iterate_stations_atomic(mphy->hw, ++ mt7915_sta_check_hw_queues, ++ &purged); ++ if (purged) ++ usleep_range(10000, 15000); ++ mutex_unlock(&mphy->dev->mcu.mutex); ++ phy->stuck_queue_check = 0; ++ } ++ + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, + MT7915_WATCHDOG_TIME); + } +--- a/mt7915/mmio.c ++++ b/mt7915/mmio.c +@@ -183,6 +183,8 @@ static const u32 mt7915_offs[] = { + [MIB_ARNG] = 0x4b8, + [WTBLON_TOP_WDUCR] = 0x0, + [WTBL_UPDATE] = 0x030, ++ [PLE_ENQ] = 0x060, ++ [PLE_DEQ] = 0x080, + [PLE_FL_Q_EMPTY] = 0x0b0, + [PLE_FL_Q_CTRL] = 0x1b0, + [PLE_AC_QEMPTY] = 0x500, +@@ -258,6 +260,8 @@ static const u32 mt7916_offs[] = { + [MIB_ARNG] = 0x0b0, + [WTBLON_TOP_WDUCR] = 0x200, + [WTBL_UPDATE] = 0x230, ++ [PLE_ENQ] = 0x320, ++ [PLE_DEQ] = 0x330, + [PLE_FL_Q_EMPTY] = 0x360, + [PLE_FL_Q_CTRL] = 0x3e0, + [PLE_AC_QEMPTY] = 0x600, +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -86,6 +86,9 @@ + + #define MT7915_RTS_LEN_THRES 0x92b + ++#define MT7915_PLE_PURGE_MAX_ITER 64 ++#define MT7915_PLE_QUEUE_TIMEOUT (HZ * 5) ++ + struct mt7915_vif; + struct mt7915_sta; + struct mt7915_dfs_pulse; +@@ -134,6 +137,12 @@ struct mt7915_twt_flow { + + DECLARE_EWMA(avg_signal, 10, 8) + ++struct mt7915_hw_queue_state { ++ u32 head; ++ u32 tail; ++ unsigned long last_update; ++}; ++ + struct mt7915_sta { + struct mt76_wcid wcid; /* must be first */ + +@@ -149,6 +158,8 @@ struct mt7915_sta { + unsigned long jiffies; + struct mt76_connac_sta_key_conf bip; + ++ struct mt7915_hw_queue_state hwq_state[4]; ++ + struct { + u8 flowid_mask; + struct mt7915_twt_flow flow[MT7915_MAX_STA_TWT_AGRT]; +@@ -223,6 +234,8 @@ struct mt7915_phy { + u32 rx_ampdu_ts; + u32 ampdu_ref; + ++ u8 stuck_queue_check; ++ + struct mt76_mib_stats mib; + struct mt76_channel_state state_ts; + +@@ -290,6 +303,8 @@ struct mt7915_dev { + } coredump; + #endif + ++ struct mutex qctrl_mutex; ++ + struct list_head sta_rc_list; + struct list_head twt_list; + spinlock_t reg_lock; +--- a/mt7915/regs.h ++++ b/mt7915/regs.h +@@ -111,6 +111,8 @@ enum offs_rev { + MIB_ARNG, + WTBLON_TOP_WDUCR, + WTBL_UPDATE, ++ PLE_ENQ, ++ PLE_DEQ, + PLE_FL_Q_EMPTY, + PLE_FL_Q_CTRL, + PLE_AC_QEMPTY, +@@ -151,8 +153,28 @@ enum offs_rev { + + #define MT_FL_Q_EMPTY MT_PLE(__OFFS(PLE_FL_Q_EMPTY)) + #define MT_FL_Q0_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL)) ++#define MT_FL_Q0_CTRL_EXECUTE BIT(31) ++#define MT_FL_Q0_CTRL_SRC_QID GENMASK(30, 24) + #define MT_FL_Q2_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL) + 0x8) ++#define MT_FL_Q2_CTRL_HFID GENMASK(11, 0) ++#define MT_FL_Q2_CTRL_TFID GENMASK(27, 16) + #define MT_FL_Q3_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL) + 0xc) ++#define MT_FL_Q3_CTRL_PKT_NUM GENMASK(11, 0) ++ ++#define MT_PLE_ENQ(idx) MT_PLE(__OFFS(PLE_ENQ) + (idx * 4)) ++#define MT_PLE_DEQ(idx) MT_PLE(__OFFS(PLE_DEQ) + (idx * 4)) ++#define MT_PLE_DEQ_0_EXECUTE BIT(31) ++#define MT_PLE_DEQ_0_SRC_QID GENMASK(30, 24) ++#define MT_PLE_DEQ_0_ENQ_VALID BIT(23) ++#define MT_PLE_DEQ_0_ENQ_SUB_TYPE GENMASK(22, 20) ++#define MT_PLE_DEQ_0_DEQ_SUB_TYPE GENMASK(19, 16) ++#define MT_PLE_DEQ_0_DEQ_SRC_WCID GENMASK(9, 0) ++#define MT_PLE_DEQ_1_FID_END GENMASK(27, 16) ++#define MT_PLE_DEQ_1_FID_START GENMASK(11, 0) ++#define MT_PLE_DEQ_2_DST_QID GENMASK(30, 24) ++#define MT_PLE_DEQ_3_TAIL_FID GENMASK(27, 16) ++#define MT_PLE_DEQ_3_EMPTY BIT(15) ++#define MT_PLE_DEQ_3_HEAD_FID GENMASK(11, 0) + + #define MT_PLE_FREEPG_CNT MT_PLE(__OFFS(PLE_FREEPG_CNT)) + #define MT_PLE_FREEPG_HEAD_TAIL MT_PLE(__OFFS(PLE_FREEPG_HEAD_TAIL)) diff --git a/package/kernel/mt76/patches/smartrg-0001-mt76-add-dfs-debugs.patch b/package/kernel/mt76/patches/smartrg-0001-mt76-add-dfs-debugs.patch new file mode 100644 index 0000000000..16c2e5fb86 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0001-mt76-add-dfs-debugs.patch @@ -0,0 +1,56 @@ +--- a/mt7615/mcu.c ++++ b/mt7615/mcu.c +@@ -386,7 +386,10 @@ mt7615_mcu_rx_radar_detected(struct mt76 + + if (!dev->radar_pattern.n_pulses && !r->long_detected && + !r->constant_prf_detected && !r->staggered_prf_detected) ++ { ++ dev_info(dev->mt76.dev, "%s: called but no radar detected\n", __func__); + return; ++ } + + if (r->band_idx && dev->mt76.phys[MT_BAND1]) + mphy = dev->mt76.phys[MT_BAND1]; +@@ -394,6 +397,12 @@ mt7615_mcu_rx_radar_detected(struct mt76 + if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC) + return; + ++ dev_info(dev->mt76.dev, "%s: RADAR DETECTED r->band_idx=%d\n", __func__, r->band_idx); ++ dev_dbg(dev->mt76.dev, "%s: n_pulses=%u long_detected=%u constant_prf_detected=%u staggered_prf_detected=%u\n", ++ __func__, dev->radar_pattern.n_pulses, r->long_detected, r->constant_prf_detected, r->staggered_prf_detected); ++ dev_dbg(dev->mt76.dev, "%s: radar_type_idx=%u periodic_pulse_num=%u long_pulse_num=%u hw_pulse_num=%u\n", ++ __func__, r->radar_type_idx, r->periodic_pulse_num, r->long_pulse_num, r->hw_pulse_num); ++ + ieee80211_radar_detected(mphy->hw, NULL); + dev->hw_pattern++; + } +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -336,6 +336,12 @@ mt7915_mcu_rx_radar_detected(struct mt79 + if (!mphy) + return; + ++ dev_info(dev->mt76.dev, "%s: RADAR DETECTED r->rdd_idx=%d\n", __func__, r->rdd_idx); ++ dev_dbg(dev->mt76.dev, "%s: long_detected=%u constant_prf_detected=%u staggered_prf_detected=%u\n", ++ __func__, r->long_detected, r->constant_prf_detected, r->staggered_prf_detected); ++ dev_dbg(dev->mt76.dev, "%s: radar_type_idx=%u periodic_pulse_num=%u long_pulse_num=%u hw_pulse_num=%u\n", ++ __func__, r->radar_type_idx, r->periodic_pulse_num, r->long_pulse_num, r->hw_pulse_num); ++ + if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) + cfg80211_background_radar_event(mphy->hw->wiphy, + &dev->rdd2_chandef, +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -549,6 +549,12 @@ mt7996_mcu_rx_radar_detected(struct mt79 + if (!mphy) + goto err; + ++ dev_info(dev->mt76.dev, "%s: RADAR DETECTED r->rdd_idx=%d\n", __func__, r->rdd_idx); ++ dev_dbg(dev->mt76.dev, "%s: long_detected=%u constant_prf_detected=%u staggered_prf_detected=%u\n", ++ __func__, r->long_detected, r->constant_prf_detected, r->staggered_prf_detected); ++ dev_dbg(dev->mt76.dev, "%s: radar_type_idx=%u periodic_pulse_num=%u long_pulse_num=%u hw_pulse_num=%u\n", ++ __func__, r->radar_type_idx, r->periodic_pulse_num, r->long_pulse_num, r->hw_pulse_num); ++ + if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) { + cfg80211_background_radar_event(mphy->hw->wiphy, + &dev->rdd2_chandef, diff --git a/package/kernel/mt76/patches/smartrg-0002-mt76-set-sane-default-rate-if-rate-info-is-missing.patch b/package/kernel/mt76/patches/smartrg-0002-mt76-set-sane-default-rate-if-rate-info-is-missing.patch new file mode 100644 index 0000000000..d90adfa02f --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0002-mt76-set-sane-default-rate-if-rate-info-is-missing.patch @@ -0,0 +1,36 @@ +From f8e1383faa5c7942263a0c5c98028bf8653440f4 Mon Sep 17 00:00:00 2001 +From: Chad Monroe +Date: Fri, 20 Aug 2021 08:33:11 -0700 +Subject: [PATCH] mt76: set sane default rate if rate info is missing + +If no rate can be found via beacon (e.g. hidden network) then +set a sane default of either 11Mbps (2G) or 24Mbps (5G). Using these +higher rates ensures we can still connect to APs which have some of +the lower basic rates disabled. + +Signed-off-by: Chad Monroe +--- + mac80211.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/mt76_connac_mac.c ++++ b/mt76_connac_mac.c +@@ -348,6 +348,18 @@ legacy: + if (band != NL80211_BAND_2GHZ) + offset = 4; + ++ if (band == NL80211_BAND_2GHZ) { ++ if (rateidx < 0) ++ rateidx = 3; /* 11Mbps */ ++ } else { ++ offset = 4; ++ ++ if (band == NL80211_BAND_5GHZ) { ++ if (rateidx < 0) ++ rateidx = 4; /* 24Mbps */ ++ } ++ } ++ + /* pick the lowest rate for hidden nodes */ + if (rateidx < 0) + rateidx = 0; diff --git a/package/kernel/mt76/patches/smartrg-0003-mt76-eeprom-add-nvmem-debugs.patch b/package/kernel/mt76/patches/smartrg-0003-mt76-eeprom-add-nvmem-debugs.patch new file mode 100644 index 0000000000..cc52b11d15 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0003-mt76-eeprom-add-nvmem-debugs.patch @@ -0,0 +1,11 @@ +--- a/eeprom.c ++++ b/eeprom.c +@@ -144,6 +144,8 @@ int mt76_get_of_data_from_nvmem(struct m + + memcpy(eep, data, len); + ++ dev_info(dev->dev, "nvmem cell: %s loaded %d bytes", cell_name, len); ++ + exit: + kfree(data); + diff --git a/package/kernel/mt76/patches/smartrg-0004-mt76-reset-channel-state-during-scanning.patch b/package/kernel/mt76/patches/smartrg-0004-mt76-reset-channel-state-during-scanning.patch new file mode 100644 index 0000000000..04eb78a7af --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0004-mt76-reset-channel-state-during-scanning.patch @@ -0,0 +1,37 @@ +From 54b61cebb3e5d27aba7b293fe9d11d45df1acbd4 Mon Sep 17 00:00:00 2001 +From: Michael-CY Lee +Date: Thu, 16 Oct 2025 11:02:00 +0800 +Subject: [PATCH 13/89] wifi: mt76: reset channel state during scanning + +Reset the channel state of all channels during scanning to prevent the +ACS algorithm from selecting unexpected channel. + +Signed-off-by: Michael-CY Lee +Signed-off-by: Shayne Chen +--- + mac80211.c | 3 ++- + scan.c | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/mac80211.c ++++ b/mac80211.c +@@ -1054,7 +1054,8 @@ int __mt76_set_channel(struct mt76_phy * + if (!offchannel) + phy->main_chandef = *chandef; + +- if (chandef->chan != phy->main_chandef.chan) ++ if (chandef->chan != phy->main_chandef.chan || ++ test_bit(MT76_SCANNING, &phy->state)) + memset(phy->chan_state, 0, sizeof(*phy->chan_state)); + + ret = dev->drv->set_channel(phy); +--- a/scan.c ++++ b/scan.c +@@ -206,6 +206,7 @@ int mt76_hw_scan(struct ieee80211_hw *hw + dev->scan.vif = vif; + dev->scan.phy = phy; + dev->scan.mlink = mlink; ++ set_bit(MT76_SCANNING, &phy->state); + ieee80211_queue_delayed_work(dev->phy.hw, &dev->scan_work, 0); + + out: diff --git a/package/kernel/mt76/patches/smartrg-0005-mt76-remove-redundant-survey-update-in-mt76_get_survey.patch b/package/kernel/mt76/patches/smartrg-0005-mt76-remove-redundant-survey-update-in-mt76_get_survey.patch new file mode 100644 index 0000000000..28dce638e6 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0005-mt76-remove-redundant-survey-update-in-mt76_get_survey.patch @@ -0,0 +1,23 @@ +From: Chad Monroe +Date: Wed, 25 Mar 2026 18:50:40 -0700 +Subject: [PATCH] mt76: don't force survey update in mt76_get_survey() + +All drivers already refresh survey data every 100-250ms via mac_work. + +Signed-off-by: Chad Monroe +--- + mac80211.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/mac80211.c ++++ b/mac80211.c +@@ -1133,9 +1133,6 @@ int mt76_get_survey(struct ieee80211_hw + + sband = mt76_get_survey_sband(phy, &idx); + +- if (idx == 0 && phy->dev->drv->update_survey) +- mt76_update_survey(phy); +- + if (sband || !hw->wiphy->n_radio) + break; + } diff --git a/package/kernel/mt76/patches/smartrg-0010-mt76-mt7915-read-efuse-data-and-cache-to-otp-for-sys.patch b/package/kernel/mt76/patches/smartrg-0010-mt76-mt7915-read-efuse-data-and-cache-to-otp-for-sys.patch new file mode 100644 index 0000000000..e0def29773 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0010-mt76-mt7915-read-efuse-data-and-cache-to-otp-for-sys.patch @@ -0,0 +1,67 @@ +From 39e98638b5af402dd2119cf206914a7f5a6fe22d Mon Sep 17 00:00:00 2001 +From: Chad Monroe +Date: Thu, 17 Mar 2022 12:50:10 -0700 +Subject: [PATCH] mt76: mt7915: read efuse data and cache to otp for sysfs + access + +Signed-off-by: Chad Monroe +--- + mt7915/eeprom.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +--- a/mt7915/eeprom.c ++++ b/mt7915/eeprom.c +@@ -120,11 +120,53 @@ out: + return ret; + } + ++static int mt7915_efuse_load(struct mt7915_dev *dev, u16 eeprom_size) ++{ ++ u8 free_block_num; ++ u32 block_num, i; ++ ++ mt7915_mcu_get_eeprom_free_block(dev, &free_block_num); ++ /* efuse info not enough */ ++ if (free_block_num >= 29) ++ return -EINVAL; ++ ++ /* read eeprom data from efuse */ ++ block_num = DIV_ROUND_UP(eeprom_size, MT7915_EEPROM_BLOCK_SIZE); ++ ++ for (i = 0; i < block_num; i++) ++ mt7915_mcu_get_eeprom(dev, i * MT7915_EEPROM_BLOCK_SIZE, NULL); ++ ++ dev_info(dev->mt76.dev, "read efuse data size=%lu, caching to OTP\n", ++ dev->mt76.eeprom.size); ++ ++ /* cache to otp.. mt76_eeprom_init() will allocate new eeprom data */ ++ dev->mt76.otp.data = dev->mt76.eeprom.data; ++ dev->mt76.otp.size = dev->mt76.eeprom.size; ++ ++ dev->mt76.eeprom.data = NULL; ++ dev->mt76.eeprom.size = 0; ++ ++ return 0; ++} ++ + static int mt7915_eeprom_load(struct mt7915_dev *dev) + { + int ret; + u16 eeprom_size = mt7915_eeprom_size(dev); + ++ /* allocate eeprom storage.. used to read efuse */ ++ dev->mt76.eeprom.data = devm_kzalloc(dev->mt76.dev, eeprom_size, GFP_KERNEL); ++ dev->mt76.eeprom.size = eeprom_size; ++ ++ if (!dev->mt76.eeprom.data) ++ return -ENOMEM; ++ ++ if (mt7915_efuse_load(dev, eeprom_size) != 0) { ++ /* eeprom data pointer not saved to otp, free it */ ++ devm_kfree(dev->mt76.dev, dev->mt76.eeprom.data); ++ dev->mt76.eeprom.size = 0; ++ } ++ + ret = mt76_eeprom_init(&dev->mt76, eeprom_size); + if (ret < 0) + return ret; diff --git a/package/kernel/mt76/patches/smartrg-0011-mt76-mt7915-make-pre-cal-mcu-command-synchronous.patch b/package/kernel/mt76/patches/smartrg-0011-mt76-mt7915-make-pre-cal-mcu-command-synchronous.patch new file mode 100644 index 0000000000..acf25e35e9 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0011-mt76-mt7915-make-pre-cal-mcu-command-synchronous.patch @@ -0,0 +1,21 @@ +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -3007,7 +3007,7 @@ static int mt7915_mcu_set_pre_cal(struct + skb_put_data(skb, &req, sizeof(req)); + skb_put_data(skb, data, len); + +- return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, false); ++ return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); + } + + int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev) +@@ -3028,6 +3028,9 @@ int mt7915_mcu_apply_group_cal(struct mt + + len = min_t(u32, total, MT_EE_CAL_UNIT); + ++ dev_dbg(dev->mt76.dev, "apply pre-cal idx=%u cal[0]=0x%02x len=%d total=%d\n", ++ idx, ((unsigned char *)cal)[0], len, total); ++ + ret = mt7915_mcu_set_pre_cal(dev, idx, cal, len, + MCU_EXT_CMD(GROUP_PRE_CAL_INFO)); + if (ret) diff --git a/package/kernel/mt76/patches/smartrg-0013-mt76-mt7915-fix-use-after-free-in-sta-poll.patch b/package/kernel/mt76/patches/smartrg-0013-mt76-mt7915-fix-use-after-free-in-sta-poll.patch new file mode 100644 index 0000000000..48509e144a --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0013-mt76-mt7915-fix-use-after-free-in-sta-poll.patch @@ -0,0 +1,34 @@ +From: Chad Monroe +Date: Thu, 12 Feb 2026 20:09:43 -0800 +Subject: [PATCH] mt76: mt7915: fix use-after-free in sta poll + +Move rcu_read_lock() before list_splice_init() so the entire poll list +processing is RCU-protected. Without this, a gap exists between +grabbing poll list entries and entering the RCU read-side section +allowing synchronize_net() to complete on another CPU and sta_info to +be freed (via kfree, not kfree_rcu) while entries are still queued +for processing. This results in a NULL dereference when accessing +sta->sdata in ieee80211_sta_register_airtime(). + +Signed-off-by: Chad Monroe +--- + mt7915/mac.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -102,12 +102,12 @@ static void mt7915_mac_sta_poll(struct m + LIST_HEAD(sta_poll_list); + int i; + ++ rcu_read_lock(); ++ + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + +- rcu_read_lock(); +- + while (true) { + bool clear = false; + u32 addr, val; diff --git a/package/kernel/mt76/patches/smartrg-0014-mt76-mt7915-print-hwrev-at-boot.patch b/package/kernel/mt76/patches/smartrg-0014-mt76-mt7915-print-hwrev-at-boot.patch new file mode 100644 index 0000000000..1d7e8c4c08 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0014-mt76-mt7915-print-hwrev-at-boot.patch @@ -0,0 +1,11 @@ +--- a/mt7915/mmio.c ++++ b/mt7915/mmio.c +@@ -789,7 +789,7 @@ static int mt7915_mmio_init(struct mt76_ + + mdev->rev = (device_id << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); +- dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); ++ dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + return 0; + } diff --git a/package/kernel/mt76/patches/smartrg-0015-mt76-mt7915-rdd-antenna-support.patch b/package/kernel/mt76/patches/smartrg-0015-mt76-mt7915-rdd-antenna-support.patch new file mode 100644 index 0000000000..d59496a345 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0015-mt76-mt7915-rdd-antenna-support.patch @@ -0,0 +1,98 @@ +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include "mt7915.h" + #include "mac.h" + #include "mcu.h" +@@ -837,6 +838,11 @@ mt7915_init_hardware(struct mt7915_dev * + + INIT_WORK(&dev->init_work, mt7915_init_work); + ++ if (dev->mt76.dev->of_node) { ++ of_property_read_u32(dev->mt76.dev->of_node, "rdd_antenna", ++ &dev->phy.rdd_antenna); ++ } ++ + ret = mt7915_dma_init(dev, phy2); + if (ret) + return ret; +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -2142,6 +2142,27 @@ static void mt7915_dfs_stop_radar_detect + mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, rdd_idx, 0, 0); + } + ++static int mt7915_dfs_set_wf_ant(struct mt7915_dev *dev, int rdd_idx, int start) ++{ ++ int err = 0; ++ ++ if (is_mt7915(&dev->mt76)) { ++ u32 rdd_antenna = dev->dbdc_support ? 2 : 0; ++ ++ if (dev->phy.rdd_antenna) ++ rdd_antenna = dev->phy.rdd_antenna; ++ ++ if (start) ++ dev_info(dev->mt76.dev, "%s: dts rdd_antenna=%u rdd_antenna=%u rdd_idx=%d\n", ++ __func__, dev->phy.rdd_antenna, rdd_antenna, rdd_idx); ++ ++ err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, rdd_idx, ++ 0, rdd_antenna); ++ } ++ ++ return err; ++} ++ + static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int rdd_idx) + { + int err, region; +@@ -2163,12 +2184,18 @@ static int mt7915_dfs_start_rdd(struct m + if (err < 0) + return err; + ++#if 0 + if (is_mt7915(&dev->mt76)) { + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, rdd_idx, + 0, dev->dbdc_support ? 2 : 0); + if (err < 0) + return err; + } ++#endif ++ ++ err = mt7915_dfs_set_wf_ant(dev, rdd_idx, 1); ++ if (err < 0) ++ return err; + + return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, rdd_idx, 0, 1); + } +@@ -2275,13 +2302,16 @@ stop: + if (err < 0) + return err; + ++#if 0 + if (is_mt7915(&dev->mt76)) { + err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, + rdd_idx, 0, dev->dbdc_support ? 2 : 0); + if (err < 0) + return err; + } ++#endif + ++ mt7915_dfs_set_wf_ant(dev, phy->mt76->band_idx, 0); + mt7915_dfs_stop_radar_detector(phy); + phy->mt76->dfs_state = MT_DFS_STATE_DISABLED; + +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -222,6 +222,7 @@ struct mt7915_phy { + u32 throttle_temp[2]; /* 0: critical high, 1: maximum */ + + u32 rxfilter; ++ u32 rdd_antenna; + u64 omac_mask; + + u16 noise; diff --git a/package/kernel/mt76/patches/smartrg-0016-mt76-mt7915-add-debugging-for-MCU-command-timeouts.patch b/package/kernel/mt76/patches/smartrg-0016-mt76-mt7915-add-debugging-for-MCU-command-timeouts.patch new file mode 100644 index 0000000000..a8c4dc8a37 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0016-mt76-mt7915-add-debugging-for-MCU-command-timeouts.patch @@ -0,0 +1,62 @@ +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -162,8 +162,19 @@ mt7915_mcu_parse_response(struct mt76_de + int ret = 0; + + if (!skb) { +- dev_err(mdev->dev, "Message %08x (seq %d) timeout\n", +- cmd, seq); ++ const char* first = "Secondary"; ++ ++ if (!mdev->first_failed_mcu_cmd) ++ first = "Initial"; ++ ++ dev_err(mdev->dev, "MCU: %s Failure: Message %08x (cid %lx ext_cid: %lx seq %d) timeout. Last successful cmd: 0x%x\n", ++ first, ++ cmd, FIELD_GET(__MCU_CMD_FIELD_ID, cmd), ++ FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd), seq, ++ mdev->last_successful_mcu_cmd); ++ ++ if (!mdev->first_failed_mcu_cmd) ++ mdev->first_failed_mcu_cmd = cmd; + + if (!test_and_set_bit(MT76_MCU_RESET, &dev->mphy.state)) { + dev->recovery.restart = true; +@@ -175,11 +186,25 @@ mt7915_mcu_parse_response(struct mt76_de + return -ETIMEDOUT; + } + ++ mdev->last_successful_mcu_cmd = cmd; ++ ++ if (mdev->first_failed_mcu_cmd) { ++ dev_err(mdev->dev, "MCU: First success after failure: Message %08x (cid %lx ext_cid: %lx seq %d)\n", ++ cmd, FIELD_GET(__MCU_CMD_FIELD_ID, cmd), ++ FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd), seq); ++ mdev->first_failed_mcu_cmd = 0; ++ } ++ + rxd = (struct mt76_connac2_mcu_rxd *)skb->data; + if (seq != rxd->seq && + !(rxd->eid == MCU_CMD_EXT_CID && + rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT)) ++ { ++ dev_dbg(mdev->dev, "ERROR: MCU: Sequence mismatch in response, seq: %d rxd->seq: %d cmd: %0x\n", ++ seq, rxd->seq, cmd); ++ + return -EAGAIN; ++ } + + if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) { + skb_pull(skb, sizeof(*rxd) - 4); +--- a/mt76.h ++++ b/mt76.h +@@ -1051,6 +1051,9 @@ struct mt76_dev { + }; + + atomic_t bus_hung; ++ ++ int first_failed_mcu_cmd; ++ int last_successful_mcu_cmd; + }; + + /* per-phy stats. */ diff --git a/package/kernel/mt76/patches/smartrg-0017-wifi-mt76-mt7915-enable-PPDU-TXS-for-tx-statistics.patch b/package/kernel/mt76/patches/smartrg-0017-wifi-mt76-mt7915-enable-PPDU-TXS-for-tx-statistics.patch new file mode 100644 index 0000000000..4b4af30a01 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0017-wifi-mt76-mt7915-enable-PPDU-TXS-for-tx-statistics.patch @@ -0,0 +1,197 @@ +From: Chad Monroe +Date: Tue, 10 Mar 2026 19:49:43 -0700 +Subject: [PATCH] wifi: mt76: mt7915: enable PPDU TXS for tx statistics + +PPDU TXS hardware enables and software routing were gated on WED, +leaving tx rate and byte counters dark in non-WED configurations. + +Enable PPDU TXS unconditionally, route TXS by format rather than PID, +and assign MT_PACKET_ID_WED for all data frames so fill_txs() can +gate rate updates to data-path TXS only. + +Move retry/failure accumulation out of shared fill_txs() into +mt7915_mac_add_txs() with is_mt7915() guard -- MT7916/MT7981/MT7986 +obtain these from TX_FREE v3 instead. + +Remove the jiffies-based TX status request throttling that was a +workaround for the missing PPDU path. + +Based-on-work-by: Peter Chiu +Based-on-work-by: Benjamin Lin +Signed-off-by: Chad Monroe +--- + mt76_connac.h | 2 +- + mt76_connac_mac.c | 24 +++++++++++------------- + mt7915/init.c | 3 +-- + mt7915/mac.c | 26 ++++++++++++-------------- + mt7915/main.c | 1 - + mt7915/mt7915.h | 1 - + tx.c | 5 ++--- + 7 files changed, 27 insertions(+), 35 deletions(-) + +--- a/mt76_connac.h ++++ b/mt76_connac.h +@@ -461,7 +461,7 @@ u16 mt76_connac2_mac_tx_rate_val(struct + struct ieee80211_bss_conf *conf, + bool beacon, bool mcast); + bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, +- __le32 *txs_data); ++ int pid, __le32 *txs_data); + bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid, + int pid, __le32 *txs_data); + void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev, +--- a/mt76_connac_mac.c ++++ b/mt76_connac_mac.c +@@ -634,7 +634,7 @@ void mt76_connac2_mac_write_txwi(struct + EXPORT_SYMBOL_GPL(mt76_connac2_mac_write_txwi); + + bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, +- __le32 *txs_data) ++ int pid, __le32 *txs_data) + { + struct mt76_sta_stats *stats = &wcid->stats; + struct ieee80211_supported_band *sband; +@@ -646,15 +646,10 @@ bool mt76_connac2_mac_fill_txs(struct mt + txs = le32_to_cpu(txs_data[0]); + + /* PPDU based reporting */ +- if (mtk_wed_device_active(&dev->mmio.wed) && +- FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) { ++ if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) { + stats->tx_bytes += + le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE) - + le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_BYTE); +- stats->tx_failed += +- le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT); +- stats->tx_retries += +- le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT); + + if (wcid->sta) { + struct ieee80211_sta *sta; +@@ -668,6 +663,9 @@ bool mt76_connac2_mac_fill_txs(struct mt + } + } + ++ if (pid != MT_PACKET_ID_WED) ++ return true; ++ + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); + + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); +@@ -762,13 +760,13 @@ bool mt76_connac2_mac_add_txs_skb(struct + int pid, __le32 *txs_data) + { + struct sk_buff_head list; +- struct sk_buff *skb; +- +- if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) == MT_TXS_PPDU_FMT) +- return false; ++ struct sk_buff *skb = NULL; + + mt76_tx_status_lock(dev, &list); +- skb = mt76_tx_status_skb_get(dev, wcid, pid, &list); ++ ++ if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) == MT_TXS_MPDU_FMT) ++ skb = mt76_tx_status_skb_get(dev, wcid, pid, &list); ++ + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + +@@ -780,7 +778,7 @@ bool mt76_connac2_mac_add_txs_skb(struct + !!(info->flags & IEEE80211_TX_STAT_ACK); + info->status.rates[0].idx = -1; + +- mt76_connac2_mac_fill_txs(dev, wcid, txs_data); ++ mt76_connac2_mac_fill_txs(dev, wcid, pid, txs_data); + mt76_tx_status_skb_done(dev, skb, &list); + } + mt76_tx_status_unlock(dev, &list); +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -551,8 +551,7 @@ mt7915_mac_init_band(struct mt7915_dev * + /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than + * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set. + */ +- if (mtk_wed_device_active(&dev->mt76.mmio.wed)) +- mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H); ++ mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H); + } + + static void +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -747,17 +747,6 @@ int mt7915_tx_prepare_skb(struct mt76_de + if (!wcid) + wcid = &dev->mt76.global_wcid; + +- if (sta) { +- struct mt7915_sta *msta; +- +- msta = (struct mt7915_sta *)sta->drv_priv; +- +- if (time_after(jiffies, msta->jiffies + HZ / 4)) { +- info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; +- msta->jiffies = jiffies; +- } +- } +- + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; + +@@ -1005,10 +994,19 @@ static void mt7915_mac_add_txs(struct mt + + msta = container_of(wcid, struct mt7915_sta, wcid); + +- if (pid == MT_PACKET_ID_WED) +- mt76_connac2_mac_fill_txs(&dev->mt76, wcid, txs_data); +- else ++ if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) == MT_TXS_PPDU_FMT) { ++ if (is_mt7915(&dev->mt76)) { ++ struct mt76_sta_stats *stats = &wcid->stats; ++ ++ stats->tx_failed += ++ le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT); ++ stats->tx_retries += ++ le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT); ++ } ++ mt76_connac2_mac_fill_txs(&dev->mt76, wcid, pid, txs_data); ++ } else { + mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data); ++ } + + if (!wcid->sta) + goto out; +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -765,7 +765,6 @@ int mt7915_mac_sta_add(struct mt76_dev * + msta->wcid.sta_disabled = 1; + msta->wcid.idx = idx; + msta->wcid.phy_idx = ext_phy; +- msta->jiffies = jiffies; + + if (sta->tdls) + set_bit(MT_WCID_FLAG_TDLS_PEER, &msta->wcid.flags); +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -155,7 +155,6 @@ struct mt7915_sta { + struct ewma_avg_signal avg_ack_signal; + + unsigned long changed; +- unsigned long jiffies; + struct mt76_connac_sta_key_conf bip; + + struct mt7915_hw_queue_state hwq_state[4]; +--- a/tx.c ++++ b/tx.c +@@ -137,9 +137,8 @@ mt76_tx_status_skb_add(struct mt76_dev * + + if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS | + IEEE80211_TX_CTL_RATE_CTRL_PROBE))) { +- if (mtk_wed_device_active(&dev->mmio.wed) && +- ((info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) || +- ieee80211_is_data(hdr->frame_control))) ++ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP || ++ ieee80211_is_data(hdr->frame_control)) + return MT_PACKET_ID_WED; + + return MT_PACKET_ID_NO_SKB; diff --git a/package/kernel/mt76/patches/smartrg-0020-wifi-mt76-route-mgmt-frames-for-inactive-sta-to-altx.patch b/package/kernel/mt76/patches/smartrg-0020-wifi-mt76-route-mgmt-frames-for-inactive-sta-to-altx.patch new file mode 100644 index 0000000000..cd4f439602 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0020-wifi-mt76-route-mgmt-frames-for-inactive-sta-to-altx.patch @@ -0,0 +1,48 @@ +From: Chad Monroe +Date: Wed, 03 Jun 2026 11:02:13 -0700 +Subject: [PATCH] wifi: mt76: route mgmt frames for inactive STA contexts to ALTX + +Frames addressed to a wcid with no live per-STA context (global/vif +management, or a peer being torn down) must egress on the LMAC ALTX +queue. Otherwise they wait on a per-STA AC queue the firmware no longer +services, which can stall the shared per-band TX ring during assoc and +disassoc churn. + +This augments the existing predicate rather than replacing it: deauth +and offchannel frames are already routed to ALTX for power-save reasons; +this adds the orthogonal teardown case (disassoc, action, and other +management frames to an inactive context). The tx.c hunk is core, gated +by MT_DRV_HW_MGMT_TXQ, so it also covers the other connac drivers, whose +mapping sends qid >= MT_TXQ_PSD to ALTX identically. + +Signed-off-by: Chad Monroe +--- + mt7996/mac.c | 3 +++ + tx.c | 4 +++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -895,6 +895,9 @@ void mt7996_mac_write_txwi(struct mt7996 + } else if (beacon) { + p_fmt = MT_TX_TYPE_FW; + q_idx = MT_LMAC_BCN0; ++ } else if (!wcid->sta || wcid->sta_disabled) { ++ p_fmt = MT_TX_TYPE_CT; ++ q_idx = MT_LMAC_ALTX0; + } else if (qid >= MT_TXQ_PSD) { + p_fmt = MT_TX_TYPE_CT; + q_idx = MT_LMAC_ALTX0; +--- a/tx.c ++++ b/tx.c +@@ -672,7 +672,9 @@ mt76_txq_schedule_pending_wcid(struct mt + !ieee80211_is_data_present(hdr->frame_control) && + (!ieee80211_is_bufferable_mmpdu(skb) || + ieee80211_is_deauth(hdr->frame_control) || +- head == &wcid->tx_offchannel)) ++ head == &wcid->tx_offchannel || ++ (ieee80211_is_mgmt(hdr->frame_control) && ++ (!wcid->sta || wcid->sta_disabled)))) + qid = MT_TXQ_PSD; + + q = phy->q_tx[qid]; diff --git a/package/kernel/mt76/patches/smartrg-0120-wifi-mt76-mt7996-add-per-band-token-limit.patch b/package/kernel/mt76/patches/smartrg-0120-wifi-mt76-mt7996-add-per-band-token-limit.patch new file mode 100644 index 0000000000..fd174cc93a --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0120-wifi-mt76-mt7996-add-per-band-token-limit.patch @@ -0,0 +1,290 @@ +From: Chad Monroe +Date: Tue, 18 Nov 2025 14:04:24 -0800 +Subject: [PATCH] wifi: mt76: mt7996: add per-band token limit + +Multi-radio devices use a single token pool for all bands. Add +per-band token limit to prevent one band from interfering with +another. + +Add sysfs file to dump current token info for debugging. + +Signed-off-by: Chad Monroe +--- + mac80211.c | 1 + + mt76.h | 9 ++++++++- + mt76_connac_mac.c | 4 ++++ + mt7915/mac.c | 3 ++- + mt7921/pci_mac.c | 4 +++- + mt7925/pci_mac.c | 4 +++- + mt7996/debugfs.c | 33 +++++++++++++++++++++++++++++++++ + mt7996/init.c | 2 ++ + mt7996/mac.c | 8 +++++++- + mt7996/mt7996.h | 1 + + tx.c | 21 ++++++++++++++++++--- + 11 files changed, 82 insertions(+), 8 deletions(-) + +--- a/mt76.h ++++ b/mt76.h +@@ -465,6 +465,8 @@ struct mt76_txwi_cache { + + u8 qid; + u8 phy_idx; ++ u16 wcid; ++ unsigned long jiffies; + }; + + struct mt76_rx_tid { +@@ -929,6 +931,8 @@ struct mt76_phy { + bool al; + u8 pin; + } leds; ++ ++ int tokens; + }; + + struct mt76_dev { +@@ -982,6 +986,7 @@ struct mt76_dev { + u16 token_count; + u16 token_start; + u16 token_size; ++ u16 token_threshold; + + spinlock_t rx_token_lock; + struct idr rx_token; +@@ -2060,7 +2065,8 @@ static inline bool mt76_queue_is_npu_txf + + struct mt76_txwi_cache * + mt76_token_release(struct mt76_dev *dev, int token, bool *wake); +-int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi); ++int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi, ++ u8 phy_idx); + void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked); + struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token); + int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr, +--- a/mac80211.c ++++ b/mac80211.c +@@ -727,6 +727,7 @@ mt76_alloc_device(struct device *pdev, u + INIT_LIST_HEAD(&dev->txwi_cache); + INIT_LIST_HEAD(&dev->rxwi_cache); + dev->token_size = dev->drv->token_size; ++ dev->token_threshold = dev->token_size; + INIT_DELAYED_WORK(&dev->scan_work, mt76_scan_work); + spin_lock_init(&dev->scan_lock); + +--- a/mt76_connac_mac.c ++++ b/mt76_connac_mac.c +@@ -1223,8 +1223,12 @@ void mt76_connac2_tx_token_put(struct mt + + spin_lock_bh(&dev->token_lock); + idr_for_each_entry(&dev->token, txwi, id) { ++ struct mt76_phy *phy = mt76_dev_phy(dev, txwi->phy_idx); ++ + mt76_connac2_txwi_free(dev, txwi, NULL, NULL); + dev->token_count--; ++ if (phy->tokens > 0) ++ phy->tokens--; + } + spin_unlock_bh(&dev->token_lock); + idr_destroy(&dev->token); +--- a/tx.c ++++ b/tx.c +@@ -923,22 +923,33 @@ void __mt76_set_tx_blocked(struct mt76_d + } + EXPORT_SYMBOL_GPL(__mt76_set_tx_blocked); + +-int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi) ++int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi, ++ u8 phy_idx) + { +- int token; ++ struct mt76_phy *phy = mt76_dev_phy(dev, phy_idx); ++ int token = -EBUSY; + + spin_lock_bh(&dev->token_lock); + ++ if (dev->token_threshold && ++ phy->tokens >= dev->token_threshold) ++ goto out; ++ + token = idr_alloc(&dev->token, *ptxwi, dev->token_start, + dev->token_start + dev->token_size, + GFP_ATOMIC); + if (token >= dev->token_start) { ++ struct mt76_phy *mphy = mt76_dev_phy(dev, phy_idx); ++ + dev->token_count++; + + if ((*ptxwi)->qid == MT_TXQ_PSD) { +- struct mt76_phy *mphy = mt76_dev_phy(dev, (*ptxwi)->phy_idx); + atomic_inc(&mphy->mgmt_tx_pending); + } ++ ++ (*ptxwi)->phy_idx = phy_idx; ++ mphy->tokens++; ++ + } + + #ifdef CONFIG_NET_MEDIATEK_SOC_WED +@@ -950,6 +961,7 @@ int mt76_token_consume(struct mt76_dev * + if (dev->token_count >= dev->token_size - MT76_TOKEN_FREE_THR) + __mt76_set_tx_blocked(dev, true); + ++out: + spin_unlock_bh(&dev->token_lock); + + return token; +@@ -978,12 +990,16 @@ struct mt76_txwi_cache * + mt76_token_release(struct mt76_dev *dev, int token, bool *wake) + { + struct mt76_txwi_cache *txwi; ++ struct mt76_phy *phy = NULL; + + spin_lock_bh(&dev->token_lock); + + txwi = idr_remove(&dev->token, token); + if (txwi) { ++ phy = mt76_dev_phy(dev, txwi->phy_idx); + dev->token_count--; ++ if (phy->tokens > 0) ++ phy->tokens--; + + if (txwi->qid == MT_TXQ_PSD) { + struct mt76_phy *mphy = mt76_dev_phy(dev, txwi->phy_idx); +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -749,8 +749,9 @@ int mt7915_tx_prepare_skb(struct mt76_de + + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; ++ t->wcid = wcid->idx; + +- id = mt76_token_consume(mdev, &t); ++ id = mt76_token_consume(mdev, &t, wcid->phy_idx); + if (id < 0) + return id; + +--- a/mt7921/pci_mac.c ++++ b/mt7921/pci_mac.c +@@ -26,8 +26,10 @@ int mt7921e_tx_prepare_skb(struct mt76_d + + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; ++ t->wcid = wcid->idx; ++ t->jiffies = jiffies; + +- id = mt76_token_consume(mdev, &t); ++ id = mt76_token_consume(mdev, &t, wcid->phy_idx); + if (id < 0) + return id; + +--- a/mt7925/pci_mac.c ++++ b/mt7925/pci_mac.c +@@ -27,8 +27,10 @@ int mt7925e_tx_prepare_skb(struct mt76_d + + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; ++ t->wcid = wcid->idx; ++ t->jiffies = jiffies; + +- id = mt76_token_consume(mdev, &t); ++ id = mt76_token_consume(mdev, &t, wcid->phy_idx); + if (id < 0) + return id; + +--- a/mt7996/mt7996.h ++++ b/mt7996/mt7996.h +@@ -94,6 +94,7 @@ + #define MT7996_EXT_EEPROM_BLOCK_SIZE 1024 + #define MT7996_TOKEN_SIZE 16384 + #define MT7996_HW_TOKEN_SIZE 8192 ++#define MT7996_PER_BAND_TOKEN_SIZE 4000 + + #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ + #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ +--- a/mt7996/init.c ++++ b/mt7996/init.c +@@ -1773,6 +1773,8 @@ int mt7996_register_device(struct mt7996 + if (ret) + return ret; + ++ dev->mt76.token_threshold = MT7996_PER_BAND_TOKEN_SIZE; ++ + mt7996_for_each_phy(dev, phy) + mt7996_thermal_init(phy); + +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -1049,8 +1049,10 @@ int mt7996_tx_prepare_skb(struct mt76_de + + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); + t->skb = tx_info->skb; ++ t->wcid = wcid->idx; ++ t->jiffies = jiffies; + +- id = mt76_token_consume(mdev, &t); ++ id = mt76_token_consume(mdev, &t, wcid->phy_idx); + if (id < 0) + return id; + +@@ -2206,8 +2208,12 @@ void mt7996_tx_token_put(struct mt7996_d + + spin_lock_bh(&dev->mt76.token_lock); + idr_for_each_entry(&dev->mt76.token, txwi, id) { ++ struct mt76_phy *phy = mt76_dev_phy(&dev->mt76, txwi->phy_idx); ++ + mt7996_txwi_free(dev, txwi, NULL, NULL, NULL); + dev->mt76.token_count--; ++ if (phy->tokens > 0) ++ phy->tokens--; + } + spin_unlock_bh(&dev->mt76.token_lock); + idr_destroy(&dev->mt76.token); +--- a/mt7996/debugfs.c ++++ b/mt7996/debugfs.c +@@ -839,6 +839,37 @@ mt7996_twt_stats(struct seq_file *s, voi + return 0; + } + ++static int mt7996_token_read(struct seq_file *s, void *data) ++{ ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ struct mt76_dev *mdev = &dev->mt76; ++ int msdu_id, i; ++ struct mt76_txwi_cache *txwi; ++ ++ seq_printf(s, "Token from host:\n"); ++ spin_lock_bh(&mdev->token_lock); ++ idr_for_each_entry(&mdev->token, txwi, msdu_id) { ++ seq_printf(s, "%4d: wcid %4u band %u pending %u ms\n", msdu_id, ++ txwi->wcid, txwi->phy_idx, ++ jiffies_to_msecs(jiffies - txwi->jiffies)); ++ } ++ seq_printf(s, "\n"); ++ for (i = 0; i < __MT_MAX_BAND; i++) { ++ struct mt76_phy *phy = mt76_dev_phy(mdev, i); ++ u16 limit = mdev->token_threshold ?: mdev->token_size; ++ ++ if (!mt7996_band_valid(dev, i)) ++ continue; ++ ++ seq_printf(s, "band%u consumed: %d, free: %d total: %d\n", ++ i, phy->tokens, ++ limit - phy->tokens, limit); ++ } ++ spin_unlock_bh(&mdev->token_lock); ++ ++ return 0; ++} ++ + /* The index of RF registers use the generic regidx, combined with two parts: + * WF selection [31:24] and offset [23:0]. + */ +@@ -893,6 +924,8 @@ int mt7996_init_debugfs(struct mt7996_de + &fops_implicit_txbf); + debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir, + mt7996_twt_stats); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "token", dir, ++ mt7996_token_read); + debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); + + debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); diff --git a/package/kernel/mt76/patches/smartrg-0121-wifi-mt76-mt7996-add-debugsfs-to-dump-tx-tokens.patch b/package/kernel/mt76/patches/smartrg-0121-wifi-mt76-mt7996-add-debugsfs-to-dump-tx-tokens.patch new file mode 100644 index 0000000000..6798060e95 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0121-wifi-mt76-mt7996-add-debugsfs-to-dump-tx-tokens.patch @@ -0,0 +1,95 @@ +From: Chad Monroe +Date: Tue, 18 Nov 2025 15:40:09 -0800 +Subject: [PATCH] wifi: mt76: mt7996: add debugfs to dump tx tokens + +Add debugfs to dump skb data for tx tokens. + +Signed-off-by: Chad Monroe +--- + mt7996/debugfs.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ + mt7996/mt7996.h | 2 + + 2 files changed, 58 insertions(+) + +--- a/mt7996/mt7996.h ++++ b/mt7996/mt7996.h +@@ -505,6 +505,8 @@ struct mt7996_dev { + u8 fw_debug_bin; + u16 fw_debug_seq; + ++ u32 token_debug_idx; ++ + struct dentry *debugfs_dir; + struct rchan *relay_fwlog; + +--- a/mt7996/debugfs.c ++++ b/mt7996/debugfs.c +@@ -870,6 +870,59 @@ static int mt7996_token_read(struct seq_ + return 0; + } + ++static int mt7996_token_txd_read(struct seq_file *s, void *data) ++{ ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ struct mt76_dev *mdev = &dev->mt76; ++ struct mt76_txwi_cache *t; ++ struct sk_buff *skb = NULL; ++ u8 *txwi_buf; ++ size_t txwi_len = mdev->drv->txwi_size; ++ ++ txwi_buf = kzalloc(txwi_len, GFP_KERNEL); ++ if (!txwi_buf) ++ return -ENOMEM; ++ ++ spin_lock_bh(&mdev->token_lock); ++ t = idr_find(&mdev->token, dev->token_debug_idx); ++ if (t) { ++ memcpy(txwi_buf, mt76_get_txwi_ptr(mdev, t), txwi_len); ++ if (t->skb) ++ skb = skb_get(t->skb); ++ } ++ spin_unlock_bh(&mdev->token_lock); ++ ++ if (!t) { ++ seq_printf(s, "token %u not in use\n", dev->token_debug_idx); ++ goto out; ++ } ++ ++ seq_printf(s, "token %u (wcid %u, phy %u)\n", ++ dev->token_debug_idx, t->wcid, t->phy_idx); ++ seq_puts(s, "[TXD]\n"); ++ seq_hex_dump(s, "", DUMP_PREFIX_OFFSET, 16, 1, txwi_buf, ++ txwi_len, false); ++ ++ if (skb) { ++ u32 dump_len = skb->len; ++ ++ if (dump_len > 512) ++ dump_len = 512; ++ seq_printf(s, "\n[SKB len=%u dump=%u]\n", skb->len, dump_len); ++ seq_hex_dump(s, "", DUMP_PREFIX_OFFSET, 16, 1, ++ skb->data, dump_len, false); ++ } else { ++ seq_puts(s, "\n[SKB] none\n"); ++ } ++ ++out: ++ kfree(txwi_buf); ++ if (skb) ++ dev_kfree_skb_any(skb); ++ ++ return 0; ++} ++ + /* The index of RF registers use the generic regidx, combined with two parts: + * WF selection [31:24] and offset [23:0]. + */ +@@ -926,6 +979,9 @@ int mt7996_init_debugfs(struct mt7996_de + mt7996_twt_stats); + debugfs_create_devm_seqfile(dev->mt76.dev, "token", dir, + mt7996_token_read); ++ debugfs_create_u32("token_idx", 0600, dir, &dev->token_debug_idx); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "token_txd", dir, ++ mt7996_token_txd_read); + debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); + + debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); diff --git a/package/kernel/mt76/patches/smartrg-0901-wifi-mt76-fix-incorrect-HE-TX-GI-report.patch b/package/kernel/mt76/patches/smartrg-0901-wifi-mt76-fix-incorrect-HE-TX-GI-report.patch new file mode 100644 index 0000000000..f5b81b7648 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0901-wifi-mt76-fix-incorrect-HE-TX-GI-report.patch @@ -0,0 +1,489 @@ +From 0833b8306d6614f28f9be5df2174667e486cdab7 Mon Sep 17 00:00:00 2001 +From: Evelyn Tsai +Date: Thu, 18 May 2023 18:11:37 +0800 +Subject: [PATCH 01/76] wifi: mt76: fix incorrect HE TX GI report + +Change GI reporting source from static capability to rate-tuning module. + +Signed-off-by: Benjamin Lin +--- + mt76.h | 4 ++ + mt7915/init.c | 4 ++ + mt7915/mac.c | 64 ++++++++++++------- + mt7915/main.c | 7 +++ + mt7915/mcu.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/mcu.h | 58 +++++++++++++++++ + mt7915/mt7915.h | 6 ++ + 7 files changed, 282 insertions(+), 22 deletions(-) + +--- a/mt76.h ++++ b/mt76.h +@@ -335,12 +335,16 @@ struct mt76_queue_ops { + bool reset_idx); + }; + ++#define MT_PHY_TYPE_LEGACY GENMASK(2, 0) ++#define MT_PHY_TYPE_EXT GENMASK(7, 3) ++ + enum mt76_phy_type { + MT_PHY_TYPE_CCK, + MT_PHY_TYPE_OFDM, + MT_PHY_TYPE_HT, + MT_PHY_TYPE_HT_GF, + MT_PHY_TYPE_VHT, ++ MT_PHY_TYPE_HE_REMAP, + MT_PHY_TYPE_HE_SU = 8, + MT_PHY_TYPE_HE_EXT_SU, + MT_PHY_TYPE_HE_TB, +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -697,6 +697,8 @@ mt7915_register_ext_phy(struct mt7915_de + struct mt76_phy *mphy = phy->mt76; + int ret; + ++ INIT_LIST_HEAD(&phy->stats_list); ++ spin_lock_init(&phy->stats_lock); + INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work); + + mt7915_eeprom_parse_hw_cap(dev, phy); +@@ -1233,6 +1235,8 @@ int mt7915_register_device(struct mt7915 + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; ++ INIT_LIST_HEAD(&dev->phy.stats_list); ++ spin_lock_init(&dev->phy.stats_lock); + INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work); + INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work); + INIT_LIST_HEAD(&dev->sta_rc_list); +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -177,15 +177,7 @@ static void mt7915_mac_sta_poll(struct m + rx_cur); + } + +- /* +- * We don't support reading GI info from txs packets. +- * For accurate tx status reporting and AQL improvement, +- * we need to make sure that flags match so polling GI +- * from per-sta counters directly. +- */ + rate = &msta->wcid.rate; +- addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 7); +- val = mt76_rr(dev, addr); + + switch (rate->bw) { + case RATE_INFO_BW_160: +@@ -202,18 +194,6 @@ static void mt7915_mac_sta_poll(struct m + break; + } + +- if (rate->flags & RATE_INFO_FLAGS_HE_MCS) { +- u8 offs = 24 + 2 * bw; +- +- rate->he_gi = (val & (0x3 << offs)) >> offs; +- } else if (rate->flags & +- (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) { +- if (val & BIT(12 + bw)) +- rate->flags |= RATE_INFO_FLAGS_SHORT_GI; +- else +- rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI; +- } +- + /* get signal strength of resp frames (CTS/BA/ACK) */ + addr = mt7915_mac_wtbl_lmac_addr(dev, idx, 30); + val = mt76_rr(dev, addr); +@@ -888,6 +868,7 @@ mt7915_mac_tx_free(struct mt7915_dev *de + info = le32_to_cpu(*cur_info); + if (info & MT_TX_FREE_PAIR) { + struct mt7915_sta *msta; ++ struct mt7915_phy *phy; + u16 idx; + + idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); +@@ -898,6 +879,15 @@ mt7915_mac_tx_free(struct mt7915_dev *de + + msta = container_of(wcid, struct mt7915_sta, wcid); + mt76_wcid_add_poll(&dev->mt76, &msta->wcid); ++ ++ if (!test_bit(MT76_MCU_RESET, &mdev->phy.state)) { ++ phy = msta->vif->phy; ++ spin_lock_bh(&phy->stats_lock); ++ if (list_empty(&msta->stats_list)) ++ list_add_tail(&msta->stats_list, &phy->stats_list); ++ spin_unlock_bh(&phy->stats_lock); ++ } ++ + continue; + } + +@@ -976,6 +966,7 @@ mt7915_mac_tx_free_v0(struct mt7915_dev + static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) + { + struct mt7915_sta *msta = NULL; ++ struct mt7915_phy *phy; + struct mt76_wcid *wcid; + __le32 *txs_data = data; + u16 wcidx; +@@ -1014,6 +1005,11 @@ static void mt7915_mac_add_txs(struct mt + + mt76_wcid_add_poll(&dev->mt76, &msta->wcid); + ++ phy = msta->vif->phy; ++ spin_lock_bh(&phy->stats_lock); ++ if (list_empty(&msta->stats_list)) ++ list_add_tail(&msta->stats_list, &phy->stats_list); ++ spin_unlock_bh(&phy->stats_lock); + out: + rcu_read_unlock(); + } +@@ -1946,6 +1942,27 @@ static void mt7915_mac_severe_check(stru + phy->trb_ts = trb; + } + ++static void mt7915_mac_sta_stats_work(struct mt7915_phy *phy) ++{ ++ struct mt7915_sta *sta; ++ LIST_HEAD(list); ++ ++ spin_lock_bh(&phy->stats_lock); ++ list_splice_init(&phy->stats_list, &list); ++ ++ while (!list_empty(&list)) { ++ sta = list_first_entry(&list, struct mt7915_sta, stats_list); ++ list_del_init(&sta->stats_list); ++ spin_unlock_bh(&phy->stats_lock); ++ ++ mt7915_mcu_get_tx_rate(phy, sta->wcid.idx); ++ ++ spin_lock_bh(&phy->stats_lock); ++ } ++ ++ spin_unlock_bh(&phy->stats_lock); ++} ++ + void mt7915_mac_sta_rc_work(struct work_struct *work) + { + struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work); +@@ -2110,6 +2127,11 @@ void mt7915_mac_work(struct work_struct + mt7915_mcu_muru_debug_get(phy); + } + ++ if (++phy->stats_work_count == 10) { ++ phy->stats_work_count = 0; ++ mt7915_mac_sta_stats_work(phy); ++ } ++ + mutex_unlock(&mphy->dev->mutex); + + mt76_tx_status_check(mphy->dev, false); +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -761,6 +761,7 @@ int mt7915_mac_sta_add(struct mt76_dev * + + INIT_LIST_HEAD(&msta->rc_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); ++ INIT_LIST_HEAD(&msta->stats_list); + msta->vif = mvif; + msta->wcid.sta_disabled = 1; + msta->wcid.idx = idx; +@@ -880,6 +881,7 @@ void mt7915_mac_sta_remove(struct mt76_d + { + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; ++ struct mt7915_phy *phy = msta->vif->phy; + + mt7915_mac_wtbl_update(dev, msta->wcid.idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); +@@ -890,6 +892,11 @@ void mt7915_mac_sta_remove(struct mt76_d + if (!list_empty(&msta->rc_list)) + list_del_init(&msta->rc_list); + spin_unlock_bh(&mdev->sta_poll_lock); ++ ++ spin_lock_bh(&phy->stats_lock); ++ if (!list_empty(&msta->stats_list)) ++ list_del_init(&msta->stats_list); ++ spin_unlock_bh(&phy->stats_lock); + } + + static void mt7915_tx(struct ieee80211_hw *hw, +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -4093,6 +4093,167 @@ int mt7915_mcu_set_protection(struct mt7 + MCU_EXT_CMD(BSS_INFO_UPDATE), true); + } + ++static int ++mt7915_mcu_parse_tx_gi(struct mt76_dev *dev, u8 mode, u8 gi, u8 bw, ++ struct rate_info *rate) ++{ ++ /* Legacy drivers only use 3 bits for PHY mode. For backward ++ * compatibility, HE and newer PHY mode indices are remapped ++ * to the extended bits. ++ */ ++ if (u8_get_bits(mode, MT_PHY_TYPE_LEGACY) == MT_PHY_TYPE_HE_REMAP) ++ mode = u8_get_bits(mode, MT_PHY_TYPE_EXT); ++ ++ switch (mode) { ++ case MT_PHY_TYPE_CCK: ++ case MT_PHY_TYPE_OFDM: ++ break; ++ case MT_PHY_TYPE_HT: ++ case MT_PHY_TYPE_HT_GF: ++ case MT_PHY_TYPE_VHT: ++ if (gi) ++ rate->flags |= RATE_INFO_FLAGS_SHORT_GI; ++ break; ++ case MT_PHY_TYPE_HE_SU: ++ case MT_PHY_TYPE_HE_EXT_SU: ++ case MT_PHY_TYPE_HE_TB: ++ case MT_PHY_TYPE_HE_MU: ++ if (!is_mt7915(dev)) { ++ switch (bw) { ++ case MCU_PHY_BW_20: ++ gi = u8_get_bits(gi, HE_GI_BW_20); ++ break; ++ case MCU_PHY_BW_40: ++ gi = u8_get_bits(gi, HE_GI_BW_40); ++ break; ++ case MCU_PHY_BW_80: ++ gi = u8_get_bits(gi, HE_GI_BW_80); ++ break; ++ case MCU_PHY_BW_160: ++ gi = u8_get_bits(gi, HE_GI_BW_160); ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ if (gi > NL80211_RATE_INFO_HE_GI_3_2) ++ return -EINVAL; ++ ++ rate->he_gi = gi; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int mt7915_mcu_get_tx_rate_v1(struct mt7915_phy *phy, u16 wcidx) ++{ ++ struct mt7915_mcu_ra_info_v1 *rate; ++ struct mt7915_dev *dev = phy->dev; ++ struct mt76_phy *mphy = phy->mt76; ++ struct mt76_wcid *wcid; ++ struct sk_buff *skb; ++ int ret; ++ ++ struct { ++ __le32 category; ++ u8 wcidx_lo; ++ u8 band; ++ u8 wcidx_hi; ++ u8 rsv[5]; ++ } req = { ++ .category = cpu_to_le32(MCU_GET_TX_RATE), ++ .wcidx_lo = to_wcid_lo(wcidx), ++ .band = mphy->band_idx, ++ .wcidx_hi = to_wcid_hi(wcidx) ++ }; ++ ++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(GET_TX_STAT), ++ &req, sizeof(req), true, &skb); ++ if (ret) ++ return ret; ++ ++ rate = (struct mt7915_mcu_ra_info_v1 *)skb->data; ++ if ((rate->wcidx_hi << 8 | rate->wcidx_lo) != wcidx) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ rcu_read_lock(); ++ wcid = rcu_dereference(dev->mt76.wcid[wcidx]); ++ if (!wcid) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ ret = mt7915_mcu_parse_tx_gi(mphy->dev, rate->mode, rate->gi, ++ rate->bw, &wcid->rate); ++unlock: ++ rcu_read_unlock(); ++out: ++ dev_kfree_skb(skb); ++ ++ return ret; ++} ++ ++static int mt7915_mcu_get_tx_rate_v2(struct mt7915_phy *phy, u16 wcidx) ++{ ++ struct mt7915_mcu_ra_info_v2 *rate; ++ struct mt7915_dev *dev = phy->dev; ++ struct mt76_phy *mphy = phy->mt76; ++ struct mt76_wcid *wcid; ++ struct sk_buff *skb; ++ int ret; ++ ++ struct { ++ u8 category; ++ u8 band; ++ __le16 wcidx; ++ } req = { ++ .category = MCU_GET_TX_RATE, ++ .band = mphy->band_idx, ++ .wcidx = cpu_to_le16(wcidx) ++ }; ++ ++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(GET_TX_STAT), ++ &req, sizeof(req), true, &skb); ++ if (ret) ++ return ret; ++ ++ rate = (struct mt7915_mcu_ra_info_v2 *)skb->data; ++ if (le16_to_cpu(rate->wcidx) != wcidx) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ rcu_read_lock(); ++ wcid = rcu_dereference(dev->mt76.wcid[wcidx]); ++ if (!wcid) { ++ ret = -EINVAL; ++ goto unlock; ++ } ++ ++ ret = mt7915_mcu_parse_tx_gi(mphy->dev, rate->mode, rate->gi, ++ rate->bw, &wcid->rate); ++unlock: ++ rcu_read_unlock(); ++out: ++ dev_kfree_skb(skb); ++ ++ return ret; ++} ++ ++int mt7915_mcu_get_tx_rate(struct mt7915_phy *phy, u16 wcidx) ++{ ++ if (is_mt7915(&phy->dev->mt76)) ++ return mt7915_mcu_get_tx_rate_v1(phy, wcidx); ++ else ++ return mt7915_mcu_get_tx_rate_v2(phy, wcidx); ++} ++ + int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif, + struct cfg80211_he_bss_color *he_bss_color) + { +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -161,6 +161,61 @@ struct mt7915_mcu_eeprom_info { + u8 data[16]; + } __packed; + ++enum { ++ MCU_PHY_BW_20 = 0, ++ MCU_PHY_BW_40, ++ MCU_PHY_BW_80, ++ MCU_PHY_BW_160, ++ MCU_PHY_BW_10, ++ MCU_PHY_BW_5, ++ MCU_PHY_BW_8080, ++ MCU_PHY_BW_320, ++ MCU_PHY_BW_NUM ++}; ++ ++#define HE_GI_BW_20 GENMASK(1, 0) ++#define HE_GI_BW_40 GENMASK(3, 2) ++#define HE_GI_BW_80 GENMASK(5, 4) ++#define HE_GI_BW_160 GENMASK(7, 6) ++ ++struct mt7915_mcu_ra_info_v1 { ++ u8 wcidx_lo; ++ u8 band; ++ u8 wcidx_hi; ++ u8 rsv1[46]; ++ ++ u8 mode; ++ u8 flags; ++ u8 stbc; ++ u8 gi; ++ u8 bw; ++ u8 ldpc; ++ u8 mcs; ++ u8 nss; ++ u8 ltf; ++ ++ u8 rsv2[8]; ++}; ++ ++struct mt7915_mcu_ra_info_v2 { ++ u8 category; ++ u8 rsv1; ++ __le16 num; ++ __le16 wcidx; ++ ++ u8 mode; ++ u8 flags; ++ u8 stbc; ++ u8 gi; ++ u8 bw; ++ u8 ldpc; ++ u8 mcs; ++ u8 nss; ++ u8 ltf; ++ ++ u8 rsv2; ++}; ++ + struct mt7915_mcu_phy_rx_info { + u8 category; + u8 rate; +@@ -542,4 +597,7 @@ enum { + sizeof(struct bss_info_bmc_rate) +\ + sizeof(struct bss_info_ext_bss)) + ++enum { ++ MCU_GET_TX_RATE = 4 ++}; + #endif +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -149,6 +149,7 @@ struct mt7915_sta { + struct mt7915_vif *vif; + + struct list_head rc_list; ++ struct list_head stats_list; + u32 airtime_ac[8]; + + int ack_signal; +@@ -242,6 +243,10 @@ struct mt7915_phy { + bool sku_limit_en:1; + bool sku_path_en:1; + ++ u8 stats_work_count; ++ struct list_head stats_list; ++ spinlock_t stats_lock; ++ + #ifdef CONFIG_NL80211_TESTMODE + struct { + u32 *reg_backup; +@@ -545,6 +550,7 @@ int mt7915_mcu_get_chan_mib_info(struct + int mt7915_mcu_get_temperature(struct mt7915_phy *phy); + int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state); + int mt7915_mcu_set_thermal_protect(struct mt7915_phy *phy); ++int mt7915_mcu_get_tx_rate(struct mt7915_phy *phy, u16 wcidx); + int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct rate_info *rate); + int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1239,6 +1239,7 @@ enum { + MCU_EXT_CMD_EDCA_UPDATE = 0x27, + MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A, + MCU_EXT_CMD_THERMAL_CTRL = 0x2c, ++ MCU_EXT_CMD_GET_TX_STAT = 0x30, + MCU_EXT_CMD_WTBL_UPDATE = 0x32, + MCU_EXT_CMD_SET_DRR_CTRL = 0x36, + MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, diff --git a/package/kernel/mt76/patches/smartrg-0902-wifi-mt76-mt7915-add-pc-stack-dump-for-WM-s-coredump.patch b/package/kernel/mt76/patches/smartrg-0902-wifi-mt76-mt7915-add-pc-stack-dump-for-WM-s-coredump.patch new file mode 100644 index 0000000000..984db0af52 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0902-wifi-mt76-mt7915-add-pc-stack-dump-for-WM-s-coredump.patch @@ -0,0 +1,626 @@ +From 044f6b5284b02b6f41e91d0e8bfb5a022b43cbf9 Mon Sep 17 00:00:00 2001 +From: Bo Jiao +Date: Mon, 22 May 2023 13:49:37 +0800 +Subject: [PATCH 02/21] wifi: mt76: mt7915: add pc stack dump for WM's + coredump. + +Signed-off-by: Bo Jiao +--- + mt76.h | 11 +++ + mt76_connac_mcu.c | 9 +++ + mt7915/coredump.c | 169 +++++++++++++++++++++++++++++++--------------- + mt7915/coredump.h | 34 +++++++--- + mt7915/mac.c | 33 ++++++--- + mt7915/mt7915.h | 2 +- + mt7915/regs.h | 20 ++++++ + 7 files changed, 207 insertions(+), 71 deletions(-) + +--- a/mt76.h ++++ b/mt76.h +@@ -41,6 +41,8 @@ + #define MT76_WED_WDS_MIN 256 + #define MT76_WED_WDS_MAX 272 + ++#define MT76_BUILD_TIME_LEN 24 ++ + #define MT_QFLAG_WED_RING GENMASK(1, 0) + #define MT_QFLAG_WED_TYPE GENMASK(4, 2) + #define MT_QFLAG_WED BIT(5) +@@ -88,6 +90,12 @@ enum mt76_bus_type { + MT76_BUS_SDIO, + }; + ++enum mt76_ram_type { ++ MT76_RAM_TYPE_WM, ++ MT76_RAM_TYPE_WA, ++ __MT76_RAM_TYPE_MAX, ++}; ++ + enum mt76_wed_type { + MT76_WED_Q_TX, + MT76_WED_Q_TXFREE, +@@ -965,6 +973,9 @@ struct mt76_dev { + struct device *dma_dev; + + struct mt76_mcu mcu; ++ struct mt76_connac2_patch_hdr *patch_hdr; ++ struct mt76_connac2_fw_trailer *wm_hdr; ++ struct mt76_connac2_fw_trailer *wa_hdr; + + struct net_device *napi_dev; + struct net_device *tx_napi_dev; +--- a/mt76_connac_mcu.c ++++ b/mt76_connac_mcu.c +@@ -3069,6 +3069,9 @@ int mt76_connac2_load_ram(struct mt76_de + goto out; + } + ++ dev->wm_hdr = devm_kzalloc(dev->dev, sizeof(*hdr), GFP_KERNEL); ++ memcpy(dev->wm_hdr, hdr, sizeof(*hdr)); ++ + snprintf(dev->hw->wiphy->fw_version, + sizeof(dev->hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); +@@ -3098,6 +3101,9 @@ int mt76_connac2_load_ram(struct mt76_de + goto out; + } + ++ dev->wa_hdr = devm_kzalloc(dev->dev, sizeof(*hdr), GFP_KERNEL); ++ memcpy(dev->wa_hdr, hdr, sizeof(*hdr)); ++ + snprintf(dev->hw->wiphy->fw_version, + sizeof(dev->hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); +@@ -3168,6 +3174,9 @@ int mt76_connac2_load_patch(struct mt76_ + dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s", + be32_to_cpu(hdr->hw_sw_ver), hdr->build_date); + ++ dev->patch_hdr = devm_kzalloc(dev->dev, sizeof(*hdr), GFP_KERNEL); ++ memcpy(dev->patch_hdr, hdr, sizeof(*hdr)); ++ + for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) { + struct mt76_connac2_patch_sec *sec; + u32 len, addr, mode; +--- a/mt7915/coredump.c ++++ b/mt7915/coredump.c +@@ -7,7 +7,7 @@ + #include + #include "coredump.h" + +-static bool coredump_memdump; ++static bool coredump_memdump = true; + module_param(coredump_memdump, bool, 0644); + MODULE_PARM_DESC(coredump_memdump, "Optional ability to dump firmware memory"); + +@@ -86,8 +86,11 @@ static const struct mt7915_mem_region mt + }; + + const struct mt7915_mem_region* +-mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num) ++mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u8 type, u32 *num) + { ++ if (type == MT76_RAM_TYPE_WA) ++ return NULL; ++ + switch (mt76_chip(&dev->mt76)) { + case 0x7915: + *num = ARRAY_SIZE(mt7915_mem_regions); +@@ -104,14 +107,14 @@ mt7915_coredump_get_mem_layout(struct mt + } + } + +-static int mt7915_coredump_get_mem_size(struct mt7915_dev *dev) ++static int mt7915_coredump_get_mem_size(struct mt7915_dev *dev, u8 type) + { + const struct mt7915_mem_region *mem_region; + size_t size = 0; + u32 num; + int i; + +- mem_region = mt7915_coredump_get_mem_layout(dev, &num); ++ mem_region = mt7915_coredump_get_mem_layout(dev, type, &num); + if (!mem_region) + return 0; + +@@ -128,9 +131,9 @@ static int mt7915_coredump_get_mem_size( + return size; + } + +-struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev) ++struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev, u8 type) + { +- struct mt7915_crash_data *crash_data = dev->coredump.crash_data; ++ struct mt7915_crash_data *crash_data = dev->coredump.crash_data[type]; + + lockdep_assert_held(&dev->dump_mutex); + +@@ -141,12 +144,15 @@ struct mt7915_crash_data *mt7915_coredum + } + + static void +-mt7915_coredump_fw_state(struct mt7915_dev *dev, struct mt7915_coredump *dump, ++mt7915_coredump_fw_state(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump, + bool *exception) + { +- u32 state, count, type; ++ u32 state, count, category; ++ ++ if (type == MT76_RAM_TYPE_WA) ++ return; + +- type = (u32)mt76_get_field(dev, MT_FW_EXCEPT_TYPE, GENMASK(7, 0)); ++ category = (u32)mt76_get_field(dev, MT_FW_EXCEPT_TYPE, GENMASK(7, 0)); + state = (u32)mt76_get_field(dev, MT_FW_ASSERT_STAT, GENMASK(7, 0)); + count = is_mt7915(&dev->mt76) ? + (u32)mt76_get_field(dev, MT_FW_EXCEPT_COUNT, GENMASK(15, 8)) : +@@ -155,7 +161,7 @@ mt7915_coredump_fw_state(struct mt7915_d + /* normal mode: driver can manually trigger assert for detail info */ + if (!count) + strscpy(dump->fw_state, "normal", sizeof(dump->fw_state)); +- else if (state > 1 && (count == 1) && type == 5) ++ else if (state > 1 && (count == 1) && category == 5) + strscpy(dump->fw_state, "assert", sizeof(dump->fw_state)); + else if ((state > 1 && count == 1) || count > 1) + strscpy(dump->fw_state, "exception", sizeof(dump->fw_state)); +@@ -164,11 +170,14 @@ mt7915_coredump_fw_state(struct mt7915_d + } + + static void +-mt7915_coredump_fw_trace(struct mt7915_dev *dev, struct mt7915_coredump *dump, ++mt7915_coredump_fw_trace(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump, + bool exception) + { + u32 n, irq, sch, base = MT_FW_EINT_INFO; + ++ if (type == MT76_RAM_TYPE_WA) ++ return; ++ + /* trap or run? */ + dump->last_msg_id = mt76_rr(dev, MT_FW_LAST_MSG_ID); + +@@ -221,31 +230,61 @@ mt7915_coredump_fw_trace(struct mt7915_d + } + + static void +-mt7915_coredump_fw_stack(struct mt7915_dev *dev, struct mt7915_coredump *dump, ++mt7915_coredump_fw_stack(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump, + bool exception) + { +- u32 oldest, i, idx; ++ u32 reg, i; ++ ++ if (type == MT76_RAM_TYPE_WA) ++ return; ++ ++ /* read current PC */ ++ mt76_rmw_field(dev, MT_CONN_DBG_CTL_LOG_SEL, ++ MT_CONN_DBG_CTL_PC_LOG_SEL, 0x22); ++ for (i = 0; i < 10; i++) { ++ dump->pc_cur[i] = mt76_rr(dev, MT_CONN_DBG_CTL_PC_LOG); ++ usleep_range(100, 500); ++ } + + /* stop call stack record */ +- if (!exception) +- mt76_clear(dev, 0x89050200, BIT(0)); ++ if (!exception) { ++ mt76_clear(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0)); ++ mt76_clear(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0)); ++ } + +- oldest = (u32)mt76_get_field(dev, 0x89050200, GENMASK(20, 16)) + 2; +- for (i = 0; i < 16; i++) { +- idx = ((oldest + 2 * i + 1) % 32); +- dump->call_stack[i] = mt76_rr(dev, 0x89050204 + idx * 4); ++ /* read PC log */ ++ dump->pc_dbg_ctrl = mt76_rr(dev, MT_MCU_WM_EXCP_PC_CTRL); ++ dump->pc_cur_idx = FIELD_GET(MT_MCU_WM_EXCP_PC_CTRL_IDX_STATUS, ++ dump->pc_dbg_ctrl); ++ for (i = 0; i < 32; i++) { ++ reg = MT_MCU_WM_EXCP_PC_LOG + i * 4; ++ dump->pc_stack[i] = mt76_rr(dev, reg); ++ } ++ ++ /* read LR log */ ++ dump->lr_dbg_ctrl = mt76_rr(dev, MT_MCU_WM_EXCP_LR_CTRL); ++ dump->lr_cur_idx = FIELD_GET(MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS, ++ dump->lr_dbg_ctrl); ++ for (i = 0; i < 32; i++) { ++ reg = MT_MCU_WM_EXCP_LR_LOG + i * 4; ++ dump->lr_stack[i] = mt76_rr(dev, reg); + } + + /* start call stack record */ +- if (!exception) +- mt76_set(dev, 0x89050200, BIT(0)); ++ if (!exception) { ++ mt76_set(dev, MT_MCU_WM_EXCP_PC_CTRL, BIT(0)); ++ mt76_set(dev, MT_MCU_WM_EXCP_LR_CTRL, BIT(0)); ++ } + } + + static void +-mt7915_coredump_fw_task(struct mt7915_dev *dev, struct mt7915_coredump *dump) ++mt7915_coredump_fw_task(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump) + { + u32 offs = is_mt7915(&dev->mt76) ? 0xe0 : 0x170; + ++ if (type == MT76_RAM_TYPE_WA) ++ return; ++ + strscpy(dump->task_qid, "(task queue id) read, write", + sizeof(dump->task_qid)); + +@@ -266,10 +305,13 @@ mt7915_coredump_fw_task(struct mt7915_de + } + + static void +-mt7915_coredump_fw_context(struct mt7915_dev *dev, struct mt7915_coredump *dump) ++mt7915_coredump_fw_context(struct mt7915_dev *dev, u8 type, struct mt7915_coredump *dump) + { + u32 count, idx, id; + ++ if (type == MT76_RAM_TYPE_WA) ++ return; ++ + count = mt76_rr(dev, MT_FW_CIRQ_COUNT); + + /* current context */ +@@ -299,9 +341,10 @@ mt7915_coredump_fw_context(struct mt7915 + } + } + +-static struct mt7915_coredump *mt7915_coredump_build(struct mt7915_dev *dev) ++static struct mt7915_coredump *mt7915_coredump_build(struct mt7915_dev *dev, u8 type) + { +- struct mt7915_crash_data *crash_data = dev->coredump.crash_data; ++ struct mt76_dev *mdev = &dev->mt76; ++ struct mt7915_crash_data *crash_data = dev->coredump.crash_data[type]; + struct mt7915_coredump *dump; + struct mt7915_coredump_mem *dump_mem; + size_t len, sofar = 0, hdr_len = sizeof(*dump); +@@ -326,23 +369,34 @@ static struct mt7915_coredump *mt7915_co + + dump = (struct mt7915_coredump *)(buf); + dump->len = len; ++ dump->hdr_len = hdr_len; + + /* plain text */ + strscpy(dump->magic, "mt76-crash-dump", sizeof(dump->magic)); + strscpy(dump->kernel, init_utsname()->release, sizeof(dump->kernel)); +- strscpy(dump->fw_ver, dev->mt76.hw->wiphy->fw_version, ++ strscpy(dump->fw_ver, mdev->hw->wiphy->fw_version, + sizeof(dump->fw_ver)); ++ strscpy(dump->fw_type, ((type == MT76_RAM_TYPE_WA) ? "WA" : "WM"), ++ sizeof(dump->fw_type)); ++ strscpy(dump->fw_patch_date, mdev->patch_hdr->build_date, ++ sizeof(dump->fw_patch_date)); ++ strscpy(dump->fw_ram_date[MT76_RAM_TYPE_WM], ++ mdev->wm_hdr->build_date, ++ sizeof(mdev->wm_hdr->build_date)); ++ strscpy(dump->fw_ram_date[MT76_RAM_TYPE_WA], ++ mdev->wa_hdr->build_date, ++ sizeof(mdev->wa_hdr->build_date)); + + guid_copy(&dump->guid, &crash_data->guid); + dump->tv_sec = crash_data->timestamp.tv_sec; + dump->tv_nsec = crash_data->timestamp.tv_nsec; + dump->device_id = mt76_chip(&dev->mt76); + +- mt7915_coredump_fw_state(dev, dump, &exception); +- mt7915_coredump_fw_trace(dev, dump, exception); +- mt7915_coredump_fw_task(dev, dump); +- mt7915_coredump_fw_context(dev, dump); +- mt7915_coredump_fw_stack(dev, dump, exception); ++ mt7915_coredump_fw_state(dev, type, dump, &exception); ++ mt7915_coredump_fw_trace(dev, type, dump, exception); ++ mt7915_coredump_fw_task(dev, type, dump); ++ mt7915_coredump_fw_context(dev, type, dump); ++ mt7915_coredump_fw_stack(dev, type, dump, exception); + + /* gather memory content */ + dump_mem = (struct mt7915_coredump_mem *)(buf + sofar); +@@ -356,17 +410,19 @@ static struct mt7915_coredump *mt7915_co + return dump; + } + +-int mt7915_coredump_submit(struct mt7915_dev *dev) ++int mt7915_coredump_submit(struct mt7915_dev *dev, u8 type) + { + struct mt7915_coredump *dump; + +- dump = mt7915_coredump_build(dev); ++ dump = mt7915_coredump_build(dev, type); + if (!dump) { + dev_warn(dev->mt76.dev, "no crash dump data found\n"); + return -ENODATA; + } + + dev_coredumpv(dev->mt76.dev, dump, dump->len, GFP_KERNEL); ++ dev_info(dev->mt76.dev, "%s coredump completed\n", ++ wiphy_name(dev->mt76.hw->wiphy)); + + return 0; + } +@@ -374,23 +430,26 @@ int mt7915_coredump_submit(struct mt7915 + int mt7915_coredump_register(struct mt7915_dev *dev) + { + struct mt7915_crash_data *crash_data; ++ int i; + +- crash_data = vzalloc(sizeof(*dev->coredump.crash_data)); +- if (!crash_data) +- return -ENOMEM; +- +- dev->coredump.crash_data = crash_data; +- +- if (coredump_memdump) { +- crash_data->memdump_buf_len = mt7915_coredump_get_mem_size(dev); +- if (!crash_data->memdump_buf_len) +- /* no memory content */ +- return 0; +- +- crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len); +- if (!crash_data->memdump_buf) { +- vfree(crash_data); ++ for (i = 0; i < __MT76_RAM_TYPE_MAX; i++) { ++ crash_data = vzalloc(sizeof(*dev->coredump.crash_data[i])); ++ if (!crash_data) + return -ENOMEM; ++ ++ dev->coredump.crash_data[i] = crash_data; ++ ++ if (coredump_memdump) { ++ crash_data->memdump_buf_len = mt7915_coredump_get_mem_size(dev, i); ++ if (!crash_data->memdump_buf_len) ++ /* no memory content */ ++ return 0; ++ ++ crash_data->memdump_buf = vzalloc(crash_data->memdump_buf_len); ++ if (!crash_data->memdump_buf) { ++ vfree(crash_data); ++ return -ENOMEM; ++ } + } + } + +@@ -399,13 +458,17 @@ int mt7915_coredump_register(struct mt79 + + void mt7915_coredump_unregister(struct mt7915_dev *dev) + { +- if (dev->coredump.crash_data->memdump_buf) { +- vfree(dev->coredump.crash_data->memdump_buf); +- dev->coredump.crash_data->memdump_buf = NULL; +- dev->coredump.crash_data->memdump_buf_len = 0; +- } ++ int i; + +- vfree(dev->coredump.crash_data); +- dev->coredump.crash_data = NULL; ++ for (i = 0; i < __MT76_RAM_TYPE_MAX; i++) { ++ if (dev->coredump.crash_data[i]->memdump_buf) { ++ vfree(dev->coredump.crash_data[i]->memdump_buf); ++ dev->coredump.crash_data[i]->memdump_buf = NULL; ++ dev->coredump.crash_data[i]->memdump_buf_len = 0; ++ } ++ ++ vfree(dev->coredump.crash_data[i]); ++ dev->coredump.crash_data[i] = NULL; ++ } + } + +--- a/mt7915/coredump.h ++++ b/mt7915/coredump.h +@@ -4,6 +4,7 @@ + #ifndef _COREDUMP_H_ + #define _COREDUMP_H_ + ++#include "../mt76_connac_mcu.h" + #include "mt7915.h" + + struct trace { +@@ -15,6 +16,7 @@ struct mt7915_coredump { + char magic[16]; + + u32 len; ++ u32 hdr_len; + + guid_t guid; + +@@ -26,12 +28,28 @@ struct mt7915_coredump { + char kernel[64]; + /* firmware version */ + char fw_ver[ETHTOOL_FWVERS_LEN]; ++ char fw_patch_date[MT76_BUILD_TIME_LEN]; ++ char fw_ram_date[__MT76_RAM_TYPE_MAX][MT76_BUILD_TIME_LEN]; + + u32 device_id; + ++ /* fw type */ ++ char fw_type[8]; + /* exception state */ + char fw_state[12]; + ++ /* program counters */ ++ u32 pc_dbg_ctrl; ++ u32 pc_cur_idx; ++ u32 pc_cur[10]; ++ /* PC registers */ ++ u32 pc_stack[32]; ++ ++ u32 lr_dbg_ctrl; ++ u32 lr_cur_idx; ++ /* LR registers */ ++ u32 lr_stack[32]; ++ + u32 last_msg_id; + u32 eint_info_idx; + u32 irq_info_idx; +@@ -70,9 +88,6 @@ struct mt7915_coredump { + u32 handler; + } context; + +- /* link registers calltrace */ +- u32 call_stack[16]; +- + /* memory content */ + u8 data[]; + } __packed; +@@ -83,6 +98,7 @@ struct mt7915_coredump_mem { + } __packed; + + struct mt7915_mem_hdr { ++ char name[64]; + u32 start; + u32 len; + u8 data[]; +@@ -98,26 +114,26 @@ struct mt7915_mem_region { + #ifdef CONFIG_DEV_COREDUMP + + const struct mt7915_mem_region * +-mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num); +-struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev); +-int mt7915_coredump_submit(struct mt7915_dev *dev); ++mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u8 type, u32 *num); ++struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev, u8 type); ++int mt7915_coredump_submit(struct mt7915_dev *dev, u8 type); + int mt7915_coredump_register(struct mt7915_dev *dev); + void mt7915_coredump_unregister(struct mt7915_dev *dev); + + #else /* CONFIG_DEV_COREDUMP */ + + static inline const struct mt7915_mem_region * +-mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num) ++mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u8 type, u32 *num) + { + return NULL; + } + +-static inline int mt7915_coredump_submit(struct mt7915_dev *dev) ++static inline int mt7915_coredump_submit(struct mt7915_dev *dev, u8 type) + { + return 0; + } + +-static inline struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev) ++static inline struct mt7915_crash_data *mt7915_coredump_new(struct mt7915_dev *dev, u8 type) + { + return NULL; + } +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1588,28 +1588,31 @@ void mt7915_mac_reset_work(struct work_s + } + + /* firmware coredump */ +-void mt7915_mac_dump_work(struct work_struct *work) ++static void mt7915_mac_fw_coredump(struct mt7915_dev *dev, u8 type) + { + const struct mt7915_mem_region *mem_region; + struct mt7915_crash_data *crash_data; +- struct mt7915_dev *dev; + struct mt7915_mem_hdr *hdr; + size_t buf_len; + int i; + u32 num; + u8 *buf; + +- dev = container_of(work, struct mt7915_dev, dump_work); ++ if (type != MT76_RAM_TYPE_WM) { ++ dev_warn(dev->mt76.dev, "%s currently only supports WM coredump!\n", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ return; ++ } + + mutex_lock(&dev->dump_mutex); + +- crash_data = mt7915_coredump_new(dev); ++ crash_data = mt7915_coredump_new(dev, type); + if (!crash_data) { + mutex_unlock(&dev->dump_mutex); +- goto skip_coredump; ++ return; + } + +- mem_region = mt7915_coredump_get_mem_layout(dev, &num); ++ mem_region = mt7915_coredump_get_mem_layout(dev, type, &num); + if (!mem_region || !crash_data->memdump_buf_len) { + mutex_unlock(&dev->dump_mutex); + goto skip_memdump; +@@ -1619,6 +1622,9 @@ void mt7915_mac_dump_work(struct work_st + buf_len = crash_data->memdump_buf_len; + + /* dumping memory content... */ ++ dev_info(dev->mt76.dev, "%s start coredump for %s\n", ++ wiphy_name(dev->mt76.hw->wiphy), ++ ((type == MT76_RAM_TYPE_WA) ? "WA" : "WM")); + memset(buf, 0, buf_len); + for (i = 0; i < num; i++) { + if (mem_region->len > buf_len) { +@@ -1636,6 +1642,7 @@ void mt7915_mac_dump_work(struct work_st + mt7915_memcpy_fromio(dev, buf, mem_region->start, + mem_region->len); + ++ strscpy(hdr->name, mem_region->name, sizeof(mem_region->name)); + hdr->start = mem_region->start; + hdr->len = mem_region->len; + +@@ -1652,8 +1659,18 @@ void mt7915_mac_dump_work(struct work_st + mutex_unlock(&dev->dump_mutex); + + skip_memdump: +- mt7915_coredump_submit(dev); +-skip_coredump: ++ mt7915_coredump_submit(dev, type); ++} ++ ++void mt7915_mac_dump_work(struct work_struct *work) ++{ ++ struct mt7915_dev *dev; ++ ++ dev = container_of(work, struct mt7915_dev, dump_work); ++ ++ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WM_WDT) ++ mt7915_mac_fw_coredump(dev, MT76_RAM_TYPE_WM); ++ + queue_work(dev->mt76.wq, &dev->reset_work); + } + +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -304,7 +304,7 @@ struct mt7915_dev { + struct mutex dump_mutex; + #ifdef CONFIG_DEV_COREDUMP + struct { +- struct mt7915_crash_data *crash_data; ++ struct mt7915_crash_data *crash_data[__MT76_RAM_TYPE_MAX]; + } coredump; + #endif + +--- a/mt7915/regs.h ++++ b/mt7915/regs.h +@@ -1248,4 +1248,24 @@ enum offs_rev { + #define MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR MT_MCU_WM_CIRQ(0x108) + #define MT_MCU_WM_CIRQ_EINT_SOFT_ADDR MT_MCU_WM_CIRQ(0x118) + ++/* CONN DBG */ ++#define MT_CONN_DBG_CTL_BASE 0x18060000 ++#define MT_CONN_DBG_CTL(ofs) (MT_CONN_DBG_CTL_BASE + (ofs)) ++#define MT_CONN_DBG_CTL_LOG_SEL MT_CONN_DBG_CTL(0x090) ++#define MT_CONN_DBG_CTL_PC_LOG_SEL GENMASK(7, 2) ++#define MT_CONN_DBG_CTL_GPR_LOG_SEL GENMASK(13, 8) ++#define MT_CONN_DBG_CTL_PC_LOG MT_CONN_DBG_CTL(0x204) ++#define MT_CONN_DBG_CTL_GPR_LOG MT_CONN_DBG_CTL(0x204) ++ ++/* CONN MCU EXCP CON */ ++#define MT_MCU_WM_EXCP_BASE 0x89050000 ++ ++#define MT_MCU_WM_EXCP(ofs) (MT_MCU_WM_EXCP_BASE + (ofs)) ++#define MT_MCU_WM_EXCP_PC_CTRL MT_MCU_WM_EXCP(0x100) ++#define MT_MCU_WM_EXCP_PC_CTRL_IDX_STATUS GENMASK(20, 16) ++#define MT_MCU_WM_EXCP_PC_LOG MT_MCU_WM_EXCP(0x104) ++#define MT_MCU_WM_EXCP_LR_CTRL MT_MCU_WM_EXCP(0x200) ++#define MT_MCU_WM_EXCP_LR_CTRL_IDX_STATUS GENMASK(20, 16) ++#define MT_MCU_WM_EXCP_LR_LOG MT_MCU_WM_EXCP(0x204) ++ + #endif diff --git a/package/kernel/mt76/patches/smartrg-0903-wifi-mt76-mt7915-move-temperature-margin-check-to-mt.patch b/package/kernel/mt76/patches/smartrg-0903-wifi-mt76-mt7915-move-temperature-margin-check-to-mt.patch new file mode 100644 index 0000000000..ce4d0000b6 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0903-wifi-mt76-mt7915-move-temperature-margin-check-to-mt.patch @@ -0,0 +1,49 @@ +From 677047b23e7e4a2d96f86f235f21694873c8e13a Mon Sep 17 00:00:00 2001 +From: Howard Hsu +Date: Thu, 13 Jul 2023 15:50:00 +0800 +Subject: [PATCH 03/15] wifi: mt76: mt7915: move temperature margin check to + mt7915_thermal_temp_store() + +Originally, we would reduce the 10-degree margin to the restore +temperature, but the user would not be aware of this when setting it. +Moving the margin reduction to the user setting check allows the user to +clearly understand that there is a 10-degree difference between the +restore and trigger temperature. + +Signed-off-by: Howard Hsu +--- + mt7915/init.c | 7 ++++--- + mt7915/mcu.c | 3 +-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -87,12 +87,13 @@ static ssize_t mt7915_thermal_temp_store + mutex_lock(&phy->dev->mt76.mutex); + val = DIV_ROUND_CLOSEST(clamp_val(val, 60 * 1000, 130 * 1000), 1000); + ++ /* add a safety margin ~10 */ + if ((i - 1 == MT7915_CRIT_TEMP_IDX && +- val > phy->throttle_temp[MT7915_MAX_TEMP_IDX]) || ++ val > phy->throttle_temp[MT7915_MAX_TEMP_IDX] - 10) || + (i - 1 == MT7915_MAX_TEMP_IDX && +- val < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) { ++ val - 10 < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) { + dev_err(phy->dev->mt76.dev, +- "temp1_max shall be greater than temp1_crit."); ++ "temp1_max shall be 10 degrees greater than temp1_crit."); + mutex_unlock(&phy->dev->mt76.mutex); + return -EINVAL; + } +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -3354,8 +3354,7 @@ int mt7915_mcu_set_thermal_protect(struc + + /* set high-temperature trigger threshold */ + req.ctrl.ctrl_id = THERMAL_PROTECT_ENABLE; +- /* add a safety margin ~10 */ +- req.restore_temp = cpu_to_le32(phy->throttle_temp[0] - 10); ++ req.restore_temp = cpu_to_le32(phy->throttle_temp[0]); + req.trigger_temp = cpu_to_le32(phy->throttle_temp[1]); + req.sustain_time = cpu_to_le16(10); + diff --git a/package/kernel/mt76/patches/smartrg-0904-wifi-mt76-mt7915-fix-txpower-issues.patch b/package/kernel/mt76/patches/smartrg-0904-wifi-mt76-mt7915-fix-txpower-issues.patch new file mode 100644 index 0000000000..6634605b88 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0904-wifi-mt76-mt7915-fix-txpower-issues.patch @@ -0,0 +1,103 @@ +From ef7571d5c4f04db586f9623bf00a336181ead29a Mon Sep 17 00:00:00 2001 +From: Evelyn Tsai +Date: Sat, 29 Jul 2023 04:53:47 +0800 +Subject: [PATCH 04/15] wifi: mt76: mt7915: fix txpower issues + +--- + eeprom.c | 2 +- + mt7915/debugfs.c | 48 ++++++++++++++++++++++++++---------------------- + mt7915/main.c | 1 + + 3 files changed, 28 insertions(+), 23 deletions(-) + +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -974,9 +974,9 @@ mt7915_xmit_queues_show(struct seq_file + + DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues); + +-#define mt7915_txpower_puts(rate) \ ++#define mt7915_txpower_puts(rate, _len) \ + ({ \ +- len += scnprintf(buf + len, sz - len, "%-16s:", #rate " (TMAC)"); \ ++ len += scnprintf(buf + len, sz - len, "%-*s:", _len, #rate " (TMAC)"); \ + for (i = 0; i < mt7915_sku_group_len[SKU_##rate]; i++, offs++) \ + len += scnprintf(buf + len, sz - len, " %6d", txpwr[offs]); \ + len += scnprintf(buf + len, sz - len, "\n"); \ +@@ -1018,43 +1018,47 @@ mt7915_rate_txpower_get(struct file *fil + len += scnprintf(buf + len, sz - len, + "\nPhy%d Tx power table (channel %d)\n", + phy != &dev->phy, phy->mt76->chandef.chan->hw_value); +- len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s\n", ++ len += scnprintf(buf + len, sz - len, "%-23s %6s %6s %6s %6s\n", + " ", "1m", "2m", "5m", "11m"); +- mt7915_txpower_puts(CCK); ++ mt7915_txpower_puts(CCK, 23); + + len += scnprintf(buf + len, sz - len, +- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", ++ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m", + "54m"); +- mt7915_txpower_puts(OFDM); ++ mt7915_txpower_puts(OFDM, 23); + + len += scnprintf(buf + len, sz - len, +- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", ++ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", + "mcs5", "mcs6", "mcs7"); +- mt7915_txpower_puts(HT_BW20); ++ mt7915_txpower_puts(HT_BW20, 23); + + len += scnprintf(buf + len, sz - len, +- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", ++ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", + "mcs6", "mcs7", "mcs32"); +- mt7915_txpower_puts(HT_BW40); ++ mt7915_txpower_puts(HT_BW40, 23); + + len += scnprintf(buf + len, sz - len, +- "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", ++ "%-23s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", + " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", + "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11"); +- mt7915_txpower_puts(VHT_BW20); +- mt7915_txpower_puts(VHT_BW40); +- mt7915_txpower_puts(VHT_BW80); +- mt7915_txpower_puts(VHT_BW160); +- mt7915_txpower_puts(HE_RU26); +- mt7915_txpower_puts(HE_RU52); +- mt7915_txpower_puts(HE_RU106); +- mt7915_txpower_puts(HE_RU242); +- mt7915_txpower_puts(HE_RU484); +- mt7915_txpower_puts(HE_RU996); +- mt7915_txpower_puts(HE_RU2x996); ++ mt7915_txpower_puts(VHT_BW20, 23); ++ mt7915_txpower_puts(VHT_BW40, 23); ++ mt7915_txpower_puts(VHT_BW80, 23); ++ mt7915_txpower_puts(VHT_BW160, 23); ++ mt7915_txpower_puts(HE_RU26, 23); ++ mt7915_txpower_puts(HE_RU52, 23); ++ mt7915_txpower_puts(HE_RU106, 23); ++ len += scnprintf(buf + len, sz - len, "BW20/"); ++ mt7915_txpower_puts(HE_RU242, 18); ++ len += scnprintf(buf + len, sz - len, "BW40/"); ++ mt7915_txpower_puts(HE_RU484, 18); ++ len += scnprintf(buf + len, sz - len, "BW80/"); ++ mt7915_txpower_puts(HE_RU996, 18); ++ len += scnprintf(buf + len, sz - len, "BW160/"); ++ mt7915_txpower_puts(HE_RU2x996, 17); + + reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(band) : + MT_WF_PHY_TPC_CTRL_STAT_MT7916(band); +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -1161,6 +1161,7 @@ mt7915_set_antenna(struct ieee80211_hw * + mt76_set_stream_caps(phy->mt76, true); + mt7915_set_stream_vht_txbf_caps(phy); + mt7915_set_stream_he_caps(phy); ++ mt7915_mcu_set_txpower_sku(phy); + + mutex_unlock(&dev->mt76.mutex); + diff --git a/package/kernel/mt76/patches/smartrg-0907-wifi-mt76-mt7915-add-post-channel-switch-for-DFS-cha.patch b/package/kernel/mt76/patches/smartrg-0907-wifi-mt76-mt7915-add-post-channel-switch-for-DFS-cha.patch new file mode 100644 index 0000000000..b00b9cebc7 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0907-wifi-mt76-mt7915-add-post-channel-switch-for-DFS-cha.patch @@ -0,0 +1,49 @@ +From 38052cd0314deee3874609064a924e394b5e0115 Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Thu, 16 Nov 2023 14:41:54 +0800 +Subject: [PATCH 07/15] wifi: mt76: mt7915: add post channel switch for DFS + channel switching + +Signed-off-by: StanleyYP Wang +--- + mt7915/main.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -739,6 +739,27 @@ mt7915_channel_switch_beacon(struct ieee + mutex_unlock(&dev->mt76.mutex); + } + ++static int ++mt7915_post_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) ++{ ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct cfg80211_chan_def *chandef = &phy->mt76->chandef; ++ int ret; ++ ++ ret = cfg80211_chandef_dfs_required(hw->wiphy, chandef, NL80211_IFTYPE_AP); ++ if (ret <= 0) ++ goto out; ++ ++ ieee80211_stop_queues(hw); ++ ret = mt7915_set_channel(phy->mt76); ++ if (ret) ++ goto out; ++ ieee80211_wake_queues(hw); ++ ++out: ++ return ret; ++} ++ + int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +@@ -1846,6 +1867,7 @@ const struct ieee80211_ops mt7915_ops = + .get_txpower = mt76_get_txpower, + .set_sar_specs = mt7915_set_sar_specs, + .channel_switch_beacon = mt7915_channel_switch_beacon, ++ .post_channel_switch = mt7915_post_channel_switch, + .get_stats = mt7915_get_stats, + .get_et_sset_count = mt7915_get_et_sset_count, + .get_et_stats = mt7915_get_et_stats, diff --git a/package/kernel/mt76/patches/smartrg-0909-wifi-mt76-mt7915-remove-redundant-argument-in-add_be.patch b/package/kernel/mt76/patches/smartrg-0909-wifi-mt76-mt7915-remove-redundant-argument-in-add_be.patch new file mode 100644 index 0000000000..b3288c0b74 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0909-wifi-mt76-mt7915-remove-redundant-argument-in-add_be.patch @@ -0,0 +1,71 @@ +From 60da266641835e35733b8a3eb6c847c08673735c Mon Sep 17 00:00:00 2001 +From: MeiChia Chiu +Date: Wed, 24 Jan 2024 15:04:33 +0800 +Subject: [PATCH 09/15] wifi: mt76: mt7915: remove redundant argument in + add_beacon function + +Remove redundant argument "changed". + +Signed-off-by: MeiChia Chiu +--- + mt7915/mac.c | 3 +-- + mt7915/main.c | 4 ++-- + mt7915/mcu.c | 3 +-- + mt7915/mt7915.h | 2 +- + 4 files changed, 5 insertions(+), 7 deletions(-) + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1256,8 +1256,7 @@ mt7915_update_vif_beacon(void *priv, u8 + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: +- mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon, +- BSS_CHANGED_BEACON_ENABLED); ++ mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon); + break; + default: + break; +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -662,7 +662,7 @@ static void mt7915_bss_info_changed(stru + + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) +- mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); ++ mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); + + if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | + BSS_CHANGED_FILS_DISCOVERY)) +@@ -735,7 +735,7 @@ mt7915_channel_switch_beacon(struct ieee + struct mt7915_dev *dev = mt7915_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); +- mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON); ++ mt7915_mcu_add_beacon(hw, vif, true); + mutex_unlock(&dev->mt76.mutex); + } + +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -2082,8 +2082,7 @@ mt7915_mcu_add_inband_discov(struct mt79 + MCU_EXT_CMD(BSS_INFO_UPDATE), true); + } + +-int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- int en, u32 changed) ++int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en) + { + struct mt7915_dev *dev = mt7915_hw_dev(hw); + struct mt7915_phy *phy = mt7915_hw_phy(hw); +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -502,7 +502,7 @@ int mt7915_mcu_update_bss_color(struct m + int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif, + u32 changed); + int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +- int enable, u32 changed); ++ int enable); + int mt7915_mcu_set_protection(struct mt7915_phy *phy, struct ieee80211_vif *vif, + u8 ht_mode, bool use_cts_prot); + int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif, diff --git a/package/kernel/mt76/patches/smartrg-0917-wifi-mt76-mt7915-adjust-rx-filter.patch b/package/kernel/mt76/patches/smartrg-0917-wifi-mt76-mt7915-adjust-rx-filter.patch new file mode 100644 index 0000000000..53e8ee94ee --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0917-wifi-mt76-mt7915-adjust-rx-filter.patch @@ -0,0 +1,53 @@ +From b241c6831557c3141801dc2f87e839269ef7bad1 Mon Sep 17 00:00:00 2001 +From: Howard Hsu +Date: Fri, 19 Apr 2024 15:43:23 +0800 +Subject: [PATCH] wifi: mt76: mt7915: adjust rx filter + +Adjust rx filter setting to drop the packet that we do not need to +receive. + +Fixes: e57b7901469f ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets") +Signed-off-by: Howard Hsu +--- + mt7915/main.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -487,7 +487,8 @@ static int mt7915_config(struct ieee8021 + rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + dev->monitor_mask &= ~BIT(band); + } else { +- rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; ++ rxfilter &= ~(MT_WF_RFCR_DROP_A2_BSSID | ++ MT_WF_RFCR_DROP_OTHER_UC); + dev->monitor_mask |= BIT(band); + } + +@@ -550,13 +551,14 @@ static void mt7915_configure_filter(stru + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | +- MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); ++ phy->rxfilter |= MT_WF_RFCR_DROP_VERSION; + + MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | + MT_WF_RFCR_DROP_A3_MAC | +- MT_WF_RFCR_DROP_A3_BSSID); ++ MT_WF_RFCR_DROP_A3_BSSID | ++ MT_WF_RFCR_DROP_A2_BSSID); + + MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL); + +@@ -567,7 +569,8 @@ static void mt7915_configure_filter(stru + *total_flags = flags; + rxfilter = phy->rxfilter; + if (hw->conf.flags & IEEE80211_CONF_MONITOR) +- rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; ++ rxfilter &= ~(MT_WF_RFCR_DROP_A2_BSSID | ++ MT_WF_RFCR_DROP_OTHER_UC); + else + rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + mt76_wr(dev, MT_WF_RFCR(band), rxfilter); diff --git a/package/kernel/mt76/patches/smartrg-0918-wifi-mt76-mt7915-update-power-on-sequence.patch b/package/kernel/mt76/patches/smartrg-0918-wifi-mt76-mt7915-update-power-on-sequence.patch new file mode 100644 index 0000000000..a1b48c11b0 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-0918-wifi-mt76-mt7915-update-power-on-sequence.patch @@ -0,0 +1,134 @@ +From b8076a11b6051ed0fe1deb6c94e97bf80a13fbff Mon Sep 17 00:00:00 2001 +From: Peter Chiu +Date: Thu, 14 Mar 2024 17:55:12 +0800 +Subject: [PATCH] wifi: mt76: mt7915: update power on sequence + +Update power on sequence to prevent unexpected behavior. + +Signed-off-by: Peter Chiu + +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -346,6 +346,8 @@ struct mt7915_dev { + struct reset_control *rstc; + void __iomem *dcm; + void __iomem *sku; ++ ++ u32 adie_type; + }; + + enum { +--- a/mt7915/regs.h ++++ b/mt7915/regs.h +@@ -804,6 +804,7 @@ enum offs_rev { + #define MT_TOP_RGU_SYSRAM_PDN (MT_TOP_RGU_BASE + 0x050) + #define MT_TOP_RGU_SYSRAM_SLP (MT_TOP_RGU_BASE + 0x054) + #define MT_TOP_WFSYS_PWR (MT_TOP_RGU_BASE + 0x010) ++#define MT_TOP_BGFYS_PWR (MT_TOP_RGU_BASE + 0x020) + #define MT_TOP_PWR_EN_MASK BIT(7) + #define MT_TOP_PWR_ACK_MASK BIT(6) + #define MT_TOP_PWR_KEY_MASK GENMASK(31, 16) +@@ -915,6 +916,7 @@ enum offs_rev { + #define MT_ADIE_SLP_CTRL(_band, ofs) (MT_ADIE_SLP_CTRL_BASE(_band) + (ofs)) + + #define MT_ADIE_SLP_CTRL_CK0(_band) MT_ADIE_SLP_CTRL(_band, 0x120) ++#define MT_ADIE_SLP_CTRL_CK1(_band) MT_ADIE_SLP_CTRL(_band, 0x124) + + /* ADIE */ + #define MT_ADIE_CHIP_ID 0x02c +--- a/mt7915/soc.c ++++ b/mt7915/soc.c +@@ -260,6 +260,7 @@ static int mt7986_wmac_consys_lockup(str + MT_INFRACFG_TX_EN_MASK, + FIELD_PREP(MT_INFRACFG_TX_EN_MASK, enable)); + ++ usleep_range(1000, 2000); + return 0; + } + +@@ -844,6 +845,10 @@ static void mt7986_wmac_subsys_setting(s + MT_CONN_INFRA_OSC_STB_TIME_MASK, 0x80706); + + /* prevent subsys from power on/of in a short time interval */ ++ mt76_rmw(dev, MT_TOP_BGFYS_PWR, ++ MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK, ++ (0x42540000)); ++ + mt76_rmw(dev, MT_TOP_WFSYS_PWR, + MT_TOP_PWR_ACK_MASK | MT_TOP_PWR_KEY_MASK, + MT_TOP_PWR_KEY); +@@ -914,7 +919,7 @@ static void mt7986_wmac_clock_enable(str + + read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), + USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, +- dev, MT_ADIE_SLP_CTRL_CK0(0)); ++ dev, MT_ADIE_SLP_CTRL_CK0(1)); + } + mt76_wmac_spi_unlock(dev); + +@@ -1154,12 +1159,14 @@ int mt7986_wmac_enable(struct mt7915_dev + if (ret) + return ret; + ++ dev->adie_type = adie_type; ++ + return mt7986_wmac_sku_update(dev, adie_type); + } + + void mt7986_wmac_disable(struct mt7915_dev *dev) + { +- u32 cur; ++ u32 cur, i; + + mt7986_wmac_top_wfsys_wakeup(dev, true); + +@@ -1178,6 +1185,20 @@ void mt7986_wmac_disable(struct mt7915_d + mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_MCU_BPLL_CFG_MASK, 0x2); + mt76_rmw_field(dev, MT_AFE_DIG_EN_02(0), MT_AFE_WPLL_CFG_MASK, 0x2); + ++ /* Disable adie top clock */ ++ mt76_wmac_spi_lock(dev); ++ for (i = 0; i < 2; i++) { ++ if (is_7975(dev, i, dev->adie_type) || is_7976(dev, i, dev->adie_type)) { ++ mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK1(i), ++ MT_SLP_CTRL_EN_MASK, 0x0); ++ ++ read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), ++ USEC_PER_MSEC, 50 * USEC_PER_MSEC, ++ false, dev, MT_ADIE_SLP_CTRL_CK1(i)); ++ } ++ } ++ mt76_wmac_spi_unlock(dev); ++ + /* Reset EMI */ + mt76_rmw_field(dev, MT_CONN_INFRA_EMI_REQ, + MT_CONN_INFRA_EMI_REQ_MASK, 0x1); +@@ -1189,6 +1210,28 @@ void mt7986_wmac_disable(struct mt7915_d + MT_CONN_INFRA_INFRA_REQ_MASK, 0x0); + + mt7986_wmac_top_wfsys_wakeup(dev, false); ++ ++ mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP, ++ MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x1); ++ ++ usleep_range(1000, 1100); ++ ++ mt76_wmac_spi_lock(dev); ++ for (i = 0; i < 2; i++) { ++ if (is_7975(dev, i, dev->adie_type) || is_7976(dev, i, dev->adie_type)) { ++ mt76_rmw_field(dev, MT_ADIE_SLP_CTRL_CK0(i), ++ MT_SLP_CTRL_EN_MASK, 0x0); ++ ++ read_poll_timeout(mt76_rr, cur, !(cur & MT_SLP_CTRL_BSY_MASK), ++ USEC_PER_MSEC, 50 * USEC_PER_MSEC, ++ false, dev, MT_ADIE_SLP_CTRL_CK0(i)); ++ } ++ } ++ mt76_wmac_spi_unlock(dev); ++ ++ mt76_rmw(dev, MT_TOP_CONN_INFRA_WAKEUP, ++ MT_TOP_CONN_INFRA_WAKEUP_MASK, 0x0); ++ + mt7986_wmac_consys_lockup(dev, true); + mt7986_wmac_consys_reset(dev, false); + } diff --git a/package/kernel/mt76/patches/smartrg-1008-wifi-mt76-testmode-rework-testmode-init-registers.patch b/package/kernel/mt76/patches/smartrg-1008-wifi-mt76-testmode-rework-testmode-init-registers.patch new file mode 100644 index 0000000000..24d97d5fad --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1008-wifi-mt76-testmode-rework-testmode-init-registers.patch @@ -0,0 +1,455 @@ +From 88ebb3ad1cef268dd72f9e1892ef58bdb6b94a93 Mon Sep 17 00:00:00 2001 +From: Shayne Chen +Date: Mon, 6 Jun 2022 19:46:26 +0800 +Subject: [PATCH 20/76] wifi: mt76: testmode: rework testmode init registers + +--- + mac80211.c | 3 +- + mt76.h | 5 ++ + mt76_connac_mcu.h | 1 + + mt7915/mcu.h | 1 + + mt7915/mmio.c | 2 + + mt7915/regs.h | 16 +++++- + mt7915/testmode.c | 134 +++++++++++++++++++++++++++++++++++----------- + mt7915/testmode.h | 28 ++++++++++ + testmode.c | 6 ++- + testmode.h | 3 ++ + 10 files changed, 164 insertions(+), 35 deletions(-) + +--- a/mac80211.c ++++ b/mac80211.c +@@ -952,7 +952,8 @@ void mt76_rx(struct mt76_dev *dev, enum + } + + #ifdef CONFIG_NL80211_TESTMODE +- if (phy->test.state == MT76_TM_STATE_RX_FRAMES) { ++ if (!(phy->test.flag & MT_TM_FW_RX_COUNT) && ++ phy->test.state == MT76_TM_STATE_RX_FRAMES) { + phy->test.rx_stats.packets[q]++; + if (status->flag & RX_FLAG_FAILED_FCS_CRC) + phy->test.rx_stats.fcs_error[q]++; +--- a/mt76.h ++++ b/mt76.h +@@ -809,6 +809,8 @@ struct mt76_testmode_ops { + int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg); + }; + ++#define MT_TM_FW_RX_COUNT BIT(0) ++ + struct mt76_testmode_data { + enum mt76_testmode_state state; + +@@ -840,6 +842,8 @@ struct mt76_testmode_data { + + u8 addr[3][ETH_ALEN]; + ++ u8 flag; ++ + u32 tx_pending; + u32 tx_queued; + u16 tx_queued_limit; +@@ -847,6 +851,7 @@ struct mt76_testmode_data { + struct { + u64 packets[__MT_RXQ_MAX]; + u64 fcs_error[__MT_RXQ_MAX]; ++ u64 len_mismatch; + } rx_stats; + }; + +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1269,6 +1269,7 @@ enum { + MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a, + MCU_EXT_CMD_SET_RDD_TH = 0x9d, + MCU_EXT_CMD_MURU_CTRL = 0x9f, ++ MCU_EXT_CMD_RX_STAT = 0xa4, + MCU_EXT_CMD_SET_SPR = 0xa8, + MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab, + MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac, +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -9,6 +9,7 @@ + enum { + MCU_ATE_SET_TRX = 0x1, + MCU_ATE_SET_FREQ_OFFSET = 0xa, ++ MCU_ATE_SET_PHY_COUNT = 0x11, + MCU_ATE_SET_SLOT_TIME = 0x13, + MCU_ATE_CLEAN_TXQUEUE = 0x1c, + }; +--- a/mt7915/mmio.c ++++ b/mt7915/mmio.c +@@ -120,6 +120,7 @@ static const u32 mt7986_reg[] = { + }; + + static const u32 mt7915_offs[] = { ++ [TMAC_TCR2] = 0x05c, + [TMAC_CDTR] = 0x090, + [TMAC_ODTR] = 0x094, + [TMAC_ATCR] = 0x098, +@@ -197,6 +198,7 @@ static const u32 mt7915_offs[] = { + }; + + static const u32 mt7916_offs[] = { ++ [TMAC_TCR2] = 0x004, + [TMAC_CDTR] = 0x0c8, + [TMAC_ODTR] = 0x0cc, + [TMAC_ATCR] = 0x00c, +--- a/mt7915/regs.h ++++ b/mt7915/regs.h +@@ -48,6 +48,7 @@ enum reg_rev { + }; + + enum offs_rev { ++ TMAC_TCR2, + TMAC_CDTR, + TMAC_ODTR, + TMAC_ATCR, +@@ -225,6 +226,12 @@ enum offs_rev { + #define MT_TRB_RXPSR0_RX_WTBL_PTR GENMASK(25, 16) + #define MT_TRB_RXPSR0_RX_RMAC_PTR GENMASK(9, 0) + ++#define MT_MDP_TOP_DBG_WDT_CTRL MT_MDP(0x0d0) ++#define MT_MDP_TOP_DBG_WDT_CTRL_TDP_DIS_BLK BIT(7) ++ ++#define MT_MDP_TOP_DBG_CTRL MT_MDP(0x0dc) ++#define MT_MDP_TOP_DBG_CTRL_ENQ_MODE BIT(30) ++ + /* TMAC: band 0(0x820e4000), band 1(0x820f4000) */ + #define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000) + #define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) +@@ -233,6 +240,9 @@ enum offs_rev { + #define MT_TMAC_TCR0_TX_BLINK GENMASK(7, 6) + #define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25) + ++#define MT_TMAC_TCR2(_band) MT_WF_TMAC(_band, __OFFS(TMAC_TCR2)) ++#define MT_TMAC_TCR2_SCH_DET_DIS BIT(19) ++ + #define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, __OFFS(TMAC_CDTR)) + #define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, __OFFS(TMAC_ODTR)) + #define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) +@@ -515,8 +525,10 @@ enum offs_rev { + #define MT_AGG_PCR0_VHT_PROT BIT(13) + #define MT_AGG_PCR0_PTA_WIN_DIS BIT(15) + +-#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23) +-#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0) ++#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23) ++#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0) ++#define MT_AGG_PCR1_RTS0_NUM_THRES_MT7916 GENMASK(29, 24) ++#define MT_AGG_PCR1_RTS0_LEN_THRES_MT7916 GENMASK(22, 0) + + #define MT_AGG_ACR0(_band) MT_WF_AGG(_band, __OFFS(AGG_ACR0)) + #define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) +--- a/mt7915/testmode.c ++++ b/mt7915/testmode.c +@@ -30,7 +30,7 @@ struct reg_band { + { _list.band[0] = MT_##_reg(0, _idx); \ + _list.band[1] = MT_##_reg(1, _idx); } + +-#define TM_REG_MAX_ID 17 ++#define TM_REG_MAX_ID 20 + static struct reg_band reg_backup_list[TM_REG_MAX_ID]; + + +@@ -134,6 +134,21 @@ mt7915_tm_clean_hwq(struct mt7915_phy *p + } + + static int ++mt7915_tm_set_phy_count(struct mt7915_phy *phy, u8 control) ++{ ++ struct mt7915_dev *dev = phy->dev; ++ struct mt7915_tm_cmd req = { ++ .testmode_en = 1, ++ .param_idx = MCU_ATE_SET_PHY_COUNT, ++ .param.cfg.enable = control, ++ .param.cfg.band = phy != &dev->phy, ++ }; ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req, ++ sizeof(req), false); ++} ++ ++static int + mt7915_tm_set_slot_time(struct mt7915_phy *phy, u8 slot_time, u8 sifs) + { + struct mt7915_dev *dev = phy->dev; +@@ -336,7 +351,7 @@ mt7915_tm_reg_backup_restore(struct mt79 + { + int n_regs = ARRAY_SIZE(reg_backup_list); + struct mt7915_dev *dev = phy->dev; +- u32 *b = phy->test.reg_backup; ++ u32 *b = phy->test.reg_backup, val; + u8 band = phy->mt76->band_idx; + int i; + +@@ -349,18 +364,28 @@ mt7915_tm_reg_backup_restore(struct mt79 + REG_BAND(reg_backup_list[6], AGG_MRCR); + REG_BAND(reg_backup_list[7], TMAC_TFCR0); + REG_BAND(reg_backup_list[8], TMAC_TCR0); +- REG_BAND(reg_backup_list[9], AGG_ATCR1); +- REG_BAND(reg_backup_list[10], AGG_ATCR3); +- REG_BAND(reg_backup_list[11], TMAC_TRCR0); +- REG_BAND(reg_backup_list[12], TMAC_ICR0); +- REG_BAND_IDX(reg_backup_list[13], ARB_DRNGR0, 0); +- REG_BAND_IDX(reg_backup_list[14], ARB_DRNGR0, 1); +- REG_BAND(reg_backup_list[15], WF_RFCR); +- REG_BAND(reg_backup_list[16], WF_RFCR1); ++ REG_BAND(reg_backup_list[9], TMAC_TCR2); ++ REG_BAND(reg_backup_list[10], AGG_ATCR1); ++ REG_BAND(reg_backup_list[11], AGG_ATCR3); ++ REG_BAND(reg_backup_list[12], TMAC_TRCR0); ++ REG_BAND(reg_backup_list[13], TMAC_ICR0); ++ REG_BAND_IDX(reg_backup_list[14], ARB_DRNGR0, 0); ++ REG_BAND_IDX(reg_backup_list[15], ARB_DRNGR0, 1); ++ REG_BAND(reg_backup_list[16], WF_RFCR); ++ REG_BAND(reg_backup_list[17], WF_RFCR1); ++ ++ if (is_mt7916(&dev->mt76)) { ++ reg_backup_list[18].band[band] = MT_MDP_TOP_DBG_WDT_CTRL; ++ reg_backup_list[19].band[band] = MT_MDP_TOP_DBG_CTRL; ++ } + + if (phy->mt76->test.state == MT76_TM_STATE_OFF) { +- for (i = 0; i < n_regs; i++) +- mt76_wr(dev, reg_backup_list[i].band[band], b[i]); ++ for (i = 0; i < n_regs; i++) { ++ u8 reg = reg_backup_list[i].band[band]; ++ ++ if (reg) ++ mt76_wr(dev, reg, b[i]); ++ } + return; + } + +@@ -380,8 +405,13 @@ mt7915_tm_reg_backup_restore(struct mt79 + MT_AGG_PCR0_BW40_PROT | MT_AGG_PCR0_BW80_PROT); + mt76_set(dev, MT_AGG_PCR0(band, 0), MT_AGG_PCR0_PTA_WIN_DIS); + +- mt76_wr(dev, MT_AGG_PCR0(band, 1), MT_AGG_PCR1_RTS0_NUM_THRES | +- MT_AGG_PCR1_RTS0_LEN_THRES); ++ if (is_mt7915(&dev->mt76)) ++ val = MT_AGG_PCR1_RTS0_NUM_THRES | MT_AGG_PCR1_RTS0_LEN_THRES; ++ else ++ val = MT_AGG_PCR1_RTS0_NUM_THRES_MT7916 | ++ MT_AGG_PCR1_RTS0_LEN_THRES_MT7916; ++ ++ mt76_wr(dev, MT_AGG_PCR0(band, 1), val); + + mt76_clear(dev, MT_AGG_MRCR(band), MT_AGG_MRCR_BAR_CNT_LIMIT | + MT_AGG_MRCR_LAST_RTS_CTS_RN | MT_AGG_MRCR_RTS_FAIL_LIMIT | +@@ -394,10 +424,19 @@ mt7915_tm_reg_backup_restore(struct mt79 + + mt76_wr(dev, MT_TMAC_TFCR0(band), 0); + mt76_clear(dev, MT_TMAC_TCR0(band), MT_TMAC_TCR0_TBTT_STOP_CTRL); ++ mt76_set(dev, MT_TMAC_TCR2(band), MT_TMAC_TCR2_SCH_DET_DIS); + + /* config rx filter for testmode rx */ + mt76_wr(dev, MT_WF_RFCR(band), 0xcf70a); + mt76_wr(dev, MT_WF_RFCR1(band), 0); ++ ++ if (is_mt7916(&dev->mt76)) { ++ /* enable MDP Tx block mode */ ++ mt76_clear(dev, MT_MDP_TOP_DBG_WDT_CTRL, ++ MT_MDP_TOP_DBG_WDT_CTRL_TDP_DIS_BLK); ++ mt76_clear(dev, MT_MDP_TOP_DBG_CTRL, ++ MT_MDP_TOP_DBG_CTRL_ENQ_MODE); ++ } + } + + static void +@@ -419,6 +458,8 @@ mt7915_tm_init(struct mt7915_phy *phy, b + state = en ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT; + mt7915_mcu_add_sta(dev, phy->monitor_vif, NULL, state, true); + ++ phy->mt76->test.flag |= MT_TM_FW_RX_COUNT; ++ + if (!en) + mt7915_tm_set_tam_arb(phy, en, 0); + } +@@ -481,18 +522,63 @@ mt7915_tm_set_tx_frames(struct mt7915_ph + mt7915_tm_set_trx(phy, TM_MAC_TX, en); + } + ++static int ++mt7915_tm_get_rx_stats(struct mt7915_phy *phy, bool clear) ++{ ++#define CMD_RX_STAT_BAND 0x3 ++ struct mt76_testmode_data *td = &phy->mt76->test; ++ struct mt7915_tm_rx_stat_band *rs_band; ++ struct mt7915_dev *dev = phy->dev; ++ struct sk_buff *skb; ++ struct { ++ u8 format_id; ++ u8 band; ++ u8 _rsv[2]; ++ } __packed req = { ++ .format_id = CMD_RX_STAT_BAND, ++ .band = phy->mt76->band_idx, ++ }; ++ int ret; ++ ++ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(RX_STAT), ++ &req, sizeof(req), true, &skb); ++ if (ret) ++ return ret; ++ ++ rs_band = (struct mt7915_tm_rx_stat_band *)skb->data; ++ /* pr_info("mdrdy_cnt = %d\n", le32_to_cpu(rs_band->mdrdy_cnt)); */ ++ /* pr_info("fcs_err = %d\n", le16_to_cpu(rs_band->fcs_err)); */ ++ /* pr_info("len_mismatch = %d\n", le16_to_cpu(rs_band->len_mismatch)); */ ++ /* pr_info("fcs_ok = %d\n", le16_to_cpu(rs_band->fcs_succ)); */ ++ ++ if (!clear) { ++ enum mt76_rxq_id q = req.band ? MT_RXQ_BAND1 : MT_RXQ_MAIN; ++ ++ td->rx_stats.packets[q] += le32_to_cpu(rs_band->mdrdy_cnt); ++ td->rx_stats.fcs_error[q] += le16_to_cpu(rs_band->fcs_err); ++ td->rx_stats.len_mismatch += le16_to_cpu(rs_band->len_mismatch); ++ } ++ ++ dev_kfree_skb(skb); ++ ++ return 0; ++} ++ + static void + mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en) + { + mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false); + + if (en) { +- struct mt7915_dev *dev = phy->dev; +- + mt7915_tm_update_channel(phy); + + /* read-clear */ +- mt76_rr(dev, MT_MIB_SDR3(phy->mt76->band_idx)); ++ mt7915_tm_get_rx_stats(phy, true); ++ ++ /* clear fw count */ ++ mt7915_tm_set_phy_count(phy, 0); ++ mt7915_tm_set_phy_count(phy, 1); ++ + mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en); + } + } +@@ -723,12 +809,8 @@ static int + mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg) + { + struct mt7915_phy *phy = mphy->priv; +- struct mt7915_dev *dev = phy->dev; +- enum mt76_rxq_id q; + void *rx, *rssi; +- u16 fcs_err; + int i; +- u32 cnt; + + rx = nla_nest_start(msg, MT76_TM_STATS_ATTR_LAST_RX); + if (!rx) +@@ -772,15 +854,7 @@ mt7915_tm_dump_stats(struct mt76_phy *mp + + nla_nest_end(msg, rx); + +- cnt = mt76_rr(dev, MT_MIB_SDR3(phy->mt76->band_idx)); +- fcs_err = is_mt7915(&dev->mt76) ? FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK, cnt) : +- FIELD_GET(MT_MIB_SDR3_FCS_ERR_MASK_MT7916, cnt); +- +- q = phy->mt76->band_idx ? MT_RXQ_BAND1 : MT_RXQ_MAIN; +- mphy->test.rx_stats.packets[q] += fcs_err; +- mphy->test.rx_stats.fcs_error[q] += fcs_err; +- +- return 0; ++ return mt7915_tm_get_rx_stats(phy, false); + } + + const struct mt76_testmode_ops mt7915_testmode_ops = { +--- a/mt7915/testmode.h ++++ b/mt7915/testmode.h +@@ -33,6 +33,12 @@ struct mt7915_tm_clean_txq { + u8 rsv; + }; + ++struct mt7915_tm_cfg { ++ u8 enable; ++ u8 band; ++ u8 _rsv[2]; ++}; ++ + struct mt7915_tm_cmd { + u8 testmode_en; + u8 param_idx; +@@ -43,6 +49,7 @@ struct mt7915_tm_cmd { + struct mt7915_tm_freq_offset freq; + struct mt7915_tm_slot_time slot; + struct mt7915_tm_clean_txq clean; ++ struct mt7915_tm_cfg cfg; + u8 test[72]; + } param; + } __packed; +@@ -102,4 +109,25 @@ enum { + TAM_ARB_OP_MODE_FORCE_SU = 5, + }; + ++struct mt7915_tm_rx_stat_band { ++ u8 category; ++ ++ /* mac */ ++ __le16 fcs_err; ++ __le16 len_mismatch; ++ __le16 fcs_succ; ++ __le32 mdrdy_cnt; ++ /* phy */ ++ __le16 fcs_err_cck; ++ __le16 fcs_err_ofdm; ++ __le16 pd_cck; ++ __le16 pd_ofdm; ++ __le16 sig_err_cck; ++ __le16 sfd_err_cck; ++ __le16 sig_err_ofdm; ++ __le16 tag_err_ofdm; ++ __le16 mdrdy_cnt_cck; ++ __le16 mdrdy_cnt_ofdm; ++}; ++ + #endif +--- a/testmode.c ++++ b/testmode.c +@@ -448,8 +448,7 @@ int mt76_testmode_cmd(struct ieee80211_h + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_LDPC], &td->tx_rate_ldpc, 0, 1) || + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_STBC], &td->tx_rate_stbc, 0, 1) || + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_LTF], &td->tx_ltf, 0, 2) || +- mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], +- &td->tx_antenna_mask, 0, 0xff) || ++ mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask, 1, 0xff) || + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_SPE_IDX], &td->tx_spe_idx, 0, 27) || + mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE], + &td->tx_duty_cycle, 0, 99) || +@@ -561,6 +560,9 @@ mt76_testmode_dump_stats(struct mt76_phy + nla_put_u64_64bit(msg, MT76_TM_STATS_ATTR_RX_PACKETS, rx_packets, + MT76_TM_STATS_ATTR_PAD) || + nla_put_u64_64bit(msg, MT76_TM_STATS_ATTR_RX_FCS_ERROR, rx_fcs_error, ++ MT76_TM_STATS_ATTR_PAD) || ++ nla_put_u64_64bit(msg, MT76_TM_STATS_ATTR_RX_LEN_MISMATCH, ++ td->rx_stats.len_mismatch, + MT76_TM_STATS_ATTR_PAD)) + return -EMSGSIZE; + +--- a/testmode.h ++++ b/testmode.h +@@ -101,6 +101,8 @@ enum mt76_testmode_attr { + * @MT76_TM_STATS_ATTR_RX_FCS_ERROR: number of rx packets with FCS error (u64) + * @MT76_TM_STATS_ATTR_LAST_RX: information about the last received packet + * see &enum mt76_testmode_rx_attr ++ * @MT76_TM_STATS_ATTR_RX_LEN_MISMATCH: number of rx packets with length ++ * mismatch error (u64) + */ + enum mt76_testmode_stats_attr { + MT76_TM_STATS_ATTR_UNSPEC, +@@ -113,6 +115,7 @@ enum mt76_testmode_stats_attr { + MT76_TM_STATS_ATTR_RX_PACKETS, + MT76_TM_STATS_ATTR_RX_FCS_ERROR, + MT76_TM_STATS_ATTR_LAST_RX, ++ MT76_TM_STATS_ATTR_RX_LEN_MISMATCH, + + /* keep last */ + NUM_MT76_TM_STATS_ATTRS, diff --git a/package/kernel/mt76/patches/smartrg-1016-wifi-mt76-mt7915-refine-twt-mcu-update-flow.patch b/package/kernel/mt76/patches/smartrg-1016-wifi-mt76-mt7915-refine-twt-mcu-update-flow.patch new file mode 100644 index 0000000000..b66f515319 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1016-wifi-mt76-mt7915-refine-twt-mcu-update-flow.patch @@ -0,0 +1,85 @@ +From 174faa97cf0fdc8f26e4b8c13fd3c4b8d19ced15 Mon Sep 17 00:00:00 2001 +From: Yi-Chia Hsieh +Date: Wed, 9 Oct 2024 23:13:29 +0000 +Subject: [PATCH] wifi: mt76: mt7915: refine twt mcu update flow + +Fix potential issue that if the twt mcu update command fail, the twt_list entry +is not undo and will remain in the list. Also, remove unecessary parameter for +twt delete flow. + +Signed-off-by: Yi-Chia Hsieh +--- + mt7915/debugfs.c | 4 ++-- + mt7915/mac.c | 4 +++- + mt7915/mcu.c | 22 ++++++++++++---------- + 3 files changed, 17 insertions(+), 13 deletions(-) + +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -1244,7 +1244,7 @@ mt7915_twt_stats(struct seq_file *s, voi + struct mt7915_dev *dev = dev_get_drvdata(s->private); + struct mt7915_twt_flow *iter; + +- rcu_read_lock(); ++ mutex_lock(&dev->mt76.mutex); + + seq_puts(s, " wcid | id | flags | exp | mantissa"); + seq_puts(s, " | duration | tsf |\n"); +@@ -1259,7 +1259,7 @@ mt7915_twt_stats(struct seq_file *s, voi + iter->exp, iter->mantissa, + iter->duration, iter->tsf); + +- rcu_read_unlock(); ++ mutex_unlock(&dev->mt76.mutex); + + return 0; + } +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -2530,8 +2530,10 @@ void mt7915_mac_add_twt_setup(struct iee + } + flow->tsf = le64_to_cpu(twt_agrt->twt); + +- if (mt7915_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD)) ++ if (mt7915_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD)) { ++ list_del(&flow->list); + goto unlock; ++ } + + setup_cmd = TWT_SETUP_CMD_ACCEPT; + dev->twt.table_mask |= BIT(table_id); +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -4307,20 +4307,22 @@ int mt7915_mcu_twt_agrt_update(struct mt + .own_mac_idx = mvif->mt76.omac_idx, + .flowid = flow->id, + .peer_id = cpu_to_le16(flow->wcid), +- .duration = flow->duration, + .bss_idx = mvif->mt76.idx, +- .start_tsf = cpu_to_le64(flow->tsf), +- .mantissa = flow->mantissa, +- .exponent = flow->exp, + .is_ap = true, + }; + +- if (flow->protection) +- req.agrt_params |= TWT_AGRT_PROTECT; +- if (!flow->flowtype) +- req.agrt_params |= TWT_AGRT_ANNOUNCE; +- if (flow->trigger) +- req.agrt_params |= TWT_AGRT_TRIGGER; ++ if (cmd == MCU_TWT_AGRT_ADD) { ++ req.start_tsf = cpu_to_le64(flow->tsf); ++ req.mantissa = flow->mantissa; ++ req.exponent = flow->exp; ++ req.duration = flow->duration; ++ if (flow->protection) ++ req.agrt_params |= TWT_AGRT_PROTECT; ++ if (!flow->flowtype) ++ req.agrt_params |= TWT_AGRT_ANNOUNCE; ++ if (flow->trigger) ++ req.agrt_params |= TWT_AGRT_TRIGGER; ++ } + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TWT_AGRT_UPDATE), + &req, sizeof(req), true); diff --git a/package/kernel/mt76/patches/smartrg-1023-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch b/package/kernel/mt76/patches/smartrg-1023-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch new file mode 100644 index 0000000000..07c2d37e36 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1023-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch @@ -0,0 +1,260 @@ +From 2b1ca7b7f8e5c65abd254b51a7a79418457684ea Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Thu, 30 Mar 2023 15:12:37 +0800 +Subject: [PATCH 35/76] wifi: mt76: mt7915: add cal free data merge support + +1. add basic cal free data support +2. add E3 low yield rate workaround for panther E3 with 7976 adie +3. add Harrier freq offset workaround + +Signed-off-by: StanleyYP Wang +--- + mt7915/eeprom.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/mcu.c | 13 ++-- + mt7915/mt7915.h | 1 + + 3 files changed, 198 insertions(+), 4 deletions(-) + +--- a/mt7915/eeprom.c ++++ b/mt7915/eeprom.c +@@ -306,6 +306,190 @@ void mt7915_eeprom_parse_hw_cap(struct m + dev->chainshift = hweight8(dev->mphy.chainmask); + } + ++static int mt7915_apply_cal_free_data(struct mt7915_dev *dev) ++{ ++#define MT_EE_CAL_FREE_MAX_SIZE 70 ++#define MT_EE_FREQ_OFFSET 0x77 ++#define MT_EE_ADIE1_MT7976C_OFFSET 0x270 ++#define MT_EE_ADIE1_E3_OFFSET 0x271 ++#define MT_EE_END_OFFSET 0xffff ++#define MT_EE_ADIE1_BASE_7896 0x1000 ++ enum adie_type { ++ ADIE_7975, ++ ADIE_7976, ++ }; ++ enum ddie_type { ++ DDIE_7915, ++ DDIE_7916, ++ }; ++ static const u16 ddie_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = { ++ [DDIE_7915] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, ++ 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23, 0x24, ++ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, ++ 0x52, 0x70, 0x71, 0x72, 0x76, 0xa8, 0xa9, 0xaa, 0xab, 0xac, ++ 0xad, 0xae, 0xaf, -1}, ++ [DDIE_7916] = {0x30, 0x31, 0x34, 0x35, 0x36, 0x38, 0x3c, 0x3a, 0x3d, 0x44, ++ 0x46, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xe0, -1}, ++ }; ++ static const u16 adie_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = { ++ [ADIE_7975] = {0x7cd, 0x7cf, 0x7d1, 0x7d3, 0x802, 0x803, 0x804, 0x805, 0x806, ++ 0x808, 0x80a, 0x80b, 0x80c, 0x80d, 0x80e, 0x810, 0x812, 0x813, ++ 0x814, 0x815, 0x816, 0x818, 0x81a, 0x81b, 0x81c, 0x81d, 0x81e, ++ 0x820, 0x822, 0x823, 0x824, 0x825, 0x826, 0x827, 0x828, 0x829, ++ 0x82f, 0x8c0, 0x8c1, 0x8c2, 0x8c3, 0x9a0, 0x8d0, 0x8d1, 0x8d7, ++ 0x8d8, 0x8fa, 0x9a1, 0x9a5, 0x9a6, 0x9a8, 0x9aa, 0x9b0, 0x9b1, ++ 0x9b2, 0x9b3, 0x9b4, 0x9b5, 0x9b6, 0x9b7, -1}, ++ [ADIE_7976] = {0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x253, 0x255, 0x257, ++ 0x259, 0x990, 0x991, 0x994, 0x995, 0x9a6, 0x9a8, 0x9aa, -1}, ++ }; ++ static const u16 eep_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = { ++ [ADIE_7975] = {0xe00, 0xe01, 0xe02, 0xe03, 0xe04, 0xe05, 0xe06, 0xe07, 0xe08, ++ 0xe09, 0xe0a, 0xe0b, 0xe0c, 0xe0d, 0x80e, 0xe0f, 0xe10, 0xe11, ++ 0xe12, 0xe13, 0xe14, 0xe15, 0xe16, 0xe17, 0xe18, 0xe19, 0xe1a, ++ 0xe1b, 0xe1c, 0xe1d, 0xe1e, 0xe1f, 0xe20, 0xe21, 0xe22, 0xe23, ++ 0xe24, 0xe25, 0xe26, 0xe27, 0xe28, 0xe29, 0xe2a, 0xe2b, 0xe2c, ++ 0xe2d, 0xe2e, 0xe2f, 0xe33, 0xe34, 0xe36, 0xe38, 0xe39, 0xe3a, ++ 0xe3b, 0xe3c, 0xe3d, 0xe3e, 0xe3f, 0xe40, -1}, ++ [ADIE_7976] = {0x33c, 0x33d, 0x33e, 0x33f, 0x340, 0x341, 0x343, 0x345, 0x347, ++ 0x349, 0x359, 0x35a, 0x35d, 0x35e, 0x36a, 0x36c, 0x36e, -1}, ++ }; ++ static const u16 *ddie_offs; ++ static const u16 *adie_offs[__MT_MAX_BAND]; ++ static const u16 *eep_offs[__MT_MAX_BAND]; ++ static u16 adie_base[__MT_MAX_BAND] = {0}; ++ u8 *eeprom = dev->mt76.eeprom.data; ++ u8 buf[MT7915_EEPROM_BLOCK_SIZE]; ++ int adie_id, band, i, ret; ++ ++ switch (mt76_chip(&dev->mt76)) { ++ case 0x7915: ++ ddie_offs = ddie_offs_list[DDIE_7915]; ++ ret = mt7915_mcu_get_eeprom(dev, MT_EE_ADIE_FT_VERSION, buf); ++ if (ret) ++ return ret; ++ adie_id = buf[MT_EE_ADIE_FT_VERSION % MT7915_EEPROM_BLOCK_SIZE] - 1; ++ adie_offs[0] = adie_offs_list[ADIE_7975]; ++ /* same as adie offset */ ++ eep_offs[0] = NULL; ++ break; ++ case 0x7906: ++ case 0x7981: ++ if (is_mt7916(&dev->mt76)) ++ ddie_offs = ddie_offs_list[DDIE_7916]; ++ adie_offs[0] = adie_offs_list[ADIE_7976]; ++ eep_offs[0] = NULL; ++ break; ++ case 0x7986: ++ adie_id = mt7915_check_adie(dev, true); ++ switch (adie_id) { ++ case MT7975_ONE_ADIE: ++ case MT7975_DUAL_ADIE: ++ adie_offs[0] = adie_offs_list[ADIE_7975]; ++ eep_offs[0] = NULL; ++ if (adie_id == MT7975_DUAL_ADIE) { ++ adie_offs[1] = adie_offs_list[ADIE_7975]; ++ eep_offs[1] = eep_offs_list[ADIE_7975]; ++ } ++ break; ++ case MT7976_ONE_ADIE_DBDC: ++ case MT7976_ONE_ADIE: ++ case MT7976_DUAL_ADIE: { ++ u16 base = 0, offset = MT_EE_ADIE1_MT7976C_OFFSET; ++ ++ adie_offs[0] = adie_offs_list[ADIE_7976]; ++ eep_offs[0] = NULL; ++ if (adie_id == MT7976_DUAL_ADIE) { ++ adie_offs[1] = adie_offs_list[ADIE_7976]; ++ eep_offs[1] = eep_offs_list[ADIE_7976]; ++ base = MT_EE_ADIE1_BASE_7896; ++ } ++ ++ /* E3 re-bonding workaround */ ++ ret = mt7915_mcu_get_eeprom(dev, offset + base, buf); ++ if (ret) ++ break; ++ offset = (offset + base) % MT7915_EEPROM_BLOCK_SIZE; ++ eeprom[MT_EE_ADIE1_MT7976C_OFFSET] = buf[offset]; ++ offset = (MT_EE_ADIE1_E3_OFFSET + base) % MT7915_EEPROM_BLOCK_SIZE; ++ eeprom[MT_EE_ADIE1_E3_OFFSET] = buf[offset]; ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ adie_base[1] = MT_EE_ADIE1_BASE_7896; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* ddie */ ++ if (ddie_offs) { ++ u16 ddie_offset; ++ u32 block_num, prev_block_num = -1; ++ ++ for (i = 0; i < MT_EE_CAL_FREE_MAX_SIZE; i++) { ++ ddie_offset = ddie_offs[i]; ++ block_num = ddie_offset / MT7915_EEPROM_BLOCK_SIZE; ++ ++ if (ddie_offset == MT_EE_END_OFFSET) ++ break; ++ ++ if (prev_block_num != block_num) { ++ ret = mt7915_mcu_get_eeprom(dev, ddie_offset, buf); ++ if (ret) { ++ prev_block_num = -1; ++ continue; ++ } ++ } ++ ++ eeprom[ddie_offset] = buf[ddie_offset % MT7915_EEPROM_BLOCK_SIZE]; ++ prev_block_num = block_num; ++ } ++ } ++ ++ /* adie */ ++ for (band = 0; band < __MT_MAX_BAND; band++) { ++ u16 adie_offset, eep_offset; ++ u32 block_num, prev_block_num = -1; ++ ++ if (!adie_offs[band]) ++ continue; ++ ++ for (i = 0; i < MT_EE_CAL_FREE_MAX_SIZE; i++) { ++ adie_offset = adie_offs[band][i] + adie_base[band]; ++ eep_offset = adie_offset; ++ if (eep_offs[band]) ++ eep_offset = eep_offs[band][i]; ++ block_num = adie_offset / MT7915_EEPROM_BLOCK_SIZE; ++ ++ if (adie_offs[band][i] == MT_EE_END_OFFSET) ++ break; ++ ++ if (is_mt7915(&dev->mt76) && !adie_id && ++ adie_offset >= 0x8c0 && adie_offset <= 0x8c3) ++ continue; ++ ++ if (prev_block_num != block_num) { ++ ret = mt7915_mcu_get_eeprom(dev, adie_offset, buf); ++ if (ret) { ++ prev_block_num = -1; ++ continue; ++ } ++ } ++ ++ eeprom[eep_offset] = buf[adie_offset % MT7915_EEPROM_BLOCK_SIZE]; ++ prev_block_num = block_num; ++ ++ /* workaround for Harrier */ ++ if (is_mt7915(&dev->mt76) && adie_offset == 0x9a1) ++ eeprom[MT_EE_FREQ_OFFSET] = eeprom[adie_offset]; ++ } ++ } ++ ++ return 0; ++} ++ + int mt7915_eeprom_init(struct mt7915_dev *dev) + { + int ret; +@@ -322,6 +506,11 @@ int mt7915_eeprom_init(struct mt7915_dev + } + + mt7915_eeprom_load_precal(dev); ++ ++ ret = mt7915_apply_cal_free_data(dev); ++ if (ret) ++ return ret; ++ + mt7915_eeprom_parse_hw_cap(dev, &dev->phy); + memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + ETH_ALEN); +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -2963,6 +2963,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_ + struct mt7915_mcu_eeprom_info *res; + struct sk_buff *skb; + u8 *buf = read_buf; ++ bool valid; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, +@@ -2972,9 +2973,15 @@ int mt7915_mcu_get_eeprom(struct mt7915_ + return ret; + + res = (struct mt7915_mcu_eeprom_info *)skb->data; +- if (!buf) +- buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); +- memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE); ++ valid = !!le32_to_cpu(res->valid); ++ ++ if (valid) { ++ if (!buf) ++ buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr); ++ memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE); ++ } else { ++ ret = -EINVAL; ++ }; + + dev_kfree_skb(skb); + +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -456,6 +456,7 @@ u32 mt7915_wed_init_buf(void *ptr, dma_a + + int mt7915_register_device(struct mt7915_dev *dev); + void mt7915_unregister_device(struct mt7915_dev *dev); ++void mt7915_eeprom_rebonding(struct mt7915_dev *dev); + int mt7915_eeprom_init(struct mt7915_dev *dev); + void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, + struct mt7915_phy *phy); diff --git a/package/kernel/mt76/patches/smartrg-1031-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch b/package/kernel/mt76/patches/smartrg-1031-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch new file mode 100644 index 0000000000..11edb35450 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1031-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch @@ -0,0 +1,162 @@ +From ace56f2c1ee008bcab3191494d7ed92538e50339 Mon Sep 17 00:00:00 2001 +From: Bo Jiao +Date: Mon, 22 May 2023 15:30:21 +0800 +Subject: [PATCH 43/76] wifi: mt76: mt7915: add debugfs for fw coredump. + +Signed-off-by: Bo Jiao +--- + mt7915/debugfs.c | 22 +++++++++++++++++----- + mt7915/mac.c | 30 +++++++++++++++++++++++++++--- + mt7915/mcu.h | 6 +++++- + mt7915/mt7915.h | 9 +++++++++ + 4 files changed, 58 insertions(+), 9 deletions(-) + +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -79,8 +79,10 @@ mt7915_sys_recovery_set(struct file *fil + * 4: trigger & enable system error L3 tx abort + * 5: trigger & enable system error L3 tx disable. + * 6: trigger & enable system error L3 bf recovery. +- * 7: trigger & enable system error full recovery. +- * 8: trigger firmware crash. ++ * 8: trigger & enable system error full recovery. ++ * 9: trigger firmware crash. ++ * 10: trigger grab wa firmware coredump. ++ * 11: trigger grab wm firmware coredump. + */ + case SER_QUERY: + ret = mt7915_mcu_set_ser(dev, 0, 0, band); +@@ -105,7 +107,7 @@ mt7915_sys_recovery_set(struct file *fil + if (ret) + return ret; + +- dev->recovery.state |= MT_MCU_CMD_WDT_MASK; ++ dev->recovery.state |= MT_MCU_CMD_WM_WDT; + mt7915_reset(dev); + break; + +@@ -114,6 +116,12 @@ mt7915_sys_recovery_set(struct file *fil + mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR, BIT(18)); + mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_SOFT_ADDR, BIT(18)); + break; ++ ++ case SER_SET_FW_COREDUMP_WA: ++ mt7915_coredump(dev, MT7915_COREDUMP_MANUAL_WA); ++ break; ++ case SER_SET_FW_COREDUMP_WM: ++ mt7915_coredump(dev, MT7915_COREDUMP_MANUAL_WM); + default: + break; + } +@@ -154,9 +162,13 @@ mt7915_sys_recovery_get(struct file *fil + desc += scnprintf(buff + desc, bufsz - desc, + "6: trigger system error L3 bf recovery\n"); + desc += scnprintf(buff + desc, bufsz - desc, +- "7: trigger system error full recovery\n"); ++ "8: trigger system error full recovery\n"); ++ desc += scnprintf(buff + desc, bufsz - desc, ++ "9: trigger firmware crash\n"); ++ desc += scnprintf(buff + desc, bufsz - desc, ++ "10: trigger grab wa firmware coredump\n"); + desc += scnprintf(buff + desc, bufsz - desc, +- "8: trigger firmware crash\n"); ++ "11: trigger grab wm firmware coredump\n"); + + /* SER statistics */ + desc += scnprintf(buff + desc, bufsz - desc, +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1667,10 +1667,34 @@ void mt7915_mac_dump_work(struct work_st + + dev = container_of(work, struct mt7915_dev, dump_work); + +- if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WM_WDT) ++ if (dev->dump_state == MT7915_COREDUMP_MANUAL_WA || ++ READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT) ++ mt7915_mac_fw_coredump(dev, MT76_RAM_TYPE_WA); ++ ++ if (dev->dump_state == MT7915_COREDUMP_MANUAL_WM || ++ READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WM_WDT) + mt7915_mac_fw_coredump(dev, MT76_RAM_TYPE_WM); + +- queue_work(dev->mt76.wq, &dev->reset_work); ++ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) ++ queue_work(dev->mt76.wq, &dev->reset_work); ++ ++ dev->dump_state = MT7915_COREDUMP_IDLE; ++} ++ ++void mt7915_coredump(struct mt7915_dev *dev, u8 state) ++{ ++ if (state == MT7915_COREDUMP_IDLE || ++ state > MT7915_COREDUMP_AUTO) ++ return; ++ ++ if (dev->dump_state != MT7915_COREDUMP_IDLE) ++ return; ++ ++ dev->dump_state = state; ++ dev_info(dev->mt76.dev, "%s attempting grab coredump\n", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ ++ queue_work(dev->mt76.wq, &dev->dump_work); + } + + void mt7915_reset(struct mt7915_dev *dev) +@@ -1689,7 +1713,7 @@ void mt7915_reset(struct mt7915_dev *dev + wiphy_name(dev->mt76.hw->wiphy)); + + mt7915_irq_disable(dev, MT_INT_MCU_CMD); +- queue_work(dev->mt76.wq, &dev->dump_work); ++ mt7915_coredump(dev, MT7915_COREDUMP_AUTO); + return; + } + +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -571,8 +571,12 @@ enum { + SER_SET_RECOVER_L3_TX_ABORT, + SER_SET_RECOVER_L3_TX_DISABLE, + SER_SET_RECOVER_L3_BF, +- SER_SET_RECOVER_FULL, ++ SER_SET_RECOVER_FULL = 8, ++ /* fw assert */ + SER_SET_SYSTEM_ASSERT, ++ /* coredump */ ++ SER_SET_FW_COREDUMP_WA, ++ SER_SET_FW_COREDUMP_WM, + /* action */ + SER_ENABLE = 2, + SER_RECOVER +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -94,6 +94,13 @@ struct mt7915_sta; + struct mt7915_dfs_pulse; + struct mt7915_dfs_pattern; + ++enum mt7915_coredump_state { ++ MT7915_COREDUMP_IDLE = 0, ++ MT7915_COREDUMP_MANUAL_WA, ++ MT7915_COREDUMP_MANUAL_WM, ++ MT7915_COREDUMP_AUTO, ++}; ++ + enum mt7915_txq_id { + MT7915_TXQ_FWDL = 16, + MT7915_TXQ_MCU_WM, +@@ -302,6 +309,7 @@ struct mt7915_dev { + + /* protects coredump data */ + struct mutex dump_mutex; ++ u8 dump_state; + #ifdef CONFIG_DEV_COREDUMP + struct { + struct mt7915_crash_data *crash_data[__MT76_RAM_TYPE_MAX]; +@@ -473,6 +481,7 @@ int mt7915_dma_start(struct mt7915_dev * + int mt7915_txbf_init(struct mt7915_dev *dev); + void mt7915_init_txpower(struct mt7915_phy *phy); + void mt7915_reset(struct mt7915_dev *dev); ++void mt7915_coredump(struct mt7915_dev *dev, u8 state); + int mt7915_run(struct ieee80211_hw *hw); + int mt7915_mcu_init(struct mt7915_dev *dev); + int mt7915_mcu_init_firmware(struct mt7915_dev *dev); diff --git a/package/kernel/mt76/patches/smartrg-1033-wifi-mt76-mt7915-add-txpower-info-dump-support.patch b/package/kernel/mt76/patches/smartrg-1033-wifi-mt76-mt7915-add-txpower-info-dump-support.patch new file mode 100644 index 0000000000..8e60d43de2 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1033-wifi-mt76-mt7915-add-txpower-info-dump-support.patch @@ -0,0 +1,138 @@ +From 35f6ac0e81382f76932b195a75fe0fa4ebc690e7 Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Tue, 11 Jul 2023 17:06:04 +0800 +Subject: [PATCH 45/76] wifi: mt76: mt7915: add txpower info dump support + +Signed-off-by: StanleyYP Wang +--- + mt7915/debugfs.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ + mt7915/mcu.c | 2 ++ + mt7915/mcu.h | 3 +- + 3 files changed, 91 insertions(+), 1 deletion(-) + +--- a/mt7915/debugfs.c ++++ b/mt7915/debugfs.c +@@ -1251,6 +1251,91 @@ mt7915_txpower_path_show(struct seq_file + DEFINE_SHOW_ATTRIBUTE(mt7915_txpower_path); + + static int ++mt7915_txpower_info_show(struct seq_file *file, void *data) ++{ ++ struct mt7915_phy *phy = file->private; ++ struct { ++ u8 category; ++ u8 rsv1; ++ ++ /* basic info */ ++ u8 band_idx; ++ u8 band; ++ ++ /* board type info */ ++ bool is_epa; ++ bool is_elna; ++ ++ /* power percentage info */ ++ bool percentage_ctrl_enable; ++ s8 power_drop_level; ++ ++ /* frond-end loss TX info */ ++ s8 front_end_loss_tx[4]; ++ ++ /* frond-end loss RX info */ ++ s8 front_end_loss_rx[4]; ++ ++ /* thermal info */ ++ bool thermal_compensate_enable; ++ s8 thermal_compensate_value; ++ u8 rsv2; ++ ++ /* TX power max/min limit info */ ++ s8 max_power_bound; ++ s8 min_power_bound; ++ ++ /* power limit info */ ++ bool sku_enable; ++ bool bf_backoff_enable; ++ ++ /* MU TX power info */ ++ bool mu_tx_power_manual_enable; ++ s8 mu_tx_power_auto; ++ s8 mu_tx_power_manual; ++ u8 rsv3; ++ } __packed basic_info = {}; ++ int ret; ++ ++ ret = mt7915_mcu_get_txpower_sku(phy, (s8 *)&basic_info, sizeof(basic_info), ++ TX_POWER_INFO_BASIC); ++ if (ret || basic_info.category != TX_POWER_INFO_BASIC) ++ goto out; ++ ++ seq_puts(file, "======================== BASIC INFO ========================\n"); ++ seq_printf(file, " Band Index: %d, Channel Band: %d\n", ++ basic_info.band_idx, basic_info.band); ++ seq_printf(file, " PA Type: %s\n", basic_info.is_epa ? "ePA" : "iPA"); ++ seq_printf(file, " LNA Type: %s\n", basic_info.is_elna ? "eLNA" : "iLNA"); ++ seq_puts(file, "------------------------------------------------------------\n"); ++ seq_printf(file, " SKU: %s\n", basic_info.sku_enable ? "enable" : "disable"); ++ seq_printf(file, " Percentage Control: %s\n", ++ basic_info.percentage_ctrl_enable ? "enable" : "disable"); ++ seq_printf(file, " Power Drop: %d [dBm]\n", basic_info.power_drop_level >> 1); ++ seq_printf(file, " Backoff: %s\n", ++ basic_info.bf_backoff_enable ? "enable" : "disable"); ++ seq_printf(file, " TX Front-end Loss: %d, %d, %d, %d\n", ++ basic_info.front_end_loss_tx[0], basic_info.front_end_loss_tx[1], ++ basic_info.front_end_loss_tx[2], basic_info.front_end_loss_tx[3]); ++ seq_printf(file, " RX Front-end Loss: %d, %d, %d, %d\n", ++ basic_info.front_end_loss_rx[0], basic_info.front_end_loss_rx[1], ++ basic_info.front_end_loss_rx[2], basic_info.front_end_loss_rx[3]); ++ seq_printf(file, " MU TX Power Mode: %s\n", ++ basic_info.mu_tx_power_manual_enable ? "manual" : "auto"); ++ seq_printf(file, " MU TX Power (Auto / Manual): %d / %d [0.5 dBm]\n", ++ basic_info.mu_tx_power_auto, basic_info.mu_tx_power_manual); ++ seq_printf(file, " Thermal Compensation: %s\n", ++ basic_info.thermal_compensate_enable ? "enable" : "disable"); ++ seq_printf(file, " Theraml Compensation Value: %d\n", ++ basic_info.thermal_compensate_value); ++ ++out: ++ return ret; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(mt7915_txpower_info); ++ ++static int + mt7915_twt_stats(struct seq_file *s, void *data) + { + struct mt7915_dev *dev = dev_get_drvdata(s->private); +@@ -1338,6 +1423,8 @@ int mt7915_init_debugfs(struct mt7915_ph + &mt7915_txpower_fops); + debugfs_create_file("txpower_path", 0400, dir, phy, + &mt7915_txpower_path_fops); ++ debugfs_create_file("txpower_info", 0400, dir, phy, ++ &mt7915_txpower_info_fops); + debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir, + mt7915_twt_stats); + debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -3619,6 +3619,8 @@ int mt7915_mcu_get_txpower_sku(struct mt + return -EINVAL; + } + memcpy(txpower, skb->data + 4, len); ++ } else if (category == TX_POWER_INFO_BASIC) { ++ memcpy(txpower, skb->data, len); + } + + dev_kfree_skb(skb); +--- a/mt7915/mcu.h ++++ b/mt7915/mcu.h +@@ -514,7 +514,8 @@ enum { + }; + + enum { +- TX_POWER_INFO_PATH = 1, ++ TX_POWER_INFO_BASIC, ++ TX_POWER_INFO_PATH, + TX_POWER_INFO_RATE, + }; + diff --git a/package/kernel/mt76/patches/smartrg-1035-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch b/package/kernel/mt76/patches/smartrg-1035-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch new file mode 100644 index 0000000000..554cbf84fd --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1035-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch @@ -0,0 +1,20 @@ +From dc3bc9dadab098db977049a805ec458d19b2011d Mon Sep 17 00:00:00 2001 +From: MeiChia Chiu +Date: Tue, 8 Aug 2023 11:20:58 +0800 +Subject: [PATCH 47/76] wifi: mt76: mt7915: Establish BA in VO queue + +--- + mt76_connac_mac.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/mt76_connac_mac.c ++++ b/mt76_connac_mac.c +@@ -1161,8 +1161,6 @@ void mt76_connac2_tx_check_aggr(struct i + return; + + tid = le32_get_bits(txwi[1], MT_TXD1_TID); +- if (tid >= 6) /* skip VO queue */ +- return; + + val = le32_to_cpu(txwi[2]); + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | diff --git a/package/kernel/mt76/patches/smartrg-1040-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch b/package/kernel/mt76/patches/smartrg-1040-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch new file mode 100644 index 0000000000..dac43c0487 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1040-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch @@ -0,0 +1,42 @@ +From 493e528b81ef05cb34d63440b8f0f731aaf60c08 Mon Sep 17 00:00:00 2001 +From: Bo Jiao +Date: Mon, 11 Sep 2023 17:11:24 +0800 +Subject: [PATCH 52/76] wifi: mt76: mt7915: add debug log for SER flow. + +Signed-off-by: Bo Jiao +--- + mt7915/mac.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1504,6 +1504,9 @@ void mt7915_mac_reset_work(struct work_s + if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) + return; + ++ dev_info(dev->mt76.dev,"==== %s L1 SER recovery start ====", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + ieee80211_stop_queues(mt76_hw(dev)); + if (ext_phy) + ieee80211_stop_queues(ext_phy->hw); +@@ -1584,6 +1587,9 @@ void mt7915_mac_reset_work(struct work_s + ieee80211_queue_delayed_work(ext_phy->hw, + &phy2->mt76->mac_work, + MT7915_WATCHDOG_TIME); ++ ++ dev_info(dev->mt76.dev,"==== %s L1 SER recovery completed ====", ++ wiphy_name(dev->mt76.hw->wiphy)); + } + + /* firmware coredump */ +@@ -1699,6 +1705,9 @@ void mt7915_coredump(struct mt7915_dev * + + void mt7915_reset(struct mt7915_dev *dev) + { ++ dev_info(dev->mt76.dev, "%s SER recovery state: 0x%08x\n", ++ wiphy_name(dev->mt76.hw->wiphy), READ_ONCE(dev->recovery.state)); ++ + if (!dev->recovery.hw_init_done) + return; + diff --git a/package/kernel/mt76/patches/smartrg-1041-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch b/package/kernel/mt76/patches/smartrg-1041-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch new file mode 100644 index 0000000000..b2d86e8400 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1041-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch @@ -0,0 +1,22 @@ +From f4ae3b90eb43f820b65e55085936ce8a7fb508fd Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Wed, 20 Sep 2023 11:10:57 +0800 +Subject: [PATCH 53/76] wifi: mt76: mt7915: add additional chain signal info to + station dump + +Signed-off-by: StanleyYP Wang +--- + mt7915/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -417,7 +417,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *de + if (v0 & MT_PRXV_HT_AD_CODE) + status->enc_flags |= RX_ENC_FLAG_LDPC; + +- status->chains = mphy->antenna_mask; ++ status->chains = mphy->chainmask >> (status->phy_idx * dev->chainshift); + status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v1); + status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1); + status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1); diff --git a/package/kernel/mt76/patches/smartrg-1044-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch b/package/kernel/mt76/patches/smartrg-1044-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch new file mode 100644 index 0000000000..c2cd5bfe6d --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1044-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch @@ -0,0 +1,71 @@ +From c3880a47f6c4b0b8c2f2d2eb7824cb3545db8a60 Mon Sep 17 00:00:00 2001 +From: "Henry.Yen" +Date: Mon, 11 Dec 2023 16:01:55 +0800 +Subject: [PATCH 56/76] wifi: mt76: mt7915 add mt7981 efuse variants support + +--- + mt7915/eeprom.c | 22 ++++++++++++++++++++++ + mt7915/mt7915.h | 7 ++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + +--- a/mt7915/eeprom.c ++++ b/mt7915/eeprom.c +@@ -198,6 +198,21 @@ static int mt7915_eeprom_load(struct mt7 + return mt7915_check_eeprom(dev); + } + ++static int mt7915_eeprom_parse_efuse_hw_cap(struct mt7915_dev *dev) ++{ ++#define WTBL_SIZE_GROUP GENMASK(1, 0) ++ u32 buf; ++ int ret; ++ ++ ret = mt76_get_of_data_from_nvmem(&dev->mt76, &buf, "variant", 4); ++ if (ret) ++ return ret; ++ ++ dev->limited_wtbl_size = buf & WTBL_SIZE_GROUP; ++ ++ return 0; ++} ++ + static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) + { + struct mt7915_dev *dev = phy->dev; +@@ -260,6 +275,13 @@ void mt7915_eeprom_parse_hw_cap(struct m + u8 path, nss, nss_max = 4, *eeprom = dev->mt76.eeprom.data; + struct mt76_phy *mphy = phy->mt76; + u8 band = phy->mt76->band_idx; ++ int ret; ++ ++ if (is_mt7981(&dev->mt76)) { ++ ret = mt7915_eeprom_parse_efuse_hw_cap(dev); ++ if (ret) ++ dev->limited_wtbl_size = true; ++ } + + mt7915_eeprom_parse_band_config(phy); + +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -324,6 +324,7 @@ struct mt7915_dev { + + u32 hw_pattern; + ++ bool limited_wtbl_size; + bool dbdc_support; + bool flash_mode; + bool muru_debug; +@@ -577,7 +578,11 @@ void mt7915_mcu_exit(struct mt7915_dev * + + static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev) + { +- return is_mt7915(&dev->mt76) ? MT7915_WTBL_SIZE : MT7916_WTBL_SIZE; ++ if (is_mt7915(&dev->mt76) || ++ (is_mt7981(&dev->mt76) && dev->limited_wtbl_size)) ++ return MT7915_WTBL_SIZE; ++ ++ return MT7916_WTBL_SIZE; + } + + static inline u16 mt7915_eeprom_size(struct mt7915_dev *dev) diff --git a/package/kernel/mt76/patches/smartrg-1052-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch b/package/kernel/mt76/patches/smartrg-1052-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch new file mode 100644 index 0000000000..2ad378ad77 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1052-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch @@ -0,0 +1,136 @@ +From faaaf4ee3fc3f230cc3c039f114296f12e00e98c Mon Sep 17 00:00:00 2001 +From: Henry Yen +Date: Wed, 6 Mar 2024 12:42:06 +0800 +Subject: [PATCH] wifi: mt76: mt7915: remove unnecessary register settings + +Remove unnecessary register settings from the driver layer, +and let firmware take over the configuration control. + +Signed-off-by: Henry.Yen +--- + mt7915/init.c | 35 ----------------------------------- + mt7915/mac.c | 43 +------------------------------------------ + 2 files changed, 1 insertion(+), 77 deletions(-) + +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -490,30 +490,6 @@ mt7915_mac_init_band(struct mt7915_dev * + { + u32 mask, set; + +- mt76_rmw_field(dev, MT_TMAC_CTCR0(band), +- MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); +- mt76_set(dev, MT_TMAC_CTCR0(band), +- MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | +- MT_TMAC_CTCR0_INS_DDLMT_EN); +- +- mask = MT_MDP_RCFR0_MCU_RX_MGMT | +- MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR | +- MT_MDP_RCFR0_MCU_RX_CTL_BAR; +- set = FIELD_PREP(MT_MDP_RCFR0_MCU_RX_MGMT, MT_MDP_TO_HIF) | +- FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR, MT_MDP_TO_HIF) | +- FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_BAR, MT_MDP_TO_HIF); +- mt76_rmw(dev, MT_MDP_BNRCFR0(band), mask, set); +- +- mask = MT_MDP_RCFR1_MCU_RX_BYPASS | +- MT_MDP_RCFR1_RX_DROPPED_UCAST | +- MT_MDP_RCFR1_RX_DROPPED_MCAST; +- set = FIELD_PREP(MT_MDP_RCFR1_MCU_RX_BYPASS, MT_MDP_TO_HIF) | +- FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_UCAST, MT_MDP_TO_HIF) | +- FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF); +- mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set); +- +- mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 0x680); +- + /* mt7915: disable rx rate report by default due to hw issues */ + mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); + +@@ -624,23 +600,12 @@ mt7915_init_led_mux(struct mt7915_dev *d + void mt7915_mac_init(struct mt7915_dev *dev) + { + int i; +- u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680; +- +- /* config pse qid6 wfdma port selection */ +- if (!is_mt7915(&dev->mt76) && dev->hif2) +- mt76_rmw(dev, MT_WF_PP_TOP_RXQ_WFDMA_CF_5, 0, +- MT_WF_PP_TOP_RXQ_QID6_WFDMA_HIF_SEL_MASK); +- +- mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, rx_len); + + if (!is_mt7915(&dev->mt76)) + mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT); + else + mt76_clear(dev, MT_PLE_HOST_RPT0, MT_PLE_HOST_RPT0_TX_LATENCY); + +- /* enable hardware de-agg */ +- mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); +- + for (i = 0; i < mt7915_wtbl_size(dev); i++) + mt7915_mac_wtbl_update(dev, i, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1119,61 +1119,20 @@ void mt7915_mac_reset_counters(struct mt + + void mt7915_mac_set_timing(struct mt7915_phy *phy) + { +- s16 coverage_class = phy->coverage_class; + struct mt7915_dev *dev = phy->dev; +- struct mt7915_phy *ext_phy = mt7915_ext_phy(dev); +- u32 val, reg_offset; +- u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | +- FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); +- u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | +- FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); ++ u32 val; + u8 band = phy->mt76->band_idx; +- int eifs_ofdm = 84, sifs = 10, offset; + bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); + + if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) + return; + +- if (ext_phy) +- coverage_class = max_t(s16, dev->phy.coverage_class, +- ext_phy->coverage_class); +- +- mt76_set(dev, MT_ARB_SCR(band), +- MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); +- udelay(1); +- +- offset = 3 * coverage_class; +- reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | +- FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); +- +- if (!is_mt7915(&dev->mt76)) { +- if (!a_band) { +- mt76_wr(dev, MT_TMAC_ICR1(band), +- FIELD_PREP(MT_IFS_EIFS_CCK, 314)); +- eifs_ofdm = 78; +- } else { +- eifs_ofdm = 84; +- } +- } else if (a_band) { +- sifs = 16; +- } +- +- mt76_wr(dev, MT_TMAC_CDTR(band), cck + reg_offset); +- mt76_wr(dev, MT_TMAC_ODTR(band), ofdm + reg_offset); +- mt76_wr(dev, MT_TMAC_ICR0(band), +- FIELD_PREP(MT_IFS_EIFS_OFDM, eifs_ofdm) | +- FIELD_PREP(MT_IFS_RIFS, 2) | +- FIELD_PREP(MT_IFS_SIFS, sifs) | +- FIELD_PREP(MT_IFS_SLOT, phy->slottime)); +- + if (phy->slottime < 20 || a_band) + val = MT7915_CFEND_RATE_DEFAULT; + else + val = MT7915_CFEND_RATE_11B; + + mt76_rmw_field(dev, MT_AGG_ACR0(band), MT_AGG_ACR_CFEND_RATE, val); +- mt76_clear(dev, MT_ARB_SCR(band), +- MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); + } + + void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool band) diff --git a/package/kernel/mt76/patches/smartrg-1054-wifi-mt76-mt7915-set-channel-after-sta-is-associated.patch b/package/kernel/mt76/patches/smartrg-1054-wifi-mt76-mt7915-set-channel-after-sta-is-associated.patch new file mode 100644 index 0000000000..e1896fa78d --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-1054-wifi-mt76-mt7915-set-channel-after-sta-is-associated.patch @@ -0,0 +1,61 @@ +From 1d18008ab9d67f318932ed993103bd46d9f0215d Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Thu, 21 Mar 2024 16:52:34 +0800 +Subject: [PATCH 1051/1052] wifi: mt76: mt7915: set channel after sta is + associated to adjust switch reason + +when sta is associated to AP operating in DFS channel, a channel +setting operation is required to change the channel switch reason +from CH_SWTICH_DFS to CH_SWITCH_NORMAL. +Note that the switch reason for DFS channel during authentication is +CH_SWITCH_DFS since the DFS state is still USABLE at that point + +Signed-off-by: StanleyYP Wang +--- + mt7915/main.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- a/mt7915/main.c ++++ b/mt7915/main.c +@@ -763,6 +763,33 @@ out: + return ret; + } + ++static void ++mt7915_event_callback(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ const struct ieee80211_event *event) ++{ ++ struct mt7915_phy *phy = mt7915_hw_phy(hw); ++ struct mt7915_dev *dev = phy->dev; ++ int ret; ++ ++ switch (event->type) { ++ case MLME_EVENT: ++ if (event->u.mlme.data == ASSOC_EVENT && ++ event->u.mlme.status == MLME_SUCCESS) { ++ dev_info(dev->mt76.dev, "%s: set channel after association", __func__); ++ ieee80211_stop_queues(hw); ++ ret = mt7915_set_channel(phy->mt76); ++ if (ret) ++ return; ++ ieee80211_wake_queues(hw); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return; ++} ++ + int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +@@ -1871,6 +1898,7 @@ const struct ieee80211_ops mt7915_ops = + .set_sar_specs = mt7915_set_sar_specs, + .channel_switch_beacon = mt7915_channel_switch_beacon, + .post_channel_switch = mt7915_post_channel_switch, ++ .event_callback = mt7915_event_callback, + .get_stats = mt7915_get_stats, + .get_et_sset_count = mt7915_get_et_sset_count, + .get_et_stats = mt7915_get_et_stats, diff --git a/package/kernel/mt76/patches/smartrg-4000-0008-mtk-wifi-mt76-mt7996-enable-ser-query.patch b/package/kernel/mt76/patches/smartrg-4000-0008-mtk-wifi-mt76-mt7996-enable-ser-query.patch new file mode 100644 index 0000000000..dfddc4e0ea --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-0008-mtk-wifi-mt76-mt7996-enable-ser-query.patch @@ -0,0 +1,24 @@ +From 696641eb6a9fe9dc2d3cef2473a68ee8cf9503ff Mon Sep 17 00:00:00 2001 +From: Peter Chiu +Date: Mon, 30 Oct 2023 20:19:41 +0800 +Subject: [PATCH 08/17] mtk: wifi: mt76: mt7996: enable ser query + +Do not return -EINVAL when action is UNI_CMD_SER_QUERY for user +to dump SER information from FW. + +Signed-off-by: Peter Chiu +--- + mt7996/mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -4753,6 +4753,8 @@ int mt7996_mcu_set_ser(struct mt7996_dev + }; + + switch (action) { ++ case UNI_CMD_SER_QUERY: ++ break; + case UNI_CMD_SER_SET: + req.set.mask = cpu_to_le32(val); + break; diff --git a/package/kernel/mt76/patches/smartrg-4000-0016-mtk-wifi-mt76-mt7996-add-preamble-puncture-support-f.patch b/package/kernel/mt76/patches/smartrg-4000-0016-mtk-wifi-mt76-mt7996-add-preamble-puncture-support-f.patch new file mode 100644 index 0000000000..9730359fac --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-0016-mtk-wifi-mt76-mt7996-add-preamble-puncture-support-f.patch @@ -0,0 +1,111 @@ +From caf4cdd101e795aeff0c269f34c4496bda7609b6 Mon Sep 17 00:00:00 2001 +From: Howard Hsu +Date: Fri, 22 Sep 2023 10:32:37 +0800 +Subject: [PATCH 16/17] mtk: wifi: mt76: mt7996: add preamble puncture support + for mt7996 + +Add support configure preamble puncture feature through mcu commands. + +Signed-off-by: Howard Hsu +--- + mt76_connac_mcu.h | 1 + + mt7996/mcu.c | 30 ++++++++++++++++++++++++++++++ + mt7996/mcu.h | 4 ++++ + mt7996/mt7996.h | 2 ++ + 4 files changed, 37 insertions(+) + +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1313,6 +1313,7 @@ enum { + MCU_UNI_CMD_CHANNEL_SWITCH = 0x34, + MCU_UNI_CMD_THERMAL = 0x35, + MCU_UNI_CMD_VOW = 0x37, ++ MCU_UNI_CMD_PP = 0x38, + MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40, + MCU_UNI_CMD_RSSI_MONITOR = 0x41, + MCU_UNI_CMD_TESTMODE_CTRL = 0x46, +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -5526,3 +5526,43 @@ int mt7996_mcu_set_dup_wtbl(struct mt799 + return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(CHIP_CONFIG), &req, + sizeof(req), true); + } ++ ++int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, u8 mode, u16 bitmap) ++{ ++ struct mt7996_dev *dev = phy->dev; ++ bool pp_auto = (mode == PP_FW_MODE); ++ struct { ++ u8 _rsv1[4]; ++ ++ __le16 tag; ++ __le16 len; ++ u8 mgmt_mode; ++ u8 band_idx; ++ u8 force_bitmap_ctrl; ++ u8 auto_mode; ++ __le16 bitmap; ++ u8 _rsv2[2]; ++ } __packed req = { ++ .tag = cpu_to_le16(UNI_CMD_PP_EN_CTRL), ++ .len = cpu_to_le16(sizeof(req) - 4), ++ ++ .mgmt_mode = !pp_auto, ++ .band_idx = phy->mt76->band_idx, ++ .force_bitmap_ctrl = (mode == PP_USR_MODE) ? 2 : 0, ++ .auto_mode = pp_auto, ++ .bitmap = cpu_to_le16(bitmap), ++ }; ++ ++ if (phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ || ++ mode > PP_USR_MODE) ++ return 0; ++ ++ if (bitmap && phy->punct_bitmap == bitmap) ++ return 0; ++ ++ phy->punct_bitmap = bitmap; ++ phy->pp_mode = mode; ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(PP), ++ &req, sizeof(req), false); ++} +--- a/mt7996/mcu.h ++++ b/mt7996/mcu.h +@@ -1070,6 +1070,16 @@ enum { + MT7996_SEC_MODE_MAX, + }; + ++enum { ++ UNI_CMD_PP_EN_CTRL, ++}; ++ ++enum pp_mode { ++ PP_DISABLE = 0, ++ PP_FW_MODE, ++ PP_USR_MODE, ++}; ++ + #define MT7996_PATCH_SEC GENMASK(31, 24) + #define MT7996_PATCH_SCRAMBLE_KEY GENMASK(15, 8) + #define MT7996_PATCH_AES_KEY GENMASK(7, 0) +--- a/mt7996/mt7996.h ++++ b/mt7996/mt7996.h +@@ -401,6 +401,9 @@ struct mt7996_phy { + bool has_aux_rx; + bool counter_reset; + bool rdd_tx_paused; ++ ++ u8 pp_mode; ++ u16 punct_bitmap; + }; + + struct mt7996_dev { +@@ -929,6 +932,7 @@ int mt7996_mcu_wtbl_update_hdr_trans(str + struct mt7996_vif_link *link, + struct mt7996_sta_link *msta_link); + int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode); ++int mt7996_mcu_set_pp_en(struct mt7996_phy *phy, u8 mode, u16 bitmap); + int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, diff --git a/package/kernel/mt76/patches/smartrg-4000-0017-mtk-wifi-mt76-mt7996-add-sanity-check-for-NAPI-sched.patch b/package/kernel/mt76/patches/smartrg-4000-0017-mtk-wifi-mt76-mt7996-add-sanity-check-for-NAPI-sched.patch new file mode 100644 index 0000000000..45d71f3f4e --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-0017-mtk-wifi-mt76-mt7996-add-sanity-check-for-NAPI-sched.patch @@ -0,0 +1,33 @@ +From 2b1c18a06ab12124b50b6ee45f7ec070071560d7 Mon Sep 17 00:00:00 2001 +From: "Henry.Yen" +Date: Tue, 16 Jan 2024 11:30:02 +0800 +Subject: [PATCH 17/17] mtk: wifi: mt76: mt7996: add sanity check for NAPI + schedule + +Add sanity check for NAPI schedule. + +It's observed that host driver might occasionally receive +interrupts from unexpected Rx ring, whose Rx NAPI hasn't been +prepared yet. Under such situation, __napi_poll crash issue +would occur, so we add sanity check to prevent it. + +If without this patch, we might encounter kernel crash issue +especially in WED-on & RRO-on software path. + +Signed-off-by: Henry.Yen + +--- + mt7996/mmio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mt7996/mmio.c ++++ b/mt7996/mmio.c +@@ -774,7 +774,7 @@ static void mt7996_irq_tasklet(struct ta + napi_schedule(&dev->mt76.tx_napi); + + for (i = 0; i < __MT_RXQ_MAX; i++) { +- if ((intr & MT_INT_RX(i))) ++ if ((intr & MT_INT_RX(i)) && dev->mt76.napi[i].poll) + napi_schedule(&dev->mt76.napi[i]); + } + diff --git a/package/kernel/mt76/patches/smartrg-4000-0045-mtk-wifi-mt76-mt7996-flush-stale-per-station-PLE-tokens.patch b/package/kernel/mt76/patches/smartrg-4000-0045-mtk-wifi-mt76-mt7996-flush-stale-per-station-PLE-tokens.patch new file mode 100644 index 0000000000..59a1016be7 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-0045-mtk-wifi-mt76-mt7996-flush-stale-per-station-PLE-tokens.patch @@ -0,0 +1,218 @@ +From: Chad Monroe +Date: Wed, 25 Mar 2026 16:19:06 -0700 +Subject: [PATCH] wifi: mt76: mt7996: flush stale per-station PLE tokens + +Stations that disconnect or stall can leave TX tokens stranded in the +PLE, eventually exhausting the pool and blocking transmission for +other clients. + +Signed-off-by: Chad Monroe +--- + mac80211.c | 2 + + mt76.h | 6 +++- + mt7996/mac.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ + mt7996/mcu.c | 36 ++++++++++++++++++++++++++++ + mt7996/mcu.h | 1 + mt7996/mt7996.h | 7 +++++ + 6 files changed, 110 insertions(+), 1 deletion(-) + +--- a/mac80211.c ++++ b/mac80211.c +@@ -1716,6 +1716,8 @@ void mt76_wcid_init(struct mt76_wcid *wc + idr_init(&wcid->pktid); + + INIT_LIST_HEAD(&wcid->poll_list); ++ ++ spin_lock_init(&wcid->token_lock); + } + EXPORT_SYMBOL_GPL(mt76_wcid_init); + +--- a/mt76.h ++++ b/mt76.h +@@ -444,6 +444,10 @@ struct mt76_wcid { + struct list_head poll_list; + + struct mt76_wcid *def_wcid; ++ ++ unsigned long last_seen; ++ u16 used_token; ++ spinlock_t token_lock; + }; + + struct mt76_txq { +@@ -932,7 +936,7 @@ struct mt76_phy { + #endif + + struct delayed_work mac_work; +- u8 mac_work_count; ++ u16 mac_work_count; + + struct { + struct sk_buff *head; +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -1056,6 +1056,10 @@ int mt7996_tx_prepare_skb(struct mt76_de + if (id < 0) + return id; + ++ spin_lock_bh(&wcid->token_lock); ++ wcid->used_token++; ++ spin_unlock_bh(&wcid->token_lock); ++ + /* Since the rules of HW MLD address translation are not fully + * compatible with 802.11 EAPOL frame, we do the translation by + * software +@@ -1253,6 +1257,21 @@ mt7996_txwi_free(struct mt7996_dev *dev, + __le32 *txwi; + u16 wcid_idx; + ++ if (t->wcid < MT7996_WTBL_STA) { ++ struct mt76_wcid *token_wcid; ++ ++ rcu_read_lock(); ++ token_wcid = rcu_dereference(mdev->wcid[t->wcid]); ++ if (token_wcid) { ++ spin_lock_bh(&token_wcid->token_lock); ++ if (token_wcid->used_token) ++ token_wcid->used_token--; ++ token_wcid->last_seen = jiffies; ++ spin_unlock_bh(&token_wcid->token_lock); ++ } ++ rcu_read_unlock(); ++ } ++ + mt76_connac_txp_skb_unmap(mdev, t); + if (!t->skb) + goto out; +@@ -2907,6 +2926,41 @@ void mt7996_mac_sta_rc_work(struct work_ + mutex_unlock(&dev->mt76.mutex); + } + ++static void mt7996_flush_pending_token(struct mt7996_dev *dev) ++{ ++#define MT7996_PLE_FLUSH_THRESHOLD 128 ++#define MT7996_PLE_FLUSH_TIMEOUT (2 * 60 * HZ) ++ u8 sta_bitmap[MT7996_WTBL_GROUP_SIZE_MT7996]; ++ u16 sta_cnt = 0, i; ++ ++ memset(&sta_bitmap, 0, sizeof(sta_bitmap)); ++ ++ rcu_read_lock(); ++ for (i = 0; i < MT7996_WTBL_STA; i++) { ++ struct mt76_wcid *wcid = rcu_dereference(dev->mt76.wcid[i]); ++ ++ if (!wcid) ++ continue; ++ ++ spin_lock_bh(&wcid->token_lock); ++ if (wcid->used_token > MT7996_PLE_FLUSH_THRESHOLD && ++ time_after(jiffies, wcid->last_seen + MT7996_PLE_FLUSH_TIMEOUT)) { ++ sta_bitmap[i >> 3] |= BIT(i % 8); ++ sta_cnt++; ++ } ++ spin_unlock_bh(&wcid->token_lock); ++ } ++ rcu_read_unlock(); ++ ++ if (sta_cnt) { ++ dev_info(dev->mt76.dev, ++ "flushing PLE for %u station(s) with >%d stale tokens\n", ++ sta_cnt, MT7996_PLE_FLUSH_THRESHOLD); ++ mt7996_mcu_flush_ple(dev, MT7996_PLE_FLUSH_THRESHOLD, ++ sta_bitmap, sta_cnt); ++ } ++} ++ + void mt7996_mac_work(struct work_struct *work) + { + struct mt7996_phy *phy; +@@ -2929,6 +2983,11 @@ void mt7996_mac_work(struct work_struct + mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT); + mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT); + } ++ ++ if (mphy->mac_work_count == 1200) { ++ mphy->mac_work_count = 0; ++ mt7996_flush_pending_token(phy->dev); ++ } + } + + mutex_unlock(&mphy->dev->mutex); +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -3686,6 +3686,42 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996 + sizeof(data), false); + } + ++int mt7996_mcu_flush_ple(struct mt7996_dev *dev, u16 threshold, ++ u8 *sta_bitmap, u16 sta_cnt) ++{ ++ struct { ++ u8 _rsv1[4]; ++ ++ __le16 tag; ++ __le16 len; ++ ++ __le16 threshold; ++ __le16 sta_cnt; ++ u8 band; ++ u8 _rsv2[3]; ++ u8 sta_bitmap[MT7996_WTBL_GROUP_SIZE_MT7996]; ++ u8 _rsv3[3]; ++ } __packed req = { ++ .tag = cpu_to_le16(UNI_WSYS_CONFIG_PLE_FLUSH_PEER), ++ .len = sizeof(req) - 4, ++ .threshold = cpu_to_le16(threshold), ++ .sta_cnt = cpu_to_le16(sta_cnt), ++ .band = 0xff, ++ }; ++ int len = sizeof(req); ++ ++ if (!is_mt7996(&dev->mt76)) { ++ req.len -= MT7996_WTBL_GROUP_SIZE_DIFF; ++ len -= MT7996_WTBL_GROUP_SIZE_DIFF; ++ } ++ ++ req.len = cpu_to_le16(req.len); ++ memcpy(&req.sta_bitmap, sta_bitmap, sizeof(req.sta_bitmap)); ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(WSYS_CONFIG), ++ &req, len, false); ++} ++ + static int mt7996_mcu_set_mwds(struct mt7996_dev *dev, bool enabled) + { + struct { +--- a/mt7996/mcu.h ++++ b/mt7996/mcu.h +@@ -965,6 +965,7 @@ enum { + enum { + UNI_WSYS_CONFIG_FW_LOG_CTRL, + UNI_WSYS_CONFIG_FW_DBG_CTRL, ++ UNI_WSYS_CONFIG_PLE_FLUSH_PEER = 0x4, + }; + + enum { +--- a/mt7996/mt7996.h ++++ b/mt7996/mt7996.h +@@ -22,6 +22,11 @@ + #define MT7996_WATCHDOG_TIME (HZ / 10) + #define MT7996_RESET_TIMEOUT (30 * HZ) + ++#define MT7996_WTBL_GROUP_SIZE_MT7996 ((1088 >> 3) + 1) ++#define MT7996_WTBL_GROUP_SIZE_MT7990 ((544 >> 3) + 1) ++#define MT7996_WTBL_GROUP_SIZE_DIFF (MT7996_WTBL_GROUP_SIZE_MT7996 - \ ++ MT7996_WTBL_GROUP_SIZE_MT7990) ++ + #define MT7996_TX_RING_SIZE 2048 + #define MT7996_TX_MCU_RING_SIZE 256 + #define MT7996_TX_FWDL_RING_SIZE 128 +@@ -760,6 +765,8 @@ int mt7996_mcu_set_fixed_rate_ctrl(struc + int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta, + void *data, u8 link_id, u32 field); + int mt7996_mcu_set_eeprom(struct mt7996_dev *dev); ++int mt7996_mcu_flush_ple(struct mt7996_dev *dev, u16 threshold, ++ u8 *sta_bitmap, u16 sta_cnt); + int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len, + enum mt7996_eeprom_mode mode); + int mt7996_mcu_get_efuse_free_block(struct mt7996_dev *dev, u8 *block_num); diff --git a/package/kernel/mt76/patches/smartrg-4000-0056-mtk-wifi-mt76-mt7996-trigger-channel-calibration-for-DFS.patch b/package/kernel/mt76/patches/smartrg-4000-0056-mtk-wifi-mt76-mt7996-trigger-channel-calibration-for-DFS.patch new file mode 100644 index 0000000000..d1cf74cee4 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-0056-mtk-wifi-mt76-mt7996-trigger-channel-calibration-for-DFS.patch @@ -0,0 +1,86 @@ +From 58ac8d0be8729ca48c5b85c2fddefd6a6b1f871b Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Fri, 17 May 2024 14:49:50 +0800 +Subject: [PATCH 56/89] mtk: mt76: mt7996: trigger channel calibration for DFS + +Trigger channel calibration (set channel with switch reason = NORMAL) +for DFS link after STA is associated. +Without this patch, 5G link might have high PER during T.P. test + +Signed-off-by: StanleyYP Wang +--- + mt7996/main.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/mt7996/main.c ++++ b/mt7996/main.c +@@ -26,6 +26,11 @@ int mt7996_run(struct mt7996_phy *phy) + if (ret) + return ret; + ++ /* set a parking channel */ ++ ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH); ++ if (ret) ++ return ret; ++ + ret = mt7996_mcu_set_thermal_throttling(phy, MT7996_THERMAL_THROTTLE_MAX); + if (ret) + return ret; +@@ -2506,6 +2511,49 @@ mt7996_set_eml_op_mode(struct ieee80211_ + return ret; + } + ++static void ++mt7996_event_callback(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ++ const struct ieee80211_event *event) ++{ ++ struct mt7996_dev *dev = mt7996_hw_dev(hw); ++ unsigned long valid_links; ++ unsigned int link_id; ++ ++ switch (event->type) { ++ case MLME_EVENT: ++ if (event->u.mlme.data != ASSOC_EVENT || ++ event->u.mlme.status != MLME_SUCCESS) ++ break; ++ ++ valid_links = vif->valid_links ?: BIT(0); ++ ++ ieee80211_stop_queues(hw); ++ mutex_lock(&dev->mt76.mutex); ++ for_each_set_bit(link_id, &valid_links, IEEE80211_MLD_MAX_NUM_LINKS) { ++ struct mt7996_vif_link *mconf; ++ struct mt7996_phy *phy; ++ ++ mconf = mt7996_vif_link(dev, vif, link_id); ++ if (!mconf) ++ continue; ++ ++ phy = mt7996_vif_link_phy(mconf); ++ if (!phy) ++ continue; ++ ++ if (!cfg80211_reg_can_beacon(hw->wiphy, ++ &phy->mt76->chandef, ++ NL80211_IFTYPE_AP)) ++ mt7996_set_channel(phy->mt76); ++ } ++ mutex_unlock(&dev->mt76.mutex); ++ ieee80211_wake_queues(hw); ++ break; ++ default: ++ break; ++ } ++} ++ + const struct ieee80211_ops mt7996_ops = { + .add_chanctx = mt76_add_chanctx, + .remove_chanctx = mt76_remove_chanctx, +@@ -2538,6 +2586,7 @@ const struct ieee80211_ops mt7996_ops = + .get_txpower = mt7996_get_txpower, + .channel_switch_beacon = mt7996_channel_switch_beacon, + .post_channel_switch = mt7996_post_channel_switch, ++ .event_callback = mt7996_event_callback, + .get_stats = mt7996_get_stats, + .get_et_sset_count = mt7996_get_et_sset_count, + .get_et_stats = mt7996_get_et_stats, diff --git a/package/kernel/mt76/patches/smartrg-4000-0102-mtk-wifi-mt76-mt7996-refactor-mcu-commands-flow-for-stati.patch b/package/kernel/mt76/patches/smartrg-4000-0102-mtk-wifi-mt76-mt7996-refactor-mcu-commands-flow-for-stati.patch new file mode 100644 index 0000000000..76609f4431 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-0102-mtk-wifi-mt76-mt7996-refactor-mcu-commands-flow-for-stati.patch @@ -0,0 +1,71 @@ +From 9305ab328f24a593aa20953a960cd5077c3e87b7 Mon Sep 17 00:00:00 2001 +From: Peter Chiu +Date: Wed, 18 Jun 2025 13:26:13 +0800 +Subject: [PATCH 102/119] mtk: mt76: mt7996: refactor mcu commands flow for + station mode + +Fix two possible issues +1. Driver needs to update BMC STAREC before UC STAREC. +When configuring UC STAREC, it would init RA algo based on STA cap +and BSS cap. The BSS cap is stored in BMC STAREC so driver needs to +update BMC STAREC before UC STAREC. +2. Remove BMC STAREC when CHANGED_BSSID and the bssid is null. +Driver needs to remove BMC STAREC when station disconnect to the +AP. Without this patch, station cannot update the mac address when it +connect to the other AP with different mac address, + +The original flow change leads to incorrect BMC WTBL settings of station +interface since some fields are not ready filled by mac80211, preventing +the firmware from parsing MU EDCA IE from the beacon and degrading MU +uplink performance. + +Signed-off-by: Peter Chiu +--- + mt7996/main.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/mt7996/main.c ++++ b/mt7996/main.c +@@ -923,8 +923,7 @@ mt7996_vif_cfg_changed(struct ieee80211_ + &link->mt76, &link->msta_link, + true); + mt7996_mcu_add_sta(dev, link_conf, NULL, link, NULL, +- CONN_STATE_PORT_SECURE, +- !!(changed & BSS_CHANGED_BSSID)); ++ CONN_STATE_PORT_SECURE, false); + } + } + +@@ -977,6 +976,9 @@ mt7996_link_info_changed(struct ieee8021 + CONN_STATE_PORT_SECURE, + !!(changed & BSS_CHANGED_BSSID)); + } ++ if (changed & BSS_CHANGED_BSSID && is_zero_ether_addr(info->bssid)) ++ mt7996_mcu_add_sta(dev, info, NULL, link, &link->msta_link, ++ CONN_STATE_DISCONNECT, false); + + if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) + mt7996_mcu_set_protection(phy, link, info->ht_operation_mode, +@@ -1272,6 +1274,7 @@ mt7996_mac_sta_add_links(struct mt7996_d + struct ieee80211_link_sta *link_sta; + struct mt7996_sta_link *msta_link; + struct mt7996_vif_link *link; ++ struct mt7996_phy *phy; + struct mt76_phy *mphy; + + msta_link = mt76_dereference(msta->link[link_id], &dev->mt76); +@@ -1304,6 +1307,14 @@ mt7996_mac_sta_add_links(struct mt7996_d + goto error_unlink; + } + ++ phy = mphy->priv; ++ ++ /* Update bss capability after associated and before add station */ ++ if (vif->type == NL80211_IFTYPE_STATION) ++ mt7996_mcu_add_bss_info(phy, vif, link_conf, ++ &link->mt76, &link->msta_link, ++ true); ++ + err = mt7996_mac_sta_init_link(dev, link_conf, link_sta, link, + link_id); + if (err) diff --git a/package/kernel/mt76/patches/smartrg-4000-1000-mtk-wifi-mt76-mt7996-add-debug-tool.patch b/package/kernel/mt76/patches/smartrg-4000-1000-mtk-wifi-mt76-mt7996-add-debug-tool.patch new file mode 100644 index 0000000000..531d31f427 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-1000-mtk-wifi-mt76-mt7996-add-debug-tool.patch @@ -0,0 +1,5116 @@ +From 1e463d48da75799dd89a9ba28eb37e1e18c4a40b Mon Sep 17 00:00:00 2001 +From: Shayne Chen +Date: Fri, 24 Mar 2023 14:02:32 +0800 +Subject: [PATCH 013/223] mtk: mt76: mt7996: add debug tool + +Add PSM bit in sta_info + +Remove the duplicate function in mtk_debugfs.c & mtk_debug_i.c +Only enable mt7996_mcu_fw_log_2_host function in mcu.c + +Support more ids category NDPA/NDP TXD/FBK and debug log recommended by +CTD members. + +This commit equals to run the follwoing commands on Logan driver: +command: +1. iwpriv ra0 set fw_dbg=1:84 +2. iwpriv ra0 set fw_dbg=2:84 +3. iwpriv ra0 set fw_dbg=1:101 + +mtk: wifi: mt76: mt7996: add wtbl_info support for mt7992 + +mtk: wifi: mt76: mt7996: add mt7992 & mt7996 CR debug offset revision + +mtk: wifi: mt76: mt7992: refactor code for FW log + +Refactor code for FW log. + +mtk: wifi: mt76: mt7996: support disable muru debug info when recording fwlog + +When we record fwlog, we will also enable recording muru debug info log by +default. However, in certain test scenarios, this can result in +recording too many logs, causing inconvenience during issue analysis. +Therefore, this commit adds an debug option, fw_debug_muru_disable, in +debugfs. User can modify this option to enable/disable recording muru +debug info log. + +[Usage] +Set: +$ echo val > debugfs/fw_debug_muru_disable +Get: +$ cat debugfs/fw_debug_muru_disable + +val can be the following values: +0 = enable recording muru debug info (Default value) +1 = disable recording muru debug info + +mtk: wifi: mt76: mt7996: add adie id & ver dump + +Do not show fw version in fw_wm_info. +The fw_wm_info is used to dump fw status when wm crash. When wm crash, +we are not able to use any mcu command. + +Change-Id: Ie10390b01f17db893dbfbf3221bf63a4bd1fe38f +Change-Id: I4483f9f506ecbdbb49c2ceb99ec76c32b930c67e +Change-Id: I00c760b31009142848e32b1249d305800585e7fd +Change-Id: Ifddd4db86982d39f2d39d198b8f5d3e7028983c2 +Change-Id: I591b558a9eec2fbd46d166c9bb1580a94e22072c +Signed-off-by: Howard Hsu +Signed-off-by: MeiChia Chiu +Signed-off-by: StanleyYP Wang +Signed-off-by: Benjamin Lin +Signed-off-by: Shayne Chen +Signed-off-by: Peter Chiu +--- + mt76.h | 2 + + mt7996/Makefile | 4 + + mt7996/coredump.c | 10 +- + mt7996/coredump.h | 7 + + mt7996/debugfs.c | 128 ++- + mt7996/mac.c | 3 + + mt7996/mt7996.h | 13 + + mt7996/mtk_debug.h | 2286 ++++++++++++++++++++++++++++++++++++++ + mt7996/mtk_debugfs.c | 2506 ++++++++++++++++++++++++++++++++++++++++++ + mt7996/mtk_mcu.c | 39 + + mt7996/mtk_mcu.h | 19 + + tools/CMakeLists.txt | 7 + + tools/fwlog.c | 25 +- + 13 files changed, 5024 insertions(+), 25 deletions(-) + create mode 100644 mt7996/mtk_debug.h + create mode 100644 mt7996/mtk_debugfs.c + create mode 100644 mt7996/mtk_mcu.c + create mode 100644 mt7996/mtk_mcu.h + +--- a/mt7996/Makefile ++++ b/mt7996/Makefile +@@ -1,5 +1,8 @@ + # SPDX-License-Identifier: BSD-3-Clause-Clear + ++ccflags-y += -DCONFIG_MT76_LEDS ++ccflags-y += -DCONFIG_MTK_DEBUG ++ + obj-$(CONFIG_MT7996E) += mt7996e.o + + mt7996e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ +@@ -7,3 +10,5 @@ mt7996e-y := pci.o init.o dma.o eeprom.o + + mt7996e-$(CONFIG_MT7996_NPU) += npu.o + mt7996e-$(CONFIG_DEV_COREDUMP) += coredump.o ++ ++mt7996e-y += mtk_debugfs.o mtk_mcu.o +--- a/mt7996/debugfs.c ++++ b/mt7996/debugfs.c +@@ -320,11 +320,39 @@ mt7996_fw_debug_wm_set(void *data, u64 v + DEBUG_SPL, + DEBUG_RPT_RX, + DEBUG_RPT_RA = 68, +- } debug; ++ DEBUG_IDS_SND = 84, ++ DEBUG_IDS_PP = 93, ++ DEBUG_IDS_RA = 94, ++ DEBUG_IDS_BF = 95, ++ DEBUG_IDS_SR = 96, ++ DEBUG_IDS_RU = 97, ++ DEBUG_IDS_MUMIMO = 98, ++ DEBUG_IDS_ERR_LOG = 101, ++ }; ++ u8 debug_category[] = { ++ DEBUG_TXCMD, ++ DEBUG_CMD_RPT_TX, ++ DEBUG_CMD_RPT_TRIG, ++ DEBUG_SPL, ++ DEBUG_RPT_RX, ++ DEBUG_RPT_RA, ++ DEBUG_IDS_SND, ++ DEBUG_IDS_PP, ++ DEBUG_IDS_RA, ++ DEBUG_IDS_BF, ++ DEBUG_IDS_SR, ++ DEBUG_IDS_RU, ++ DEBUG_IDS_MUMIMO, ++ DEBUG_IDS_ERR_LOG, ++ }; + bool tx, rx, en; + int ret; ++ u8 i; + + dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0; ++#ifdef CONFIG_MTK_DEBUG ++ dev->fw_debug_wm = val; ++#endif + + if (dev->fw_debug_bin) + val = MCU_FW_LOG_RELAY; +@@ -339,18 +367,21 @@ mt7996_fw_debug_wm_set(void *data, u64 v + if (ret) + return ret; + +- for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RA; debug++) { +- if (debug == 67) +- continue; +- +- if (debug == DEBUG_RPT_RX) ++ for (i = 0; i < ARRAY_SIZE(debug_category); i++) { ++ if (debug_category[i] == DEBUG_RPT_RX) + val = en && rx; + else + val = en && tx; + +- ret = mt7996_mcu_fw_dbg_ctrl(dev, debug, val); ++ ret = mt7996_mcu_fw_dbg_ctrl(dev, debug_category[i], val); + if (ret) + return ret; ++ ++ if (debug_category[i] == DEBUG_IDS_SND && en) { ++ ret = mt7996_mcu_fw_dbg_ctrl(dev, debug_category[i], 2); ++ if (ret) ++ return ret; ++ } + } + + return 0; +@@ -423,6 +454,39 @@ remove_buf_file_cb(struct dentry *f) + } + + static int ++mt7996_fw_debug_muru_set(void *data) ++{ ++ struct mt7996_dev *dev = data; ++ enum { ++ DEBUG_BSRP_STATUS = 256, ++ DEBUG_TX_DATA_BYTE_CONUT, ++ DEBUG_RX_DATA_BYTE_CONUT, ++ DEBUG_RX_TOTAL_BYTE_CONUT, ++ DEBUG_INVALID_TID_BSR, ++ DEBUG_UL_LONG_TERM_PPDU_TYPE, ++ DEBUG_DL_LONG_TERM_PPDU_TYPE, ++ DEBUG_PPDU_CLASS_TRIG_ONOFF, ++ DEBUG_AIRTIME_BUSY_STATUS, ++ DEBUG_UL_OFDMA_MIMO_STATUS, ++ DEBUG_RU_CANDIDATE, ++ DEBUG_MEC_UPDATE_AMSDU, ++ } debug; ++ int ret; ++ ++ if (dev->fw_debug_muru_disable) ++ return 0; ++ ++ for (debug = DEBUG_BSRP_STATUS; debug <= DEBUG_MEC_UPDATE_AMSDU; debug++) { ++ ret = mt7996_mcu_muru_dbg_info(dev, debug, ++ dev->fw_debug_bin & BIT(0)); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int + mt7996_fw_debug_bin_set(void *data, u64 val) + { + static struct rchan_callbacks relay_cb = { +@@ -430,17 +494,23 @@ mt7996_fw_debug_bin_set(void *data, u64 + .remove_buf_file = remove_buf_file_cb, + }; + struct mt7996_dev *dev = data; ++ int ret; + +- if (!dev->relay_fwlog) ++ if (!dev->relay_fwlog) { + dev->relay_fwlog = relay_open("fwlog_data", dev->debugfs_dir, + 1500, 512, &relay_cb, NULL); +- if (!dev->relay_fwlog) +- return -ENOMEM; ++ if (!dev->relay_fwlog) ++ return -ENOMEM; ++ } + + dev->fw_debug_bin = val; + + relay_reset(dev->relay_fwlog); + ++ ret = mt7996_fw_debug_muru_set(dev); ++ if (ret) ++ return ret; ++ + return mt7996_fw_debug_wm_set(dev, dev->fw_debug_wm); + } + +@@ -954,6 +1024,30 @@ mt7996_rf_regval_set(void *data, u64 val + DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7996_rf_regval_get, + mt7996_rf_regval_set, "0x%08llx\n"); + ++static int ++mt7996_fw_debug_muru_disable_set(void *data, u64 val) ++{ ++ struct mt7996_dev *dev = data; ++ ++ dev->fw_debug_muru_disable = !!val; ++ ++ return 0; ++} ++ ++static int ++mt7996_fw_debug_muru_disable_get(void *data, u64 *val) ++{ ++ struct mt7996_dev *dev = data; ++ ++ *val = dev->fw_debug_muru_disable; ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_muru_disable, ++ mt7996_fw_debug_muru_disable_get, ++ mt7996_fw_debug_muru_disable_set, "%lld\n"); ++ + int mt7996_init_debugfs(struct mt7996_dev *dev) + { + struct dentry *dir; +@@ -989,9 +1083,16 @@ int mt7996_init_debugfs(struct mt7996_de + &fops_radar_trigger); + debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir, + mt7996_rdd_monitor); ++ debugfs_create_file("fw_debug_muru_disable", 0600, dir, dev, ++ &fops_fw_debug_muru_disable); + + dev->debugfs_dir = dir; + ++#ifdef CONFIG_MTK_DEBUG ++ debugfs_create_u16("wlan_idx", 0600, dir, &dev->wlan_idx); ++ mt7996_mtk_init_debugfs(dev, dir); ++#endif ++ + return 0; + } + +@@ -1003,7 +1104,11 @@ mt7996_debugfs_write_fwlog(struct mt7996 + unsigned long flags; + void *dest; + ++ if (!dev->relay_fwlog) ++ return; ++ + spin_lock_irqsave(&lock, flags); ++ + dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4); + if (dest) { + *(u32 *)dest = hdrlen + len; +@@ -1036,9 +1141,6 @@ void mt7996_debugfs_rx_fw_monitor(struct + .msg_type = cpu_to_le16(PKT_TYPE_RX_FW_MONITOR), + }; + +- if (!dev->relay_fwlog) +- return; +- + hdr.serial_id = cpu_to_le16(dev->fw_debug_seq++); + hdr.timestamp = cpu_to_le32(mt76_rr(dev, MT_LPON_FRCR(0))); + hdr.len = *(__le16 *)data; +--- a/mt7996/mt7996.h ++++ b/mt7996/mt7996.h +@@ -512,6 +512,7 @@ struct mt7996_dev { + u8 fw_debug_wa; + u8 fw_debug_bin; + u16 fw_debug_seq; ++ bool fw_debug_muru_disable; + + u32 token_debug_idx; + +@@ -530,6 +531,17 @@ struct mt7996_dev { + u8 type:4; + u8 fem:4; + } var; ++ ++#ifdef CONFIG_MTK_DEBUG ++ u16 wlan_idx; ++ struct { ++ u8 sku_disable; ++ u32 fw_dbg_module; ++ u8 fw_dbg_lv; ++ u32 bcn_total_cnt[__MT_MAX_BAND]; ++ } dbg; ++ const struct mt7996_dbg_reg_desc *dbg_reg; ++#endif + }; + + enum { +@@ -956,7 +968,8 @@ int mt7996_mmio_wed_init(struct mt7996_d + u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id); + + #ifdef CONFIG_MTK_DEBUG +-int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir); ++int mt7996_mtk_init_debugfs(struct mt7996_dev *dev, struct dentry *dir); ++int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val); + #endif + + int mt7996_dma_rro_init(struct mt7996_dev *dev); +--- /dev/null ++++ b/mt7996/mtk_debug.h +@@ -0,0 +1,2286 @@ ++#ifndef __MTK_DEBUG_H ++#define __MTK_DEBUG_H ++ ++#ifdef CONFIG_MTK_DEBUG ++#define NO_SHIFT_DEFINE 0xFFFFFFFF ++#define BITS(m, n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) ++ ++#define GET_FIELD(_field, _reg) \ ++ ({ \ ++ (((_reg) & (_field##_MASK)) >> (_field##_SHIFT)); \ ++ }) ++ ++#define __DBG_OFFS(id) (dev->dbg_reg->offs_rev[(id)]) ++ ++enum dbg_offs_rev { ++ AGG_AALCR2, ++ AGG_AALCR3, ++ AGG_AALCR4, ++ AGG_AALCR5, ++ AGG_AALCR6, ++ AGG_AALCR7, ++ MIB_TDRCR0, ++ MIB_TDRCR1, ++ MIB_TDRCR2, ++ MIB_TDRCR3, ++ MIB_TDRCR4, ++ MIB_RSCR26, ++ MIB_TSCR18, ++ MIB_TRDR0, ++ MIB_TRDR2, ++ MIB_TRDR3, ++ MIB_TRDR4, ++ MIB_TRDR5, ++ MIB_TRDR6, ++ MIB_TRDR7, ++ MIB_TRDR8, ++ MIB_TRDR9, ++ MIB_TRDR10, ++ MIB_TRDR11, ++ MIB_TRDR12, ++ MIB_TRDR13, ++ MIB_TRDR14, ++ MIB_TRDR15, ++ MIB_MSR0, ++ MIB_MSR1, ++ MIB_MSR2, ++ MIB_MCTR5, ++ MIB_MCTR6, ++ __MT_DBG_OFFS_REV_MAX, ++}; ++ ++static const u32 mt7996_dbg_offs[] = { ++ [AGG_AALCR2] = 0x128, ++ [AGG_AALCR3] = 0x12c, ++ [AGG_AALCR4] = 0x130, ++ [AGG_AALCR5] = 0x134, ++ [AGG_AALCR6] = 0x138, ++ [AGG_AALCR7] = 0x13c, ++ [MIB_TDRCR0] = 0x728, ++ [MIB_TDRCR1] = 0x72c, ++ [MIB_TDRCR2] = 0x730, ++ [MIB_TDRCR3] = 0x734, ++ [MIB_TDRCR4] = 0x738, ++ [MIB_RSCR26] = 0x950, ++ [MIB_TSCR18] = 0xa1c, ++ [MIB_TRDR0] = 0xa24, ++ [MIB_TRDR2] = 0xa2c, ++ [MIB_TRDR3] = 0xa30, ++ [MIB_TRDR4] = 0xa34, ++ [MIB_TRDR5] = 0xa38, ++ [MIB_TRDR6] = 0xa3c, ++ [MIB_TRDR7] = 0xa40, ++ [MIB_TRDR8] = 0xa44, ++ [MIB_TRDR9] = 0xa48, ++ [MIB_TRDR10] = 0xa4c, ++ [MIB_TRDR11] = 0xa50, ++ [MIB_TRDR12] = 0xa54, ++ [MIB_TRDR13] = 0xa58, ++ [MIB_TRDR14] = 0xa5c, ++ [MIB_TRDR15] = 0xa60, ++ [MIB_MSR0] = 0xa64, ++ [MIB_MSR1] = 0xa68, ++ [MIB_MSR2] = 0xa6c, ++ [MIB_MCTR5] = 0xa70, ++ [MIB_MCTR6] = 0xa74, ++}; ++ ++static const u32 mt7992_dbg_offs[] = { ++ [AGG_AALCR2] = 0x12c, ++ [AGG_AALCR3] = 0x130, ++ [AGG_AALCR4] = 0x134, ++ [AGG_AALCR5] = 0x138, ++ [AGG_AALCR6] = 0x13c, ++ [AGG_AALCR7] = 0x140, ++ [MIB_TDRCR0] = 0x768, ++ [MIB_TDRCR1] = 0x76c, ++ [MIB_TDRCR2] = 0x770, ++ [MIB_TDRCR3] = 0x774, ++ [MIB_TDRCR4] = 0x778, ++ [MIB_RSCR26] = 0x994, ++ [MIB_TSCR18] = 0xb18, ++ [MIB_TRDR0] = 0xb20, ++ [MIB_TRDR2] = 0xb28, ++ [MIB_TRDR3] = 0xb2c, ++ [MIB_TRDR4] = 0xb30, ++ [MIB_TRDR5] = 0xb34, ++ [MIB_TRDR6] = 0xb38, ++ [MIB_TRDR7] = 0xb3c, ++ [MIB_TRDR8] = 0xb40, ++ [MIB_TRDR9] = 0xb44, ++ [MIB_TRDR10] = 0xb48, ++ [MIB_TRDR11] = 0xb4c, ++ [MIB_TRDR12] = 0xb50, ++ [MIB_TRDR13] = 0xb54, ++ [MIB_TRDR14] = 0xb58, ++ [MIB_TRDR15] = 0xb5c, ++ [MIB_MSR0] = 0xb60, ++ [MIB_MSR1] = 0xb64, ++ [MIB_MSR2] = 0xb68, ++ [MIB_MCTR5] = 0xb6c, ++ [MIB_MCTR6] = 0xb70, ++}; ++ ++/* used to differentiate between generations */ ++struct mt7996_dbg_reg_desc { ++ const u32 id; ++ const u32 *offs_rev; ++}; ++ ++/* AGG */ ++#define BN0_WF_AGG_TOP_BASE 0x820e2000 ++#define BN1_WF_AGG_TOP_BASE 0x820f2000 ++#define IP1_BN0_WF_AGG_TOP_BASE 0x830e2000 ++ ++#define BN0_WF_AGG_TOP_SCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x0) // 2000 ++#define BN0_WF_AGG_TOP_SCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x4) // 2004 ++#define BN0_WF_AGG_TOP_SCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x8) // 2008 ++#define BN0_WF_AGG_TOP_BCR_ADDR (BN0_WF_AGG_TOP_BASE + 0xc) // 200C ++#define BN0_WF_AGG_TOP_BWCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x10) // 2010 ++#define BN0_WF_AGG_TOP_ARCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x14) // 2014 ++#define BN0_WF_AGG_TOP_ARUCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x18) // 2018 ++#define BN0_WF_AGG_TOP_ARDCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x1c) // 201C ++#define BN0_WF_AGG_TOP_AALCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x20) // 2020 ++#define BN0_WF_AGG_TOP_AALCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x24) // 2024 ++#define BN0_WF_AGG_TOP_PCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x28) // 2028 ++#define BN0_WF_AGG_TOP_PCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x2c) // 202C ++#define BN0_WF_AGG_TOP_TTCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x30) // 2030 ++#define BN0_WF_AGG_TOP_TTCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x34) // 2034 ++#define BN0_WF_AGG_TOP_ACR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x38) // 2038 ++#define BN0_WF_AGG_TOP_ACR4_ADDR (BN0_WF_AGG_TOP_BASE + 0x3c) // 203C ++#define BN0_WF_AGG_TOP_ACR5_ADDR (BN0_WF_AGG_TOP_BASE + 0x40) // 2040 ++#define BN0_WF_AGG_TOP_ACR6_ADDR (BN0_WF_AGG_TOP_BASE + 0x44) // 2044 ++#define BN0_WF_AGG_TOP_ACR8_ADDR (BN0_WF_AGG_TOP_BASE + 0x4c) // 204C ++#define BN0_WF_AGG_TOP_MRCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x50) // 2050 ++#define BN0_WF_AGG_TOP_MMPDR_ADDR (BN0_WF_AGG_TOP_BASE + 0x54) // 2054 ++#define BN0_WF_AGG_TOP_GFPDR_ADDR (BN0_WF_AGG_TOP_BASE + 0x58) // 2058 ++#define BN0_WF_AGG_TOP_VHTPDR_ADDR (BN0_WF_AGG_TOP_BASE + 0x5c) // 205C ++#define BN0_WF_AGG_TOP_HEPDR_ADDR (BN0_WF_AGG_TOP_BASE + 0x60) // 2060 ++#define BN0_WF_AGG_TOP_CTCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x64) // 2064 ++#define BN0_WF_AGG_TOP_ATCR3_ADDR (BN0_WF_AGG_TOP_BASE + 0x68) // 2068 ++#define BN0_WF_AGG_TOP_SRCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x6c) // 206C ++#define BN0_WF_AGG_TOP_VBCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x70) // 2070 ++#define BN0_WF_AGG_TOP_TCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x74) // 2074 ++#define BN0_WF_AGG_TOP_SRHS_ADDR (BN0_WF_AGG_TOP_BASE + 0x78) // 2078 ++#define BN0_WF_AGG_TOP_DBRCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x7c) // 207C ++#define BN0_WF_AGG_TOP_DBRCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x80) // 2080 ++#define BN0_WF_AGG_TOP_CTETCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x84) // 2084 ++#define BN0_WF_AGG_TOP_WPDR_ADDR (BN0_WF_AGG_TOP_BASE + 0x88) // 2088 ++#define BN0_WF_AGG_TOP_PLRPDR_ADDR (BN0_WF_AGG_TOP_BASE + 0x8c) // 208C ++#define BN0_WF_AGG_TOP_CECR_ADDR (BN0_WF_AGG_TOP_BASE + 0x90) // 2090 ++#define BN0_WF_AGG_TOP_OMRCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x94) // 2094 ++#define BN0_WF_AGG_TOP_OMRCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x98) // 2098 ++#define BN0_WF_AGG_TOP_OMRCR2_ADDR (BN0_WF_AGG_TOP_BASE + 0x9c) // 209C ++#define BN0_WF_AGG_TOP_OMRCR3_ADDR (BN0_WF_AGG_TOP_BASE + 0xa0) // 20A0 ++#define BN0_WF_AGG_TOP_TMCR_ADDR (BN0_WF_AGG_TOP_BASE + 0xa4) // 20A4 ++#define BN0_WF_AGG_TOP_TWTCR_ADDR (BN0_WF_AGG_TOP_BASE + 0xa8) // 20A8 ++#define BN0_WF_AGG_TOP_TWTSTACR_ADDR (BN0_WF_AGG_TOP_BASE + 0xac) // 20AC ++#define BN0_WF_AGG_TOP_TWTE0TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xb0) // 20B0 ++#define BN0_WF_AGG_TOP_TWTE1TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xb4) // 20B4 ++#define BN0_WF_AGG_TOP_TWTE2TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xb8) // 20B8 ++#define BN0_WF_AGG_TOP_TWTE3TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xbc) // 20BC ++#define BN0_WF_AGG_TOP_TWTE4TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xc0) // 20C0 ++#define BN0_WF_AGG_TOP_TWTE5TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xc4) // 20C4 ++#define BN0_WF_AGG_TOP_TWTE6TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xc8) // 20C8 ++#define BN0_WF_AGG_TOP_TWTE7TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xcc) // 20CC ++#define BN0_WF_AGG_TOP_TWTE8TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xd0) // 20D0 ++#define BN0_WF_AGG_TOP_TWTE9TB_ADDR (BN0_WF_AGG_TOP_BASE + 0xd4) // 20D4 ++#define BN0_WF_AGG_TOP_TWTEATB_ADDR (BN0_WF_AGG_TOP_BASE + 0xd8) // 20D8 ++#define BN0_WF_AGG_TOP_TWTEBTB_ADDR (BN0_WF_AGG_TOP_BASE + 0xdc) // 20DC ++#define BN0_WF_AGG_TOP_TWTECTB_ADDR (BN0_WF_AGG_TOP_BASE + 0xe0) // 20E0 ++#define BN0_WF_AGG_TOP_TWTEDTB_ADDR (BN0_WF_AGG_TOP_BASE + 0xe4) // 20E4 ++#define BN0_WF_AGG_TOP_TWTEETB_ADDR (BN0_WF_AGG_TOP_BASE + 0xe8) // 20E8 ++#define BN0_WF_AGG_TOP_TWTEFTB_ADDR (BN0_WF_AGG_TOP_BASE + 0xec) // 20EC ++#define BN0_WF_AGG_TOP_ATCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x108) // 2108 ++#define BN0_WF_AGG_TOP_ATCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x10c) // 210C ++#define BN0_WF_AGG_TOP_TCCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x110) // 2110 ++#define BN0_WF_AGG_TOP_TFCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x114) // 2114 ++#define BN0_WF_AGG_TOP_MUCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x118) // 2118 ++#define BN0_WF_AGG_TOP_MUCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x11c) // 211C ++#define BN0_WF_AGG_TOP_AALCR2_ADDR (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR2)) ++#define BN0_WF_AGG_TOP_AALCR3_ADDR (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR3)) ++#define BN0_WF_AGG_TOP_AALCR4_ADDR (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR4)) ++#define BN0_WF_AGG_TOP_AALCR5_ADDR (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR5)) ++#define BN0_WF_AGG_TOP_AALCR6_ADDR (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR6)) ++#define BN0_WF_AGG_TOP_AALCR7_ADDR (BN0_WF_AGG_TOP_BASE + __DBG_OFFS(AGG_AALCR7)) ++#define BN0_WF_AGG_TOP_CSDCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x150) // 2150 ++#define BN0_WF_AGG_TOP_CSDCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x154) // 2154 ++#define BN0_WF_AGG_TOP_CSDCR2_ADDR (BN0_WF_AGG_TOP_BASE + 0x158) // 2158 ++#define BN0_WF_AGG_TOP_CSDCR3_ADDR (BN0_WF_AGG_TOP_BASE + 0x15c) // 215C ++#define BN0_WF_AGG_TOP_CSDCR4_ADDR (BN0_WF_AGG_TOP_BASE + 0x160) // 2160 ++#define BN0_WF_AGG_TOP_DYNSCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x178) // 2178 ++#define BN0_WF_AGG_TOP_DYNSSCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x198) // 2198 ++#define BN0_WF_AGG_TOP_TCDCNT0_ADDR (BN0_WF_AGG_TOP_BASE + 0x2c8) // 22C8 ++#define BN0_WF_AGG_TOP_TCDCNT1_ADDR (BN0_WF_AGG_TOP_BASE + 0x2cc) // 22CC ++#define BN0_WF_AGG_TOP_TCSR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x2d0) // 22D0 ++#define BN0_WF_AGG_TOP_TCSR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x2d4) // 22D4 ++#define BN0_WF_AGG_TOP_TCSR2_ADDR (BN0_WF_AGG_TOP_BASE + 0x2d8) // 22D8 ++#define BN0_WF_AGG_TOP_DCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x2e4) // 22E4 ++#define BN0_WF_AGG_TOP_SMDCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x2e8) // 22E8 ++#define BN0_WF_AGG_TOP_TXCMDSMCR_ADDR (BN0_WF_AGG_TOP_BASE + 0x2ec) // 22EC ++#define BN0_WF_AGG_TOP_SMCR0_ADDR (BN0_WF_AGG_TOP_BASE + 0x2f0) // 22F0 ++#define BN0_WF_AGG_TOP_SMCR1_ADDR (BN0_WF_AGG_TOP_BASE + 0x2f4) // 22F4 ++#define BN0_WF_AGG_TOP_SMCR2_ADDR (BN0_WF_AGG_TOP_BASE + 0x2f8) // 22F8 ++#define BN0_WF_AGG_TOP_SMCR3_ADDR (BN0_WF_AGG_TOP_BASE + 0x2fc) // 22FC ++ ++#define BN0_WF_AGG_TOP_AALCR0_AC01_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR0_ADDR ++#define BN0_WF_AGG_TOP_AALCR0_AC01_AGG_LIMIT_MASK 0x03FF0000 // AC01_AGG_LIMIT[25..16] ++#define BN0_WF_AGG_TOP_AALCR0_AC01_AGG_LIMIT_SHFT 16 ++#define BN0_WF_AGG_TOP_AALCR0_AC00_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR0_ADDR ++#define BN0_WF_AGG_TOP_AALCR0_AC00_AGG_LIMIT_MASK 0x000003FF // AC00_AGG_LIMIT[9..0] ++#define BN0_WF_AGG_TOP_AALCR0_AC00_AGG_LIMIT_SHFT 0 ++ ++#define BN0_WF_AGG_TOP_AALCR1_AC03_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR1_ADDR ++#define BN0_WF_AGG_TOP_AALCR1_AC03_AGG_LIMIT_MASK 0x03FF0000 // AC03_AGG_LIMIT[25..16] ++#define BN0_WF_AGG_TOP_AALCR1_AC03_AGG_LIMIT_SHFT 16 ++#define BN0_WF_AGG_TOP_AALCR1_AC02_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR1_ADDR ++#define BN0_WF_AGG_TOP_AALCR1_AC02_AGG_LIMIT_MASK 0x000003FF // AC02_AGG_LIMIT[9..0] ++#define BN0_WF_AGG_TOP_AALCR1_AC02_AGG_LIMIT_SHFT 0 ++ ++#define BN0_WF_AGG_TOP_AALCR2_AC11_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR2_ADDR ++#define BN0_WF_AGG_TOP_AALCR2_AC11_AGG_LIMIT_MASK 0x03FF0000 // AC11_AGG_LIMIT[25..16] ++#define BN0_WF_AGG_TOP_AALCR2_AC11_AGG_LIMIT_SHFT 16 ++#define BN0_WF_AGG_TOP_AALCR2_AC10_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR2_ADDR ++#define BN0_WF_AGG_TOP_AALCR2_AC10_AGG_LIMIT_MASK 0x000003FF // AC10_AGG_LIMIT[9..0] ++#define BN0_WF_AGG_TOP_AALCR2_AC10_AGG_LIMIT_SHFT 0 ++ ++#define BN0_WF_AGG_TOP_AALCR3_AC13_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR3_ADDR ++#define BN0_WF_AGG_TOP_AALCR3_AC13_AGG_LIMIT_MASK 0x03FF0000 // AC13_AGG_LIMIT[25..16] ++#define BN0_WF_AGG_TOP_AALCR3_AC13_AGG_LIMIT_SHFT 16 ++#define BN0_WF_AGG_TOP_AALCR3_AC12_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR3_ADDR ++#define BN0_WF_AGG_TOP_AALCR3_AC12_AGG_LIMIT_MASK 0x000003FF // AC12_AGG_LIMIT[9..0] ++#define BN0_WF_AGG_TOP_AALCR3_AC12_AGG_LIMIT_SHFT 0 ++ ++#define BN0_WF_AGG_TOP_AALCR4_AC21_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR4_ADDR ++#define BN0_WF_AGG_TOP_AALCR4_AC21_AGG_LIMIT_MASK 0x03FF0000 // AC21_AGG_LIMIT[25..16] ++#define BN0_WF_AGG_TOP_AALCR4_AC21_AGG_LIMIT_SHFT 16 ++#define BN0_WF_AGG_TOP_AALCR4_AC20_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR4_ADDR ++#define BN0_WF_AGG_TOP_AALCR4_AC20_AGG_LIMIT_MASK 0x000003FF // AC20_AGG_LIMIT[9..0] ++#define BN0_WF_AGG_TOP_AALCR4_AC20_AGG_LIMIT_SHFT 0 ++ ++#define BN0_WF_AGG_TOP_AALCR5_AC23_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR5_ADDR ++#define BN0_WF_AGG_TOP_AALCR5_AC23_AGG_LIMIT_MASK 0x03FF0000 // AC23_AGG_LIMIT[25..16] ++#define BN0_WF_AGG_TOP_AALCR5_AC23_AGG_LIMIT_SHFT 16 ++#define BN0_WF_AGG_TOP_AALCR5_AC22_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR5_ADDR ++#define BN0_WF_AGG_TOP_AALCR5_AC22_AGG_LIMIT_MASK 0x000003FF // AC22_AGG_LIMIT[9..0] ++#define BN0_WF_AGG_TOP_AALCR5_AC22_AGG_LIMIT_SHFT 0 ++ ++#define BN0_WF_AGG_TOP_AALCR6_AC31_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR6_ADDR ++#define BN0_WF_AGG_TOP_AALCR6_AC31_AGG_LIMIT_MASK 0x03FF0000 // AC31_AGG_LIMIT[25..16] ++#define BN0_WF_AGG_TOP_AALCR6_AC31_AGG_LIMIT_SHFT 16 ++#define BN0_WF_AGG_TOP_AALCR6_AC30_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR6_ADDR ++#define BN0_WF_AGG_TOP_AALCR6_AC30_AGG_LIMIT_MASK 0x000003FF // AC30_AGG_LIMIT[9..0] ++#define BN0_WF_AGG_TOP_AALCR6_AC30_AGG_LIMIT_SHFT 0 ++#define BN0_WF_AGG_TOP_AALCR7_AC33_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR7_ADDR ++#define BN0_WF_AGG_TOP_AALCR7_AC33_AGG_LIMIT_MASK 0x03FF0000 // AC33_AGG_LIMIT[25..16] ++#define BN0_WF_AGG_TOP_AALCR7_AC33_AGG_LIMIT_SHFT 16 ++#define BN0_WF_AGG_TOP_AALCR7_AC32_AGG_LIMIT_ADDR BN0_WF_AGG_TOP_AALCR7_ADDR ++#define BN0_WF_AGG_TOP_AALCR7_AC32_AGG_LIMIT_MASK 0x000003FF // AC32_AGG_LIMIT[9..0] ++#define BN0_WF_AGG_TOP_AALCR7_AC32_AGG_LIMIT_SHFT 0 ++ ++/* DMA */ ++struct queue_desc { ++ u32 hw_desc_base; ++ u16 ring_size; ++ char *const ring_info; ++}; ++ ++// HOST DMA ++#define WF_WFDMA_HOST_DMA0_BASE 0xd4000 ++ ++#define WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x200) /* 4200 */ ++#define WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0X204) /* 4204 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x208) /* 4208 */ ++ ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_ADDR \ ++ WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK \ ++ 0x00000008 /* RX_DMA_BUSY[3] */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_ADDR \ ++ WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK \ ++ 0x00000004 /* RX_DMA_EN[2] */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_ADDR \ ++ WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK \ ++ 0x00000002 /* TX_DMA_BUSY[1] */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_ADDR \ ++ WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK \ ++ 0x00000001 /* TX_DMA_EN[0] */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 ++ ++ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x300) /* 4300 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x304) /* 4304 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x308) /* 4308 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x30c) /* 430C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x310) /* 4310 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x314) /* 4314 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x318) /* 4318 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x31c) /* 431C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x320) /* 4320 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x324) /* 4324 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x328) /* 4328 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x32c) /* 432C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x330) /* 4330 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x334) /* 4334 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x338) /* 4338 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x33c) /* 433C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x340) /* 4340 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x344) /* 4344 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x348) /* 4348 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x34c) /* 434C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x350) /* 4350 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x354) /* 4354 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x358) /* 4358 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x35c) /* 435C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x360) /* 4360 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x364) /* 4364 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x368) /* 4368 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x36c) /* 436C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x400) /* 4400 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x404) /* 4404 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x408) /* 4408 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x40c) /* 440C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x410) /* 4410 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x414) /* 4414 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x418) /* 4418 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x41c) /* 441C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x420) /* 4420 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x424) /* 4424 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x428) /* 4428 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x42c) /* 442C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING19_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x430) /* 4430 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING19_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x434) /* 4434 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING19_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x438) /* 4438 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING19_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x43c) /* 443C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING20_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x440) /* 4440 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING20_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x444) /* 4444 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING20_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x448) /* 4448 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING20_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x44c) /* 444C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING21_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x450) /* 4450 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING21_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x454) /* 4454 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING21_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x458) /* 4458 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING21_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x45c) /* 445c */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING22_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x460) // 4460 ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING22_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x464) // 4464 ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING22_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x468) // 4468 ++#define WF_WFDMA_HOST_DMA0_WPDMA_TX_RING22_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x46c) // 446C ++ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x500) /* 4500 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x504) /* 4504 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x508) /* 4508 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x50c) /* 450C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x510) /* 4510 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x514) /* 4514 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x518) /* 4518 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x51c) /* 451C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x520) /* 4520 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x524) /* 4524 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x528) /* 4528 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x52C) /* 452C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x530) /* 4530 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x534) /* 4534 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x538) /* 4538 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x53C) /* 453C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x540) /* 4540 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x544) /* 4544 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x548) /* 4548 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x54c) /* 454C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x550) /* 4550 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x554) /* 4554 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x558) /* 4558 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x55c) /* 455C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x560) /* 4560 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x564) /* 4564 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x568) /* 4568 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x56c) /* 456C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x570) /* 4570 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x574) /* 4574 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x578) /* 4578 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x57c) /* 457C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x580) /* 4580 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x584) /* 4584 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x588) /* 4588 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x58c) /* 458C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING9_CTRL0_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x590) /* 4590 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING9_CTRL1_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x594) /* 4594 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING9_CTRL2_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x598) /* 4598 */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING9_CTRL3_ADDR \ ++ (WF_WFDMA_HOST_DMA0_BASE + 0x59c) /* 459C */ ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING10_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5a0) // 45A0 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING10_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5a4) // 45A4 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING10_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5a8) // 45A8 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING10_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5ac) // 45AC ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING11_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5b0) // 45B0 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING11_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5b4) // 45B4 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING11_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5b8) // 45B8 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING11_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5bc) // 45BC ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING12_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5C0) // 45C0 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING12_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5C4) // 45C4 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING12_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5C8) // 45C8 ++#define WF_WFDMA_HOST_DMA0_WPDMA_RX_RING12_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_BASE + 0x5CC) // 45CC ++ ++// HOST PCIE1 DMA ++#define WF_WFDMA_HOST_DMA0_PCIE1_BASE 0xd8000 ++ ++#define WF_WFDMA_HOST_DMA0_PCIE1_HOST_INT_STA_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x200) // 8200 ++#define WF_WFDMA_HOST_DMA0_PCIE1_HOST_INT_ENA_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0X204) // 8204 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x208) // 8208 ++ ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_PDMA_BT_SIZE_SHFT 4 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK 0x00000008 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_RX_DMA_EN_MASK 0x00000004 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK 0x00000002 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_TX_DMA_EN_MASK 0x00000001 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 ++ ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING21_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x450) // 8450 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING21_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x454) // 8454 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING21_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x458) // 8458 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING21_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x45c) // 845C ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING22_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x460) // 8460 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING22_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x464) // 8464 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING22_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x468) // 8468 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING22_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x46c) // 846C ++ ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING3_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x530) // 8530 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING3_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x534) // 8534 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING3_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x538) // 8538 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING3_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x53C) // 853C ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING5_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x550) // 8550 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING5_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x554) // 8554 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING5_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x558) // 8558 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING5_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x55c) // 855C ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING6_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x560) // 8560 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING6_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x564) // 8564 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING6_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x568) // 8568 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING6_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x56c) // 856C ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL0_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x570) // 8570 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL1_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x574) // 8574 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL2_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x578) // 8578 ++#define WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL3_ADDR (WF_WFDMA_HOST_DMA0_PCIE1_BASE + 0x57c) // 857C ++//MCU DMA ++//#define WF_WFDMA_MCU_DMA0_BASE 0x02000 ++#define WF_WFDMA_MCU_DMA0_BASE 0x54000000 ++ ++#define WF_WFDMA_MCU_DMA0_HOST_INT_STA_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x200) // 0200 ++#define WF_WFDMA_MCU_DMA0_HOST_INT_ENA_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0X204) // 0204 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x208) // 0208 ++ ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_ADDR WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK 0x00000008 // RX_DMA_BUSY[3] ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_ADDR WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK 0x00000004 // RX_DMA_EN[2] ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_ADDR WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK 0x00000002 // TX_DMA_BUSY[1] ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_ADDR WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK 0x00000001 // TX_DMA_EN[0] ++#define WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 ++ ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x300) // 0300 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x304) // 0304 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x308) // 0308 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x30c) // 030C ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING1_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x310) // 0310 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING1_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x314) // 0314 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING1_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x318) // 0318 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING1_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x31c) // 031C ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING2_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x320) // 0320 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING2_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x324) // 0324 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING2_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x328) // 0328 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING2_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x32c) // 032C ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING3_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x330) // 0330 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING3_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x334) // 0334 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING3_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x338) // 0338 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING3_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x33c) // 033C ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING4_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x340) // 0340 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING4_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x344) // 0344 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING4_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x348) // 0348 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING4_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x34c) // 034C ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING5_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x350) // 0350 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING5_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x354) // 0354 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING5_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x358) // 0358 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING5_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x35c) // 035C ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING6_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x360) // 0360 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING6_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x364) // 0364 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING6_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x368) // 0368 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING6_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x36c) // 036C ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING7_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x370) // 0370 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING7_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x374) // 0374 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING7_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x378) // 0378 ++#define WF_WFDMA_MCU_DMA0_WPDMA_TX_RING7_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x37c) // 037C ++ ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x500) // 0500 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x504) // 0504 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x508) // 0508 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x50c) // 050C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x510) // 0510 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x514) // 0514 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x518) // 0518 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x51c) // 051C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING2_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x520) // 0520 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING2_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x524) // 0524 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING2_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x528) // 0528 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING2_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x52C) // 052C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING3_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x530) // 0530 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING3_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x534) // 0534 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING3_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x538) // 0538 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING3_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x53C) // 053C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING4_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x540) // 0540 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING4_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x544) // 0544 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING4_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x548) // 0548 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING4_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x54C) // 054C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING5_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x550) // 0550 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING5_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x554) // 0554 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING5_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x558) // 0558 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING5_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x55C) // 055C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING6_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x560) // 0560 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING6_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x564) // 0564 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING6_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x568) // 0568 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING6_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x56c) // 056C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING7_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x570) // 0570 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING7_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x574) // 0574 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING7_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x578) // 0578 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING7_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x57c) // 057C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING8_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x580) // 0580 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING8_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x584) // 0584 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING8_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x588) // 0588 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING8_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x58c) // 058C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING9_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x590) // 0590 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING9_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x594) // 0594 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING9_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x598) // 0598 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING9_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x59c) // 059C ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING10_CTRL0_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x5A0) // 05A0 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING10_CTRL1_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x5A4) // 05A4 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING10_CTRL2_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x5A8) // 05A8 ++#define WF_WFDMA_MCU_DMA0_WPDMA_RX_RING10_CTRL3_ADDR (WF_WFDMA_MCU_DMA0_BASE + 0x5Ac) // 05AC ++ ++// MEM DMA ++#define WF_WFDMA_MEM_DMA_BASE 0x58000000 ++ ++#define WF_WFDMA_MEM_DMA_HOST_INT_STA_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x200) // 0200 ++#define WF_WFDMA_MEM_DMA_HOST_INT_ENA_ADDR (WF_WFDMA_MEM_DMA_BASE + 0X204) // 0204 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x208) // 0208 ++ ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_ADDR WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK 0x00000008 // RX_DMA_BUSY[3] ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT 3 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_ADDR WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_MASK 0x00000004 // RX_DMA_EN[2] ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_SHFT 2 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_ADDR WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK 0x00000002 // TX_DMA_BUSY[1] ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT 1 ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_ADDR WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_ADDR ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_MASK 0x00000001 // TX_DMA_EN[0] ++#define WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_SHFT 0 ++ ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING0_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x300) // 0300 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING0_CTRL1_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x304) // 0304 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING0_CTRL2_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x308) // 0308 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING0_CTRL3_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x30c) // 030C ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING1_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x310) // 0310 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING1_CTRL1_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x314) // 0314 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING1_CTRL2_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x318) // 0318 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING1_CTRL3_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x31c) // 031C ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING2_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x320) // 0320 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING2_CTRL1_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x324) // 0324 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING2_CTRL2_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x328) // 0328 ++#define WF_WFDMA_MEM_DMA_WPDMA_TX_RING2_CTRL3_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x32c) // 032C ++ ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING0_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x500) // 0500 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING0_CTRL1_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x504) // 0504 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING0_CTRL2_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x508) // 0508 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING0_CTRL3_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x50c) // 050C ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING1_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x510) // 0510 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING1_CTRL1_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x514) // 0514 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING1_CTRL2_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x518) // 0518 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING1_CTRL3_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x51c) // 051C ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING2_CTRL0_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x520) // 0520 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING2_CTRL1_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x524) // 0524 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING2_CTRL2_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x528) // 0528 ++#define WF_WFDMA_MEM_DMA_WPDMA_RX_RING2_CTRL3_ADDR (WF_WFDMA_MEM_DMA_BASE + 0x52C) // 052C ++ ++/* MIB */ ++#define WF_UMIB_TOP_BASE 0x820cd000 ++#define BN0_WF_MIB_TOP_BASE 0x820ed000 ++#define BN1_WF_MIB_TOP_BASE 0x820fd000 ++#define IP1_BN0_WF_MIB_TOP_BASE 0x830ed000 ++ ++#define WF_UMIB_TOP_B0BROCR_ADDR (WF_UMIB_TOP_BASE + 0x484) // D484 ++#define WF_UMIB_TOP_B0BRBCR_ADDR (WF_UMIB_TOP_BASE + 0x4D4) // D4D4 ++#define WF_UMIB_TOP_B0BRDCR_ADDR (WF_UMIB_TOP_BASE + 0x524) // D524 ++#define WF_UMIB_TOP_B1BROCR_ADDR (WF_UMIB_TOP_BASE + 0x5E8) // D5E8 ++#define WF_UMIB_TOP_B2BROCR_ADDR (WF_UMIB_TOP_BASE + 0x74C) // D74C ++ ++#define BN0_WF_MIB_TOP_M0SCR0_ADDR (BN0_WF_MIB_TOP_BASE + 0x000) // D000 ++#define BN0_WF_MIB_TOP_M0SDR6_ADDR (BN0_WF_MIB_TOP_BASE + 0x020) // D020 ++#define BN0_WF_MIB_TOP_M0SDR9_ADDR (BN0_WF_MIB_TOP_BASE + 0x024) // D024 ++#define BN0_WF_MIB_TOP_M0SDR18_ADDR (BN0_WF_MIB_TOP_BASE + 0x030) // D030 ++#define BN0_WF_MIB_TOP_BTOCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x400) // D400 ++#define BN0_WF_MIB_TOP_BTBCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x450) // D450 ++#define BN0_WF_MIB_TOP_BTDCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x590) // D590 ++#define BN0_WF_MIB_TOP_BTCR_ADDR (BN0_WF_MIB_TOP_BASE + 0x5A0) // D5A0 ++#define BN0_WF_MIB_TOP_RVSR0_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RVSR0)) ++ ++#define BN0_WF_MIB_TOP_TSCR0_ADDR (BN0_WF_MIB_TOP_BASE + 0x6B0) // D6B0 ++#define BN0_WF_MIB_TOP_TSCR3_ADDR (BN0_WF_MIB_TOP_BASE + 0x6BC) // D6BC ++#define BN0_WF_MIB_TOP_TSCR4_ADDR (BN0_WF_MIB_TOP_BASE + 0x6C0) // D6C0 ++#define BN0_WF_MIB_TOP_TSCR5_ADDR (BN0_WF_MIB_TOP_BASE + 0x6C4) // D6C4 ++#define BN0_WF_MIB_TOP_TSCR6_ADDR (BN0_WF_MIB_TOP_BASE + 0x6C8) // D6C8 ++#define BN0_WF_MIB_TOP_TSCR7_ADDR (BN0_WF_MIB_TOP_BASE + 0x6D0) // D6D0 ++#define BN0_WF_MIB_TOP_TSCR8_ADDR (BN0_WF_MIB_TOP_BASE + 0x6CC) // D6CC ++ ++#define BN0_WF_MIB_TOP_TBCR0_ADDR (BN0_WF_MIB_TOP_BASE + 0x6EC) // D6EC ++#define BN0_WF_MIB_TOP_TBCR1_ADDR (BN0_WF_MIB_TOP_BASE + 0x6F0) // D6F0 ++#define BN0_WF_MIB_TOP_TBCR2_ADDR (BN0_WF_MIB_TOP_BASE + 0x6F4) // D6F4 ++#define BN0_WF_MIB_TOP_TBCR3_ADDR (BN0_WF_MIB_TOP_BASE + 0x6F8) // D6F8 ++#define BN0_WF_MIB_TOP_TBCR4_ADDR (BN0_WF_MIB_TOP_BASE + 0x6FC) // D6FC ++ ++#define BN0_WF_MIB_TOP_TDRCR0_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR0)) ++#define BN0_WF_MIB_TOP_TDRCR1_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR1)) ++#define BN0_WF_MIB_TOP_TDRCR2_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR2)) ++#define BN0_WF_MIB_TOP_TDRCR3_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR3)) ++#define BN0_WF_MIB_TOP_TDRCR4_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TDRCR4)) ++ ++#define BN0_WF_MIB_TOP_BTSCR0_ADDR (BN0_WF_MIB_TOP_BASE + 0x5E0) // D5E0 ++#define BN0_WF_MIB_TOP_BTSCR1_ADDR (BN0_WF_MIB_TOP_BASE + 0x5F0) // D5F0 ++#define BN0_WF_MIB_TOP_BTSCR2_ADDR (BN0_WF_MIB_TOP_BASE + 0x600) // D600 ++#define BN0_WF_MIB_TOP_BTSCR3_ADDR (BN0_WF_MIB_TOP_BASE + 0x610) // D610 ++#define BN0_WF_MIB_TOP_BTSCR4_ADDR (BN0_WF_MIB_TOP_BASE + 0x620) // D620 ++#define BN0_WF_MIB_TOP_BTSCR5_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_BTSCR5)) ++#define BN0_WF_MIB_TOP_BTSCR6_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_BTSCR6)) ++ ++#define BN0_WF_MIB_TOP_RSCR1_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR1)) ++#define BN0_WF_MIB_TOP_BSCR2_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_BSCR2)) ++#define BN0_WF_MIB_TOP_TSCR18_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TSCR18)) ++ ++#define BN0_WF_MIB_TOP_MSR0_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MSR0)) ++#define BN0_WF_MIB_TOP_MSR1_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MSR1)) ++#define BN0_WF_MIB_TOP_MSR2_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MSR2)) ++#define BN0_WF_MIB_TOP_MCTR5_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MCTR5)) ++#define BN0_WF_MIB_TOP_MCTR6_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_MCTR6)) ++ ++#define BN0_WF_MIB_TOP_RSCR26_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_RSCR26)) ++#define BN0_WF_MIB_TOP_RSCR27_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR27)) ++#define BN0_WF_MIB_TOP_RSCR28_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR28)) ++#define BN0_WF_MIB_TOP_RSCR31_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR31)) ++#define BN0_WF_MIB_TOP_RSCR33_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR33)) ++#define BN0_WF_MIB_TOP_RSCR35_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR35)) ++#define BN0_WF_MIB_TOP_RSCR36_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_RSCR36)) ++ ++#define BN0_WF_MIB_TOP_TSCR3_AMPDU_MPDU_COUNT_MASK 0xFFFFFFFF // AMPDU_MPDU_COUNT[31..0] ++#define BN0_WF_MIB_TOP_TSCR4_AMPDU_ACKED_COUNT_MASK 0xFFFFFFFF // AMPDU_ACKED_COUNT[31..0] ++#define BN0_WF_MIB_TOP_M0SDR6_CHANNEL_IDLE_COUNT_MASK 0x0000FFFF // CHANNEL_IDLE_COUNT[15..0] ++#define BN0_WF_MIB_TOP_M0SDR9_CCA_NAV_TX_TIME_MASK 0x00FFFFFF // CCA_NAV_TX_TIME[23..0] ++#define BN0_WF_MIB_TOP_RSCR26_RX_MDRDY_COUNT_MASK 0xFFFFFFFF // RX_MDRDY_COUNT[31..0] ++#define BN0_WF_MIB_TOP_MSR0_CCK_MDRDY_TIME_MASK 0xFFFFFFFF // CCK_MDRDY_TIME[31..0] ++#define BN0_WF_MIB_TOP_MSR1_OFDM_LG_MIXED_VHT_MDRDY_TIME_MASK 0xFFFFFFFF // OFDM_LG_MIXED_VHT_MDRDY_TIME[31..0] ++#define BN0_WF_MIB_TOP_MSR2_OFDM_GREEN_MDRDY_TIME_MASK 0xFFFFFFFF // OFDM_GREEN_MDRDY_TIME[31..0] ++#define BN0_WF_MIB_TOP_MCTR5_P_CCA_TIME_MASK 0xFFFFFFFF // P_CCA_TIME[31..0] ++#define BN0_WF_MIB_TOP_MCTR6_S_CCA_TIME_MASK 0xFFFFFFFF // S_CCA_TIME[31..0] ++#define BN0_WF_MIB_TOP_M0SDR18_P_ED_TIME_MASK 0x00FFFFFF // P_ED_TIME[23..0] ++#define BN0_WF_MIB_TOP_TSCR18_BEACONTXCOUNT_MASK 0xFFFFFFFF // BEACONTXCOUNT[31..0] ++#define BN0_WF_MIB_TOP_TBCR0_TX_20MHZ_CNT_MASK 0xFFFFFFFF // TX_20MHZ_CNT[31..0] ++#define BN0_WF_MIB_TOP_TBCR1_TX_40MHZ_CNT_MASK 0xFFFFFFFF // TX_40MHZ_CNT[31..0] ++#define BN0_WF_MIB_TOP_TBCR2_TX_80MHZ_CNT_MASK 0xFFFFFFFF // TX_80MHZ_CNT[31..0] ++#define BN0_WF_MIB_TOP_TBCR3_TX_160MHZ_CNT_MASK 0xFFFFFFFF // TX_160MHZ_CNT[31..0] ++#define BN0_WF_MIB_TOP_TBCR4_TX_320MHZ_CNT_MASK 0xFFFFFFFF // TX_320MHZ_CNT[31..0] ++#define BN0_WF_MIB_TOP_BSCR2_MUBF_TX_COUNT_MASK 0xFFFFFFFF // MUBF_TX_COUNT[31..0] ++#define BN0_WF_MIB_TOP_RVSR0_VEC_MISS_COUNT_MASK 0xFFFFFFFF // VEC_MISS_COUNT[31..0] ++#define BN0_WF_MIB_TOP_RSCR35_DELIMITER_FAIL_COUNT_MASK 0xFFFFFFFF // DELIMITER_FAIL_COUNT[31..0] ++#define BN0_WF_MIB_TOP_RSCR1_RX_FCS_ERROR_COUNT_MASK 0xFFFFFFFF // RX_FCS_ERROR_COUNT[31..0] ++#define BN0_WF_MIB_TOP_RSCR33_RX_FIFO_FULL_COUNT_MASK 0xFFFFFFFF // RX_FIFO_FULL_COUNT[31..0] ++#define BN0_WF_MIB_TOP_RSCR36_RX_LEN_MISMATCH_MASK 0xFFFFFFFF // RX_LEN_MISMATCH[31..0] ++#define BN0_WF_MIB_TOP_RSCR31_RX_MPDU_COUNT_MASK 0xFFFFFFFF // RX_MPDU_COUNT[31..0] ++#define BN0_WF_MIB_TOP_BTSCR5_RTSTXCOUNTn_MASK 0xFFFFFFFF // RTSTXCOUNTn[31..0] ++#define BN0_WF_MIB_TOP_BTSCR6_RTSRETRYCOUNTn_MASK 0xFFFFFFFF // RTSRETRYCOUNTn[31..0] ++#define BN0_WF_MIB_TOP_BTSCR0_BAMISSCOUNTn_MASK 0xFFFFFFFF // BAMISSCOUNTn[31..0] ++#define BN0_WF_MIB_TOP_BTSCR1_ACKFAILCOUNTn_MASK 0xFFFFFFFF // ACKFAILCOUNTn[31..0] ++#define BN0_WF_MIB_TOP_BTSCR2_FRAMERETRYCOUNTn_MASK 0xFFFFFFFF // FRAMERETRYCOUNTn[31..0] ++#define BN0_WF_MIB_TOP_BTSCR3_FRAMERETRY2COUNTn_MASK 0xFFFFFFFF // FRAMERETRY2COUNTn[31..0] ++#define BN0_WF_MIB_TOP_BTSCR4_FRAMERETRY3COUNTn_MASK 0xFFFFFFFF // FRAMERETRY3COUNTn[31..0] ++#define BN0_WF_MIB_TOP_TRARC0_ADDR (BN0_WF_MIB_TOP_BASE + 0x0B0) // D0B0 ++#define BN0_WF_MIB_TOP_TRARC1_ADDR (BN0_WF_MIB_TOP_BASE + 0x0B4) // D0B4 ++#define BN0_WF_MIB_TOP_TRARC2_ADDR (BN0_WF_MIB_TOP_BASE + 0x0B8) // D0B8 ++#define BN0_WF_MIB_TOP_TRARC3_ADDR (BN0_WF_MIB_TOP_BASE + 0x0BC) // D0BC ++#define BN0_WF_MIB_TOP_TRARC4_ADDR (BN0_WF_MIB_TOP_BASE + 0x0C0) // D0C0 ++#define BN0_WF_MIB_TOP_TRARC5_ADDR (BN0_WF_MIB_TOP_BASE + 0x0C4) // D0C4 ++#define BN0_WF_MIB_TOP_TRARC6_ADDR (BN0_WF_MIB_TOP_BASE + 0x0C8) // D0C8 ++#define BN0_WF_MIB_TOP_TRARC7_ADDR (BN0_WF_MIB_TOP_BASE + 0x0CC) // D0CC ++ ++#define BN0_WF_MIB_TOP_TRDR0_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR0)) ++#define BN0_WF_MIB_TOP_TRDR1_ADDR (BN0_WF_MIB_TOP_BASE + __OFFS(MIB_TRDR1)) ++#define BN0_WF_MIB_TOP_TRDR2_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR2)) ++#define BN0_WF_MIB_TOP_TRDR3_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR3)) ++#define BN0_WF_MIB_TOP_TRDR4_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR4)) ++#define BN0_WF_MIB_TOP_TRDR5_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR5)) ++#define BN0_WF_MIB_TOP_TRDR6_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR6)) ++#define BN0_WF_MIB_TOP_TRDR7_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR7)) ++#define BN0_WF_MIB_TOP_TRDR8_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR8)) ++#define BN0_WF_MIB_TOP_TRDR9_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR9)) ++#define BN0_WF_MIB_TOP_TRDR10_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR10)) ++#define BN0_WF_MIB_TOP_TRDR11_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR11)) ++#define BN0_WF_MIB_TOP_TRDR12_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR12)) ++#define BN0_WF_MIB_TOP_TRDR13_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR13)) ++#define BN0_WF_MIB_TOP_TRDR14_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR14)) ++#define BN0_WF_MIB_TOP_TRDR15_ADDR (BN0_WF_MIB_TOP_BASE + __DBG_OFFS(MIB_TRDR15)) ++ ++#define BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_ADDR BN0_WF_MIB_TOP_TRARC0_ADDR ++#define BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_MASK 0x03FF0000 // AGG_RANG_SEL_1[25..16] ++#define BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_SHFT 16 ++#define BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_ADDR BN0_WF_MIB_TOP_TRARC0_ADDR ++#define BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_MASK 0x000003FF // AGG_RANG_SEL_0[9..0] ++#define BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_ADDR BN0_WF_MIB_TOP_TRARC1_ADDR ++#define BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_MASK 0x03FF0000 // AGG_RANG_SEL_3[25..16] ++#define BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_SHFT 16 ++#define BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_ADDR BN0_WF_MIB_TOP_TRARC1_ADDR ++#define BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_MASK 0x000003FF // AGG_RANG_SEL_2[9..0] ++#define BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_ADDR BN0_WF_MIB_TOP_TRARC2_ADDR ++#define BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_MASK 0x03FF0000 // AGG_RANG_SEL_5[25..16] ++#define BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_SHFT 16 ++#define BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_ADDR BN0_WF_MIB_TOP_TRARC2_ADDR ++#define BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_MASK 0x000003FF // AGG_RANG_SEL_4[9..0] ++#define BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_ADDR BN0_WF_MIB_TOP_TRARC3_ADDR ++#define BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_MASK 0x03FF0000 // AGG_RANG_SEL_7[25..16] ++#define BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_SHFT 16 ++#define BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_ADDR BN0_WF_MIB_TOP_TRARC3_ADDR ++#define BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_MASK 0x000003FF // AGG_RANG_SEL_6[9..0] ++#define BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_ADDR BN0_WF_MIB_TOP_TRARC4_ADDR ++#define BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_MASK 0x03FF0000 // AGG_RANG_SEL_9[25..16] ++#define BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_SHFT 16 ++#define BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_ADDR BN0_WF_MIB_TOP_TRARC4_ADDR ++#define BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_MASK 0x000003FF // AGG_RANG_SEL_8[9..0] ++#define BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_ADDR BN0_WF_MIB_TOP_TRARC5_ADDR ++#define BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_MASK 0x03FF0000 // AGG_RANG_SEL_11[25..16] ++#define BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_SHFT 16 ++#define BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_ADDR BN0_WF_MIB_TOP_TRARC5_ADDR ++#define BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_MASK 0x000003FF // AGG_RANG_SEL_10[9..0] ++#define BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_ADDR BN0_WF_MIB_TOP_TRARC6_ADDR ++#define BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_MASK 0x03FF0000 // AGG_RANG_SEL_13[25..16] ++#define BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_SHFT 16 ++#define BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_ADDR BN0_WF_MIB_TOP_TRARC6_ADDR ++#define BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_MASK 0x000003FF // AGG_RANG_SEL_12[9..0] ++#define BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_SHFT 0 ++ ++#define BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_ADDR BN0_WF_MIB_TOP_TRARC7_ADDR ++#define BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_MASK 0x000003FF // AGG_RANG_SEL_14[9..0] ++#define BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_SHFT 0 ++ ++/* RRO TOP */ ++#define WF_RRO_TOP_BASE 0xA000 /*0x820C2000 */ ++#define WF_RRO_TOP_IND_CMD_0_CTRL0_ADDR (WF_RRO_TOP_BASE + 0x40) // 2040 ++ // ++/* WTBL */ ++enum mt7996_wtbl_type { ++ WTBL_TYPE_LMAC, /* WTBL in LMAC */ ++ WTBL_TYPE_UMAC, /* WTBL in UMAC */ ++ WTBL_TYPE_KEY, /* Key Table */ ++ MAX_NUM_WTBL_TYPE ++}; ++ ++struct berse_wtbl_parse { ++ u8 *name; ++ u32 mask; ++ u32 shift; ++ u8 new_line; ++}; ++ ++enum muar_idx { ++ MUAR_INDEX_OWN_MAC_ADDR_0 = 0, ++ MUAR_INDEX_OWN_MAC_ADDR_1, ++ MUAR_INDEX_OWN_MAC_ADDR_2, ++ MUAR_INDEX_OWN_MAC_ADDR_3, ++ MUAR_INDEX_OWN_MAC_ADDR_4, ++ MUAR_INDEX_OWN_MAC_ADDR_BC_MC = 0xE, ++ MUAR_INDEX_UNMATCHED = 0xF, ++ MUAR_INDEX_OWN_MAC_ADDR_11 = 0x11, ++ MUAR_INDEX_OWN_MAC_ADDR_12, ++ MUAR_INDEX_OWN_MAC_ADDR_13, ++ MUAR_INDEX_OWN_MAC_ADDR_14, ++ MUAR_INDEX_OWN_MAC_ADDR_15, ++ MUAR_INDEX_OWN_MAC_ADDR_16, ++ MUAR_INDEX_OWN_MAC_ADDR_17, ++ MUAR_INDEX_OWN_MAC_ADDR_18, ++ MUAR_INDEX_OWN_MAC_ADDR_19, ++ MUAR_INDEX_OWN_MAC_ADDR_1A, ++ MUAR_INDEX_OWN_MAC_ADDR_1B, ++ MUAR_INDEX_OWN_MAC_ADDR_1C, ++ MUAR_INDEX_OWN_MAC_ADDR_1D, ++ MUAR_INDEX_OWN_MAC_ADDR_1E, ++ MUAR_INDEX_OWN_MAC_ADDR_1F, ++ MUAR_INDEX_OWN_MAC_ADDR_20, ++ MUAR_INDEX_OWN_MAC_ADDR_21, ++ MUAR_INDEX_OWN_MAC_ADDR_22, ++ MUAR_INDEX_OWN_MAC_ADDR_23, ++ MUAR_INDEX_OWN_MAC_ADDR_24, ++ MUAR_INDEX_OWN_MAC_ADDR_25, ++ MUAR_INDEX_OWN_MAC_ADDR_26, ++ MUAR_INDEX_OWN_MAC_ADDR_27, ++ MUAR_INDEX_OWN_MAC_ADDR_28, ++ MUAR_INDEX_OWN_MAC_ADDR_29, ++ MUAR_INDEX_OWN_MAC_ADDR_2A, ++ MUAR_INDEX_OWN_MAC_ADDR_2B, ++ MUAR_INDEX_OWN_MAC_ADDR_2C, ++ MUAR_INDEX_OWN_MAC_ADDR_2D, ++ MUAR_INDEX_OWN_MAC_ADDR_2E, ++ MUAR_INDEX_OWN_MAC_ADDR_2F ++}; ++ ++enum cipher_suit { ++ IGTK_CIPHER_SUIT_NONE = 0, ++ IGTK_CIPHER_SUIT_BIP, ++ IGTK_CIPHER_SUIT_BIP_256 ++}; ++ ++#define LWTBL_LEN_IN_DW 36 ++#define UWTBL_LEN_IN_DW 16 ++ ++#define MT_DBG_WTBL_BASE 0x820D8000 ++ ++#define MT_DBG_WTBLON_TOP_BASE 0x820d4000 ++#define MT_DBG_WTBLON_TOP_WDUCR_ADDR (MT_DBG_WTBLON_TOP_BASE + 0x0370) // 4370 ++#define MT_DBG_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0) ++ ++#define MT_DBG_UWTBL_TOP_BASE 0x820c4000 ++#define MT_DBG_UWTBL_TOP_WDUCR_ADDR (MT_DBG_UWTBL_TOP_BASE + 0x0104) // 4104 ++#define MT_DBG_UWTBL_TOP_WDUCR_GROUP GENMASK(5, 0) ++#define MT_DBG_UWTBL_TOP_WDUCR_TARGET BIT(31) ++ ++#define LWTBL_IDX2BASE_ID GENMASK(14, 8) ++#define LWTBL_IDX2BASE_DW GENMASK(7, 2) ++#define LWTBL_IDX2BASE(_id, _dw) (MT_DBG_WTBL_BASE | \ ++ FIELD_PREP(LWTBL_IDX2BASE_ID, _id) | \ ++ FIELD_PREP(LWTBL_IDX2BASE_DW, _dw)) ++ ++#define UWTBL_IDX2BASE_ID GENMASK(12, 6) ++#define UWTBL_IDX2BASE_DW GENMASK(5, 2) ++#define UWTBL_IDX2BASE(_id, _dw) (MT_DBG_UWTBL_TOP_BASE | 0x2000 | \ ++ FIELD_PREP(UWTBL_IDX2BASE_ID, _id) | \ ++ FIELD_PREP(UWTBL_IDX2BASE_DW, _dw)) ++ ++#define KEYTBL_IDX2BASE_KEY GENMASK(12, 6) ++#define KEYTBL_IDX2BASE_DW GENMASK(5, 2) ++#define KEYTBL_IDX2BASE(_key, _dw) (MT_DBG_UWTBL_TOP_BASE | 0x2000 | \ ++ FIELD_PREP(KEYTBL_IDX2BASE_KEY, _key) | \ ++ FIELD_PREP(KEYTBL_IDX2BASE_DW, _dw)) ++ ++// UMAC WTBL ++// DW0 ++#define WF_UWTBL_PEER_MLD_ADDRESS_47_32__DW 0 ++#define WF_UWTBL_PEER_MLD_ADDRESS_47_32__ADDR 0 ++#define WF_UWTBL_PEER_MLD_ADDRESS_47_32__MASK 0x0000ffff // 15- 0 ++#define WF_UWTBL_PEER_MLD_ADDRESS_47_32__SHIFT 0 ++#define WF_UWTBL_OWN_MLD_ID_DW 0 ++#define WF_UWTBL_OWN_MLD_ID_ADDR 0 ++#define WF_UWTBL_OWN_MLD_ID_MASK 0x003f0000 // 21-16 ++#define WF_UWTBL_OWN_MLD_ID_SHIFT 16 ++// DW1 ++#define WF_UWTBL_PEER_MLD_ADDRESS_31_0__DW 1 ++#define WF_UWTBL_PEER_MLD_ADDRESS_31_0__ADDR 4 ++#define WF_UWTBL_PEER_MLD_ADDRESS_31_0__MASK 0xffffffff // 31- 0 ++#define WF_UWTBL_PEER_MLD_ADDRESS_31_0__SHIFT 0 ++// DW2 ++#define WF_UWTBL_PN_31_0__DW 2 ++#define WF_UWTBL_PN_31_0__ADDR 8 ++#define WF_UWTBL_PN_31_0__MASK 0xffffffff // 31- 0 ++#define WF_UWTBL_PN_31_0__SHIFT 0 ++// DW3 ++#define WF_UWTBL_PN_47_32__DW 3 ++#define WF_UWTBL_PN_47_32__ADDR 12 ++#define WF_UWTBL_PN_47_32__MASK 0x0000ffff // 15- 0 ++#define WF_UWTBL_PN_47_32__SHIFT 0 ++#define WF_UWTBL_COM_SN_DW 3 ++#define WF_UWTBL_COM_SN_ADDR 12 ++#define WF_UWTBL_COM_SN_MASK 0x0fff0000 // 27-16 ++#define WF_UWTBL_COM_SN_SHIFT 16 ++// DW4 ++#define WF_UWTBL_TID0_SN_DW 4 ++#define WF_UWTBL_TID0_SN_ADDR 16 ++#define WF_UWTBL_TID0_SN_MASK 0x00000fff // 11- 0 ++#define WF_UWTBL_TID0_SN_SHIFT 0 ++#define WF_UWTBL_RX_BIPN_31_0__DW 4 ++#define WF_UWTBL_RX_BIPN_31_0__ADDR 16 ++#define WF_UWTBL_RX_BIPN_31_0__MASK 0xffffffff // 31- 0 ++#define WF_UWTBL_RX_BIPN_31_0__SHIFT 0 ++#define WF_UWTBL_TID1_SN_DW 4 ++#define WF_UWTBL_TID1_SN_ADDR 16 ++#define WF_UWTBL_TID1_SN_MASK 0x00fff000 // 23-12 ++#define WF_UWTBL_TID1_SN_SHIFT 12 ++#define WF_UWTBL_TID2_SN_7_0__DW 4 ++#define WF_UWTBL_TID2_SN_7_0__ADDR 16 ++#define WF_UWTBL_TID2_SN_7_0__MASK 0xff000000 // 31-24 ++#define WF_UWTBL_TID2_SN_7_0__SHIFT 24 ++// DW5 ++#define WF_UWTBL_TID2_SN_11_8__DW 5 ++#define WF_UWTBL_TID2_SN_11_8__ADDR 20 ++#define WF_UWTBL_TID2_SN_11_8__MASK 0x0000000f // 3- 0 ++#define WF_UWTBL_TID2_SN_11_8__SHIFT 0 ++#define WF_UWTBL_RX_BIPN_47_32__DW 5 ++#define WF_UWTBL_RX_BIPN_47_32__ADDR 20 ++#define WF_UWTBL_RX_BIPN_47_32__MASK 0x0000ffff // 15- 0 ++#define WF_UWTBL_RX_BIPN_47_32__SHIFT 0 ++#define WF_UWTBL_TID3_SN_DW 5 ++#define WF_UWTBL_TID3_SN_ADDR 20 ++#define WF_UWTBL_TID3_SN_MASK 0x0000fff0 // 15- 4 ++#define WF_UWTBL_TID3_SN_SHIFT 4 ++#define WF_UWTBL_TID4_SN_DW 5 ++#define WF_UWTBL_TID4_SN_ADDR 20 ++#define WF_UWTBL_TID4_SN_MASK 0x0fff0000 // 27-16 ++#define WF_UWTBL_TID4_SN_SHIFT 16 ++#define WF_UWTBL_TID5_SN_3_0__DW 5 ++#define WF_UWTBL_TID5_SN_3_0__ADDR 20 ++#define WF_UWTBL_TID5_SN_3_0__MASK 0xf0000000 // 31-28 ++#define WF_UWTBL_TID5_SN_3_0__SHIFT 28 ++// DW6 ++#define WF_UWTBL_TID5_SN_11_4__DW 6 ++#define WF_UWTBL_TID5_SN_11_4__ADDR 24 ++#define WF_UWTBL_TID5_SN_11_4__MASK 0x000000ff // 7- 0 ++#define WF_UWTBL_TID5_SN_11_4__SHIFT 0 ++#define WF_UWTBL_KEY_LOC2_DW 6 ++#define WF_UWTBL_KEY_LOC2_ADDR 24 ++#define WF_UWTBL_KEY_LOC2_MASK 0x00001fff // 12- 0 ++#define WF_UWTBL_KEY_LOC2_SHIFT 0 ++#define WF_UWTBL_TID6_SN_DW 6 ++#define WF_UWTBL_TID6_SN_ADDR 24 ++#define WF_UWTBL_TID6_SN_MASK 0x000fff00 // 19- 8 ++#define WF_UWTBL_TID6_SN_SHIFT 8 ++#define WF_UWTBL_TID7_SN_DW 6 ++#define WF_UWTBL_TID7_SN_ADDR 24 ++#define WF_UWTBL_TID7_SN_MASK 0xfff00000 // 31-20 ++#define WF_UWTBL_TID7_SN_SHIFT 20 ++// DW7 ++#define WF_UWTBL_KEY_LOC0_DW 7 ++#define WF_UWTBL_KEY_LOC0_ADDR 28 ++#define WF_UWTBL_KEY_LOC0_MASK 0x00001fff // 12- 0 ++#define WF_UWTBL_KEY_LOC0_SHIFT 0 ++#define WF_UWTBL_KEY_LOC1_DW 7 ++#define WF_UWTBL_KEY_LOC1_ADDR 28 ++#define WF_UWTBL_KEY_LOC1_MASK 0x1fff0000 // 28-16 ++#define WF_UWTBL_KEY_LOC1_SHIFT 16 ++// DW8 ++#define WF_UWTBL_AMSDU_CFG_DW 8 ++#define WF_UWTBL_AMSDU_CFG_ADDR 32 ++#define WF_UWTBL_AMSDU_CFG_MASK 0x00000fff // 11- 0 ++#define WF_UWTBL_AMSDU_CFG_SHIFT 0 ++#define WF_UWTBL_SEC_ADDR_MODE_DW 8 ++#define WF_UWTBL_SEC_ADDR_MODE_ADDR 32 ++#define WF_UWTBL_SEC_ADDR_MODE_MASK 0x00300000 // 21-20 ++#define WF_UWTBL_SEC_ADDR_MODE_SHIFT 20 ++#define WF_UWTBL_WMM_Q_DW 8 ++#define WF_UWTBL_WMM_Q_ADDR 32 ++#define WF_UWTBL_WMM_Q_MASK 0x06000000 // 26-25 ++#define WF_UWTBL_WMM_Q_SHIFT 25 ++#define WF_UWTBL_QOS_DW 8 ++#define WF_UWTBL_QOS_ADDR 32 ++#define WF_UWTBL_QOS_MASK 0x08000000 // 27-27 ++#define WF_UWTBL_QOS_SHIFT 27 ++#define WF_UWTBL_HT_DW 8 ++#define WF_UWTBL_HT_ADDR 32 ++#define WF_UWTBL_HT_MASK 0x10000000 // 28-28 ++#define WF_UWTBL_HT_SHIFT 28 ++#define WF_UWTBL_HDRT_MODE_DW 8 ++#define WF_UWTBL_HDRT_MODE_ADDR 32 ++#define WF_UWTBL_HDRT_MODE_MASK 0x20000000 // 29-29 ++#define WF_UWTBL_HDRT_MODE_SHIFT 29 ++// DW9 ++#define WF_UWTBL_RELATED_IDX0_DW 9 ++#define WF_UWTBL_RELATED_IDX0_ADDR 36 ++#define WF_UWTBL_RELATED_IDX0_MASK 0x00000fff // 11- 0 ++#define WF_UWTBL_RELATED_IDX0_SHIFT 0 ++#define WF_UWTBL_RELATED_BAND0_DW 9 ++#define WF_UWTBL_RELATED_BAND0_ADDR 36 ++#define WF_UWTBL_RELATED_BAND0_MASK 0x00003000 // 13-12 ++#define WF_UWTBL_RELATED_BAND0_SHIFT 12 ++#define WF_UWTBL_PRIMARY_MLD_BAND_DW 9 ++#define WF_UWTBL_PRIMARY_MLD_BAND_ADDR 36 ++#define WF_UWTBL_PRIMARY_MLD_BAND_MASK 0x0000c000 // 15-14 ++#define WF_UWTBL_PRIMARY_MLD_BAND_SHIFT 14 ++#define WF_UWTBL_RELATED_IDX1_DW 9 ++#define WF_UWTBL_RELATED_IDX1_ADDR 36 ++#define WF_UWTBL_RELATED_IDX1_MASK 0x0fff0000 // 27-16 ++#define WF_UWTBL_RELATED_IDX1_SHIFT 16 ++#define WF_UWTBL_RELATED_BAND1_DW 9 ++#define WF_UWTBL_RELATED_BAND1_ADDR 36 ++#define WF_UWTBL_RELATED_BAND1_MASK 0x30000000 // 29-28 ++#define WF_UWTBL_RELATED_BAND1_SHIFT 28 ++#define WF_UWTBL_SECONDARY_MLD_BAND_DW 9 ++#define WF_UWTBL_SECONDARY_MLD_BAND_ADDR 36 ++#define WF_UWTBL_SECONDARY_MLD_BAND_MASK 0xc0000000 // 31-30 ++#define WF_UWTBL_SECONDARY_MLD_BAND_SHIFT 30 ++ ++/* LMAC WTBL */ ++// DW0 ++#define WF_LWTBL_PEER_LINK_ADDRESS_47_32__DW 0 ++#define WF_LWTBL_PEER_LINK_ADDRESS_47_32__ADDR 0 ++#define WF_LWTBL_PEER_LINK_ADDRESS_47_32__MASK \ ++ 0x0000ffff // 15- 0 ++#define WF_LWTBL_PEER_LINK_ADDRESS_47_32__SHIFT 0 ++#define WF_LWTBL_MUAR_DW 0 ++#define WF_LWTBL_MUAR_ADDR 0 ++#define WF_LWTBL_MUAR_MASK \ ++ 0x003f0000 // 21-16 ++#define WF_LWTBL_MUAR_SHIFT 16 ++#define WF_LWTBL_RCA1_DW 0 ++#define WF_LWTBL_RCA1_ADDR 0 ++#define WF_LWTBL_RCA1_MASK \ ++ 0x00400000 // 22-22 ++#define WF_LWTBL_RCA1_SHIFT 22 ++#define WF_LWTBL_KID_DW 0 ++#define WF_LWTBL_KID_ADDR 0 ++#define WF_LWTBL_KID_MASK \ ++ 0x01800000 // 24-23 ++#define WF_LWTBL_KID_SHIFT 23 ++#define WF_LWTBL_RCID_DW 0 ++#define WF_LWTBL_RCID_ADDR 0 ++#define WF_LWTBL_RCID_MASK \ ++ 0x02000000 // 25-25 ++#define WF_LWTBL_RCID_SHIFT 25 ++#define WF_LWTBL_BAND_DW 0 ++#define WF_LWTBL_BAND_ADDR 0 ++#define WF_LWTBL_BAND_MASK \ ++ 0x0c000000 // 27-26 ++#define WF_LWTBL_BAND_SHIFT 26 ++#define WF_LWTBL_RV_DW 0 ++#define WF_LWTBL_RV_ADDR 0 ++#define WF_LWTBL_RV_MASK \ ++ 0x10000000 // 28-28 ++#define WF_LWTBL_RV_SHIFT 28 ++#define WF_LWTBL_RCA2_DW 0 ++#define WF_LWTBL_RCA2_ADDR 0 ++#define WF_LWTBL_RCA2_MASK \ ++ 0x20000000 // 29-29 ++#define WF_LWTBL_RCA2_SHIFT 29 ++#define WF_LWTBL_WPI_FLAG_DW 0 ++#define WF_LWTBL_WPI_FLAG_ADDR 0 ++#define WF_LWTBL_WPI_FLAG_MASK \ ++ 0x40000000 // 30-30 ++#define WF_LWTBL_WPI_FLAG_SHIFT 30 ++// DW1 ++#define WF_LWTBL_PEER_LINK_ADDRESS_31_0__DW 1 ++#define WF_LWTBL_PEER_LINK_ADDRESS_31_0__ADDR 4 ++#define WF_LWTBL_PEER_LINK_ADDRESS_31_0__MASK \ ++ 0xffffffff // 31- 0 ++#define WF_LWTBL_PEER_LINK_ADDRESS_31_0__SHIFT 0 ++// DW2 ++#define WF_LWTBL_AID_DW 2 ++#define WF_LWTBL_AID_ADDR 8 ++#define WF_LWTBL_AID_MASK \ ++ 0x00000fff // 11- 0 ++#define WF_LWTBL_AID_SHIFT 0 ++#define WF_LWTBL_GID_SU_DW 2 ++#define WF_LWTBL_GID_SU_ADDR 8 ++#define WF_LWTBL_GID_SU_MASK \ ++ 0x00001000 // 12-12 ++#define WF_LWTBL_GID_SU_SHIFT 12 ++#define WF_LWTBL_SPP_EN_DW 2 ++#define WF_LWTBL_SPP_EN_ADDR 8 ++#define WF_LWTBL_SPP_EN_MASK \ ++ 0x00002000 // 13-13 ++#define WF_LWTBL_SPP_EN_SHIFT 13 ++#define WF_LWTBL_WPI_EVEN_DW 2 ++#define WF_LWTBL_WPI_EVEN_ADDR 8 ++#define WF_LWTBL_WPI_EVEN_MASK \ ++ 0x00004000 // 14-14 ++#define WF_LWTBL_WPI_EVEN_SHIFT 14 ++#define WF_LWTBL_AAD_OM_DW 2 ++#define WF_LWTBL_AAD_OM_ADDR 8 ++#define WF_LWTBL_AAD_OM_MASK \ ++ 0x00008000 // 15-15 ++#define WF_LWTBL_AAD_OM_SHIFT 15 ++/* kite DW2 field bit 13-14 */ ++#define WF_LWTBL_DUAL_PTEC_EN_DW 2 ++#define WF_LWTBL_DUAL_PTEC_EN_ADDR 8 ++#define WF_LWTBL_DUAL_PTEC_EN_MASK \ ++ 0x00002000 // 13-13 ++#define WF_LWTBL_DUAL_PTEC_EN_SHIFT 13 ++#define WF_LWTBL_DUAL_CTS_CAP_DW 2 ++#define WF_LWTBL_DUAL_CTS_CAP_ADDR 8 ++#define WF_LWTBL_DUAL_CTS_CAP_MASK \ ++ 0x00004000 // 14-14 ++#define WF_LWTBL_DUAL_CTS_CAP_SHIFT 14 ++#define WF_LWTBL_CIPHER_SUIT_PGTK_DW 2 ++#define WF_LWTBL_CIPHER_SUIT_PGTK_ADDR 8 ++#define WF_LWTBL_CIPHER_SUIT_PGTK_MASK \ ++ 0x001f0000 // 20-16 ++#define WF_LWTBL_CIPHER_SUIT_PGTK_SHIFT 16 ++#define WF_LWTBL_FD_DW 2 ++#define WF_LWTBL_FD_ADDR 8 ++#define WF_LWTBL_FD_MASK \ ++ 0x00200000 // 21-21 ++#define WF_LWTBL_FD_SHIFT 21 ++#define WF_LWTBL_TD_DW 2 ++#define WF_LWTBL_TD_ADDR 8 ++#define WF_LWTBL_TD_MASK \ ++ 0x00400000 // 22-22 ++#define WF_LWTBL_TD_SHIFT 22 ++#define WF_LWTBL_SW_DW 2 ++#define WF_LWTBL_SW_ADDR 8 ++#define WF_LWTBL_SW_MASK \ ++ 0x00800000 // 23-23 ++#define WF_LWTBL_SW_SHIFT 23 ++#define WF_LWTBL_UL_DW 2 ++#define WF_LWTBL_UL_ADDR 8 ++#define WF_LWTBL_UL_MASK \ ++ 0x01000000 // 24-24 ++#define WF_LWTBL_UL_SHIFT 24 ++#define WF_LWTBL_TX_PS_DW 2 ++#define WF_LWTBL_TX_PS_ADDR 8 ++#define WF_LWTBL_TX_PS_MASK \ ++ 0x02000000 // 25-25 ++#define WF_LWTBL_TX_PS_SHIFT 25 ++#define WF_LWTBL_QOS_DW 2 ++#define WF_LWTBL_QOS_ADDR 8 ++#define WF_LWTBL_QOS_MASK \ ++ 0x04000000 // 26-26 ++#define WF_LWTBL_QOS_SHIFT 26 ++#define WF_LWTBL_HT_DW 2 ++#define WF_LWTBL_HT_ADDR 8 ++#define WF_LWTBL_HT_MASK \ ++ 0x08000000 // 27-27 ++#define WF_LWTBL_HT_SHIFT 27 ++#define WF_LWTBL_VHT_DW 2 ++#define WF_LWTBL_VHT_ADDR 8 ++#define WF_LWTBL_VHT_MASK \ ++ 0x10000000 // 28-28 ++#define WF_LWTBL_VHT_SHIFT 28 ++#define WF_LWTBL_HE_DW 2 ++#define WF_LWTBL_HE_ADDR 8 ++#define WF_LWTBL_HE_MASK \ ++ 0x20000000 // 29-29 ++#define WF_LWTBL_HE_SHIFT 29 ++#define WF_LWTBL_EHT_DW 2 ++#define WF_LWTBL_EHT_ADDR 8 ++#define WF_LWTBL_EHT_MASK \ ++ 0x40000000 // 30-30 ++#define WF_LWTBL_EHT_SHIFT 30 ++#define WF_LWTBL_MESH_DW 2 ++#define WF_LWTBL_MESH_ADDR 8 ++#define WF_LWTBL_MESH_MASK \ ++ 0x80000000 // 31-31 ++#define WF_LWTBL_MESH_SHIFT 31 ++// DW3 ++#define WF_LWTBL_WMM_Q_DW 3 ++#define WF_LWTBL_WMM_Q_ADDR 12 ++#define WF_LWTBL_WMM_Q_MASK \ ++ 0x00000003 // 1- 0 ++#define WF_LWTBL_WMM_Q_SHIFT 0 ++#define WF_LWTBL_EHT_SIG_MCS_DW 3 ++#define WF_LWTBL_EHT_SIG_MCS_ADDR 12 ++#define WF_LWTBL_EHT_SIG_MCS_MASK \ ++ 0x0000000c // 3- 2 ++#define WF_LWTBL_EHT_SIG_MCS_SHIFT 2 ++#define WF_LWTBL_HDRT_MODE_DW 3 ++#define WF_LWTBL_HDRT_MODE_ADDR 12 ++#define WF_LWTBL_HDRT_MODE_MASK \ ++ 0x00000010 // 4- 4 ++#define WF_LWTBL_HDRT_MODE_SHIFT 4 ++#define WF_LWTBL_BEAM_CHG_DW 3 ++#define WF_LWTBL_BEAM_CHG_ADDR 12 ++#define WF_LWTBL_BEAM_CHG_MASK \ ++ 0x00000020 // 5- 5 ++#define WF_LWTBL_BEAM_CHG_SHIFT 5 ++#define WF_LWTBL_EHT_LTF_SYM_NUM_OPT_DW 3 ++#define WF_LWTBL_EHT_LTF_SYM_NUM_OPT_ADDR 12 ++#define WF_LWTBL_EHT_LTF_SYM_NUM_OPT_MASK \ ++ 0x000000c0 // 7- 6 ++#define WF_LWTBL_EHT_LTF_SYM_NUM_OPT_SHIFT 6 ++#define WF_LWTBL_PFMU_IDX_DW 3 ++#define WF_LWTBL_PFMU_IDX_ADDR 12 ++#define WF_LWTBL_PFMU_IDX_MASK \ ++ 0x0000ff00 // 15- 8 ++#define WF_LWTBL_PFMU_IDX_SHIFT 8 ++#define WF_LWTBL_ULPF_IDX_DW 3 ++#define WF_LWTBL_ULPF_IDX_ADDR 12 ++#define WF_LWTBL_ULPF_IDX_MASK \ ++ 0x00ff0000 // 23-16 ++#define WF_LWTBL_ULPF_IDX_SHIFT 16 ++#define WF_LWTBL_RIBF_DW 3 ++#define WF_LWTBL_RIBF_ADDR 12 ++#define WF_LWTBL_RIBF_MASK \ ++ 0x01000000 // 24-24 ++#define WF_LWTBL_RIBF_SHIFT 24 ++#define WF_LWTBL_ULPF_DW 3 ++#define WF_LWTBL_ULPF_ADDR 12 ++#define WF_LWTBL_ULPF_MASK \ ++ 0x02000000 // 25-25 ++#define WF_LWTBL_ULPF_SHIFT 25 ++#define WF_LWTBL_BYPASS_TXSMM_DW 3 ++#define WF_LWTBL_BYPASS_TXSMM_ADDR 12 ++#define WF_LWTBL_BYPASS_TXSMM_MASK \ ++ 0x04000000 // 26-26 ++#define WF_LWTBL_BYPASS_TXSMM_SHIFT 26 ++#define WF_LWTBL_TBF_HT_DW 3 ++#define WF_LWTBL_TBF_HT_ADDR 12 ++#define WF_LWTBL_TBF_HT_MASK \ ++ 0x08000000 // 27-27 ++#define WF_LWTBL_TBF_HT_SHIFT 27 ++#define WF_LWTBL_TBF_VHT_DW 3 ++#define WF_LWTBL_TBF_VHT_ADDR 12 ++#define WF_LWTBL_TBF_VHT_MASK \ ++ 0x10000000 // 28-28 ++#define WF_LWTBL_TBF_VHT_SHIFT 28 ++#define WF_LWTBL_TBF_HE_DW 3 ++#define WF_LWTBL_TBF_HE_ADDR 12 ++#define WF_LWTBL_TBF_HE_MASK \ ++ 0x20000000 // 29-29 ++#define WF_LWTBL_TBF_HE_SHIFT 29 ++#define WF_LWTBL_TBF_EHT_DW 3 ++#define WF_LWTBL_TBF_EHT_ADDR 12 ++#define WF_LWTBL_TBF_EHT_MASK \ ++ 0x40000000 // 30-30 ++#define WF_LWTBL_TBF_EHT_SHIFT 30 ++#define WF_LWTBL_IGN_FBK_DW 3 ++#define WF_LWTBL_IGN_FBK_ADDR 12 ++#define WF_LWTBL_IGN_FBK_MASK \ ++ 0x80000000 // 31-31 ++#define WF_LWTBL_IGN_FBK_SHIFT 31 ++// DW4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE0_DW 4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE0_ADDR 16 ++#define WF_LWTBL_NEGOTIATED_WINSIZE0_MASK \ ++ 0x00000007 // 2- 0 ++#define WF_LWTBL_NEGOTIATED_WINSIZE0_SHIFT 0 ++#define WF_LWTBL_NEGOTIATED_WINSIZE1_DW 4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE1_ADDR 16 ++#define WF_LWTBL_NEGOTIATED_WINSIZE1_MASK \ ++ 0x00000038 // 5- 3 ++#define WF_LWTBL_NEGOTIATED_WINSIZE1_SHIFT 3 ++#define WF_LWTBL_NEGOTIATED_WINSIZE2_DW 4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE2_ADDR 16 ++#define WF_LWTBL_NEGOTIATED_WINSIZE2_MASK \ ++ 0x000001c0 // 8- 6 ++#define WF_LWTBL_NEGOTIATED_WINSIZE2_SHIFT 6 ++#define WF_LWTBL_NEGOTIATED_WINSIZE3_DW 4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE3_ADDR 16 ++#define WF_LWTBL_NEGOTIATED_WINSIZE3_MASK \ ++ 0x00000e00 // 11- 9 ++#define WF_LWTBL_NEGOTIATED_WINSIZE3_SHIFT 9 ++#define WF_LWTBL_NEGOTIATED_WINSIZE4_DW 4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE4_ADDR 16 ++#define WF_LWTBL_NEGOTIATED_WINSIZE4_MASK \ ++ 0x00007000 // 14-12 ++#define WF_LWTBL_NEGOTIATED_WINSIZE4_SHIFT 12 ++#define WF_LWTBL_NEGOTIATED_WINSIZE5_DW 4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE5_ADDR 16 ++#define WF_LWTBL_NEGOTIATED_WINSIZE5_MASK \ ++ 0x00038000 // 17-15 ++#define WF_LWTBL_NEGOTIATED_WINSIZE5_SHIFT 15 ++#define WF_LWTBL_NEGOTIATED_WINSIZE6_DW 4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE6_ADDR 16 ++#define WF_LWTBL_NEGOTIATED_WINSIZE6_MASK \ ++ 0x001c0000 // 20-18 ++#define WF_LWTBL_NEGOTIATED_WINSIZE6_SHIFT 18 ++#define WF_LWTBL_NEGOTIATED_WINSIZE7_DW 4 ++#define WF_LWTBL_NEGOTIATED_WINSIZE7_ADDR 16 ++#define WF_LWTBL_NEGOTIATED_WINSIZE7_MASK \ ++ 0x00e00000 // 23-21 ++#define WF_LWTBL_NEGOTIATED_WINSIZE7_SHIFT 21 ++#define WF_LWTBL_PE_DW 4 ++#define WF_LWTBL_PE_ADDR 16 ++#define WF_LWTBL_PE_MASK \ ++ 0x03000000 // 25-24 ++#define WF_LWTBL_PE_SHIFT 24 ++#define WF_LWTBL_DIS_RHTR_DW 4 ++#define WF_LWTBL_DIS_RHTR_ADDR 16 ++#define WF_LWTBL_DIS_RHTR_MASK \ ++ 0x04000000 // 26-26 ++#define WF_LWTBL_DIS_RHTR_SHIFT 26 ++#define WF_LWTBL_LDPC_HT_DW 4 ++#define WF_LWTBL_LDPC_HT_ADDR 16 ++#define WF_LWTBL_LDPC_HT_MASK \ ++ 0x08000000 // 27-27 ++#define WF_LWTBL_LDPC_HT_SHIFT 27 ++#define WF_LWTBL_LDPC_VHT_DW 4 ++#define WF_LWTBL_LDPC_VHT_ADDR 16 ++#define WF_LWTBL_LDPC_VHT_MASK \ ++ 0x10000000 // 28-28 ++#define WF_LWTBL_LDPC_VHT_SHIFT 28 ++#define WF_LWTBL_LDPC_HE_DW 4 ++#define WF_LWTBL_LDPC_HE_ADDR 16 ++#define WF_LWTBL_LDPC_HE_MASK \ ++ 0x20000000 // 29-29 ++#define WF_LWTBL_LDPC_HE_SHIFT 29 ++#define WF_LWTBL_LDPC_EHT_DW 4 ++#define WF_LWTBL_LDPC_EHT_ADDR 16 ++#define WF_LWTBL_LDPC_EHT_MASK \ ++ 0x40000000 // 30-30 ++#define WF_LWTBL_LDPC_EHT_SHIFT 30 ++#define WF_LWTBL_BA_MODE_DW 4 ++#define WF_LWTBL_BA_MODE_ADDR 16 ++#define WF_LWTBL_BA_MODE_MASK \ ++ 0x80000000 // 31-31 ++#define WF_LWTBL_BA_MODE_SHIFT 31 ++// DW5 ++#define WF_LWTBL_AF_DW 5 ++#define WF_LWTBL_AF_ADDR 20 ++#define WF_LWTBL_AF_MASK \ ++ 0x00000007 // 2- 0 ++#define WF_LWTBL_AF_MASK_7992 \ ++ 0x0000000f // 3- 0 ++#define WF_LWTBL_AF_SHIFT 0 ++#define WF_LWTBL_AF_HE_DW 5 ++#define WF_LWTBL_AF_HE_ADDR 20 ++#define WF_LWTBL_AF_HE_MASK \ ++ 0x00000018 // 4- 3 ++#define WF_LWTBL_AF_HE_SHIFT 3 ++#define WF_LWTBL_RTS_DW 5 ++#define WF_LWTBL_RTS_ADDR 20 ++#define WF_LWTBL_RTS_MASK \ ++ 0x00000020 // 5- 5 ++#define WF_LWTBL_RTS_SHIFT 5 ++#define WF_LWTBL_SMPS_DW 5 ++#define WF_LWTBL_SMPS_ADDR 20 ++#define WF_LWTBL_SMPS_MASK \ ++ 0x00000040 // 6- 6 ++#define WF_LWTBL_SMPS_SHIFT 6 ++#define WF_LWTBL_DYN_BW_DW 5 ++#define WF_LWTBL_DYN_BW_ADDR 20 ++#define WF_LWTBL_DYN_BW_MASK \ ++ 0x00000080 // 7- 7 ++#define WF_LWTBL_DYN_BW_SHIFT 7 ++#define WF_LWTBL_MMSS_DW 5 ++#define WF_LWTBL_MMSS_ADDR 20 ++#define WF_LWTBL_MMSS_MASK \ ++ 0x00000700 // 10- 8 ++#define WF_LWTBL_MMSS_SHIFT 8 ++#define WF_LWTBL_USR_DW 5 ++#define WF_LWTBL_USR_ADDR 20 ++#define WF_LWTBL_USR_MASK \ ++ 0x00000800 // 11-11 ++#define WF_LWTBL_USR_SHIFT 11 ++#define WF_LWTBL_SR_R_DW 5 ++#define WF_LWTBL_SR_R_ADDR 20 ++#define WF_LWTBL_SR_R_MASK \ ++ 0x00007000 // 14-12 ++#define WF_LWTBL_SR_R_SHIFT 12 ++#define WF_LWTBL_SR_ABORT_DW 5 ++#define WF_LWTBL_SR_ABORT_ADDR 20 ++#define WF_LWTBL_SR_ABORT_MASK \ ++ 0x00008000 // 15-15 ++#define WF_LWTBL_SR_ABORT_SHIFT 15 ++#define WF_LWTBL_TX_POWER_OFFSET_DW 5 ++#define WF_LWTBL_TX_POWER_OFFSET_ADDR 20 ++#define WF_LWTBL_TX_POWER_OFFSET_MASK \ ++ 0x003f0000 // 21-16 ++#define WF_LWTBL_TX_POWER_OFFSET_SHIFT 16 ++#define WF_LWTBL_LTF_EHT_DW 5 ++#define WF_LWTBL_LTF_EHT_ADDR 20 ++#define WF_LWTBL_LTF_EHT_MASK \ ++ 0x00c00000 // 23-22 ++#define WF_LWTBL_LTF_EHT_SHIFT 22 ++#define WF_LWTBL_GI_EHT_DW 5 ++#define WF_LWTBL_GI_EHT_ADDR 20 ++#define WF_LWTBL_GI_EHT_MASK \ ++ 0x03000000 // 25-24 ++#define WF_LWTBL_GI_EHT_SHIFT 24 ++#define WF_LWTBL_DOPPL_DW 5 ++#define WF_LWTBL_DOPPL_ADDR 20 ++#define WF_LWTBL_DOPPL_MASK \ ++ 0x04000000 // 26-26 ++#define WF_LWTBL_DOPPL_SHIFT 26 ++#define WF_LWTBL_TXOP_PS_CAP_DW 5 ++#define WF_LWTBL_TXOP_PS_CAP_ADDR 20 ++#define WF_LWTBL_TXOP_PS_CAP_MASK \ ++ 0x08000000 // 27-27 ++#define WF_LWTBL_TXOP_PS_CAP_SHIFT 27 ++#define WF_LWTBL_DU_I_PSM_DW 5 ++#define WF_LWTBL_DU_I_PSM_ADDR 20 ++#define WF_LWTBL_DU_I_PSM_MASK \ ++ 0x10000000 // 28-28 ++#define WF_LWTBL_DU_I_PSM_SHIFT 28 ++#define WF_LWTBL_I_PSM_DW 5 ++#define WF_LWTBL_I_PSM_ADDR 20 ++#define WF_LWTBL_I_PSM_MASK \ ++ 0x20000000 // 29-29 ++#define WF_LWTBL_I_PSM_SHIFT 29 ++#define WF_LWTBL_PSM_DW 5 ++#define WF_LWTBL_PSM_ADDR 20 ++#define WF_LWTBL_PSM_MASK \ ++ 0x40000000 // 30-30 ++#define WF_LWTBL_PSM_SHIFT 30 ++#define WF_LWTBL_SKIP_TX_DW 5 ++#define WF_LWTBL_SKIP_TX_ADDR 20 ++#define WF_LWTBL_SKIP_TX_MASK \ ++ 0x80000000 // 31-31 ++#define WF_LWTBL_SKIP_TX_SHIFT 31 ++// DW6 ++#define WF_LWTBL_CBRN_DW 6 ++#define WF_LWTBL_CBRN_ADDR 24 ++#define WF_LWTBL_CBRN_MASK \ ++ 0x00000007 // 2- 0 ++#define WF_LWTBL_CBRN_SHIFT 0 ++#define WF_LWTBL_DBNSS_EN_DW 6 ++#define WF_LWTBL_DBNSS_EN_ADDR 24 ++#define WF_LWTBL_DBNSS_EN_MASK \ ++ 0x00000008 // 3- 3 ++#define WF_LWTBL_DBNSS_EN_SHIFT 3 ++#define WF_LWTBL_BAF_EN_DW 6 ++#define WF_LWTBL_BAF_EN_ADDR 24 ++#define WF_LWTBL_BAF_EN_MASK \ ++ 0x00000010 // 4- 4 ++#define WF_LWTBL_BAF_EN_SHIFT 4 ++#define WF_LWTBL_RDGBA_DW 6 ++#define WF_LWTBL_RDGBA_ADDR 24 ++#define WF_LWTBL_RDGBA_MASK \ ++ 0x00000020 // 5- 5 ++#define WF_LWTBL_RDGBA_SHIFT 5 ++#define WF_LWTBL_R_DW 6 ++#define WF_LWTBL_R_ADDR 24 ++#define WF_LWTBL_R_MASK \ ++ 0x00000040 // 6- 6 ++#define WF_LWTBL_R_SHIFT 6 ++#define WF_LWTBL_SPE_IDX_DW 6 ++#define WF_LWTBL_SPE_IDX_ADDR 24 ++#define WF_LWTBL_SPE_IDX_MASK \ ++ 0x00000f80 // 11- 7 ++#define WF_LWTBL_SPE_IDX_SHIFT 7 ++#define WF_LWTBL_G2_DW 6 ++#define WF_LWTBL_G2_ADDR 24 ++#define WF_LWTBL_G2_MASK \ ++ 0x00001000 // 12-12 ++#define WF_LWTBL_G2_SHIFT 12 ++#define WF_LWTBL_G4_DW 6 ++#define WF_LWTBL_G4_ADDR 24 ++#define WF_LWTBL_G4_MASK \ ++ 0x00002000 // 13-13 ++#define WF_LWTBL_G4_SHIFT 13 ++#define WF_LWTBL_G8_DW 6 ++#define WF_LWTBL_G8_ADDR 24 ++#define WF_LWTBL_G8_MASK \ ++ 0x00004000 // 14-14 ++#define WF_LWTBL_G8_SHIFT 14 ++#define WF_LWTBL_G16_DW 6 ++#define WF_LWTBL_G16_ADDR 24 ++#define WF_LWTBL_G16_MASK \ ++ 0x00008000 // 15-15 ++#define WF_LWTBL_G16_SHIFT 15 ++#define WF_LWTBL_G2_LTF_DW 6 ++#define WF_LWTBL_G2_LTF_ADDR 24 ++#define WF_LWTBL_G2_LTF_MASK \ ++ 0x00030000 // 17-16 ++#define WF_LWTBL_G2_LTF_SHIFT 16 ++#define WF_LWTBL_G4_LTF_DW 6 ++#define WF_LWTBL_G4_LTF_ADDR 24 ++#define WF_LWTBL_G4_LTF_MASK \ ++ 0x000c0000 // 19-18 ++#define WF_LWTBL_G4_LTF_SHIFT 18 ++#define WF_LWTBL_G8_LTF_DW 6 ++#define WF_LWTBL_G8_LTF_ADDR 24 ++#define WF_LWTBL_G8_LTF_MASK \ ++ 0x00300000 // 21-20 ++#define WF_LWTBL_G8_LTF_SHIFT 20 ++#define WF_LWTBL_G16_LTF_DW 6 ++#define WF_LWTBL_G16_LTF_ADDR 24 ++#define WF_LWTBL_G16_LTF_MASK \ ++ 0x00c00000 // 23-22 ++#define WF_LWTBL_G16_LTF_SHIFT 22 ++#define WF_LWTBL_G2_HE_DW 6 ++#define WF_LWTBL_G2_HE_ADDR 24 ++#define WF_LWTBL_G2_HE_MASK \ ++ 0x03000000 // 25-24 ++#define WF_LWTBL_G2_HE_SHIFT 24 ++#define WF_LWTBL_G4_HE_DW 6 ++#define WF_LWTBL_G4_HE_ADDR 24 ++#define WF_LWTBL_G4_HE_MASK \ ++ 0x0c000000 // 27-26 ++#define WF_LWTBL_G4_HE_SHIFT 26 ++#define WF_LWTBL_G8_HE_DW 6 ++#define WF_LWTBL_G8_HE_ADDR 24 ++#define WF_LWTBL_G8_HE_MASK \ ++ 0x30000000 // 29-28 ++#define WF_LWTBL_G8_HE_SHIFT 28 ++#define WF_LWTBL_G16_HE_DW 6 ++#define WF_LWTBL_G16_HE_ADDR 24 ++#define WF_LWTBL_G16_HE_MASK \ ++ 0xc0000000 // 31-30 ++#define WF_LWTBL_G16_HE_SHIFT 30 ++// DW7 ++#define WF_LWTBL_BA_WIN_SIZE0_DW 7 ++#define WF_LWTBL_BA_WIN_SIZE0_ADDR 28 ++#define WF_LWTBL_BA_WIN_SIZE0_MASK \ ++ 0x0000000f // 3- 0 ++#define WF_LWTBL_BA_WIN_SIZE0_SHIFT 0 ++#define WF_LWTBL_BA_WIN_SIZE1_DW 7 ++#define WF_LWTBL_BA_WIN_SIZE1_ADDR 28 ++#define WF_LWTBL_BA_WIN_SIZE1_MASK \ ++ 0x000000f0 // 7- 4 ++#define WF_LWTBL_BA_WIN_SIZE1_SHIFT 4 ++#define WF_LWTBL_BA_WIN_SIZE2_DW 7 ++#define WF_LWTBL_BA_WIN_SIZE2_ADDR 28 ++#define WF_LWTBL_BA_WIN_SIZE2_MASK \ ++ 0x00000f00 // 11- 8 ++#define WF_LWTBL_BA_WIN_SIZE2_SHIFT 8 ++#define WF_LWTBL_BA_WIN_SIZE3_DW 7 ++#define WF_LWTBL_BA_WIN_SIZE3_ADDR 28 ++#define WF_LWTBL_BA_WIN_SIZE3_MASK \ ++ 0x0000f000 // 15-12 ++#define WF_LWTBL_BA_WIN_SIZE3_SHIFT 12 ++#define WF_LWTBL_BA_WIN_SIZE4_DW 7 ++#define WF_LWTBL_BA_WIN_SIZE4_ADDR 28 ++#define WF_LWTBL_BA_WIN_SIZE4_MASK \ ++ 0x000f0000 // 19-16 ++#define WF_LWTBL_BA_WIN_SIZE4_SHIFT 16 ++#define WF_LWTBL_BA_WIN_SIZE5_DW 7 ++#define WF_LWTBL_BA_WIN_SIZE5_ADDR 28 ++#define WF_LWTBL_BA_WIN_SIZE5_MASK \ ++ 0x00f00000 // 23-20 ++#define WF_LWTBL_BA_WIN_SIZE5_SHIFT 20 ++#define WF_LWTBL_BA_WIN_SIZE6_DW 7 ++#define WF_LWTBL_BA_WIN_SIZE6_ADDR 28 ++#define WF_LWTBL_BA_WIN_SIZE6_MASK \ ++ 0x0f000000 // 27-24 ++#define WF_LWTBL_BA_WIN_SIZE6_SHIFT 24 ++#define WF_LWTBL_BA_WIN_SIZE7_DW 7 ++#define WF_LWTBL_BA_WIN_SIZE7_ADDR 28 ++#define WF_LWTBL_BA_WIN_SIZE7_MASK \ ++ 0xf0000000 // 31-28 ++#define WF_LWTBL_BA_WIN_SIZE7_SHIFT 28 ++// DW8 ++#define WF_LWTBL_AC0_RTS_FAIL_CNT_DW 8 ++#define WF_LWTBL_AC0_RTS_FAIL_CNT_ADDR 32 ++#define WF_LWTBL_AC0_RTS_FAIL_CNT_MASK \ ++ 0x0000001f // 4- 0 ++#define WF_LWTBL_AC0_RTS_FAIL_CNT_SHIFT 0 ++#define WF_LWTBL_AC1_RTS_FAIL_CNT_DW 8 ++#define WF_LWTBL_AC1_RTS_FAIL_CNT_ADDR 32 ++#define WF_LWTBL_AC1_RTS_FAIL_CNT_MASK \ ++ 0x000003e0 // 9- 5 ++#define WF_LWTBL_AC1_RTS_FAIL_CNT_SHIFT 5 ++#define WF_LWTBL_AC2_RTS_FAIL_CNT_DW 8 ++#define WF_LWTBL_AC2_RTS_FAIL_CNT_ADDR 32 ++#define WF_LWTBL_AC2_RTS_FAIL_CNT_MASK \ ++ 0x00007c00 // 14-10 ++#define WF_LWTBL_AC2_RTS_FAIL_CNT_SHIFT 10 ++#define WF_LWTBL_AC3_RTS_FAIL_CNT_DW 8 ++#define WF_LWTBL_AC3_RTS_FAIL_CNT_ADDR 32 ++#define WF_LWTBL_AC3_RTS_FAIL_CNT_MASK \ ++ 0x000f8000 // 19-15 ++#define WF_LWTBL_AC3_RTS_FAIL_CNT_SHIFT 15 ++#define WF_LWTBL_PARTIAL_AID_DW 8 ++#define WF_LWTBL_PARTIAL_AID_ADDR 32 ++#define WF_LWTBL_PARTIAL_AID_MASK \ ++ 0x1ff00000 // 28-20 ++#define WF_LWTBL_PARTIAL_AID_SHIFT 20 ++#define WF_LWTBL_CHK_PER_DW 8 ++#define WF_LWTBL_CHK_PER_ADDR 32 ++#define WF_LWTBL_CHK_PER_MASK \ ++ 0x80000000 // 31-31 ++#define WF_LWTBL_CHK_PER_SHIFT 31 ++// DW9 ++#define WF_LWTBL_RX_AVG_MPDU_SIZE_DW 9 ++#define WF_LWTBL_RX_AVG_MPDU_SIZE_ADDR 36 ++#define WF_LWTBL_RX_AVG_MPDU_SIZE_MASK \ ++ 0x00003fff // 13- 0 ++#define WF_LWTBL_RX_AVG_MPDU_SIZE_SHIFT 0 ++#define WF_LWTBL_PRITX_SW_MODE_DW 9 ++#define WF_LWTBL_PRITX_SW_MODE_ADDR 36 ++#define WF_LWTBL_PRITX_SW_MODE_MASK \ ++ 0x00008000 // 15-15 ++#define WF_LWTBL_PRITX_SW_MODE_SHIFT 15 ++#define WF_LWTBL_PRITX_SW_MODE_MASK_7992 \ ++ 0x00004000 // 14-14 ++#define WF_LWTBL_PRITX_SW_MODE_SHIFT_7992 14 ++#define WF_LWTBL_PRITX_ERSU_DW 9 ++#define WF_LWTBL_PRITX_ERSU_ADDR 36 ++#define WF_LWTBL_PRITX_ERSU_MASK \ ++ 0x00010000 // 16-16 ++#define WF_LWTBL_PRITX_ERSU_SHIFT 16 ++#define WF_LWTBL_PRITX_ERSU_MASK_7992 \ ++ 0x00008000 // 15-15 ++#define WF_LWTBL_PRITX_ERSU_SHIFT_7992 15 ++#define WF_LWTBL_PRITX_PLR_DW 9 ++#define WF_LWTBL_PRITX_PLR_ADDR 36 ++#define WF_LWTBL_PRITX_PLR_MASK \ ++ 0x00020000 // 17-17 ++#define WF_LWTBL_PRITX_PLR_SHIFT 17 ++#define WF_LWTBL_PRITX_PLR_MASK_7992 \ ++ 0x00030000 // 17-16 ++#define WF_LWTBL_PRITX_PLR_SHIFT_7992 16 ++#define WF_LWTBL_PRITX_DCM_DW 9 ++#define WF_LWTBL_PRITX_DCM_ADDR 36 ++#define WF_LWTBL_PRITX_DCM_MASK \ ++ 0x00040000 // 18-18 ++#define WF_LWTBL_PRITX_DCM_SHIFT 18 ++#define WF_LWTBL_PRITX_ER106T_DW 9 ++#define WF_LWTBL_PRITX_ER106T_ADDR 36 ++#define WF_LWTBL_PRITX_ER106T_MASK \ ++ 0x00080000 // 19-19 ++#define WF_LWTBL_PRITX_ER106T_SHIFT 19 ++#define WF_LWTBL_FCAP_DW 9 ++#define WF_LWTBL_FCAP_ADDR 36 ++#define WF_LWTBL_FCAP_MASK \ ++ 0x00700000 // 22-20 ++#define WF_LWTBL_FCAP_SHIFT 20 ++#define WF_LWTBL_MPDU_FAIL_CNT_DW 9 ++#define WF_LWTBL_MPDU_FAIL_CNT_ADDR 36 ++#define WF_LWTBL_MPDU_FAIL_CNT_MASK \ ++ 0x03800000 // 25-23 ++#define WF_LWTBL_MPDU_FAIL_CNT_SHIFT 23 ++#define WF_LWTBL_MPDU_OK_CNT_DW 9 ++#define WF_LWTBL_MPDU_OK_CNT_ADDR 36 ++#define WF_LWTBL_MPDU_OK_CNT_MASK \ ++ 0x1c000000 // 28-26 ++#define WF_LWTBL_MPDU_OK_CNT_SHIFT 26 ++#define WF_LWTBL_RATE_IDX_DW 9 ++#define WF_LWTBL_RATE_IDX_ADDR 36 ++#define WF_LWTBL_RATE_IDX_MASK \ ++ 0xe0000000 // 31-29 ++#define WF_LWTBL_RATE_IDX_SHIFT 29 ++// DW10 ++#define WF_LWTBL_RATE1_DW 10 ++#define WF_LWTBL_RATE1_ADDR 40 ++#define WF_LWTBL_RATE1_MASK \ ++ 0x00007fff // 14- 0 ++#define WF_LWTBL_RATE1_SHIFT 0 ++#define WF_LWTBL_RATE2_DW 10 ++#define WF_LWTBL_RATE2_ADDR 40 ++#define WF_LWTBL_RATE2_MASK \ ++ 0x7fff0000 // 30-16 ++#define WF_LWTBL_RATE2_SHIFT 16 ++// DW11 ++#define WF_LWTBL_RATE3_DW 11 ++#define WF_LWTBL_RATE3_ADDR 44 ++#define WF_LWTBL_RATE3_MASK \ ++ 0x00007fff // 14- 0 ++#define WF_LWTBL_RATE3_SHIFT 0 ++#define WF_LWTBL_RATE4_DW 11 ++#define WF_LWTBL_RATE4_ADDR 44 ++#define WF_LWTBL_RATE4_MASK \ ++ 0x7fff0000 // 30-16 ++#define WF_LWTBL_RATE4_SHIFT 16 ++// DW12 ++#define WF_LWTBL_RATE5_DW 12 ++#define WF_LWTBL_RATE5_ADDR 48 ++#define WF_LWTBL_RATE5_MASK \ ++ 0x00007fff // 14- 0 ++#define WF_LWTBL_RATE5_SHIFT 0 ++#define WF_LWTBL_RATE6_DW 12 ++#define WF_LWTBL_RATE6_ADDR 48 ++#define WF_LWTBL_RATE6_MASK \ ++ 0x7fff0000 // 30-16 ++#define WF_LWTBL_RATE6_SHIFT 16 ++// DW13 ++#define WF_LWTBL_RATE7_DW 13 ++#define WF_LWTBL_RATE7_ADDR 52 ++#define WF_LWTBL_RATE7_MASK \ ++ 0x00007fff // 14- 0 ++#define WF_LWTBL_RATE7_SHIFT 0 ++#define WF_LWTBL_RATE8_DW 13 ++#define WF_LWTBL_RATE8_ADDR 52 ++#define WF_LWTBL_RATE8_MASK \ ++ 0x7fff0000 // 30-16 ++#define WF_LWTBL_RATE8_SHIFT 16 ++// DW14 ++#define WF_LWTBL_RATE1_TX_CNT_DW 14 ++#define WF_LWTBL_RATE1_TX_CNT_ADDR 56 ++#define WF_LWTBL_RATE1_TX_CNT_MASK \ ++ 0x0000ffff // 15- 0 ++#define WF_LWTBL_RATE1_TX_CNT_SHIFT 0 ++#define WF_LWTBL_CIPHER_SUIT_IGTK_DW 14 ++#define WF_LWTBL_CIPHER_SUIT_IGTK_ADDR 56 ++#define WF_LWTBL_CIPHER_SUIT_IGTK_MASK \ ++ 0x00003000 // 13-12 ++#define WF_LWTBL_CIPHER_SUIT_IGTK_SHIFT 12 ++#define WF_LWTBL_CIPHER_SUIT_BIGTK_DW 14 ++#define WF_LWTBL_CIPHER_SUIT_BIGTK_ADDR 56 ++#define WF_LWTBL_CIPHER_SUIT_BIGTK_MASK \ ++ 0x0000c000 // 15-14 ++#define WF_LWTBL_CIPHER_SUIT_BIGTK_SHIFT 14 ++#define WF_LWTBL_RATE1_FAIL_CNT_DW 14 ++#define WF_LWTBL_RATE1_FAIL_CNT_ADDR 56 ++#define WF_LWTBL_RATE1_FAIL_CNT_MASK \ ++ 0xffff0000 // 31-16 ++#define WF_LWTBL_RATE1_FAIL_CNT_SHIFT 16 ++// DW15 ++#define WF_LWTBL_RATE2_OK_CNT_DW 15 ++#define WF_LWTBL_RATE2_OK_CNT_ADDR 60 ++#define WF_LWTBL_RATE2_OK_CNT_MASK \ ++ 0x0000ffff // 15- 0 ++#define WF_LWTBL_RATE2_OK_CNT_SHIFT 0 ++#define WF_LWTBL_RATE3_OK_CNT_DW 15 ++#define WF_LWTBL_RATE3_OK_CNT_ADDR 60 ++#define WF_LWTBL_RATE3_OK_CNT_MASK \ ++ 0xffff0000 // 31-16 ++#define WF_LWTBL_RATE3_OK_CNT_SHIFT 16 ++// DW16 ++#define WF_LWTBL_CURRENT_BW_TX_CNT_DW 16 ++#define WF_LWTBL_CURRENT_BW_TX_CNT_ADDR 64 ++#define WF_LWTBL_CURRENT_BW_TX_CNT_MASK \ ++ 0x0000ffff // 15- 0 ++#define WF_LWTBL_CURRENT_BW_TX_CNT_SHIFT 0 ++#define WF_LWTBL_CURRENT_BW_FAIL_CNT_DW 16 ++#define WF_LWTBL_CURRENT_BW_FAIL_CNT_ADDR 64 ++#define WF_LWTBL_CURRENT_BW_FAIL_CNT_MASK \ ++ 0xffff0000 // 31-16 ++#define WF_LWTBL_CURRENT_BW_FAIL_CNT_SHIFT 16 ++// DW17 ++#define WF_LWTBL_OTHER_BW_TX_CNT_DW 17 ++#define WF_LWTBL_OTHER_BW_TX_CNT_ADDR 68 ++#define WF_LWTBL_OTHER_BW_TX_CNT_MASK \ ++ 0x0000ffff // 15- 0 ++#define WF_LWTBL_OTHER_BW_TX_CNT_SHIFT 0 ++#define WF_LWTBL_OTHER_BW_FAIL_CNT_DW 17 ++#define WF_LWTBL_OTHER_BW_FAIL_CNT_ADDR 68 ++#define WF_LWTBL_OTHER_BW_FAIL_CNT_MASK \ ++ 0xffff0000 // 31-16 ++#define WF_LWTBL_OTHER_BW_FAIL_CNT_SHIFT 16 ++// DW18 ++#define WF_LWTBL_RTS_OK_CNT_DW 18 ++#define WF_LWTBL_RTS_OK_CNT_ADDR 72 ++#define WF_LWTBL_RTS_OK_CNT_MASK \ ++ 0x0000ffff // 15- 0 ++#define WF_LWTBL_RTS_OK_CNT_SHIFT 0 ++#define WF_LWTBL_RTS_FAIL_CNT_DW 18 ++#define WF_LWTBL_RTS_FAIL_CNT_ADDR 72 ++#define WF_LWTBL_RTS_FAIL_CNT_MASK \ ++ 0xffff0000 // 31-16 ++#define WF_LWTBL_RTS_FAIL_CNT_SHIFT 16 ++// DW19 ++#define WF_LWTBL_DATA_RETRY_CNT_DW 19 ++#define WF_LWTBL_DATA_RETRY_CNT_ADDR 76 ++#define WF_LWTBL_DATA_RETRY_CNT_MASK \ ++ 0x0000ffff // 15- 0 ++#define WF_LWTBL_DATA_RETRY_CNT_SHIFT 0 ++#define WF_LWTBL_MGNT_RETRY_CNT_DW 19 ++#define WF_LWTBL_MGNT_RETRY_CNT_ADDR 76 ++#define WF_LWTBL_MGNT_RETRY_CNT_MASK \ ++ 0xffff0000 // 31-16 ++#define WF_LWTBL_MGNT_RETRY_CNT_SHIFT 16 ++// DW20 ++#define WF_LWTBL_AC0_CTT_CDT_CRB_DW 20 ++#define WF_LWTBL_AC0_CTT_CDT_CRB_ADDR 80 ++#define WF_LWTBL_AC0_CTT_CDT_CRB_MASK \ ++ 0xffffffff // 31- 0 ++#define WF_LWTBL_AC0_CTT_CDT_CRB_SHIFT 0 ++// DW21 ++// DO NOT process repeat field(adm[0]) ++// DW22 ++#define WF_LWTBL_AC1_CTT_CDT_CRB_DW 22 ++#define WF_LWTBL_AC1_CTT_CDT_CRB_ADDR 88 ++#define WF_LWTBL_AC1_CTT_CDT_CRB_MASK \ ++ 0xffffffff // 31- 0 ++#define WF_LWTBL_AC1_CTT_CDT_CRB_SHIFT 0 ++// DW23 ++// DO NOT process repeat field(adm[1]) ++// DW24 ++#define WF_LWTBL_AC2_CTT_CDT_CRB_DW 24 ++#define WF_LWTBL_AC2_CTT_CDT_CRB_ADDR 96 ++#define WF_LWTBL_AC2_CTT_CDT_CRB_MASK \ ++ 0xffffffff // 31- 0 ++#define WF_LWTBL_AC2_CTT_CDT_CRB_SHIFT 0 ++// DW25 ++// DO NOT process repeat field(adm[2]) ++// DW26 ++#define WF_LWTBL_AC3_CTT_CDT_CRB_DW 26 ++#define WF_LWTBL_AC3_CTT_CDT_CRB_ADDR 104 ++#define WF_LWTBL_AC3_CTT_CDT_CRB_MASK \ ++ 0xffffffff // 31- 0 ++#define WF_LWTBL_AC3_CTT_CDT_CRB_SHIFT 0 ++// DW27 ++// DO NOT process repeat field(adm[3]) ++// DW28 ++#define WF_LWTBL_RELATED_IDX0_DW 28 ++#define WF_LWTBL_RELATED_IDX0_ADDR 112 ++#define WF_LWTBL_RELATED_IDX0_MASK \ ++ 0x00000fff // 11- 0 ++#define WF_LWTBL_RELATED_IDX0_SHIFT 0 ++#define WF_LWTBL_RELATED_BAND0_DW 28 ++#define WF_LWTBL_RELATED_BAND0_ADDR 112 ++#define WF_LWTBL_RELATED_BAND0_MASK \ ++ 0x00003000 // 13-12 ++#define WF_LWTBL_RELATED_BAND0_SHIFT 12 ++#define WF_LWTBL_PRIMARY_MLD_BAND_DW 28 ++#define WF_LWTBL_PRIMARY_MLD_BAND_ADDR 112 ++#define WF_LWTBL_PRIMARY_MLD_BAND_MASK \ ++ 0x0000c000 // 15-14 ++#define WF_LWTBL_PRIMARY_MLD_BAND_SHIFT 14 ++#define WF_LWTBL_RELATED_IDX1_DW 28 ++#define WF_LWTBL_RELATED_IDX1_ADDR 112 ++#define WF_LWTBL_RELATED_IDX1_MASK \ ++ 0x0fff0000 // 27-16 ++#define WF_LWTBL_RELATED_IDX1_SHIFT 16 ++#define WF_LWTBL_RELATED_BAND1_DW 28 ++#define WF_LWTBL_RELATED_BAND1_ADDR 112 ++#define WF_LWTBL_RELATED_BAND1_MASK \ ++ 0x30000000 // 29-28 ++#define WF_LWTBL_RELATED_BAND1_SHIFT 28 ++#define WF_LWTBL_SECONDARY_MLD_BAND_DW 28 ++#define WF_LWTBL_SECONDARY_MLD_BAND_ADDR 112 ++#define WF_LWTBL_SECONDARY_MLD_BAND_MASK \ ++ 0xc0000000 // 31-30 ++#define WF_LWTBL_SECONDARY_MLD_BAND_SHIFT 30 ++// DW29 ++#define WF_LWTBL_DISPATCH_POLICY0_DW 29 ++#define WF_LWTBL_DISPATCH_POLICY0_ADDR 116 ++#define WF_LWTBL_DISPATCH_POLICY0_MASK \ ++ 0x00000003 // 1- 0 ++#define WF_LWTBL_DISPATCH_POLICY0_SHIFT 0 ++#define WF_LWTBL_DISPATCH_POLICY1_DW 29 ++#define WF_LWTBL_DISPATCH_POLICY1_ADDR 116 ++#define WF_LWTBL_DISPATCH_POLICY1_MASK \ ++ 0x0000000c // 3- 2 ++#define WF_LWTBL_DISPATCH_POLICY1_SHIFT 2 ++#define WF_LWTBL_DISPATCH_POLICY2_DW 29 ++#define WF_LWTBL_DISPATCH_POLICY2_ADDR 116 ++#define WF_LWTBL_DISPATCH_POLICY2_MASK \ ++ 0x00000030 // 5- 4 ++#define WF_LWTBL_DISPATCH_POLICY2_SHIFT 4 ++#define WF_LWTBL_DISPATCH_POLICY3_DW 29 ++#define WF_LWTBL_DISPATCH_POLICY3_ADDR 116 ++#define WF_LWTBL_DISPATCH_POLICY3_MASK \ ++ 0x000000c0 // 7- 6 ++#define WF_LWTBL_DISPATCH_POLICY3_SHIFT 6 ++#define WF_LWTBL_DISPATCH_POLICY4_DW 29 ++#define WF_LWTBL_DISPATCH_POLICY4_ADDR 116 ++#define WF_LWTBL_DISPATCH_POLICY4_MASK \ ++ 0x00000300 // 9- 8 ++#define WF_LWTBL_DISPATCH_POLICY4_SHIFT 8 ++#define WF_LWTBL_DISPATCH_POLICY5_DW 29 ++#define WF_LWTBL_DISPATCH_POLICY5_ADDR 116 ++#define WF_LWTBL_DISPATCH_POLICY5_MASK \ ++ 0x00000c00 // 11-10 ++#define WF_LWTBL_DISPATCH_POLICY5_SHIFT 10 ++#define WF_LWTBL_DISPATCH_POLICY6_DW 29 ++#define WF_LWTBL_DISPATCH_POLICY6_ADDR 116 ++#define WF_LWTBL_DISPATCH_POLICY6_MASK \ ++ 0x00003000 // 13-12 ++#define WF_LWTBL_DISPATCH_POLICY6_SHIFT 12 ++#define WF_LWTBL_DISPATCH_POLICY7_DW 29 ++#define WF_LWTBL_DISPATCH_POLICY7_ADDR 116 ++#define WF_LWTBL_DISPATCH_POLICY7_MASK \ ++ 0x0000c000 // 15-14 ++#define WF_LWTBL_DISPATCH_POLICY7_SHIFT 14 ++#define WF_LWTBL_OWN_MLD_ID_DW 29 ++#define WF_LWTBL_OWN_MLD_ID_ADDR 116 ++#define WF_LWTBL_OWN_MLD_ID_MASK \ ++ 0x003f0000 // 21-16 ++#define WF_LWTBL_OWN_MLD_ID_SHIFT 16 ++#define WF_LWTBL_EMLSR0_DW 29 ++#define WF_LWTBL_EMLSR0_ADDR 116 ++#define WF_LWTBL_EMLSR0_MASK \ ++ 0x00400000 // 22-22 ++#define WF_LWTBL_EMLSR0_SHIFT 22 ++#define WF_LWTBL_EMLMR0_DW 29 ++#define WF_LWTBL_EMLMR0_ADDR 116 ++#define WF_LWTBL_EMLMR0_MASK \ ++ 0x00800000 // 23-23 ++#define WF_LWTBL_EMLMR0_SHIFT 23 ++#define WF_LWTBL_EMLSR1_DW 29 ++#define WF_LWTBL_EMLSR1_ADDR 116 ++#define WF_LWTBL_EMLSR1_MASK \ ++ 0x01000000 // 24-24 ++#define WF_LWTBL_EMLSR1_SHIFT 24 ++#define WF_LWTBL_EMLMR1_DW 29 ++#define WF_LWTBL_EMLMR1_ADDR 116 ++#define WF_LWTBL_EMLMR1_MASK \ ++ 0x02000000 // 25-25 ++#define WF_LWTBL_EMLMR1_SHIFT 25 ++#define WF_LWTBL_EMLSR2_DW 29 ++#define WF_LWTBL_EMLSR2_ADDR 116 ++#define WF_LWTBL_EMLSR2_MASK \ ++ 0x04000000 // 26-26 ++#define WF_LWTBL_EMLSR2_SHIFT 26 ++#define WF_LWTBL_EMLMR2_DW 29 ++#define WF_LWTBL_EMLMR2_ADDR 116 ++#define WF_LWTBL_EMLMR2_MASK \ ++ 0x08000000 // 27-27 ++#define WF_LWTBL_EMLMR2_SHIFT 27 ++#define WF_LWTBL_STR_BITMAP_DW 29 ++#define WF_LWTBL_STR_BITMAP_ADDR 116 ++#define WF_LWTBL_STR_BITMAP_MASK \ ++ 0xe0000000 // 31-29 ++#define WF_LWTBL_STR_BITMAP_SHIFT 29 ++// DW30 ++#define WF_LWTBL_DISPATCH_ORDER_DW 30 ++#define WF_LWTBL_DISPATCH_ORDER_ADDR 120 ++#define WF_LWTBL_DISPATCH_ORDER_MASK \ ++ 0x0000007f // 6- 0 ++#define WF_LWTBL_DISPATCH_ORDER_SHIFT 0 ++#define WF_LWTBL_DISPATCH_RATIO_DW 30 ++#define WF_LWTBL_DISPATCH_RATIO_ADDR 120 ++#define WF_LWTBL_DISPATCH_RATIO_MASK \ ++ 0x00003f80 // 13- 7 ++#define WF_LWTBL_DISPATCH_RATIO_SHIFT 7 ++#define WF_LWTBL_LINK_MGF_DW 30 ++#define WF_LWTBL_LINK_MGF_ADDR 120 ++#define WF_LWTBL_LINK_MGF_MASK \ ++ 0xffff0000 // 31-16 ++#define WF_LWTBL_LINK_MGF_SHIFT 16 ++// DW31 ++#define WF_LWTBL_BFTX_TB_DW 31 ++#define WF_LWTBL_BFTX_TB_ADDR 124 ++#define WF_LWTBL_BFTX_TB_MASK \ ++ 0x00800000 // 23-23 ++#define WF_LWTBL_DROP_DW 31 ++#define WF_LWTBL_DROP_ADDR 124 ++#define WF_LWTBL_DROP_MASK \ ++ 0x01000000 // 24-24 ++#define WF_LWTBL_DROP_SHIFT 24 ++#define WF_LWTBL_CASCAD_DW 31 ++#define WF_LWTBL_CASCAD_ADDR 124 ++#define WF_LWTBL_CASCAD_MASK \ ++ 0x02000000 // 25-25 ++#define WF_LWTBL_CASCAD_SHIFT 25 ++#define WF_LWTBL_ALL_ACK_DW 31 ++#define WF_LWTBL_ALL_ACK_ADDR 124 ++#define WF_LWTBL_ALL_ACK_MASK \ ++ 0x04000000 // 26-26 ++#define WF_LWTBL_ALL_ACK_SHIFT 26 ++#define WF_LWTBL_MPDU_SIZE_DW 31 ++#define WF_LWTBL_MPDU_SIZE_ADDR 124 ++#define WF_LWTBL_MPDU_SIZE_MASK \ ++ 0x18000000 // 28-27 ++#define WF_LWTBL_MPDU_SIZE_SHIFT 27 ++#define WF_LWTBL_RXD_DUP_MODE_DW 31 ++#define WF_LWTBL_RXD_DUP_MODE_ADDR 124 ++#define WF_LWTBL_RXD_DUP_MODE_MASK \ ++ 0x60000000 // 30-29 ++#define WF_LWTBL_RXD_DUP_MODE_SHIFT 29 ++#define WF_LWTBL_ACK_EN_DW 31 ++#define WF_LWTBL_ACK_EN_ADDR 128 ++#define WF_LWTBL_ACK_EN_MASK \ ++ 0x80000000 // 31-31 ++#define WF_LWTBL_ACK_EN_SHIFT 31 ++// DW32 ++#define WF_LWTBL_OM_INFO_DW 32 ++#define WF_LWTBL_OM_INFO_ADDR 128 ++#define WF_LWTBL_OM_INFO_MASK \ ++ 0x00000fff // 11- 0 ++#define WF_LWTBL_OM_INFO_SHIFT 0 ++#define WF_LWTBL_OM_INFO_EHT_DW 32 ++#define WF_LWTBL_OM_INFO_EHT_ADDR 128 ++#define WF_LWTBL_OM_INFO_EHT_MASK \ ++ 0x0000f000 // 15-12 ++#define WF_LWTBL_OM_INFO_EHT_SHIFT 12 ++#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_DW 32 ++#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_ADDR 128 ++#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_MASK \ ++ 0x00010000 // 16-16 ++#define WF_LWTBL_RXD_DUP_FOR_OM_CHG_SHIFT 16 ++#define WF_LWTBL_RXD_DUP_WHITE_LIST_DW 32 ++#define WF_LWTBL_RXD_DUP_WHITE_LIST_ADDR 128 ++#define WF_LWTBL_RXD_DUP_WHITE_LIST_MASK \ ++ 0x1ffe0000 // 28-17 ++#define WF_LWTBL_RXD_DUP_WHITE_LIST_SHIFT 17 ++// DW33 ++#define WF_LWTBL_USER_RSSI_DW 33 ++#define WF_LWTBL_USER_RSSI_ADDR 132 ++#define WF_LWTBL_USER_RSSI_MASK \ ++ 0x000001ff // 8- 0 ++#define WF_LWTBL_USER_RSSI_SHIFT 0 ++#define WF_LWTBL_USER_SNR_DW 33 ++#define WF_LWTBL_USER_SNR_ADDR 132 ++#define WF_LWTBL_USER_SNR_MASK \ ++ 0x00007e00 // 14- 9 ++#define WF_LWTBL_USER_SNR_SHIFT 9 ++#define WF_LWTBL_RAPID_REACTION_RATE_DW 33 ++#define WF_LWTBL_RAPID_REACTION_RATE_ADDR 132 ++#define WF_LWTBL_RAPID_REACTION_RATE_MASK \ ++ 0x0fff0000 // 27-16 ++#define WF_LWTBL_RAPID_REACTION_RATE_SHIFT 16 ++#define WF_LWTBL_HT_AMSDU_DW 33 ++#define WF_LWTBL_HT_AMSDU_ADDR 132 ++#define WF_LWTBL_HT_AMSDU_MASK \ ++ 0x40000000 // 30-30 ++#define WF_LWTBL_HT_AMSDU_SHIFT 30 ++#define WF_LWTBL_AMSDU_CROSS_LG_DW 33 ++#define WF_LWTBL_AMSDU_CROSS_LG_ADDR 132 ++#define WF_LWTBL_AMSDU_CROSS_LG_MASK \ ++ 0x80000000 // 31-31 ++#define WF_LWTBL_AMSDU_CROSS_LG_SHIFT 31 ++// DW34 ++#define WF_LWTBL_RESP_RCPI0_DW 34 ++#define WF_LWTBL_RESP_RCPI0_ADDR 136 ++#define WF_LWTBL_RESP_RCPI0_MASK \ ++ 0x000000ff // 7- 0 ++#define WF_LWTBL_RESP_RCPI0_SHIFT 0 ++#define WF_LWTBL_RESP_RCPI1_DW 34 ++#define WF_LWTBL_RESP_RCPI1_ADDR 136 ++#define WF_LWTBL_RESP_RCPI1_MASK \ ++ 0x0000ff00 // 15- 8 ++#define WF_LWTBL_RESP_RCPI1_SHIFT 8 ++#define WF_LWTBL_RESP_RCPI2_DW 34 ++#define WF_LWTBL_RESP_RCPI2_ADDR 136 ++#define WF_LWTBL_RESP_RCPI2_MASK \ ++ 0x00ff0000 // 23-16 ++#define WF_LWTBL_RESP_RCPI2_SHIFT 16 ++#define WF_LWTBL_RESP_RCPI3_DW 34 ++#define WF_LWTBL_RESP_RCPI3_ADDR 136 ++#define WF_LWTBL_RESP_RCPI3_MASK \ ++ 0xff000000 // 31-24 ++#define WF_LWTBL_RESP_RCPI3_SHIFT 24 ++// DW35 ++#define WF_LWTBL_SNR_RX0_DW 35 ++#define WF_LWTBL_SNR_RX0_ADDR 140 ++#define WF_LWTBL_SNR_RX0_MASK \ ++ 0x0000003f // 5- 0 ++#define WF_LWTBL_SNR_RX0_SHIFT 0 ++#define WF_LWTBL_SNR_RX1_DW 35 ++#define WF_LWTBL_SNR_RX1_ADDR 140 ++#define WF_LWTBL_SNR_RX1_MASK \ ++ 0x00000fc0 // 11- 6 ++#define WF_LWTBL_SNR_RX1_SHIFT 6 ++#define WF_LWTBL_SNR_RX2_DW 35 ++#define WF_LWTBL_SNR_RX2_ADDR 140 ++#define WF_LWTBL_SNR_RX2_MASK \ ++ 0x0003f000 // 17-12 ++#define WF_LWTBL_SNR_RX2_SHIFT 12 ++#define WF_LWTBL_SNR_RX3_DW 35 ++#define WF_LWTBL_SNR_RX3_ADDR 140 ++#define WF_LWTBL_SNR_RX3_MASK \ ++ 0x00fc0000 // 23-18 ++#define WF_LWTBL_SNR_RX3_SHIFT 18 ++ ++/* WTBL Group - Packet Number */ ++/* DW 2 */ ++#define WTBL_PN0_MASK BITS(0, 7) ++#define WTBL_PN0_OFFSET 0 ++#define WTBL_PN1_MASK BITS(8, 15) ++#define WTBL_PN1_OFFSET 8 ++#define WTBL_PN2_MASK BITS(16, 23) ++#define WTBL_PN2_OFFSET 16 ++#define WTBL_PN3_MASK BITS(24, 31) ++#define WTBL_PN3_OFFSET 24 ++ ++/* DW 3 */ ++#define WTBL_PN4_MASK BITS(0, 7) ++#define WTBL_PN4_OFFSET 0 ++#define WTBL_PN5_MASK BITS(8, 15) ++#define WTBL_PN5_OFFSET 8 ++ ++/* DW 4 */ ++#define WTBL_BIPN0_MASK BITS(0, 7) ++#define WTBL_BIPN0_OFFSET 0 ++#define WTBL_BIPN1_MASK BITS(8, 15) ++#define WTBL_BIPN1_OFFSET 8 ++#define WTBL_BIPN2_MASK BITS(16, 23) ++#define WTBL_BIPN2_OFFSET 16 ++#define WTBL_BIPN3_MASK BITS(24, 31) ++#define WTBL_BIPN3_OFFSET 24 ++ ++/* DW 5 */ ++#define WTBL_BIPN4_MASK BITS(0, 7) ++#define WTBL_BIPN4_OFFSET 0 ++#define WTBL_BIPN5_MASK BITS(8, 15) ++#define WTBL_BIPN5_OFFSET 8 ++ ++/* UWTBL DW 6 */ ++#define WTBL_AMSDU_LEN_MASK BITS(0, 5) ++#define WTBL_AMSDU_LEN_OFFSET 0 ++#define WTBL_AMSDU_NUM_MASK BITS(6, 10) ++#define WTBL_AMSDU_NUM_OFFSET 6 ++#define WTBL_AMSDU_EN_MASK BIT(11) ++#define WTBL_AMSDU_EN_OFFSET 11 ++ ++/* UWTBL DW 8 */ ++#define WTBL_SEC_ADDR_MODE_MASK BITS(20, 21) ++#define WTBL_SEC_ADDR_MODE_OFFSET 20 ++ ++/* LWTBL Rate field */ ++#define WTBL_RATE_TX_RATE_MASK BITS(0, 5) ++#define WTBL_RATE_TX_RATE_OFFSET 0 ++#define WTBL_RATE_TX_MODE_MASK BITS(6, 9) ++#define WTBL_RATE_TX_MODE_OFFSET 6 ++#define WTBL_RATE_NSTS_MASK BITS(10, 13) ++#define WTBL_RATE_NSTS_OFFSET 10 ++#define WTBL_RATE_STBC_MASK BIT(14) ++#define WTBL_RATE_STBC_OFFSET 14 ++ ++/***** WTBL(LMAC) DW Offset *****/ ++/* LMAC WTBL Group - Peer Unique Information */ ++#define WTBL_GROUP_PEER_INFO_DW_0 0 ++#define WTBL_GROUP_PEER_INFO_DW_1 1 ++ ++/* WTBL Group - TxRx Capability/Information */ ++#define WTBL_GROUP_TRX_CAP_DW_2 2 ++#define WTBL_GROUP_TRX_CAP_DW_3 3 ++#define WTBL_GROUP_TRX_CAP_DW_4 4 ++#define WTBL_GROUP_TRX_CAP_DW_5 5 ++#define WTBL_GROUP_TRX_CAP_DW_6 6 ++#define WTBL_GROUP_TRX_CAP_DW_7 7 ++#define WTBL_GROUP_TRX_CAP_DW_8 8 ++#define WTBL_GROUP_TRX_CAP_DW_9 9 ++ ++/* WTBL Group - Auto Rate Table*/ ++#define WTBL_GROUP_AUTO_RATE_1_2 10 ++#define WTBL_GROUP_AUTO_RATE_3_4 11 ++#define WTBL_GROUP_AUTO_RATE_5_6 12 ++#define WTBL_GROUP_AUTO_RATE_7_8 13 ++ ++/* WTBL Group - Tx Counter */ ++#define WTBL_GROUP_TX_CNT_LINE_1 14 ++#define WTBL_GROUP_TX_CNT_LINE_2 15 ++#define WTBL_GROUP_TX_CNT_LINE_3 16 ++#define WTBL_GROUP_TX_CNT_LINE_4 17 ++#define WTBL_GROUP_TX_CNT_LINE_5 18 ++#define WTBL_GROUP_TX_CNT_LINE_6 19 ++ ++/* WTBL Group - Admission Control Counter */ ++#define WTBL_GROUP_ADM_CNT_LINE_1 20 ++#define WTBL_GROUP_ADM_CNT_LINE_2 21 ++#define WTBL_GROUP_ADM_CNT_LINE_3 22 ++#define WTBL_GROUP_ADM_CNT_LINE_4 23 ++#define WTBL_GROUP_ADM_CNT_LINE_5 24 ++#define WTBL_GROUP_ADM_CNT_LINE_6 25 ++#define WTBL_GROUP_ADM_CNT_LINE_7 26 ++#define WTBL_GROUP_ADM_CNT_LINE_8 27 ++ ++/* WTBL Group -MLO Info */ ++#define WTBL_GROUP_MLO_INFO_LINE_1 28 ++#define WTBL_GROUP_MLO_INFO_LINE_2 29 ++#define WTBL_GROUP_MLO_INFO_LINE_3 30 ++ ++/* WTBL Group -RESP Info */ ++#define WTBL_GROUP_RESP_INFO_DW_31 31 ++ ++/* WTBL Group -RX DUP Info */ ++#define WTBL_GROUP_RX_DUP_INFO_DW_32 32 ++ ++/* WTBL Group - Rx Statistics Counter */ ++#define WTBL_GROUP_RX_STAT_CNT_LINE_1 33 ++#define WTBL_GROUP_RX_STAT_CNT_LINE_2 34 ++#define WTBL_GROUP_RX_STAT_CNT_LINE_3 35 ++ ++/* UWTBL Group - HW AMSDU */ ++#define UWTBL_HW_AMSDU_DW WF_UWTBL_AMSDU_CFG_DW ++ ++/* LWTBL DW 4 */ ++#define WTBL_DIS_RHTR WF_LWTBL_DIS_RHTR_MASK ++ ++/* UWTBL DW 5 */ ++#define WTBL_KEY_LINK_DW_KEY_LOC0_MASK BITS(0, 10) ++#define WTBL_PSM WF_LWTBL_PSM_MASK ++ ++/* Need to sync with FW define */ ++#define INVALID_KEY_ENTRY WTBL_KEY_LINK_DW_KEY_LOC0_MASK ++ ++// RATE ++#define WTBL_RATE_TX_RATE_MASK BITS(0, 5) ++#define WTBL_RATE_TX_RATE_OFFSET 0 ++#define WTBL_RATE_TX_MODE_MASK BITS(6, 9) ++#define WTBL_RATE_TX_MODE_OFFSET 6 ++#define WTBL_RATE_NSTS_MASK BITS(10, 13) ++#define WTBL_RATE_NSTS_OFFSET 10 ++#define WTBL_RATE_STBC_MASK BIT(14) ++#define WTBL_RATE_STBC_OFFSET 14 ++#endif ++ ++#endif +--- /dev/null ++++ b/mt7996/mtk_debugfs.c +@@ -0,0 +1,2414 @@ ++// SPDX-License-Identifier: ISC ++/* ++ * Copyright (C) 2023 MediaTek Inc. ++ */ ++#include "mt7996.h" ++#include "../mt76.h" ++#include "mcu.h" ++#include "mac.h" ++#include "eeprom.h" ++#include "mtk_debug.h" ++#include "mtk_mcu.h" ++#include "coredump.h" ++ ++#ifdef CONFIG_MTK_DEBUG ++ ++/* AGG INFO */ ++static int ++mt7996_agginfo_read_per_band(struct seq_file *s, int band_idx) ++{ ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ u64 total_burst, total_ampdu, ampdu_cnt[16]; ++ u32 value, idx, row_idx, col_idx, start_range, agg_rang_sel[16], burst_cnt[16], band_offset = 0; ++ u8 partial_str[16] = {}, full_str[64] = {}; ++ ++ switch (band_idx) { ++ case 0: ++ band_offset = 0; ++ break; ++ case 1: ++ band_offset = BN1_WF_AGG_TOP_BASE - BN0_WF_AGG_TOP_BASE; ++ break; ++ case 2: ++ band_offset = IP1_BN0_WF_AGG_TOP_BASE - BN0_WF_AGG_TOP_BASE; ++ break; ++ default: ++ return 0; ++ } ++ ++ seq_printf(s, "Band %d AGG Status\n", band_idx); ++ seq_printf(s, "===============================\n"); ++ value = mt76_rr(dev, BN0_WF_AGG_TOP_AALCR0_ADDR + band_offset); ++ seq_printf(s, "AC00 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR0_AC00_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR0_AC00_AGG_LIMIT_SHFT); ++ seq_printf(s, "AC01 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR0_AC01_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR0_AC01_AGG_LIMIT_SHFT); ++ value = mt76_rr(dev, BN0_WF_AGG_TOP_AALCR1_ADDR + band_offset); ++ seq_printf(s, "AC02 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR1_AC02_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR1_AC02_AGG_LIMIT_SHFT); ++ seq_printf(s, "AC03 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR1_AC03_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR1_AC03_AGG_LIMIT_SHFT); ++ value = mt76_rr(dev, BN0_WF_AGG_TOP_AALCR2_ADDR + band_offset); ++ seq_printf(s, "AC10 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR2_AC10_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR2_AC10_AGG_LIMIT_SHFT); ++ seq_printf(s, "AC11 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR2_AC11_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR2_AC11_AGG_LIMIT_SHFT); ++ value = mt76_rr(dev, BN0_WF_AGG_TOP_AALCR3_ADDR + band_offset); ++ seq_printf(s, "AC12 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR3_AC12_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR3_AC12_AGG_LIMIT_SHFT); ++ seq_printf(s, "AC13 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR3_AC13_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR3_AC13_AGG_LIMIT_SHFT); ++ value = mt76_rr(dev, BN0_WF_AGG_TOP_AALCR4_ADDR + band_offset); ++ seq_printf(s, "AC20 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR4_AC20_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR4_AC20_AGG_LIMIT_SHFT); ++ seq_printf(s, "AC21 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR4_AC21_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR4_AC21_AGG_LIMIT_SHFT); ++ value = mt76_rr(dev, BN0_WF_AGG_TOP_AALCR5_ADDR + band_offset); ++ seq_printf(s, "AC22 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR5_AC22_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR5_AC22_AGG_LIMIT_SHFT); ++ seq_printf(s, "AC23 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR5_AC23_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR5_AC23_AGG_LIMIT_SHFT); ++ value = mt76_rr(dev, BN0_WF_AGG_TOP_AALCR6_ADDR + band_offset); ++ seq_printf(s, "AC30 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR6_AC30_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR6_AC30_AGG_LIMIT_SHFT); ++ seq_printf(s, "AC31 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR6_AC31_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR6_AC31_AGG_LIMIT_SHFT); ++ value = mt76_rr(dev, BN0_WF_AGG_TOP_AALCR7_ADDR + band_offset); ++ seq_printf(s, "AC32 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR7_AC32_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR7_AC32_AGG_LIMIT_SHFT); ++ seq_printf(s, "AC33 Agg limit = %d\t", (value & BN0_WF_AGG_TOP_AALCR7_AC33_AGG_LIMIT_MASK) >> BN0_WF_AGG_TOP_AALCR7_AC33_AGG_LIMIT_SHFT); ++ ++ switch (band_idx) { ++ case 0: ++ band_offset = 0; ++ break; ++ case 1: ++ band_offset = BN1_WF_MIB_TOP_BASE - BN0_WF_MIB_TOP_BASE; ++ break; ++ case 2: ++ band_offset = IP1_BN0_WF_MIB_TOP_BASE - BN0_WF_MIB_TOP_BASE; ++ break; ++ default: ++ return 0; ++ } ++ ++ seq_printf(s, "===AMPDU Related Counters===\n"); ++ ++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC0_ADDR + band_offset); ++ agg_rang_sel[0] = (value & BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_MASK) >> BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_0_SHFT; ++ agg_rang_sel[1] = (value & BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_MASK) >> BN0_WF_MIB_TOP_TRARC0_AGG_RANG_SEL_1_SHFT; ++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC1_ADDR + band_offset); ++ agg_rang_sel[2] = (value & BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_MASK) >> BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_2_SHFT; ++ agg_rang_sel[3] = (value & BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_MASK) >> BN0_WF_MIB_TOP_TRARC1_AGG_RANG_SEL_3_SHFT; ++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC2_ADDR + band_offset); ++ agg_rang_sel[4] = (value & BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_MASK) >> BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_4_SHFT; ++ agg_rang_sel[5] = (value & BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_MASK) >> BN0_WF_MIB_TOP_TRARC2_AGG_RANG_SEL_5_SHFT; ++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC3_ADDR + band_offset); ++ agg_rang_sel[6] = (value & BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_MASK) >> BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_6_SHFT; ++ agg_rang_sel[7] = (value & BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_MASK) >> BN0_WF_MIB_TOP_TRARC3_AGG_RANG_SEL_7_SHFT; ++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC4_ADDR + band_offset); ++ agg_rang_sel[8] = (value & BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_MASK) >> BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_8_SHFT; ++ agg_rang_sel[9] = (value & BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_MASK) >> BN0_WF_MIB_TOP_TRARC4_AGG_RANG_SEL_9_SHFT; ++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC5_ADDR + band_offset); ++ agg_rang_sel[10] = (value & BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_MASK) >> BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_10_SHFT; ++ agg_rang_sel[11] = (value & BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_MASK) >> BN0_WF_MIB_TOP_TRARC5_AGG_RANG_SEL_11_SHFT; ++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC6_ADDR + band_offset); ++ agg_rang_sel[12] = (value & BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_MASK) >> BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_12_SHFT; ++ agg_rang_sel[13] = (value & BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_MASK) >> BN0_WF_MIB_TOP_TRARC6_AGG_RANG_SEL_13_SHFT; ++ value = mt76_rr(dev, BN0_WF_MIB_TOP_TRARC7_ADDR + band_offset); ++ agg_rang_sel[14] = (value & BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_MASK) >> BN0_WF_MIB_TOP_TRARC7_AGG_RANG_SEL_14_SHFT; ++ ++ burst_cnt[0] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR0_ADDR + band_offset); ++ burst_cnt[1] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR1_ADDR + band_offset); ++ burst_cnt[2] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR2_ADDR + band_offset); ++ burst_cnt[3] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR3_ADDR + band_offset); ++ burst_cnt[4] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR4_ADDR + band_offset); ++ burst_cnt[5] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR5_ADDR + band_offset); ++ burst_cnt[6] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR6_ADDR + band_offset); ++ burst_cnt[7] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR7_ADDR + band_offset); ++ burst_cnt[8] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR8_ADDR + band_offset); ++ burst_cnt[9] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR9_ADDR + band_offset); ++ burst_cnt[10] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR10_ADDR + band_offset); ++ burst_cnt[11] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR11_ADDR + band_offset); ++ burst_cnt[12] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR12_ADDR + band_offset); ++ burst_cnt[13] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR13_ADDR + band_offset); ++ burst_cnt[14] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR14_ADDR + band_offset); ++ burst_cnt[15] = mt76_rr(dev, BN0_WF_MIB_TOP_TRDR15_ADDR + band_offset); ++ ++ start_range = 1; ++ total_burst = 0; ++ total_ampdu = 0; ++ agg_rang_sel[15] = 1023; ++ ++ /* Need to add 1 after read from AGG_RANG_SEL CR */ ++ for (idx = 0; idx < 16; idx++) { ++ agg_rang_sel[idx]++; ++ total_burst += burst_cnt[idx]; ++ ++ if (start_range == agg_rang_sel[idx]) ++ ampdu_cnt[idx] = (u64) start_range * burst_cnt[idx]; ++ else ++ ampdu_cnt[idx] = (u64) ((start_range + agg_rang_sel[idx]) >> 1) * burst_cnt[idx]; ++ ++ start_range = agg_rang_sel[idx] + 1; ++ total_ampdu += ampdu_cnt[idx]; ++ } ++ ++ start_range = 1; ++ sprintf(full_str, "%13s ", "Tx Agg Range:"); ++ ++ for (row_idx = 0; row_idx < 4; row_idx++) { ++ for (col_idx = 0; col_idx < 4; col_idx++, idx++) { ++ idx = 4 * row_idx + col_idx; ++ ++ if (start_range == agg_rang_sel[idx]) ++ sprintf(partial_str, "%d", agg_rang_sel[idx]); ++ else ++ sprintf(partial_str, "%d~%d", start_range, agg_rang_sel[idx]); ++ ++ start_range = agg_rang_sel[idx] + 1; ++ sprintf(full_str + strlen(full_str), "%-11s ", partial_str); ++ } ++ ++ idx = 4 * row_idx; ++ ++ seq_printf(s, "%s\n", full_str); ++ seq_printf(s, "%13s 0x%-9x 0x%-9x 0x%-9x 0x%-9x\n", ++ row_idx ? "" : "Burst count:", ++ burst_cnt[idx], burst_cnt[idx + 1], ++ burst_cnt[idx + 2], burst_cnt[idx + 3]); ++ ++ if (total_burst != 0) { ++ if (row_idx == 0) ++ sprintf(full_str, "%13s ", ++ "Burst ratio:"); ++ else ++ sprintf(full_str, "%13s ", ""); ++ ++ for (col_idx = 0; col_idx < 4; col_idx++) { ++ u64 count = (u64) burst_cnt[idx + col_idx] * 100; ++ ++ sprintf(partial_str, "(%llu%%)", ++ div64_u64(count, total_burst)); ++ sprintf(full_str + strlen(full_str), ++ "%-11s ", partial_str); ++ } ++ ++ seq_printf(s, "%s\n", full_str); ++ ++ if (row_idx == 0) ++ sprintf(full_str, "%13s ", ++ "MDPU ratio:"); ++ else ++ sprintf(full_str, "%13s ", ""); ++ ++ for (col_idx = 0; col_idx < 4; col_idx++) { ++ u64 count = ampdu_cnt[idx + col_idx] * 100; ++ ++ sprintf(partial_str, "(%llu%%)", ++ div64_u64(count, total_ampdu)); ++ sprintf(full_str + strlen(full_str), ++ "%-11s ", partial_str); ++ } ++ ++ seq_printf(s, "%s\n", full_str); ++ } ++ ++ sprintf(full_str, "%13s ", ""); ++ } ++ ++ return 0; ++} ++ ++static int mt7996_agginfo_read_band0(struct seq_file *s, void *data) ++{ ++ mt7996_agginfo_read_per_band(s, MT_BAND0); ++ return 0; ++} ++ ++static int mt7996_agginfo_read_band1(struct seq_file *s, void *data) ++{ ++ mt7996_agginfo_read_per_band(s, MT_BAND1); ++ return 0; ++} ++ ++static int mt7996_agginfo_read_band2(struct seq_file *s, void *data) ++{ ++ mt7996_agginfo_read_per_band(s, MT_BAND2); ++ return 0; ++} ++ ++/* AMSDU INFO */ ++static int mt7996_amsdu_result_read(struct seq_file *s, void *data) ++{ ++#define HW_MSDU_CNT_ADDR 0xf400 ++#define HW_MSDU_NUM_MAX 33 ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ u32 ple_stat[HW_MSDU_NUM_MAX] = {0}, total_amsdu = 0; ++ u8 i; ++ ++ for (i = 0; i < HW_MSDU_NUM_MAX; i++) ++ ple_stat[i] = mt76_rr(dev, HW_MSDU_CNT_ADDR + i * 0x04); ++ ++ seq_printf(s, "TXD counter status of MSDU:\n"); ++ ++ for (i = 0; i < HW_MSDU_NUM_MAX; i++) ++ total_amsdu += ple_stat[i]; ++ ++ for (i = 0; i < HW_MSDU_NUM_MAX; i++) { ++ seq_printf(s, "AMSDU pack count of %d MSDU in TXD: 0x%x ", i, ple_stat[i]); ++ if (total_amsdu != 0) ++ seq_printf(s, "(%d%%)\n", ple_stat[i] * 100 / total_amsdu); ++ else ++ seq_printf(s, "\n"); ++ } ++ ++ return 0; ++} ++ ++/* DBG MODLE */ ++static int ++mt7996_fw_debug_module_set(void *data, u64 module) ++{ ++ struct mt7996_dev *dev = data; ++ ++ dev->dbg.fw_dbg_module = module; ++ return 0; ++} ++ ++static int ++mt7996_fw_debug_module_get(void *data, u64 *module) ++{ ++ struct mt7996_dev *dev = data; ++ ++ *module = dev->dbg.fw_dbg_module; ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_module, mt7996_fw_debug_module_get, ++ mt7996_fw_debug_module_set, "%lld\n"); ++ ++static int ++mt7996_fw_debug_level_set(void *data, u64 level) ++{ ++ struct mt7996_dev *dev = data; ++ ++ dev->dbg.fw_dbg_lv = level; ++ mt7996_mcu_fw_dbg_ctrl(dev, dev->dbg.fw_dbg_module, dev->dbg.fw_dbg_lv); ++ return 0; ++} ++ ++static int ++mt7996_fw_debug_level_get(void *data, u64 *level) ++{ ++ struct mt7996_dev *dev = data; ++ ++ *level = dev->dbg.fw_dbg_lv; ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_level, mt7996_fw_debug_level_get, ++ mt7996_fw_debug_level_set, "%lld\n"); ++ ++/* usage: echo 0x[arg3][arg2][arg1] > fw_wa_set */ ++static int ++mt7996_wa_set(void *data, u64 val) ++{ ++ struct mt7996_dev *dev = data; ++ u32 arg1, arg2, arg3; ++ ++ arg1 = FIELD_GET(GENMASK_ULL(7, 0), val); ++ arg2 = FIELD_GET(GENMASK_ULL(15, 8), val); ++ arg3 = FIELD_GET(GENMASK_ULL(23, 16), val); ++ ++ return mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), ++ arg1, arg2, arg3); ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_wa_set, NULL, mt7996_wa_set, ++ "0x%llx\n"); ++ ++/* usage: echo 0x[arg3][arg2][arg1] > fw_wa_query */ ++static int ++mt7996_wa_query(void *data, u64 val) ++{ ++ struct mt7996_dev *dev = data; ++ u32 arg1, arg2, arg3; ++ ++ arg1 = FIELD_GET(GENMASK_ULL(7, 0), val); ++ arg2 = FIELD_GET(GENMASK_ULL(15, 8), val); ++ arg3 = FIELD_GET(GENMASK_ULL(23, 16), val); ++ ++ return mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY), ++ arg1, arg2, arg3); ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_wa_query, NULL, mt7996_wa_query, ++ "0x%llx\n"); ++ ++static int mt7996_dump_version(struct seq_file *s, void *data) ++{ ++#define MAX_ADIE_NUM 3 ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ u32 regval; ++ u16 adie_chip_id, adie_chip_ver; ++ int adie_idx; ++ static const char * const fem_type[] = { ++ [MT7996_FEM_EXT] = "eFEM", ++ [MT7996_FEM_INT] = "iFEM", ++ [MT7996_FEM_MIX] = "mixed FEM", ++ }; ++ ++ //seq_printf(s, "Version: 4.3.24.8\n"); ++ ++ if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) ++ return 0; ++ ++ //seq_printf(s, "Rom Patch Build Time: %.16s\n", dev->patch_build_date); ++ //seq_printf(s, "WM Patch Build Time: %.15s, Mode: %s\n", ++ // dev->ram_build_date[MT7996_RAM_TYPE_WM], ++ // "Normal mode"); ++ //seq_printf(s, "WA Patch Build Time: %.15s\n", ++ // dev->ram_build_date[MT7996_RAM_TYPE_WA]); ++ //seq_printf(s, "DSP Patch Build Time: %.15s\n", ++ // dev->ram_build_date[MT7996_RAM_TYPE_DSP]); ++ for (adie_idx = 0; adie_idx < MAX_ADIE_NUM; adie_idx++) { ++ mt7996_mcu_rf_regval(dev, MT_ADIE_CHIP_ID(adie_idx), ®val, false); ++ adie_chip_id = FIELD_GET(MT_ADIE_CHIP_ID_MASK, regval); ++ adie_chip_ver = FIELD_GET(MT_ADIE_VERSION_MASK, regval); ++ if (adie_chip_id) ++ seq_printf(s, "Adie %d: ID = 0x%04x, Ver = 0x%04x\n", ++ adie_idx, adie_chip_id, adie_chip_ver); ++ else ++ seq_printf(s, "Adie %d: ID = N/A, Ver = N/A\n", adie_idx); ++ } ++ seq_printf(s, "FEM type: %s\n", fem_type[dev->var.fem]); ++ ++ return 0; ++} ++ ++/* dma info dump */ ++static void ++dump_dma_tx_ring_info(struct seq_file *s, struct mt7996_dev *dev, char *str1, char *str2, u32 ring_base) ++{ ++ u32 base, cnt, cidx, didx, queue_cnt; ++ ++ base= mt76_rr(dev, ring_base); ++ cnt = mt76_rr(dev, ring_base + 4); ++ cidx = mt76_rr(dev, ring_base + 8); ++ didx = mt76_rr(dev, ring_base + 12); ++ queue_cnt = (cidx >= didx) ? (cidx - didx) : (cidx - didx + cnt); ++ ++ seq_printf(s, "%20s %6s %10x %15x %10x %10x %10x\n", str1, str2, base, cnt, cidx, didx, queue_cnt); ++} ++ ++static void ++dump_dma_rx_ring_info(struct seq_file *s, struct mt7996_dev *dev, char *str1, char *str2, u32 ring_base) ++{ ++ u32 base, ctrl1, cnt, cidx, didx, queue_cnt; ++ ++ base= mt76_rr(dev, ring_base); ++ ctrl1 = mt76_rr(dev, ring_base + 4); ++ cidx = mt76_rr(dev, ring_base + 8) & 0xfff; ++ didx = mt76_rr(dev, ring_base + 12) & 0xfff; ++ cnt = ctrl1 & 0xfff; ++ queue_cnt = (didx > cidx) ? (didx - cidx - 1) : (didx - cidx + cnt - 1); ++ ++ seq_printf(s, "%20s %6s %10x %10x(%3x) %10x %10x %10x\n", ++ str1, str2, base, ctrl1, cnt, cidx, didx, queue_cnt); ++} ++ ++static void ++mt7996_show_dma_info(struct seq_file *s, struct mt7996_dev *dev) ++{ ++ u32 sys_ctrl[10]; ++ ++ /* HOST DMA0 information */ ++ sys_ctrl[0] = mt76_rr(dev, WF_WFDMA_HOST_DMA0_HOST_INT_STA_ADDR); ++ sys_ctrl[1] = mt76_rr(dev, WF_WFDMA_HOST_DMA0_HOST_INT_ENA_ADDR); ++ sys_ctrl[2] = mt76_rr(dev, WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_ADDR); ++ ++ seq_printf(s, "HOST_DMA Configuration\n"); ++ seq_printf(s, "%10s %10s %10s %10s %10s %10s\n", ++ "DMA", "IntCSR", "IntMask", "Glocfg", "Tx/RxEn", "Tx/RxBusy"); ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "DMA0", sys_ctrl[0], sys_ctrl[1], sys_ctrl[2], ++ (sys_ctrl[2] & WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK) ++ >> WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[2] & WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK) ++ >> WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[2] & WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) ++ >> WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[2] & WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) ++ >> WF_WFDMA_HOST_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ ++ if (dev->hif2) { ++ /* HOST DMA1 information */ ++ sys_ctrl[0] = mt76_rr(dev, WF_WFDMA_HOST_DMA0_PCIE1_HOST_INT_STA_ADDR); ++ sys_ctrl[1] = mt76_rr(dev, WF_WFDMA_HOST_DMA0_PCIE1_HOST_INT_ENA_ADDR); ++ sys_ctrl[2] = mt76_rr(dev, WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_ADDR); ++ ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "DMA0P1", sys_ctrl[0], sys_ctrl[1], sys_ctrl[2], ++ (sys_ctrl[2] & WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_TX_DMA_EN_MASK) ++ >> WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[2] & WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_RX_DMA_EN_MASK) ++ >> WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[2] & WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) ++ >> WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[2] & WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) ++ >> WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ } ++ ++ seq_printf(s, "HOST_DMA0 Ring Configuration\n"); ++ seq_printf(s, "%20s %6s %10s %15s %10s %10s %10s\n", ++ "Name", "Used", "Base", "Ctrl1(Cnt)", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T0:TXD0(H2MAC)", "STA", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING0_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T1:TXD1(H2MAC)", "STA", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING1_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T2:TXD2(H2MAC)", "STA", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING2_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T3:", "STA", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING3_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T4:", "STA", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING4_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T5:", "STA", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING5_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T6:", "STA", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING6_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T16:FWDL", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING16_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T17:Cmd(H2WM)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING17_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T18:TXD0(H2WA)", "AP", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING18_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T19:TXD1(H2WA)", "AP", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING19_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T20:Cmd(H2WA)", "AP", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING20_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T21:TXD2(H2WA)", "AP", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING21_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T22:TXD3(H2WA)", "AP", ++ WF_WFDMA_HOST_DMA0_WPDMA_TX_RING22_CTRL0_ADDR); ++ ++ ++ dump_dma_rx_ring_info(s, dev, "R0:Event(WM2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING0_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R1:Event(WA2H)", "AP", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING1_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R2:TxDone0(WA2H)", "AP", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING2_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R3:TxDone1(WA2H)", "AP", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING3_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R4:Data0(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING4_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R5:Data1(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING5_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R6:BUF1(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING6_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R7:TxDone1(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING7_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R8:BUF0(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING8_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R9:TxDone0(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING9_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R10:MSDU_PG0(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING10_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R11:MSDU_PG1(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING11_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R12:MSDU_PG2(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_WPDMA_RX_RING12_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "IND:IND_CMD(MAC2H)", "Both", ++ WF_RRO_TOP_IND_CMD_0_CTRL0_ADDR); ++ ++ if (dev->hif2) { ++ seq_printf(s, "HOST_DMA0 PCIe1 Ring Configuration\n"); ++ seq_printf(s, "%20s %6s %10s %15s %10s %10s %10s\n", ++ "Name", "Used", "Base", "Ctrl1(Cnt)", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T21:TXD2(H2WA)", "AP", ++ WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING21_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T22:TXD?(H2WA)", "AP", ++ WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_TX_RING22_CTRL0_ADDR); ++ ++ dump_dma_rx_ring_info(s, dev, "R3:TxDone1(WA2H)", "AP", ++ WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING3_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R5:Data1(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING5_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R6:BUF1(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING6_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R7:TxDone1(MAC2H)", "Both", ++ WF_WFDMA_HOST_DMA0_PCIE1_WPDMA_RX_RING7_CTRL0_ADDR); ++ } ++ ++ /* MCU DMA information */ ++ sys_ctrl[0] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_ADDR); ++ sys_ctrl[1] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_HOST_INT_STA_ADDR); ++ sys_ctrl[2] = mt76_rr(dev, WF_WFDMA_MCU_DMA0_HOST_INT_ENA_ADDR); ++ ++ seq_printf(s, "MCU_DMA Configuration\n"); ++ seq_printf(s, "%10s %10s %10s %10s %10s %10s\n", ++ "DMA", "IntCSR", "IntMask", "Glocfg", "Tx/RxEn", "Tx/RxBusy"); ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "DMA0", sys_ctrl[1], sys_ctrl[2], sys_ctrl[0], ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_MASK) ++ >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_MASK) ++ >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) ++ >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) ++ >> WF_WFDMA_MCU_DMA0_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ ++ seq_printf(s, "MCU_DMA0 Ring Configuration\n"); ++ seq_printf(s, "%20s %6s %10s %15s %10s %10s %10s\n", ++ "Name", "Used", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T0:Event(WM2H)", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_TX_RING0_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T1:Event(WA2H)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_TX_RING1_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T2:TxDone0(WA2H)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_TX_RING2_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T3:TxDone1(WA2H)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_TX_RING3_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T4:TXD(WM2MAC)", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_TX_RING4_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T5:TXCMD(WM2MAC)", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_TX_RING5_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T6:TXD(WA2MAC)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_TX_RING6_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R0:FWDL", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING0_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R1:Cmd(H2WM)", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING1_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R2:TXD0(H2WA)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING2_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R3:TXD1(H2WA)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING3_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R4:Cmd(H2WA)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING4_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R5:Data0(MAC2WM)", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING5_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R6:TxDone(MAC2WM)", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING6_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R7:SPL/RPT(MAC2WM)", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING7_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R8:TxDone(MAC2WA)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING8_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R9:Data1(MAC2WM)", "Both", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING9_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R10:TXD2(H2WA)", "AP", ++ WF_WFDMA_MCU_DMA0_WPDMA_RX_RING10_CTRL0_ADDR); ++ ++ /* MEM DMA information */ ++ sys_ctrl[0] = mt76_rr(dev, WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_ADDR); ++ sys_ctrl[1] = mt76_rr(dev, WF_WFDMA_MEM_DMA_HOST_INT_STA_ADDR); ++ sys_ctrl[2] = mt76_rr(dev, WF_WFDMA_MEM_DMA_HOST_INT_ENA_ADDR); ++ ++ seq_printf(s, "MEM_DMA Configuration\n"); ++ seq_printf(s, "%10s %10s %10s %10s %10s %10s\n", ++ "DMA", "IntCSR", "IntMask", "Glocfg", "Tx/RxEn", "Tx/RxBusy"); ++ seq_printf(s, "%10s %10x %10x %10x %4x/%5x %4x/%5x\n", ++ "MEM", sys_ctrl[1], sys_ctrl[2], sys_ctrl[0], ++ (sys_ctrl[0] & WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_MASK) ++ >> WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_MASK) ++ >> WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_EN_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_MASK) ++ >> WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_TX_DMA_BUSY_SHFT, ++ (sys_ctrl[0] & WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_MASK) ++ >> WF_WFDMA_MEM_DMA_WPDMA_GLO_CFG_RX_DMA_BUSY_SHFT); ++ ++ seq_printf(s, "MEM_DMA Ring Configuration\n"); ++ seq_printf(s, "%20s %6s %10s %10s %10s %10s %10s\n", ++ "Name", "Used", "Base", "Cnt", "CIDX", "DIDX", "QCnt"); ++ dump_dma_tx_ring_info(s, dev, "T0:CmdEvent(WM2WA)", "AP", ++ WF_WFDMA_MEM_DMA_WPDMA_TX_RING0_CTRL0_ADDR); ++ dump_dma_tx_ring_info(s, dev, "T1:CmdEvent(WA2WM)", "AP", ++ WF_WFDMA_MEM_DMA_WPDMA_TX_RING1_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R0:CmdEvent(WM2WA)", "AP", ++ WF_WFDMA_MEM_DMA_WPDMA_RX_RING0_CTRL0_ADDR); ++ dump_dma_rx_ring_info(s, dev, "R1:CmdEvent(WA2WM)", "AP", ++ WF_WFDMA_MEM_DMA_WPDMA_RX_RING1_CTRL0_ADDR); ++} ++ ++static int mt7996_trinfo_read(struct seq_file *s, void *data) ++{ ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ mt7996_show_dma_info(s, dev); ++ return 0; ++} ++ ++/* MIB INFO */ ++static int mt7996_mibinfo_read_per_band(struct seq_file *s, int band_idx) ++{ ++#define BSS_NUM 4 ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ u8 bss_nums = BSS_NUM; ++ u32 idx; ++ u32 mac_val, band_offset = 0, band_offset_umib = 0; ++ u32 msdr6, msdr9, msdr18; ++ u32 rvsr0, rscr26, rscr35, mctr5, mctr6, msr0, msr1, msr2; ++ u32 tbcr0, tbcr1, tbcr2, tbcr3, tbcr4; ++ u32 btscr[7]; ++ u32 tdrcr[5]; ++ u32 mbtocr[16], mbtbcr[16], mbrocr[16], mbrbcr[16]; ++ u32 btcr, btbcr, brocr, brbcr, btdcr, brdcr; ++ u32 mu_cnt[5]; ++ u32 ampdu_cnt[3]; ++ u64 per; ++ ++ switch (band_idx) { ++ case 0: ++ band_offset = 0; ++ band_offset_umib = 0; ++ break; ++ case 1: ++ band_offset = BN1_WF_MIB_TOP_BASE - BN0_WF_MIB_TOP_BASE; ++ band_offset_umib = WF_UMIB_TOP_B1BROCR_ADDR - WF_UMIB_TOP_B0BROCR_ADDR; ++ break; ++ case 2: ++ band_offset = IP1_BN0_WF_MIB_TOP_BASE - BN0_WF_MIB_TOP_BASE; ++ band_offset_umib = WF_UMIB_TOP_B2BROCR_ADDR - WF_UMIB_TOP_B0BROCR_ADDR; ++ break; ++ default: ++ return true; ++ } ++ ++ seq_printf(s, "Band %d MIB Status\n", band_idx); ++ seq_printf(s, "===============================\n"); ++ mac_val = mt76_rr(dev, BN0_WF_MIB_TOP_M0SCR0_ADDR + band_offset); ++ seq_printf(s, "MIB Status Control=0x%x\n", mac_val); ++ ++ msdr6 = mt76_rr(dev, BN0_WF_MIB_TOP_M0SDR6_ADDR + band_offset); ++ rvsr0 = mt76_rr(dev, BN0_WF_MIB_TOP_RVSR0_ADDR + band_offset); ++ rscr35 = mt76_rr(dev, BN0_WF_MIB_TOP_RSCR35_ADDR + band_offset); ++ msdr9 = mt76_rr(dev, BN0_WF_MIB_TOP_M0SDR9_ADDR + band_offset); ++ rscr26 = mt76_rr(dev, BN0_WF_MIB_TOP_RSCR26_ADDR + band_offset); ++ mctr5 = mt76_rr(dev, BN0_WF_MIB_TOP_MCTR5_ADDR + band_offset); ++ mctr6 = mt76_rr(dev, BN0_WF_MIB_TOP_MCTR6_ADDR + band_offset); ++ msdr18 = mt76_rr(dev, BN0_WF_MIB_TOP_M0SDR18_ADDR + band_offset); ++ msr0 = mt76_rr(dev, BN0_WF_MIB_TOP_MSR0_ADDR + band_offset); ++ msr1 = mt76_rr(dev, BN0_WF_MIB_TOP_MSR1_ADDR + band_offset); ++ msr2 = mt76_rr(dev, BN0_WF_MIB_TOP_MSR2_ADDR + band_offset); ++ ampdu_cnt[0] = mt76_rr(dev, BN0_WF_MIB_TOP_TSCR0_ADDR + band_offset); ++ ampdu_cnt[1] = mt76_rr(dev, BN0_WF_MIB_TOP_TSCR3_ADDR + band_offset); ++ ampdu_cnt[2] = mt76_rr(dev, BN0_WF_MIB_TOP_TSCR4_ADDR + band_offset); ++ ampdu_cnt[1] &= BN0_WF_MIB_TOP_TSCR3_AMPDU_MPDU_COUNT_MASK; ++ ampdu_cnt[2] &= BN0_WF_MIB_TOP_TSCR4_AMPDU_ACKED_COUNT_MASK; ++ ++ seq_printf(s, "===Phy/Timing Related Counters===\n"); ++ seq_printf(s, "\tChannelIdleCnt=0x%x\n", ++ msdr6 & BN0_WF_MIB_TOP_M0SDR6_CHANNEL_IDLE_COUNT_MASK); ++ seq_printf(s, "\tCCA_NAV_Tx_Time=0x%x\n", ++ msdr9 & BN0_WF_MIB_TOP_M0SDR9_CCA_NAV_TX_TIME_MASK); ++ seq_printf(s, "\tRx_MDRDY_CNT=0x%x\n", ++ rscr26 & BN0_WF_MIB_TOP_RSCR26_RX_MDRDY_COUNT_MASK); ++ seq_printf(s, "\tCCK_MDRDY_TIME=0x%x, OFDM_MDRDY_TIME=0x%x", ++ msr0 & BN0_WF_MIB_TOP_MSR0_CCK_MDRDY_TIME_MASK, ++ msr1 & BN0_WF_MIB_TOP_MSR1_OFDM_LG_MIXED_VHT_MDRDY_TIME_MASK); ++ seq_printf(s, ", OFDM_GREEN_MDRDY_TIME=0x%x\n", ++ msr2 & BN0_WF_MIB_TOP_MSR2_OFDM_GREEN_MDRDY_TIME_MASK); ++ seq_printf(s, "\tPrim CCA Time=0x%x\n", ++ mctr5 & BN0_WF_MIB_TOP_MCTR5_P_CCA_TIME_MASK); ++ seq_printf(s, "\tSec CCA Time=0x%x\n", ++ mctr6 & BN0_WF_MIB_TOP_MCTR6_S_CCA_TIME_MASK); ++ seq_printf(s, "\tPrim ED Time=0x%x\n", ++ msdr18 & BN0_WF_MIB_TOP_M0SDR18_P_ED_TIME_MASK); ++ ++ seq_printf(s, "===Tx Related Counters(Generic)===\n"); ++ mac_val = mt76_rr(dev, BN0_WF_MIB_TOP_TSCR18_ADDR + band_offset); ++ dev->dbg.bcn_total_cnt[band_idx] += ++ (mac_val & BN0_WF_MIB_TOP_TSCR18_BEACONTXCOUNT_MASK); ++ seq_printf(s, "\tBeaconTxCnt=0x%x\n", dev->dbg.bcn_total_cnt[band_idx]); ++ dev->dbg.bcn_total_cnt[band_idx] = 0; ++ ++ tbcr0 = mt76_rr(dev, BN0_WF_MIB_TOP_TBCR0_ADDR + band_offset); ++ seq_printf(s, "\tTx 20MHz Cnt=0x%x\n", ++ tbcr0 & BN0_WF_MIB_TOP_TBCR0_TX_20MHZ_CNT_MASK); ++ tbcr1 = mt76_rr(dev, BN0_WF_MIB_TOP_TBCR1_ADDR + band_offset); ++ seq_printf(s, "\tTx 40MHz Cnt=0x%x\n", ++ tbcr1 & BN0_WF_MIB_TOP_TBCR1_TX_40MHZ_CNT_MASK); ++ tbcr2 = mt76_rr(dev, BN0_WF_MIB_TOP_TBCR2_ADDR + band_offset); ++ seq_printf(s, "\tTx 80MHz Cnt=0x%x\n", ++ tbcr2 & BN0_WF_MIB_TOP_TBCR2_TX_80MHZ_CNT_MASK); ++ tbcr3 = mt76_rr(dev, BN0_WF_MIB_TOP_TBCR3_ADDR + band_offset); ++ seq_printf(s, "\tTx 160MHz Cnt=0x%x\n", ++ tbcr3 & BN0_WF_MIB_TOP_TBCR3_TX_160MHZ_CNT_MASK); ++ tbcr4 = mt76_rr(dev, BN0_WF_MIB_TOP_TBCR4_ADDR + band_offset); ++ seq_printf(s, "\tTx 320MHz Cnt=0x%x\n", ++ tbcr4 & BN0_WF_MIB_TOP_TBCR4_TX_320MHZ_CNT_MASK); ++ seq_printf(s, "\tAMPDU Cnt=0x%x\n", ampdu_cnt[0]); ++ seq_printf(s, "\tAMPDU MPDU Cnt=0x%x\n", ampdu_cnt[1]); ++ seq_printf(s, "\tAMPDU MPDU Ack Cnt=0x%x\n", ampdu_cnt[2]); ++ per = (ampdu_cnt[2] == 0 ? ++ 0 : 1000 * (ampdu_cnt[1] - ampdu_cnt[2]) / ampdu_cnt[1]); ++ seq_printf(s, "\tAMPDU MPDU PER=%llu.%1llu%%\n", per / 10, per % 10); ++ ++ seq_printf(s, "===MU Related Counters===\n"); ++ mu_cnt[0] = mt76_rr(dev, BN0_WF_MIB_TOP_BSCR2_ADDR + band_offset); ++ mu_cnt[1] = mt76_rr(dev, BN0_WF_MIB_TOP_TSCR5_ADDR + band_offset); ++ mu_cnt[2] = mt76_rr(dev, BN0_WF_MIB_TOP_TSCR6_ADDR + band_offset); ++ mu_cnt[3] = mt76_rr(dev, BN0_WF_MIB_TOP_TSCR8_ADDR + band_offset); ++ mu_cnt[4] = mt76_rr(dev, BN0_WF_MIB_TOP_TSCR7_ADDR + band_offset); ++ ++ seq_printf(s, "\tMUBF_TX_COUNT=0x%x\n", ++ mu_cnt[0] & BN0_WF_MIB_TOP_BSCR2_MUBF_TX_COUNT_MASK); ++ seq_printf(s, "\tMU_TX_MPDU_COUNT(Ok+Fail)=0x%x\n", mu_cnt[1]); ++ seq_printf(s, "\tMU_TX_OK_MPDU_COUNT=0x%x\n", mu_cnt[2]); ++ seq_printf(s, "\tMU_TO_MU_FAIL_PPDU_COUNT=0x%x\n", mu_cnt[3]); ++ seq_printf(s, "\tSU_TX_OK_MPDU_COUNT=0x%x\n", mu_cnt[4]); ++ ++ seq_printf(s, "===Rx Related Counters(Generic)===\n"); ++ seq_printf(s, "\tVector Mismacth Cnt=0x%x\n", ++ rvsr0 & BN0_WF_MIB_TOP_RVSR0_VEC_MISS_COUNT_MASK); ++ seq_printf(s, "\tDelimiter Fail Cnt=0x%x\n", ++ rscr35 & BN0_WF_MIB_TOP_RSCR35_DELIMITER_FAIL_COUNT_MASK); ++ ++ mac_val = mt76_rr(dev, BN0_WF_MIB_TOP_RSCR1_ADDR + band_offset); ++ seq_printf(s, "\tRxFCSErrCnt=0x%x\n", ++ (mac_val & BN0_WF_MIB_TOP_RSCR1_RX_FCS_ERROR_COUNT_MASK)); ++ mac_val = mt76_rr(dev, BN0_WF_MIB_TOP_RSCR33_ADDR + band_offset); ++ seq_printf(s, "\tRxFifoFullCnt=0x%x\n", ++ (mac_val & BN0_WF_MIB_TOP_RSCR33_RX_FIFO_FULL_COUNT_MASK)); ++ mac_val = mt76_rr(dev, BN0_WF_MIB_TOP_RSCR36_ADDR + band_offset); ++ seq_printf(s, "\tRxLenMismatch=0x%x\n", ++ (mac_val & BN0_WF_MIB_TOP_RSCR36_RX_LEN_MISMATCH_MASK)); ++ mac_val = mt76_rr(dev, BN0_WF_MIB_TOP_RSCR31_ADDR + band_offset); ++ seq_printf(s, "\tRxMPDUCnt=0x%x\n", ++ (mac_val & BN0_WF_MIB_TOP_RSCR31_RX_MPDU_COUNT_MASK)); ++ mac_val = mt76_rr(dev, BN0_WF_MIB_TOP_RSCR27_ADDR + band_offset); ++ seq_printf(s, "\tRx AMPDU Cnt=0x%x\n", mac_val); ++ mac_val = mt76_rr(dev, BN0_WF_MIB_TOP_RSCR28_ADDR + band_offset); ++ seq_printf(s, "\tRx Total ByteCnt=0x%x\n", mac_val); ++ ++ ++ /* Per-BSS T/RX Counters */ ++ seq_printf(s, "===Per-BSS Related Tx/Rx Counters===\n"); ++ seq_printf(s, "BSS Idx TxCnt/DataCnt TxByteCnt RxOkCnt/DataCnt RxByteCnt\n"); ++ for (idx = 0; idx < bss_nums; idx++) { ++ btcr = mt76_rr(dev, BN0_WF_MIB_TOP_BTCR_ADDR + band_offset + idx * 4); ++ btdcr = mt76_rr(dev, BN0_WF_MIB_TOP_BTDCR_ADDR + band_offset + idx * 4); ++ btbcr = mt76_rr(dev, BN0_WF_MIB_TOP_BTBCR_ADDR + band_offset + idx * 4); ++ ++ brocr = mt76_rr(dev, WF_UMIB_TOP_B0BROCR_ADDR + band_offset_umib + idx * 4); ++ brdcr = mt76_rr(dev, WF_UMIB_TOP_B0BRDCR_ADDR + band_offset_umib + idx * 4); ++ brbcr = mt76_rr(dev, WF_UMIB_TOP_B0BRBCR_ADDR + band_offset_umib + idx * 4); ++ ++ seq_printf(s, "%d\t 0x%x/0x%x\t 0x%x \t 0x%x/0x%x \t 0x%x\n", ++ idx, btcr, btdcr, btbcr, brocr, brdcr, brbcr); ++ } ++ ++ seq_printf(s, "===Per-BSS Related MIB Counters===\n"); ++ seq_printf(s, "BSS Idx RTSTx/RetryCnt BAMissCnt AckFailCnt FrmRetry1/2/3Cnt\n"); ++ ++ /* Per-BSS TX Status */ ++ for (idx = 0; idx < bss_nums; idx++) { ++ btscr[0] = mt76_rr(dev, BN0_WF_MIB_TOP_BTSCR5_ADDR + band_offset + idx * 4); ++ btscr[1] = mt76_rr(dev, BN0_WF_MIB_TOP_BTSCR6_ADDR + band_offset + idx * 4); ++ btscr[2] = mt76_rr(dev, BN0_WF_MIB_TOP_BTSCR0_ADDR + band_offset + idx * 4); ++ btscr[3] = mt76_rr(dev, BN0_WF_MIB_TOP_BTSCR1_ADDR + band_offset + idx * 4); ++ btscr[4] = mt76_rr(dev, BN0_WF_MIB_TOP_BTSCR2_ADDR + band_offset + idx * 4); ++ btscr[5] = mt76_rr(dev, BN0_WF_MIB_TOP_BTSCR3_ADDR + band_offset + idx * 4); ++ btscr[6] = mt76_rr(dev, BN0_WF_MIB_TOP_BTSCR4_ADDR + band_offset + idx * 4); ++ ++ seq_printf(s, "%d:\t0x%x/0x%x 0x%x \t 0x%x \t 0x%x/0x%x/0x%x\n", ++ idx, (btscr[0] & BN0_WF_MIB_TOP_BTSCR5_RTSTXCOUNTn_MASK), ++ (btscr[1] & BN0_WF_MIB_TOP_BTSCR6_RTSRETRYCOUNTn_MASK), ++ (btscr[2] & BN0_WF_MIB_TOP_BTSCR0_BAMISSCOUNTn_MASK), ++ (btscr[3] & BN0_WF_MIB_TOP_BTSCR1_ACKFAILCOUNTn_MASK), ++ (btscr[4] & BN0_WF_MIB_TOP_BTSCR2_FRAMERETRYCOUNTn_MASK), ++ (btscr[5] & BN0_WF_MIB_TOP_BTSCR3_FRAMERETRY2COUNTn_MASK), ++ (btscr[6] & BN0_WF_MIB_TOP_BTSCR4_FRAMERETRY3COUNTn_MASK)); ++ } ++ ++ /* Dummy delimiter insertion result */ ++ seq_printf(s, "===Dummy delimiter insertion result===\n"); ++ tdrcr[0] = mt76_rr(dev, BN0_WF_MIB_TOP_TDRCR0_ADDR + band_offset); ++ tdrcr[1] = mt76_rr(dev, BN0_WF_MIB_TOP_TDRCR1_ADDR + band_offset); ++ tdrcr[2] = mt76_rr(dev, BN0_WF_MIB_TOP_TDRCR2_ADDR + band_offset); ++ tdrcr[3] = mt76_rr(dev, BN0_WF_MIB_TOP_TDRCR3_ADDR + band_offset); ++ tdrcr[4] = mt76_rr(dev, BN0_WF_MIB_TOP_TDRCR4_ADDR + band_offset); ++ ++ seq_printf(s, "Range0 = %d\t Range1 = %d\t Range2 = %d\t Range3 = %d\t Range4 = %d\n", ++ tdrcr[0], ++ tdrcr[1], ++ tdrcr[2], ++ tdrcr[3], ++ tdrcr[4]); ++ ++ /* Per-MBSS T/RX Counters */ ++ seq_printf(s, "===Per-MBSS Related Tx/Rx Counters===\n"); ++ seq_printf(s, "MBSSIdx TxOkCnt TxByteCnt RxOkCnt RxByteCnt\n"); ++ ++ for (idx = 0; idx < 16; idx++) { ++ mbtocr[idx] = mt76_rr(dev, BN0_WF_MIB_TOP_BTOCR_ADDR + band_offset + (bss_nums + idx) * 4); ++ mbtbcr[idx] = mt76_rr(dev, BN0_WF_MIB_TOP_BTBCR_ADDR + band_offset + (bss_nums + idx) * 4); ++ ++ mbrocr[idx] = mt76_rr(dev, WF_UMIB_TOP_B0BROCR_ADDR + band_offset_umib + (bss_nums + idx) * 4); ++ mbrbcr[idx] = mt76_rr(dev, WF_UMIB_TOP_B0BRBCR_ADDR + band_offset_umib + (bss_nums + idx) * 4); ++ } ++ ++ for (idx = 0; idx < 16; idx++) { ++ seq_printf(s, "%d\t 0x%x\t 0x%x \t 0x%x \t 0x%x\n", ++ idx, mbtocr[idx], mbtbcr[idx], mbrocr[idx], mbrbcr[idx]); ++ } ++ ++ return 0; ++} ++ ++static int mt7996_mibinfo_band0(struct seq_file *s, void *data) ++{ ++ mt7996_mibinfo_read_per_band(s, MT_BAND0); ++ return 0; ++} ++ ++static int mt7996_mibinfo_band1(struct seq_file *s, void *data) ++{ ++ mt7996_mibinfo_read_per_band(s, MT_BAND1); ++ return 0; ++} ++ ++static int mt7996_mibinfo_band2(struct seq_file *s, void *data) ++{ ++ mt7996_mibinfo_read_per_band(s, MT_BAND2); ++ return 0; ++} ++ ++/* WTBL INFO */ ++static int ++mt7996_wtbl_read_raw(struct mt7996_dev *dev, u16 idx, ++ enum mt7996_wtbl_type type, u16 start_dw, ++ u16 len, void *buf) ++{ ++ u32 *dest_cpy = (u32 *)buf; ++ u32 size_dw = len; ++ u32 src = 0; ++ ++ if (!buf) ++ return 0xFF; ++ ++ if (type == WTBL_TYPE_LMAC) { ++ mt76_wr(dev, MT_DBG_WTBLON_TOP_WDUCR_ADDR, ++ FIELD_PREP(MT_DBG_WTBLON_TOP_WDUCR_GROUP, (idx >> 7))); ++ src = LWTBL_IDX2BASE(idx, start_dw); ++ } else if (type == WTBL_TYPE_UMAC) { ++ mt76_wr(dev, MT_DBG_UWTBL_TOP_WDUCR_ADDR, ++ FIELD_PREP(MT_DBG_UWTBL_TOP_WDUCR_GROUP, (idx >> 7))); ++ src = UWTBL_IDX2BASE(idx, start_dw); ++ } else if (type == WTBL_TYPE_KEY) { ++ mt76_wr(dev, MT_DBG_UWTBL_TOP_WDUCR_ADDR, ++ MT_DBG_UWTBL_TOP_WDUCR_TARGET | ++ FIELD_PREP(MT_DBG_UWTBL_TOP_WDUCR_GROUP, (idx >> 7))); ++ src = KEYTBL_IDX2BASE(idx, start_dw); ++ } ++ ++ while (size_dw--) { ++ *dest_cpy++ = mt76_rr(dev, src); ++ src += 4; ++ }; ++ ++ return 0; ++} ++ ++#if 0 ++static int ++mt7996_wtbl_write_raw(struct mt7996_dev *dev, u16 idx, ++ enum mt7996_wtbl_type type, u16 start_dw, ++ u32 val) ++{ ++ u32 addr = 0; ++ ++ if (type == WTBL_TYPE_LMAC) { ++ mt76_wr(dev, MT_DBG_WTBLON_TOP_WDUCR_ADDR, ++ FIELD_PREP(MT_DBG_WTBLON_TOP_WDUCR_GROUP, (idx >> 7))); ++ addr = LWTBL_IDX2BASE(idx, start_dw); ++ } else if (type == WTBL_TYPE_UMAC) { ++ mt76_wr(dev, MT_DBG_UWTBL_TOP_WDUCR_ADDR, ++ FIELD_PREP(MT_DBG_UWTBL_TOP_WDUCR_GROUP, (idx >> 7))); ++ addr = UWTBL_IDX2BASE(idx, start_dw); ++ } else if (type == WTBL_TYPE_KEY) { ++ mt76_wr(dev, MT_DBG_UWTBL_TOP_WDUCR_ADDR, ++ MT_DBG_UWTBL_TOP_WDUCR_TARGET | ++ FIELD_PREP(MT_DBG_UWTBL_TOP_WDUCR_GROUP, (idx >> 7))); ++ addr = KEYTBL_IDX2BASE(idx, start_dw); ++ } ++ ++ mt76_wr(dev, addr, val); ++ ++ return 0; ++} ++#endif ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW0[] = { ++ {"MUAR_IDX", WF_LWTBL_MUAR_MASK, WF_LWTBL_MUAR_SHIFT,false}, ++ {"RCA1", WF_LWTBL_RCA1_MASK, NO_SHIFT_DEFINE, false}, ++ {"KID", WF_LWTBL_KID_MASK, WF_LWTBL_KID_SHIFT, false}, ++ {"RCID", WF_LWTBL_RCID_MASK, NO_SHIFT_DEFINE, false}, ++ {"BAND", WF_LWTBL_BAND_MASK, WF_LWTBL_BAND_SHIFT,false}, ++ {"RV", WF_LWTBL_RV_MASK, NO_SHIFT_DEFINE, false}, ++ {"RCA2", WF_LWTBL_RCA2_MASK, NO_SHIFT_DEFINE, false}, ++ {"WPI_FLAG", WF_LWTBL_WPI_FLAG_MASK, NO_SHIFT_DEFINE,true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw0_1(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LinkAddr: %02x:%02x:%02x:%02x:%02x:%02x(D0[B0~15], D1[B0~31])\n", ++ lwtbl[4], lwtbl[5], lwtbl[6], lwtbl[7], lwtbl[0], lwtbl[1]); ++ ++ /* LMAC WTBL DW 0 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 0/1\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_PEER_INFO_DW_0*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW0[i].name) { ++ ++ if (WTBL_LMAC_DW0[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW0[i].name, ++ (dw_value & WTBL_LMAC_DW0[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW0[i].name, ++ (dw_value & WTBL_LMAC_DW0[i].mask) >> WTBL_LMAC_DW0[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse *WTBL_LMAC_DW2; ++static const struct berse_wtbl_parse WTBL_LMAC_DW2_7996[] = { ++ {"AID", WF_LWTBL_AID_MASK, WF_LWTBL_AID_SHIFT, false}, ++ {"GID_SU", WF_LWTBL_GID_SU_MASK, NO_SHIFT_DEFINE, false}, ++ {"SPP_EN", WF_LWTBL_SPP_EN_MASK, NO_SHIFT_DEFINE, false}, ++ {"WPI_EVEN", WF_LWTBL_WPI_EVEN_MASK, NO_SHIFT_DEFINE, false}, ++ {"AAD_OM", WF_LWTBL_AAD_OM_MASK, NO_SHIFT_DEFINE, false}, ++ {"CIPHER_PGTK",WF_LWTBL_CIPHER_SUIT_PGTK_MASK, WF_LWTBL_CIPHER_SUIT_PGTK_SHIFT, true}, ++ {"FROM_DS", WF_LWTBL_FD_MASK, NO_SHIFT_DEFINE, false}, ++ {"TO_DS", WF_LWTBL_TD_MASK, NO_SHIFT_DEFINE, false}, ++ {"SW", WF_LWTBL_SW_MASK, NO_SHIFT_DEFINE, false}, ++ {"UL", WF_LWTBL_UL_MASK, NO_SHIFT_DEFINE, false}, ++ {"TX_POWER_SAVE", WF_LWTBL_TX_PS_MASK, NO_SHIFT_DEFINE, true}, ++ {"QOS", WF_LWTBL_QOS_MASK, NO_SHIFT_DEFINE, false}, ++ {"HT", WF_LWTBL_HT_MASK, NO_SHIFT_DEFINE, false}, ++ {"VHT", WF_LWTBL_VHT_MASK, NO_SHIFT_DEFINE, false}, ++ {"HE", WF_LWTBL_HE_MASK, NO_SHIFT_DEFINE, false}, ++ {"EHT", WF_LWTBL_EHT_MASK, NO_SHIFT_DEFINE, false}, ++ {"MESH", WF_LWTBL_MESH_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW2_7992[] = { ++ {"AID", WF_LWTBL_AID_MASK, WF_LWTBL_AID_SHIFT, false}, ++ {"GID_SU", WF_LWTBL_GID_SU_MASK, NO_SHIFT_DEFINE, false}, ++ {"DUAL_PTEC_EN", WF_LWTBL_DUAL_PTEC_EN_MASK, NO_SHIFT_DEFINE, false}, ++ {"DUAL_CTS_CAP", WF_LWTBL_DUAL_CTS_CAP_MASK, NO_SHIFT_DEFINE, false}, ++ {"CIPHER_PGTK",WF_LWTBL_CIPHER_SUIT_PGTK_MASK, WF_LWTBL_CIPHER_SUIT_PGTK_SHIFT, true}, ++ {"FROM_DS", WF_LWTBL_FD_MASK, NO_SHIFT_DEFINE, false}, ++ {"TO_DS", WF_LWTBL_TD_MASK, NO_SHIFT_DEFINE, false}, ++ {"SW", WF_LWTBL_SW_MASK, NO_SHIFT_DEFINE, false}, ++ {"UL", WF_LWTBL_UL_MASK, NO_SHIFT_DEFINE, false}, ++ {"TX_POWER_SAVE", WF_LWTBL_TX_PS_MASK, NO_SHIFT_DEFINE, true}, ++ {"QOS", WF_LWTBL_QOS_MASK, NO_SHIFT_DEFINE, false}, ++ {"HT", WF_LWTBL_HT_MASK, NO_SHIFT_DEFINE, false}, ++ {"VHT", WF_LWTBL_VHT_MASK, NO_SHIFT_DEFINE, false}, ++ {"HE", WF_LWTBL_HE_MASK, NO_SHIFT_DEFINE, false}, ++ {"EHT", WF_LWTBL_EHT_MASK, NO_SHIFT_DEFINE, false}, ++ {"MESH", WF_LWTBL_MESH_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw2(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 2 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 2\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_2*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW2[i].name) { ++ ++ if (WTBL_LMAC_DW2[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW2[i].name, ++ (dw_value & WTBL_LMAC_DW2[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW2[i].name, ++ (dw_value & WTBL_LMAC_DW2[i].mask) >> WTBL_LMAC_DW2[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW3[] = { ++ {"WMM_Q", WF_LWTBL_WMM_Q_MASK, WF_LWTBL_WMM_Q_SHIFT, false}, ++ {"EHT_SIG_MCS", WF_LWTBL_EHT_SIG_MCS_MASK, WF_LWTBL_EHT_SIG_MCS_SHIFT, false}, ++ {"HDRT_MODE", WF_LWTBL_HDRT_MODE_MASK, NO_SHIFT_DEFINE, false}, ++ {"BEAM_CHG", WF_LWTBL_BEAM_CHG_MASK, NO_SHIFT_DEFINE, false}, ++ {"EHT_LTF_SYM_NUM", WF_LWTBL_EHT_LTF_SYM_NUM_OPT_MASK, WF_LWTBL_EHT_LTF_SYM_NUM_OPT_SHIFT, true}, ++ {"PFMU_IDX", WF_LWTBL_PFMU_IDX_MASK, WF_LWTBL_PFMU_IDX_SHIFT, false}, ++ {"ULPF_IDX", WF_LWTBL_ULPF_IDX_MASK, WF_LWTBL_ULPF_IDX_SHIFT, false}, ++ {"RIBF", WF_LWTBL_RIBF_MASK, NO_SHIFT_DEFINE, false}, ++ {"ULPF", WF_LWTBL_ULPF_MASK, NO_SHIFT_DEFINE, false}, ++ {"BYPASS_TXSMM", WF_LWTBL_BYPASS_TXSMM_MASK, NO_SHIFT_DEFINE, true}, ++ {"TBF_HT", WF_LWTBL_TBF_HT_MASK, NO_SHIFT_DEFINE, false}, ++ {"TBF_VHT", WF_LWTBL_TBF_VHT_MASK, NO_SHIFT_DEFINE, false}, ++ {"TBF_HE", WF_LWTBL_TBF_HE_MASK, NO_SHIFT_DEFINE, false}, ++ {"TBF_EHT", WF_LWTBL_TBF_EHT_MASK, NO_SHIFT_DEFINE, false}, ++ {"IGN_FBK", WF_LWTBL_IGN_FBK_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw3(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 3 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 3\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_3*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW3[i].name) { ++ ++ if (WTBL_LMAC_DW3[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW3[i].name, ++ (dw_value & WTBL_LMAC_DW3[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW3[i].name, ++ (dw_value & WTBL_LMAC_DW3[i].mask) >> WTBL_LMAC_DW3[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW4[] = { ++ {"NEGOTIATED_WINSIZE0", WF_LWTBL_NEGOTIATED_WINSIZE0_MASK, WF_LWTBL_NEGOTIATED_WINSIZE0_SHIFT, false}, ++ {"WINSIZE1", WF_LWTBL_NEGOTIATED_WINSIZE1_MASK, WF_LWTBL_NEGOTIATED_WINSIZE1_SHIFT, false}, ++ {"WINSIZE2", WF_LWTBL_NEGOTIATED_WINSIZE2_MASK, WF_LWTBL_NEGOTIATED_WINSIZE2_SHIFT, false}, ++ {"WINSIZE3", WF_LWTBL_NEGOTIATED_WINSIZE3_MASK, WF_LWTBL_NEGOTIATED_WINSIZE3_SHIFT, true}, ++ {"WINSIZE4", WF_LWTBL_NEGOTIATED_WINSIZE4_MASK, WF_LWTBL_NEGOTIATED_WINSIZE4_SHIFT, false}, ++ {"WINSIZE5", WF_LWTBL_NEGOTIATED_WINSIZE5_MASK, WF_LWTBL_NEGOTIATED_WINSIZE5_SHIFT, false}, ++ {"WINSIZE6", WF_LWTBL_NEGOTIATED_WINSIZE6_MASK, WF_LWTBL_NEGOTIATED_WINSIZE6_SHIFT, false}, ++ {"WINSIZE7", WF_LWTBL_NEGOTIATED_WINSIZE7_MASK, WF_LWTBL_NEGOTIATED_WINSIZE7_SHIFT, true}, ++ {"PE", WF_LWTBL_PE_MASK, WF_LWTBL_PE_SHIFT, false}, ++ {"DIS_RHTR", WF_LWTBL_DIS_RHTR_MASK, NO_SHIFT_DEFINE, false}, ++ {"LDPC_HT", WF_LWTBL_LDPC_HT_MASK, NO_SHIFT_DEFINE, false}, ++ {"LDPC_VHT", WF_LWTBL_LDPC_VHT_MASK, NO_SHIFT_DEFINE, false}, ++ {"LDPC_HE", WF_LWTBL_LDPC_HE_MASK, NO_SHIFT_DEFINE, false}, ++ {"LDPC_EHT", WF_LWTBL_LDPC_EHT_MASK, NO_SHIFT_DEFINE, true}, ++ {"BA_MODE", WF_LWTBL_BA_MODE_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw4(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 4 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 4\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_4*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW4[i].name) { ++ if (WTBL_LMAC_DW4[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW4[i].name, ++ (dw_value & WTBL_LMAC_DW4[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW4[i].name, ++ (dw_value & WTBL_LMAC_DW4[i].mask) >> WTBL_LMAC_DW4[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse *WTBL_LMAC_DW5; ++static const struct berse_wtbl_parse WTBL_LMAC_DW5_7996[] = { ++ {"AF", WF_LWTBL_AF_MASK, WF_LWTBL_AF_SHIFT, false}, ++ {"AF_HE", WF_LWTBL_AF_HE_MASK, WF_LWTBL_AF_HE_SHIFT,false}, ++ {"RTS", WF_LWTBL_RTS_MASK, NO_SHIFT_DEFINE, false}, ++ {"SMPS", WF_LWTBL_SMPS_MASK, NO_SHIFT_DEFINE, false}, ++ {"DYN_BW", WF_LWTBL_DYN_BW_MASK, NO_SHIFT_DEFINE, true}, ++ {"MMSS", WF_LWTBL_MMSS_MASK, WF_LWTBL_MMSS_SHIFT,false}, ++ {"USR", WF_LWTBL_USR_MASK, NO_SHIFT_DEFINE, false}, ++ {"SR_RATE", WF_LWTBL_SR_R_MASK, WF_LWTBL_SR_R_SHIFT,false}, ++ {"SR_ABORT", WF_LWTBL_SR_ABORT_MASK, NO_SHIFT_DEFINE, true}, ++ {"TX_POWER_OFFSET", WF_LWTBL_TX_POWER_OFFSET_MASK, WF_LWTBL_TX_POWER_OFFSET_SHIFT, false}, ++ {"LTF_EHT", WF_LWTBL_LTF_EHT_MASK, WF_LWTBL_LTF_EHT_SHIFT, false}, ++ {"GI_EHT", WF_LWTBL_GI_EHT_MASK, WF_LWTBL_GI_EHT_SHIFT, false}, ++ {"DOPPL", WF_LWTBL_DOPPL_MASK, NO_SHIFT_DEFINE, false}, ++ {"TXOP_PS_CAP", WF_LWTBL_TXOP_PS_CAP_MASK, NO_SHIFT_DEFINE, false}, ++ {"DONOT_UPDATE_I_PSM", WF_LWTBL_DU_I_PSM_MASK, NO_SHIFT_DEFINE, true}, ++ {"I_PSM", WF_LWTBL_I_PSM_MASK, NO_SHIFT_DEFINE, false}, ++ {"PSM", WF_LWTBL_PSM_MASK, NO_SHIFT_DEFINE, false}, ++ {"SKIP_TX", WF_LWTBL_SKIP_TX_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW5_7992[] = { ++ {"AF", WF_LWTBL_AF_MASK_7992, WF_LWTBL_AF_SHIFT, false}, ++ {"RTS", WF_LWTBL_RTS_MASK, NO_SHIFT_DEFINE, false}, ++ {"SMPS", WF_LWTBL_SMPS_MASK, NO_SHIFT_DEFINE, false}, ++ {"DYN_BW", WF_LWTBL_DYN_BW_MASK, NO_SHIFT_DEFINE, true}, ++ {"MMSS", WF_LWTBL_MMSS_MASK, WF_LWTBL_MMSS_SHIFT,false}, ++ {"USR", WF_LWTBL_USR_MASK, NO_SHIFT_DEFINE, false}, ++ {"SR_RATE", WF_LWTBL_SR_R_MASK, WF_LWTBL_SR_R_SHIFT,false}, ++ {"SR_ABORT", WF_LWTBL_SR_ABORT_MASK, NO_SHIFT_DEFINE, true}, ++ {"TX_POWER_OFFSET", WF_LWTBL_TX_POWER_OFFSET_MASK, WF_LWTBL_TX_POWER_OFFSET_SHIFT, false}, ++ {"LTF_EHT", WF_LWTBL_LTF_EHT_MASK, WF_LWTBL_LTF_EHT_SHIFT, false}, ++ {"GI_EHT", WF_LWTBL_GI_EHT_MASK, WF_LWTBL_GI_EHT_SHIFT, false}, ++ {"DOPPL", WF_LWTBL_DOPPL_MASK, NO_SHIFT_DEFINE, false}, ++ {"TXOP_PS_CAP", WF_LWTBL_TXOP_PS_CAP_MASK, NO_SHIFT_DEFINE, false}, ++ {"DONOT_UPDATE_I_PSM", WF_LWTBL_DU_I_PSM_MASK, NO_SHIFT_DEFINE, true}, ++ {"I_PSM", WF_LWTBL_I_PSM_MASK, NO_SHIFT_DEFINE, false}, ++ {"PSM", WF_LWTBL_PSM_MASK, NO_SHIFT_DEFINE, false}, ++ {"SKIP_TX", WF_LWTBL_SKIP_TX_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw5(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 5 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 5\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_5*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW5[i].name) { ++ if (WTBL_LMAC_DW5[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW5[i].name, ++ (dw_value & WTBL_LMAC_DW5[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW5[i].name, ++ (dw_value & WTBL_LMAC_DW5[i].mask) >> WTBL_LMAC_DW5[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW6[] = { ++ {"CBRN", WF_LWTBL_CBRN_MASK, WF_LWTBL_CBRN_SHIFT, false}, ++ {"DBNSS_EN", WF_LWTBL_DBNSS_EN_MASK, NO_SHIFT_DEFINE, false}, ++ {"BAF_EN", WF_LWTBL_BAF_EN_MASK, NO_SHIFT_DEFINE, false}, ++ {"RDGBA", WF_LWTBL_RDGBA_MASK, NO_SHIFT_DEFINE, false}, ++ {"RDG", WF_LWTBL_R_MASK, NO_SHIFT_DEFINE, false}, ++ {"SPE_IDX", WF_LWTBL_SPE_IDX_MASK, WF_LWTBL_SPE_IDX_SHIFT, true}, ++ {"G2", WF_LWTBL_G2_MASK, NO_SHIFT_DEFINE, false}, ++ {"G4", WF_LWTBL_G4_MASK, NO_SHIFT_DEFINE, false}, ++ {"G8", WF_LWTBL_G8_MASK, NO_SHIFT_DEFINE, false}, ++ {"G16", WF_LWTBL_G16_MASK, NO_SHIFT_DEFINE, true}, ++ {"G2_LTF", WF_LWTBL_G2_LTF_MASK, WF_LWTBL_G2_LTF_SHIFT, false}, ++ {"G4_LTF", WF_LWTBL_G4_LTF_MASK, WF_LWTBL_G4_LTF_SHIFT, false}, ++ {"G8_LTF", WF_LWTBL_G8_LTF_MASK, WF_LWTBL_G8_LTF_SHIFT, false}, ++ {"G16_LTF", WF_LWTBL_G16_LTF_MASK, WF_LWTBL_G16_LTF_SHIFT, true}, ++ {"G2_HE", WF_LWTBL_G2_HE_MASK, WF_LWTBL_G2_HE_SHIFT, false}, ++ {"G4_HE", WF_LWTBL_G4_HE_MASK, WF_LWTBL_G4_HE_SHIFT, false}, ++ {"G8_HE", WF_LWTBL_G8_HE_MASK, WF_LWTBL_G8_HE_SHIFT, false}, ++ {"G16_HE", WF_LWTBL_G16_HE_MASK, WF_LWTBL_G16_HE_SHIFT, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw6(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 6 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 6\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_6*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW6[i].name) { ++ if (WTBL_LMAC_DW6[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW6[i].name, ++ (dw_value & WTBL_LMAC_DW6[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW6[i].name, ++ (dw_value & WTBL_LMAC_DW6[i].mask) >> WTBL_LMAC_DW6[i].shift); ++ i++; ++ } ++} ++ ++static void parse_fmac_lwtbl_dw7(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ int i = 0; ++ ++ /* LMAC WTBL DW 7 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 7\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_7*4]); ++ dw_value = *addr; ++ ++ for (i = 0; i < 8; i++) { ++ seq_printf(s, "\tBA_WIN_SIZE%u:%lu\n", i, ((dw_value & BITS(i*4, i*4+3)) >> i*4)); ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW8[] = { ++ {"RTS_FAIL_CNT_AC0", WF_LWTBL_AC0_RTS_FAIL_CNT_MASK, WF_LWTBL_AC0_RTS_FAIL_CNT_SHIFT, false}, ++ {"AC1", WF_LWTBL_AC1_RTS_FAIL_CNT_MASK, WF_LWTBL_AC1_RTS_FAIL_CNT_SHIFT, false}, ++ {"AC2", WF_LWTBL_AC2_RTS_FAIL_CNT_MASK, WF_LWTBL_AC2_RTS_FAIL_CNT_SHIFT, false}, ++ {"AC3", WF_LWTBL_AC3_RTS_FAIL_CNT_MASK, WF_LWTBL_AC3_RTS_FAIL_CNT_SHIFT, true}, ++ {"PARTIAL_AID", WF_LWTBL_PARTIAL_AID_MASK, WF_LWTBL_PARTIAL_AID_SHIFT, false}, ++ {"CHK_PER", WF_LWTBL_CHK_PER_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw8(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 8 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 8\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_8*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW8[i].name) { ++ if (WTBL_LMAC_DW8[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW8[i].name, ++ (dw_value & WTBL_LMAC_DW8[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW8[i].name, ++ (dw_value & WTBL_LMAC_DW8[i].mask) >> WTBL_LMAC_DW8[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse *WTBL_LMAC_DW9; ++static const struct berse_wtbl_parse WTBL_LMAC_DW9_7996[] = { ++ {"RX_AVG_MPDU_SIZE", WF_LWTBL_RX_AVG_MPDU_SIZE_MASK, WF_LWTBL_RX_AVG_MPDU_SIZE_SHIFT, false}, ++ {"PRITX_SW_MODE", WF_LWTBL_PRITX_SW_MODE_MASK, NO_SHIFT_DEFINE, false}, ++ {"PRITX_ERSU", WF_LWTBL_PRITX_ERSU_MASK, NO_SHIFT_DEFINE, false}, ++ {"PRITX_PLR", WF_LWTBL_PRITX_PLR_MASK, NO_SHIFT_DEFINE, true}, ++ {"PRITX_DCM", WF_LWTBL_PRITX_DCM_MASK, NO_SHIFT_DEFINE, false}, ++ {"PRITX_ER106T", WF_LWTBL_PRITX_ER106T_MASK, NO_SHIFT_DEFINE, true}, ++ /* {"FCAP(0:20 1:~40)", WTBL_FCAP_20_TO_160_MHZ, WTBL_FCAP_20_TO_160_MHZ_OFFSET}, */ ++ {"MPDU_FAIL_CNT", WF_LWTBL_MPDU_FAIL_CNT_MASK, WF_LWTBL_MPDU_FAIL_CNT_SHIFT, false}, ++ {"MPDU_OK_CNT", WF_LWTBL_MPDU_OK_CNT_MASK, WF_LWTBL_MPDU_OK_CNT_SHIFT, false}, ++ {"RATE_IDX", WF_LWTBL_RATE_IDX_MASK, WF_LWTBL_RATE_IDX_SHIFT, true}, ++ {NULL,} ++}; ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW9_7992[] = { ++ {"RX_AVG_MPDU_SIZE", WF_LWTBL_RX_AVG_MPDU_SIZE_MASK, WF_LWTBL_RX_AVG_MPDU_SIZE_SHIFT, false}, ++ {"PRITX_SW_MODE", WF_LWTBL_PRITX_SW_MODE_MASK_7992, NO_SHIFT_DEFINE, false}, ++ {"PRITX_ERSU", WF_LWTBL_PRITX_ERSU_MASK_7992, NO_SHIFT_DEFINE, false}, ++ {"PRITX_PLR", WF_LWTBL_PRITX_PLR_MASK_7992, NO_SHIFT_DEFINE, true}, ++ {"PRITX_DCM", WF_LWTBL_PRITX_DCM_MASK, NO_SHIFT_DEFINE, false}, ++ {"PRITX_ER106T", WF_LWTBL_PRITX_ER106T_MASK, NO_SHIFT_DEFINE, true}, ++ /* {"FCAP(0:20 1:~40)", WTBL_FCAP_20_TO_160_MHZ, WTBL_FCAP_20_TO_160_MHZ_OFFSET}, */ ++ {"MPDU_FAIL_CNT", WF_LWTBL_MPDU_FAIL_CNT_MASK, WF_LWTBL_MPDU_FAIL_CNT_SHIFT, false}, ++ {"MPDU_OK_CNT", WF_LWTBL_MPDU_OK_CNT_MASK, WF_LWTBL_MPDU_OK_CNT_SHIFT, false}, ++ {"RATE_IDX", WF_LWTBL_RATE_IDX_MASK, WF_LWTBL_RATE_IDX_SHIFT, true}, ++ {NULL,} ++}; ++ ++char *fcap_name[] = {"20MHz", "20/40MHz", "20/40/80MHz", "20/40/80/160/80+80MHz", "20/40/80/160/80+80/320MHz"}; ++ ++static void parse_fmac_lwtbl_dw9(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 9 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 9\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_9*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW9[i].name) { ++ if (WTBL_LMAC_DW9[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW9[i].name, ++ (dw_value & WTBL_LMAC_DW9[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW9[i].name, ++ (dw_value & WTBL_LMAC_DW9[i].mask) >> WTBL_LMAC_DW9[i].shift); ++ i++; ++ } ++ ++ /* FCAP parser */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "FCAP:%s\n", fcap_name[(dw_value & WF_LWTBL_FCAP_MASK) >> WF_LWTBL_FCAP_SHIFT]); ++} ++ ++#define HW_TX_RATE_TO_MODE(_x) (((_x) & WTBL_RATE_TX_MODE_MASK) >> WTBL_RATE_TX_MODE_OFFSET) ++#define HW_TX_RATE_TO_MCS(_x, _mode) ((_x) & WTBL_RATE_TX_RATE_MASK >> WTBL_RATE_TX_RATE_OFFSET) ++#define HW_TX_RATE_TO_NSS(_x) (((_x) & WTBL_RATE_NSTS_MASK) >> WTBL_RATE_NSTS_OFFSET) ++#define HW_TX_RATE_TO_STBC(_x) (((_x) & WTBL_RATE_STBC_MASK) >> WTBL_RATE_STBC_OFFSET) ++ ++#define MAX_TX_MODE 16 ++static char *HW_TX_MODE_STR[] = {"CCK", "OFDM", "HT-Mix", "HT-GF", "VHT", ++ "N/A", "N/A", "N/A", ++ "HE_SU", "HE_EXT_SU", "HE_TRIG", "HE_MU", ++ "N/A", ++ "EHT_EXT_SU", "EHT_TRIG", "EHT_MU", ++ "N/A"}; ++static char *HW_TX_RATE_CCK_STR[] = {"1M", "2Mlong", "5.5Mlong", "11Mlong", "N/A", "2Mshort", "5.5Mshort", "11Mshort", "N/A"}; ++static char *HW_TX_RATE_OFDM_STR[] = {"6M", "9M", "12M", "18M", "24M", "36M", "48M", "54M", "N/A"}; ++ ++static char *hw_rate_ofdm_str(uint16_t ofdm_idx) ++{ ++ switch (ofdm_idx) { ++ case 11: /* 6M */ ++ return HW_TX_RATE_OFDM_STR[0]; ++ ++ case 15: /* 9M */ ++ return HW_TX_RATE_OFDM_STR[1]; ++ ++ case 10: /* 12M */ ++ return HW_TX_RATE_OFDM_STR[2]; ++ ++ case 14: /* 18M */ ++ return HW_TX_RATE_OFDM_STR[3]; ++ ++ case 9: /* 24M */ ++ return HW_TX_RATE_OFDM_STR[4]; ++ ++ case 13: /* 36M */ ++ return HW_TX_RATE_OFDM_STR[5]; ++ ++ case 8: /* 48M */ ++ return HW_TX_RATE_OFDM_STR[6]; ++ ++ case 12: /* 54M */ ++ return HW_TX_RATE_OFDM_STR[7]; ++ ++ default: ++ return HW_TX_RATE_OFDM_STR[8]; ++ } ++} ++ ++static char *hw_rate_str(u8 mode, uint16_t rate_idx) ++{ ++ if (mode == 0) ++ return rate_idx < 8 ? HW_TX_RATE_CCK_STR[rate_idx] : HW_TX_RATE_CCK_STR[8]; ++ else if (mode == 1) ++ return hw_rate_ofdm_str(rate_idx); ++ else ++ return "MCS"; ++} ++ ++static void ++parse_rate(struct seq_file *s, uint16_t rate_idx, uint16_t txrate) ++{ ++ uint16_t txmode, mcs, nss, stbc; ++ ++ txmode = HW_TX_RATE_TO_MODE(txrate); ++ mcs = HW_TX_RATE_TO_MCS(txrate, txmode); ++ nss = HW_TX_RATE_TO_NSS(txrate); ++ stbc = HW_TX_RATE_TO_STBC(txrate); ++ ++ seq_printf(s, "\tRate%d(0x%x):TxMode=%d(%s), TxRate=%d(%s), Nsts=%d, STBC=%d\n", ++ rate_idx + 1, txrate, ++ txmode, (txmode < MAX_TX_MODE ? HW_TX_MODE_STR[txmode] : HW_TX_MODE_STR[MAX_TX_MODE]), ++ mcs, hw_rate_str(txmode, mcs), nss, stbc); ++} ++ ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW10[] = { ++ {"RATE1", WF_LWTBL_RATE1_MASK, WF_LWTBL_RATE1_SHIFT}, ++ {"RATE2", WF_LWTBL_RATE2_MASK, WF_LWTBL_RATE2_SHIFT}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw10(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 10 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 10\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_AUTO_RATE_1_2*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW10[i].name) { ++ parse_rate(s, i, (dw_value & WTBL_LMAC_DW10[i].mask) >> WTBL_LMAC_DW10[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW11[] = { ++ {"RATE3", WF_LWTBL_RATE3_MASK, WF_LWTBL_RATE3_SHIFT}, ++ {"RATE4", WF_LWTBL_RATE4_MASK, WF_LWTBL_RATE4_SHIFT}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw11(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 11 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 11\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_AUTO_RATE_3_4*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW11[i].name) { ++ parse_rate(s, i+2, (dw_value & WTBL_LMAC_DW11[i].mask) >> WTBL_LMAC_DW11[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW12[] = { ++ {"RATE5", WF_LWTBL_RATE5_MASK, WF_LWTBL_RATE5_SHIFT}, ++ {"RATE6", WF_LWTBL_RATE6_MASK, WF_LWTBL_RATE6_SHIFT}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw12(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 12 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 12\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_AUTO_RATE_5_6*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW12[i].name) { ++ parse_rate(s, i+4, (dw_value & WTBL_LMAC_DW12[i].mask) >> WTBL_LMAC_DW12[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW13[] = { ++ {"RATE7", WF_LWTBL_RATE7_MASK, WF_LWTBL_RATE7_SHIFT}, ++ {"RATE8", WF_LWTBL_RATE8_MASK, WF_LWTBL_RATE8_SHIFT}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw13(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 13 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 13\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_AUTO_RATE_7_8*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW13[i].name) { ++ parse_rate(s, i+6, (dw_value & WTBL_LMAC_DW13[i].mask) >> WTBL_LMAC_DW13[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW14_BMC[] = { ++ {"CIPHER_IGTK", WF_LWTBL_CIPHER_SUIT_IGTK_MASK, WF_LWTBL_CIPHER_SUIT_IGTK_SHIFT, false}, ++ {"CIPHER_BIGTK", WF_LWTBL_CIPHER_SUIT_BIGTK_MASK, WF_LWTBL_CIPHER_SUIT_BIGTK_SHIFT, true}, ++ {NULL,} ++}; ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW14[] = { ++ {"RATE1_TX_CNT", WF_LWTBL_RATE1_TX_CNT_MASK, WF_LWTBL_RATE1_TX_CNT_SHIFT, false}, ++ {"RATE1_FAIL_CNT", WF_LWTBL_RATE1_FAIL_CNT_MASK, WF_LWTBL_RATE1_FAIL_CNT_SHIFT, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw14(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr, *muar_addr = 0; ++ u32 dw_value, muar_dw_value = 0; ++ u16 i = 0; ++ ++ /* DUMP DW14 for BMC entry only */ ++ muar_addr = (u32 *)&(lwtbl[WF_LWTBL_MUAR_DW*4]); ++ muar_dw_value = *muar_addr; ++ if (((muar_dw_value & WF_LWTBL_MUAR_MASK) >> WF_LWTBL_MUAR_SHIFT) ++ == MUAR_INDEX_OWN_MAC_ADDR_BC_MC) { ++ /* LMAC WTBL DW 14 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 14\n"); ++ addr = (u32 *)&(lwtbl[WF_LWTBL_CIPHER_SUIT_IGTK_DW*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW14_BMC[i].name) { ++ if (WTBL_LMAC_DW14_BMC[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW14_BMC[i].name, ++ (dw_value & WTBL_LMAC_DW14_BMC[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW14_BMC[i].name, ++ (dw_value & WTBL_LMAC_DW14_BMC[i].mask) >> WTBL_LMAC_DW14_BMC[i].shift); ++ i++; ++ } ++ } else { ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 14\n"); ++ addr = (u32 *)&(lwtbl[WF_LWTBL_CIPHER_SUIT_IGTK_DW*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW14[i].name) { ++ if (WTBL_LMAC_DW14[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW14[i].name, ++ (dw_value & WTBL_LMAC_DW14[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW14[i].name, ++ (dw_value & WTBL_LMAC_DW14[i].mask) >> WTBL_LMAC_DW14[i].shift); ++ i++; ++ } ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW28[] = { ++ {"RELATED_IDX0", WF_LWTBL_RELATED_IDX0_MASK, WF_LWTBL_RELATED_IDX0_SHIFT, false}, ++ {"RELATED_BAND0", WF_LWTBL_RELATED_BAND0_MASK, WF_LWTBL_RELATED_BAND0_SHIFT, false}, ++ {"PRI_MLD_BAND", WF_LWTBL_PRIMARY_MLD_BAND_MASK, WF_LWTBL_PRIMARY_MLD_BAND_SHIFT, true}, ++ {"RELATED_IDX1", WF_LWTBL_RELATED_IDX1_MASK, WF_LWTBL_RELATED_IDX1_SHIFT, false}, ++ {"RELATED_BAND1", WF_LWTBL_RELATED_BAND1_MASK, WF_LWTBL_RELATED_BAND1_SHIFT, false}, ++ {"SEC_MLD_BAND", WF_LWTBL_SECONDARY_MLD_BAND_MASK, WF_LWTBL_SECONDARY_MLD_BAND_SHIFT, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw28(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 28 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 28\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_MLO_INFO_LINE_1*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW28[i].name) { ++ if (WTBL_LMAC_DW28[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW28[i].name, ++ (dw_value & WTBL_LMAC_DW28[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW28[i].name, ++ (dw_value & WTBL_LMAC_DW28[i].mask) >> ++ WTBL_LMAC_DW28[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW29[] = { ++ {"DISPATCH_POLICY_MLD_TID0", WF_LWTBL_DISPATCH_POLICY0_MASK, WF_LWTBL_DISPATCH_POLICY0_SHIFT, false}, ++ {"MLD_TID1", WF_LWTBL_DISPATCH_POLICY1_MASK, WF_LWTBL_DISPATCH_POLICY1_SHIFT, false}, ++ {"MLD_TID2", WF_LWTBL_DISPATCH_POLICY2_MASK, WF_LWTBL_DISPATCH_POLICY2_SHIFT, false}, ++ {"MLD_TID3", WF_LWTBL_DISPATCH_POLICY3_MASK, WF_LWTBL_DISPATCH_POLICY3_SHIFT, true}, ++ {"MLD_TID4", WF_LWTBL_DISPATCH_POLICY4_MASK, WF_LWTBL_DISPATCH_POLICY4_SHIFT, false}, ++ {"MLD_TID5", WF_LWTBL_DISPATCH_POLICY5_MASK, WF_LWTBL_DISPATCH_POLICY5_SHIFT, false}, ++ {"MLD_TID6", WF_LWTBL_DISPATCH_POLICY6_MASK, WF_LWTBL_DISPATCH_POLICY6_SHIFT, false}, ++ {"MLD_TID7", WF_LWTBL_DISPATCH_POLICY7_MASK, WF_LWTBL_DISPATCH_POLICY7_SHIFT, true}, ++ {"OMLD_ID", WF_LWTBL_OWN_MLD_ID_MASK, WF_LWTBL_OWN_MLD_ID_SHIFT, false}, ++ {"EMLSR0", WF_LWTBL_EMLSR0_MASK, NO_SHIFT_DEFINE, false}, ++ {"EMLMR0", WF_LWTBL_EMLMR0_MASK, NO_SHIFT_DEFINE, false}, ++ {"EMLSR1", WF_LWTBL_EMLSR1_MASK, NO_SHIFT_DEFINE, false}, ++ {"EMLMR1", WF_LWTBL_EMLMR1_MASK, NO_SHIFT_DEFINE, true}, ++ {"EMLSR2", WF_LWTBL_EMLSR2_MASK, NO_SHIFT_DEFINE, false}, ++ {"EMLMR2", WF_LWTBL_EMLMR2_MASK, NO_SHIFT_DEFINE, false}, ++ {"STR_BITMAP", WF_LWTBL_STR_BITMAP_MASK, WF_LWTBL_STR_BITMAP_SHIFT, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw29(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 29 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 29\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_MLO_INFO_LINE_2*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW29[i].name) { ++ if (WTBL_LMAC_DW29[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW29[i].name, ++ (dw_value & WTBL_LMAC_DW29[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW29[i].name, ++ (dw_value & WTBL_LMAC_DW29[i].mask) >> ++ WTBL_LMAC_DW29[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW30[] = { ++ {"DISPATCH_ORDER", WF_LWTBL_DISPATCH_ORDER_MASK, WF_LWTBL_DISPATCH_ORDER_SHIFT, false}, ++ {"DISPATCH_RATIO", WF_LWTBL_DISPATCH_RATIO_MASK, WF_LWTBL_DISPATCH_RATIO_SHIFT, false}, ++ {"LINK_MGF", WF_LWTBL_LINK_MGF_MASK, WF_LWTBL_LINK_MGF_SHIFT, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw30(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 30 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 30\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_MLO_INFO_LINE_3*4]); ++ dw_value = *addr; ++ ++ ++ while (WTBL_LMAC_DW30[i].name) { ++ if (WTBL_LMAC_DW30[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW30[i].name, ++ (dw_value & WTBL_LMAC_DW30[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW30[i].name, ++ (dw_value & WTBL_LMAC_DW30[i].mask) >> WTBL_LMAC_DW30[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW31[] = { ++ {"BFTX_TB", WF_LWTBL_BFTX_TB_MASK, NO_SHIFT_DEFINE, false}, ++ {"DROP", WF_LWTBL_DROP_MASK, NO_SHIFT_DEFINE, false}, ++ {"CASCAD", WF_LWTBL_CASCAD_MASK, NO_SHIFT_DEFINE, false}, ++ {"ALL_ACK", WF_LWTBL_ALL_ACK_MASK, NO_SHIFT_DEFINE, false}, ++ {"MPDU_SIZE", WF_LWTBL_MPDU_SIZE_MASK, WF_LWTBL_MPDU_SIZE_SHIFT, false}, ++ {"RXD_DUP_MODE", WF_LWTBL_RXD_DUP_MODE_MASK, WF_LWTBL_RXD_DUP_MODE_SHIFT, true}, ++ {"ACK_EN", WF_LWTBL_ACK_EN_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw31(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 31 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 31\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_RESP_INFO_DW_31*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW31[i].name) { ++ if (WTBL_LMAC_DW31[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW31[i].name, ++ (dw_value & WTBL_LMAC_DW31[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW31[i].name, ++ (dw_value & WTBL_LMAC_DW31[i].mask) >> ++ WTBL_LMAC_DW31[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW32[] = { ++ {"OM_INFO", WF_LWTBL_OM_INFO_MASK, WF_LWTBL_OM_INFO_SHIFT, false}, ++ {"OM_INFO_EHT", WF_LWTBL_OM_INFO_EHT_MASK, WF_LWTBL_OM_INFO_EHT_SHIFT, false}, ++ {"RXD_DUP_FOR_OM_CHG", WF_LWTBL_RXD_DUP_FOR_OM_CHG_MASK, NO_SHIFT_DEFINE, false}, ++ {"RXD_DUP_WHITE_LIST", WF_LWTBL_RXD_DUP_WHITE_LIST_MASK, WF_LWTBL_RXD_DUP_WHITE_LIST_SHIFT, false}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw32(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 32 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 32\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_RX_DUP_INFO_DW_32*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW32[i].name) { ++ if (WTBL_LMAC_DW32[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW32[i].name, ++ (dw_value & WTBL_LMAC_DW32[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW32[i].name, ++ (dw_value & WTBL_LMAC_DW32[i].mask) >> ++ WTBL_LMAC_DW32[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW33[] = { ++ {"USER_RSSI", WF_LWTBL_USER_RSSI_MASK, WF_LWTBL_USER_RSSI_SHIFT, false}, ++ {"USER_SNR", WF_LWTBL_USER_SNR_MASK, WF_LWTBL_USER_SNR_SHIFT, false}, ++ {"RAPID_REACTION_RATE", WF_LWTBL_RAPID_REACTION_RATE_MASK, WF_LWTBL_RAPID_REACTION_RATE_SHIFT, true}, ++ {"HT_AMSDU(Read Only)", WF_LWTBL_HT_AMSDU_MASK, NO_SHIFT_DEFINE, false}, ++ {"AMSDU_CROSS_LG(Read Only)", WF_LWTBL_AMSDU_CROSS_LG_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw33(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 33 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 33\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_RX_STAT_CNT_LINE_1*4]); ++ dw_value = *addr; ++ ++ while (WTBL_LMAC_DW33[i].name) { ++ if (WTBL_LMAC_DW33[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW33[i].name, ++ (dw_value & WTBL_LMAC_DW33[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW33[i].name, ++ (dw_value & WTBL_LMAC_DW33[i].mask) >> ++ WTBL_LMAC_DW33[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW34[] = { ++ {"RESP_RCPI0", WF_LWTBL_RESP_RCPI0_MASK, WF_LWTBL_RESP_RCPI0_SHIFT, false}, ++ {"RCPI1", WF_LWTBL_RESP_RCPI1_MASK, WF_LWTBL_RESP_RCPI1_SHIFT, false}, ++ {"RCPI2", WF_LWTBL_RESP_RCPI2_MASK, WF_LWTBL_RESP_RCPI2_SHIFT, false}, ++ {"RCPI3", WF_LWTBL_RESP_RCPI3_MASK, WF_LWTBL_RESP_RCPI3_SHIFT, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw34(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 34 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 34\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_RX_STAT_CNT_LINE_2*4]); ++ dw_value = *addr; ++ ++ ++ while (WTBL_LMAC_DW34[i].name) { ++ if (WTBL_LMAC_DW34[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW34[i].name, ++ (dw_value & WTBL_LMAC_DW34[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW34[i].name, ++ (dw_value & WTBL_LMAC_DW34[i].mask) >> ++ WTBL_LMAC_DW34[i].shift); ++ i++; ++ } ++} ++ ++static const struct berse_wtbl_parse WTBL_LMAC_DW35[] = { ++ {"SNR 0", WF_LWTBL_SNR_RX0_MASK, WF_LWTBL_SNR_RX0_SHIFT, false}, ++ {"SNR 1", WF_LWTBL_SNR_RX1_MASK, WF_LWTBL_SNR_RX1_SHIFT, false}, ++ {"SNR 2", WF_LWTBL_SNR_RX2_MASK, WF_LWTBL_SNR_RX2_SHIFT, false}, ++ {"SNR 3", WF_LWTBL_SNR_RX3_MASK, WF_LWTBL_SNR_RX3_SHIFT, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_lwtbl_dw35(struct seq_file *s, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ /* LMAC WTBL DW 35 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "LWTBL DW 35\n"); ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_RX_STAT_CNT_LINE_3*4]); ++ dw_value = *addr; ++ ++ ++ while (WTBL_LMAC_DW35[i].name) { ++ if (WTBL_LMAC_DW35[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_LMAC_DW35[i].name, ++ (dw_value & WTBL_LMAC_DW35[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_LMAC_DW35[i].name, ++ (dw_value & WTBL_LMAC_DW35[i].mask) >> ++ WTBL_LMAC_DW35[i].shift); ++ i++; ++ } ++} ++ ++static void parse_fmac_lwtbl_rx_stats(struct seq_file *s, u8 *lwtbl) ++{ ++ parse_fmac_lwtbl_dw33(s, lwtbl); ++ parse_fmac_lwtbl_dw34(s, lwtbl); ++ parse_fmac_lwtbl_dw35(s, lwtbl); ++} ++ ++static void parse_fmac_lwtbl_mlo_info(struct seq_file *s, u8 *lwtbl) ++{ ++ parse_fmac_lwtbl_dw28(s, lwtbl); ++ parse_fmac_lwtbl_dw29(s, lwtbl); ++ parse_fmac_lwtbl_dw30(s, lwtbl); ++} ++ ++static const struct berse_wtbl_parse WTBL_UMAC_DW9[] = { ++ {"RELATED_IDX0", WF_UWTBL_RELATED_IDX0_MASK, WF_UWTBL_RELATED_IDX0_SHIFT, false}, ++ {"RELATED_BAND0", WF_UWTBL_RELATED_BAND0_MASK, WF_UWTBL_RELATED_BAND0_SHIFT, false}, ++ {"PRI_MLD_BAND", WF_UWTBL_PRIMARY_MLD_BAND_MASK, WF_UWTBL_PRIMARY_MLD_BAND_SHIFT, true}, ++ {"RELATED_IDX1", WF_UWTBL_RELATED_IDX1_MASK, WF_UWTBL_RELATED_IDX1_SHIFT, false}, ++ {"RELATED_BAND1", WF_UWTBL_RELATED_BAND1_MASK, WF_UWTBL_RELATED_BAND1_SHIFT, false}, ++ {"SEC_MLD_BAND", WF_UWTBL_SECONDARY_MLD_BAND_MASK, WF_UWTBL_SECONDARY_MLD_BAND_SHIFT, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_uwtbl_mlo_info(struct seq_file *s, u8 *uwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "MldAddr: %02x:%02x:%02x:%02x:%02x:%02x(D0[B0~15], D1[B0~31])\n", ++ uwtbl[4], uwtbl[5], uwtbl[6], uwtbl[7], uwtbl[0], uwtbl[1]); ++ ++ /* UMAC WTBL DW 0 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "UWTBL DW 0\n"); ++ addr = (u32 *)&(uwtbl[WF_UWTBL_OWN_MLD_ID_DW*4]); ++ dw_value = *addr; ++ ++ seq_printf(s, "\t%s:%u\n", "OMLD_ID", ++ (dw_value & WF_UWTBL_OWN_MLD_ID_MASK) >> WF_UWTBL_OWN_MLD_ID_SHIFT); ++ ++ /* UMAC WTBL DW 9 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "UWTBL DW 9\n"); ++ addr = (u32 *)&(uwtbl[WF_UWTBL_RELATED_IDX0_DW*4]); ++ dw_value = *addr; ++ ++ while (WTBL_UMAC_DW9[i].name) { ++ ++ if (WTBL_UMAC_DW9[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_UMAC_DW9[i].name, ++ (dw_value & WTBL_UMAC_DW9[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_UMAC_DW9[i].name, ++ (dw_value & WTBL_UMAC_DW9[i].mask) >> ++ WTBL_UMAC_DW9[i].shift); ++ i++; ++ } ++} ++ ++static bool ++is_wtbl_bigtk_exist(u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ ++ addr = (u32 *)&(lwtbl[WF_LWTBL_MUAR_DW*4]); ++ dw_value = *addr; ++ if (((dw_value & WF_LWTBL_MUAR_MASK) >> WF_LWTBL_MUAR_SHIFT) == ++ MUAR_INDEX_OWN_MAC_ADDR_BC_MC) { ++ addr = (u32 *)&(lwtbl[WF_LWTBL_CIPHER_SUIT_BIGTK_DW*4]); ++ dw_value = *addr; ++ if (((dw_value & WF_LWTBL_CIPHER_SUIT_BIGTK_MASK) >> ++ WF_LWTBL_CIPHER_SUIT_BIGTK_SHIFT) != IGTK_CIPHER_SUIT_NONE) ++ return true; ++ } ++ ++ return false; ++} ++ ++static const struct berse_wtbl_parse WTBL_UMAC_DW2[] = { ++ {"PN0", WTBL_PN0_MASK, WTBL_PN0_OFFSET, false}, ++ {"PN1", WTBL_PN1_MASK, WTBL_PN1_OFFSET, false}, ++ {"PN2", WTBL_PN2_MASK, WTBL_PN2_OFFSET, true}, ++ {"PN3", WTBL_PN3_MASK, WTBL_PN3_OFFSET, false}, ++ {NULL,} ++}; ++ ++static const struct berse_wtbl_parse WTBL_UMAC_DW3[] = { ++ {"PN4", WTBL_PN4_MASK, WTBL_PN4_OFFSET, false}, ++ {"PN5", WTBL_PN5_MASK, WTBL_PN5_OFFSET, true}, ++ {"COM_SN", WF_UWTBL_COM_SN_MASK, WF_UWTBL_COM_SN_SHIFT, true}, ++ {NULL,} ++}; ++ ++static const struct berse_wtbl_parse WTBL_UMAC_DW4_BIPN[] = { ++ {"BIPN0", WTBL_BIPN0_MASK, WTBL_BIPN0_OFFSET, false}, ++ {"BIPN1", WTBL_BIPN1_MASK, WTBL_BIPN1_OFFSET, false}, ++ {"BIPN2", WTBL_BIPN2_MASK, WTBL_BIPN2_OFFSET, true}, ++ {"BIPN3", WTBL_BIPN3_MASK, WTBL_BIPN3_OFFSET, false}, ++ {NULL,} ++}; ++ ++static const struct berse_wtbl_parse WTBL_UMAC_DW5_BIPN[] = { ++ {"BIPN4", WTBL_BIPN4_MASK, WTBL_BIPN4_OFFSET, false}, ++ {"BIPN5", WTBL_BIPN5_MASK, WTBL_BIPN5_OFFSET, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_uwtbl_pn(struct seq_file *s, u8 *uwtbl, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u16 i = 0; ++ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "UWTBL PN\n"); ++ ++ /* UMAC WTBL DW 2/3 */ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_PN_31_0__DW*4]); ++ dw_value = *addr; ++ ++ while (WTBL_UMAC_DW2[i].name) { ++ seq_printf(s, "\t%s:%u\n", WTBL_UMAC_DW2[i].name, ++ (dw_value & WTBL_UMAC_DW2[i].mask) >> ++ WTBL_UMAC_DW2[i].shift); ++ i++; ++ } ++ ++ i = 0; ++ addr = (u32 *)&(uwtbl[WF_UWTBL_PN_47_32__DW*4]); ++ dw_value = *addr; ++ ++ while (WTBL_UMAC_DW3[i].name) { ++ seq_printf(s, "\t%s:%u\n", WTBL_UMAC_DW3[i].name, ++ (dw_value & WTBL_UMAC_DW3[i].mask) >> ++ WTBL_UMAC_DW3[i].shift); ++ i++; ++ } ++ ++ ++ /* UMAC WTBL DW 4/5 for BIGTK */ ++ if (is_wtbl_bigtk_exist(lwtbl) == true) { ++ i = 0; ++ addr = (u32 *)&(uwtbl[WF_UWTBL_RX_BIPN_31_0__DW*4]); ++ dw_value = *addr; ++ ++ while (WTBL_UMAC_DW4_BIPN[i].name) { ++ seq_printf(s, "\t%s:%u\n", WTBL_UMAC_DW4_BIPN[i].name, ++ (dw_value & WTBL_UMAC_DW4_BIPN[i].mask) >> ++ WTBL_UMAC_DW4_BIPN[i].shift); ++ i++; ++ } ++ ++ i = 0; ++ addr = (u32 *)&(uwtbl[WF_UWTBL_RX_BIPN_47_32__DW*4]); ++ dw_value = *addr; ++ ++ while (WTBL_UMAC_DW5_BIPN[i].name) { ++ seq_printf(s, "\t%s:%u\n", WTBL_UMAC_DW5_BIPN[i].name, ++ (dw_value & WTBL_UMAC_DW5_BIPN[i].mask) >> ++ WTBL_UMAC_DW5_BIPN[i].shift); ++ i++; ++ } ++ } ++} ++ ++static void parse_fmac_uwtbl_sn(struct seq_file *s, u8 *uwtbl) ++{ ++ u32 *addr = 0; ++ u32 u2SN = 0; ++ ++ /* UMAC WTBL DW SN part */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "UWTBL SN\n"); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID0_SN_DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_TID0_SN_MASK) >> WF_UWTBL_TID0_SN_SHIFT; ++ seq_printf(s, "\t%s:%u\n", "TID0_AC0_SN", u2SN); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID1_SN_DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_TID1_SN_MASK) >> WF_UWTBL_TID1_SN_SHIFT; ++ seq_printf(s, "\t%s:%u\n", "TID1_AC1_SN", u2SN); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID2_SN_7_0__DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_TID2_SN_7_0__MASK) >> ++ WF_UWTBL_TID2_SN_7_0__SHIFT; ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID2_SN_11_8__DW*4]); ++ u2SN |= (((*addr) & WF_UWTBL_TID2_SN_11_8__MASK) >> ++ WF_UWTBL_TID2_SN_11_8__SHIFT) << 8; ++ seq_printf(s, "\t%s:%u\n", "TID2_AC2_SN", u2SN); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID3_SN_DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_TID3_SN_MASK) >> WF_UWTBL_TID3_SN_SHIFT; ++ seq_printf(s, "\t%s:%u\n", "TID3_AC3_SN", u2SN); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID4_SN_DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_TID4_SN_MASK) >> WF_UWTBL_TID4_SN_SHIFT; ++ seq_printf(s, "\t%s:%u\n", "TID4_SN", u2SN); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID5_SN_3_0__DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_TID5_SN_3_0__MASK) >> ++ WF_UWTBL_TID5_SN_3_0__SHIFT; ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID5_SN_11_4__DW*4]); ++ u2SN |= (((*addr) & WF_UWTBL_TID5_SN_11_4__MASK) >> ++ WF_UWTBL_TID5_SN_11_4__SHIFT) << 4; ++ seq_printf(s, "\t%s:%u\n", "TID5_SN", u2SN); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID6_SN_DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_TID6_SN_MASK) >> WF_UWTBL_TID6_SN_SHIFT; ++ seq_printf(s, "\t%s:%u\n", "TID6_SN", u2SN); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_TID7_SN_DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_TID7_SN_MASK) >> WF_UWTBL_TID7_SN_SHIFT; ++ seq_printf(s, "\t%s:%u\n", "TID7_SN", u2SN); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_COM_SN_DW*4]); ++ u2SN = ((*addr) & WF_UWTBL_COM_SN_MASK) >> WF_UWTBL_COM_SN_SHIFT; ++ seq_printf(s, "\t%s:%u\n", "COM_SN", u2SN); ++} ++ ++static void dump_key_table( ++ struct seq_file *s, ++ uint16_t keyloc0, ++ uint16_t keyloc1, ++ uint16_t keyloc2 ++) ++{ ++#define ONE_KEY_ENTRY_LEN_IN_DW 8 ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ u8 keytbl[ONE_KEY_ENTRY_LEN_IN_DW*4] = {0}; ++ uint16_t x; ++ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "\t%s:%d\n", "keyloc0", keyloc0); ++ if (keyloc0 != INVALID_KEY_ENTRY) { ++ ++ /* Don't swap below two lines, halWtblReadRaw will ++ * write new value WF_WTBLON_TOP_WDUCR_ADDR ++ */ ++ mt7996_wtbl_read_raw(dev, keyloc0, ++ WTBL_TYPE_KEY, 0, ONE_KEY_ENTRY_LEN_IN_DW, keytbl); ++ seq_printf(s, "\t\tKEY WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_UWTBL_TOP_WDUCR_ADDR, ++ mt76_rr(dev, MT_DBG_UWTBL_TOP_WDUCR_ADDR), ++ KEYTBL_IDX2BASE(keyloc0, 0)); ++ for (x = 0; x < ONE_KEY_ENTRY_LEN_IN_DW; x++) { ++ seq_printf(s, "\t\tDW%02d: %02x %02x %02x %02x\n", ++ x, ++ keytbl[x * 4 + 3], ++ keytbl[x * 4 + 2], ++ keytbl[x * 4 + 1], ++ keytbl[x * 4]); ++ } ++ } ++ ++ seq_printf(s, "\t%s:%d\n", "keyloc1", keyloc1); ++ if (keyloc1 != INVALID_KEY_ENTRY) { ++ /* Don't swap below two lines, halWtblReadRaw will ++ * write new value WF_WTBLON_TOP_WDUCR_ADDR ++ */ ++ mt7996_wtbl_read_raw(dev, keyloc1, ++ WTBL_TYPE_KEY, 0, ONE_KEY_ENTRY_LEN_IN_DW, keytbl); ++ seq_printf(s, "\t\tKEY WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_UWTBL_TOP_WDUCR_ADDR, ++ mt76_rr(dev, MT_DBG_UWTBL_TOP_WDUCR_ADDR), ++ KEYTBL_IDX2BASE(keyloc1, 0)); ++ for (x = 0; x < ONE_KEY_ENTRY_LEN_IN_DW; x++) { ++ seq_printf(s, "\t\tDW%02d: %02x %02x %02x %02x\n", ++ x, ++ keytbl[x * 4 + 3], ++ keytbl[x * 4 + 2], ++ keytbl[x * 4 + 1], ++ keytbl[x * 4]); ++ } ++ } ++ ++ seq_printf(s, "\t%s:%d\n", "keyloc2", keyloc2); ++ if (keyloc2 != INVALID_KEY_ENTRY) { ++ /* Don't swap below two lines, halWtblReadRaw will ++ * write new value WF_WTBLON_TOP_WDUCR_ADDR ++ */ ++ mt7996_wtbl_read_raw(dev, keyloc2, ++ WTBL_TYPE_KEY, 0, ONE_KEY_ENTRY_LEN_IN_DW, keytbl); ++ seq_printf(s, "\t\tKEY WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_UWTBL_TOP_WDUCR_ADDR, ++ mt76_rr(dev, MT_DBG_UWTBL_TOP_WDUCR_ADDR), ++ KEYTBL_IDX2BASE(keyloc2, 0)); ++ for (x = 0; x < ONE_KEY_ENTRY_LEN_IN_DW; x++) { ++ seq_printf(s, "\t\tDW%02d: %02x %02x %02x %02x\n", ++ x, ++ keytbl[x * 4 + 3], ++ keytbl[x * 4 + 2], ++ keytbl[x * 4 + 1], ++ keytbl[x * 4]); ++ } ++ } ++} ++ ++static void parse_fmac_uwtbl_key_info(struct seq_file *s, u8 *uwtbl, u8 *lwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ uint16_t keyloc0 = INVALID_KEY_ENTRY; ++ uint16_t keyloc1 = INVALID_KEY_ENTRY; ++ uint16_t keyloc2 = INVALID_KEY_ENTRY; ++ ++ /* UMAC WTBL DW 7 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "UWTBL key info\n"); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_KEY_LOC0_DW*4]); ++ dw_value = *addr; ++ keyloc0 = (dw_value & WF_UWTBL_KEY_LOC0_MASK) >> WF_UWTBL_KEY_LOC0_SHIFT; ++ keyloc1 = (dw_value & WF_UWTBL_KEY_LOC1_MASK) >> WF_UWTBL_KEY_LOC1_SHIFT; ++ ++ seq_printf(s, "\t%s:%u/%u\n", "Key Loc 0/1", keyloc0, keyloc1); ++ ++ /* UMAC WTBL DW 6 for BIGTK */ ++ if (is_wtbl_bigtk_exist(lwtbl) == true) { ++ addr = (u32 *)&(uwtbl[WF_UWTBL_KEY_LOC2_DW*4]); ++ dw_value = *addr; ++ keyloc2 = (dw_value & WF_UWTBL_KEY_LOC2_MASK) >> ++ WF_UWTBL_KEY_LOC2_SHIFT; ++ seq_printf(s, "\t%s:%u\n", "Key Loc 2", keyloc2); ++ } ++ ++ /* Parse KEY link */ ++ dump_key_table(s, keyloc0, keyloc1, keyloc2); ++} ++ ++static const struct berse_wtbl_parse WTBL_UMAC_DW8[] = { ++ {"UWTBL_WMM_Q", WF_UWTBL_WMM_Q_MASK, WF_UWTBL_WMM_Q_SHIFT, false}, ++ {"UWTBL_QOS", WF_UWTBL_QOS_MASK, NO_SHIFT_DEFINE, false}, ++ {"UWTBL_HT_VHT_HE", WF_UWTBL_HT_MASK, NO_SHIFT_DEFINE, false}, ++ {"UWTBL_HDRT_MODE", WF_UWTBL_HDRT_MODE_MASK, NO_SHIFT_DEFINE, true}, ++ {NULL,} ++}; ++ ++static void parse_fmac_uwtbl_msdu_info(struct seq_file *s, u8 *uwtbl) ++{ ++ u32 *addr = 0; ++ u32 dw_value = 0; ++ u32 amsdu_len = 0; ++ u16 i = 0; ++ ++ /* UMAC WTBL DW 8 */ ++ seq_printf(s, "\t\n"); ++ seq_printf(s, "UWTBL DW8\n"); ++ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_AMSDU_CFG_DW*4]); ++ dw_value = *addr; ++ ++ while (WTBL_UMAC_DW8[i].name) { ++ ++ if (WTBL_UMAC_DW8[i].shift == NO_SHIFT_DEFINE) ++ seq_printf(s, "\t%s:%d\n", WTBL_UMAC_DW8[i].name, ++ (dw_value & WTBL_UMAC_DW8[i].mask) ? 1 : 0); ++ else ++ seq_printf(s, "\t%s:%u\n", WTBL_UMAC_DW8[i].name, ++ (dw_value & WTBL_UMAC_DW8[i].mask) >> ++ WTBL_UMAC_DW8[i].shift); ++ i++; ++ } ++ ++ /* UMAC WTBL DW 8 - SEC_ADDR_MODE */ ++ addr = (u32 *)&(uwtbl[WF_UWTBL_SEC_ADDR_MODE_DW*4]); ++ dw_value = *addr; ++ seq_printf(s, "\t%s:%lu\n", "SEC_ADDR_MODE", ++ (dw_value & WTBL_SEC_ADDR_MODE_MASK) >> WTBL_SEC_ADDR_MODE_OFFSET); ++ ++ /* UMAC WTBL DW 8 - AMSDU_CFG */ ++ seq_printf(s, "\t%s:%d\n", "HW AMSDU Enable", ++ (dw_value & WTBL_AMSDU_EN_MASK) ? 1 : 0); ++ ++ amsdu_len = (dw_value & WTBL_AMSDU_LEN_MASK) >> WTBL_AMSDU_LEN_OFFSET; ++ if (amsdu_len == 0) ++ seq_printf(s, "\t%s:invalid (WTBL value=0x%x)\n", "HW AMSDU Len", ++ amsdu_len); ++ else if (amsdu_len == 1) ++ seq_printf(s, "\t%s:%d~%d (WTBL value=0x%x)\n", "HW AMSDU Len", ++ 1, ++ 255, ++ amsdu_len); ++ else if (amsdu_len == 2) ++ seq_printf(s, "\t%s:%d~%d (WTBL value=0x%x)\n", "HW AMSDU Len", ++ 256, ++ 511, ++ amsdu_len); ++ else if (amsdu_len == 3) ++ seq_printf(s, "\t%s:%d~%d (WTBL value=0x%x)\n", "HW AMSDU Len", ++ 512, ++ 767, ++ amsdu_len); ++ else ++ seq_printf(s, "\t%s:%d~%d (WTBL value=0x%x)\n", "HW AMSDU Len", ++ 256 * (amsdu_len - 1), ++ 256 * (amsdu_len - 1) + 255, ++ amsdu_len); ++ ++ seq_printf(s, "\t%s:%lu (WTBL value=0x%lx)\n", "HW AMSDU Num", ++ ((dw_value & WTBL_AMSDU_NUM_MASK) >> WTBL_AMSDU_NUM_OFFSET) + 1, ++ (dw_value & WTBL_AMSDU_NUM_MASK) >> WTBL_AMSDU_NUM_OFFSET); ++} ++ ++static int mt7996_wtbl_read(struct seq_file *s, void *data) ++{ ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ u8 lwtbl[LWTBL_LEN_IN_DW * 4] = {0}; ++ u8 uwtbl[UWTBL_LEN_IN_DW * 4] = {0}; ++ int x; ++ ++ mt7996_wtbl_read_raw(dev, dev->wlan_idx, WTBL_TYPE_LMAC, 0, ++ LWTBL_LEN_IN_DW, lwtbl); ++ seq_printf(s, "Dump WTBL info of WLAN_IDX:%d\n", dev->wlan_idx); ++ seq_printf(s, "LMAC WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_WTBLON_TOP_WDUCR_ADDR, ++ mt76_rr(dev, MT_DBG_WTBLON_TOP_WDUCR_ADDR), ++ LWTBL_IDX2BASE(dev->wlan_idx, 0)); ++ for (x = 0; x < LWTBL_LEN_IN_DW; x++) { ++ seq_printf(s, "DW%02d: %02x %02x %02x %02x\n", ++ x, ++ lwtbl[x * 4 + 3], ++ lwtbl[x * 4 + 2], ++ lwtbl[x * 4 + 1], ++ lwtbl[x * 4]); ++ } ++ ++ /* Parse LWTBL */ ++ parse_fmac_lwtbl_dw0_1(s, lwtbl); ++ parse_fmac_lwtbl_dw2(s, lwtbl); ++ parse_fmac_lwtbl_dw3(s, lwtbl); ++ parse_fmac_lwtbl_dw4(s, lwtbl); ++ parse_fmac_lwtbl_dw5(s, lwtbl); ++ parse_fmac_lwtbl_dw6(s, lwtbl); ++ parse_fmac_lwtbl_dw7(s, lwtbl); ++ parse_fmac_lwtbl_dw8(s, lwtbl); ++ parse_fmac_lwtbl_dw9(s, lwtbl); ++ parse_fmac_lwtbl_dw10(s, lwtbl); ++ parse_fmac_lwtbl_dw11(s, lwtbl); ++ parse_fmac_lwtbl_dw12(s, lwtbl); ++ parse_fmac_lwtbl_dw13(s, lwtbl); ++ parse_fmac_lwtbl_dw14(s, lwtbl); ++ parse_fmac_lwtbl_mlo_info(s, lwtbl); ++ parse_fmac_lwtbl_dw31(s, lwtbl); ++ parse_fmac_lwtbl_dw32(s, lwtbl); ++ parse_fmac_lwtbl_rx_stats(s, lwtbl); ++ ++ mt7996_wtbl_read_raw(dev, dev->wlan_idx, WTBL_TYPE_UMAC, 0, ++ UWTBL_LEN_IN_DW, uwtbl); ++ seq_printf(s, "Dump WTBL info of WLAN_IDX:%d\n", dev->wlan_idx); ++ seq_printf(s, "UMAC WTBL Addr: group:0x%x=0x%x addr: 0x%lx\n", ++ MT_DBG_UWTBL_TOP_WDUCR_ADDR, ++ mt76_rr(dev, MT_DBG_UWTBL_TOP_WDUCR_ADDR), ++ UWTBL_IDX2BASE(dev->wlan_idx, 0)); ++ for (x = 0; x < UWTBL_LEN_IN_DW; x++) { ++ seq_printf(s, "DW%02d: %02x %02x %02x %02x\n", ++ x, ++ uwtbl[x * 4 + 3], ++ uwtbl[x * 4 + 2], ++ uwtbl[x * 4 + 1], ++ uwtbl[x * 4]); ++ } ++ ++ /* Parse UWTBL */ ++ parse_fmac_uwtbl_mlo_info(s, uwtbl); ++ parse_fmac_uwtbl_pn(s, uwtbl, lwtbl); ++ parse_fmac_uwtbl_sn(s, uwtbl); ++ parse_fmac_uwtbl_key_info(s, uwtbl, lwtbl); ++ parse_fmac_uwtbl_msdu_info(s, uwtbl); ++ ++ return 0; ++} ++ ++static int mt7996_sta_info(struct seq_file *s, void *data) ++{ ++ struct mt7996_dev *dev = dev_get_drvdata(s->private); ++ u8 lwtbl[LWTBL_LEN_IN_DW*4] = {0}; ++ u16 i = 0; ++ ++ for (i=0; i < mt7996_wtbl_size(dev); i++) { ++ mt7996_wtbl_read_raw(dev, i, WTBL_TYPE_LMAC, 0, ++ LWTBL_LEN_IN_DW, lwtbl); ++ ++ if (lwtbl[4] || lwtbl[5] || lwtbl[6] || lwtbl[7] || lwtbl[0] || lwtbl[1]) { ++ u32 *addr, dw_value; ++ ++ seq_printf(s, "wcid:%d\tAddr: %02x:%02x:%02x:%02x:%02x:%02x", ++ i, lwtbl[4], lwtbl[5], lwtbl[6], lwtbl[7], lwtbl[0], lwtbl[1]); ++ ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_2*4]); ++ dw_value = *addr; ++ seq_printf(s, "\t%s:%u", WTBL_LMAC_DW2[0].name, ++ (dw_value & WTBL_LMAC_DW2[0].mask) >> WTBL_LMAC_DW2[0].shift); ++ ++ addr = (u32 *)&(lwtbl[WTBL_GROUP_TRX_CAP_DW_5*4]); ++ dw_value = *addr; ++ seq_printf(s, "\tPSM:%u\n", !!(dw_value & WF_LWTBL_PSM_MASK)); ++ } ++ } ++ ++ return 0; ++} ++ ++int mt7996_mtk_init_debugfs(struct mt7996_dev *dev, struct dentry *dir) ++{ ++ u32 device_id = (dev->mt76.rev) >> 16; ++ int i = 0; ++ static const struct mt7996_dbg_reg_desc dbg_reg_s[] = { ++ { 0x7990, mt7996_dbg_offs }, ++ { 0x7992, mt7992_dbg_offs }, ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(dbg_reg_s); i++) { ++ if (device_id == dbg_reg_s[i].id) { ++ dev->dbg_reg = &dbg_reg_s[i]; ++ break; ++ } ++ } ++ ++ if (is_mt7996(&dev->mt76)) { ++ WTBL_LMAC_DW2 = WTBL_LMAC_DW2_7996; ++ WTBL_LMAC_DW5 = WTBL_LMAC_DW5_7996; ++ WTBL_LMAC_DW9 = WTBL_LMAC_DW9_7996; ++ } else { ++ WTBL_LMAC_DW2 = WTBL_LMAC_DW2_7992; ++ WTBL_LMAC_DW5 = WTBL_LMAC_DW5_7992; ++ WTBL_LMAC_DW9 = WTBL_LMAC_DW9_7992; ++ } ++ ++ /* agg */ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "agg_info0", dir, ++ mt7996_agginfo_read_band0); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "agg_info1", dir, ++ mt7996_agginfo_read_band1); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "agg_info2", dir, ++ mt7996_agginfo_read_band2); ++ /* amsdu */ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "amsdu_info", dir, ++ mt7996_amsdu_result_read); ++ ++ debugfs_create_file("fw_debug_module", 0600, dir, dev, ++ &fops_fw_debug_module); ++ debugfs_create_file("fw_debug_level", 0600, dir, dev, ++ &fops_fw_debug_level); ++ debugfs_create_file("fw_wa_query", 0600, dir, dev, &fops_wa_query); ++ debugfs_create_file("fw_wa_set", 0600, dir, dev, &fops_wa_set); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "fw_version", dir, ++ mt7996_dump_version); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "mib_info0", dir, ++ mt7996_mibinfo_band0); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "mib_info1", dir, ++ mt7996_mibinfo_band1); ++ debugfs_create_devm_seqfile(dev->mt76.dev, "mib_info2", dir, ++ mt7996_mibinfo_band2); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "sta_info", dir, ++ mt7996_sta_info); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir, ++ mt7996_trinfo_read); ++ ++ debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir, ++ mt7996_wtbl_read); ++ ++ debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable); ++ ++ return 0; ++} ++ ++#endif +--- /dev/null ++++ b/mt7996/mtk_mcu.c +@@ -0,0 +1,39 @@ ++// SPDX-License-Identifier: ISC ++/* ++ * Copyright (C) 2023 MediaTek Inc. ++ */ ++ ++#include ++#include ++#include "mt7996.h" ++#include "mcu.h" ++#include "mac.h" ++#include "mtk_mcu.h" ++ ++#ifdef CONFIG_MTK_DEBUG ++ ++ ++ ++ ++int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val) ++{ ++ struct { ++ u8 __rsv1[4]; ++ ++ __le16 tag; ++ __le16 len; ++ ++ __le16 item; ++ u8 __rsv2[2]; ++ __le32 value; ++ } __packed req = { ++ .tag = cpu_to_le16(UNI_CMD_MURU_DBG_INFO), ++ .len = cpu_to_le16(sizeof(req) - 4), ++ .item = cpu_to_le16(item), ++ .value = cpu_to_le32(val), ++ }; ++ ++ return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(MURU), &req, ++ sizeof(req), true); ++} ++#endif +--- /dev/null ++++ b/mt7996/mtk_mcu.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: ISC */ ++/* ++ * Copyright (C) 2023 MediaTek Inc. ++ */ ++ ++#ifndef __MT7996_MTK_MCU_H ++#define __MT7996_MTK_MCU_H ++ ++#include "../mt76_connac_mcu.h" ++ ++#ifdef CONFIG_MTK_DEBUG ++ ++enum { ++ UNI_CMD_MURU_DBG_INFO = 0x18, ++}; ++ ++#endif ++ ++#endif diff --git a/package/kernel/mt76/patches/smartrg-4000-1002-mtk-wifi-mt76-mt7996-add-check-for-hostapd-config-he.patch b/package/kernel/mt76/patches/smartrg-4000-1002-mtk-wifi-mt76-mt7996-add-check-for-hostapd-config-he.patch new file mode 100644 index 0000000000..a64a6eb4f6 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-1002-mtk-wifi-mt76-mt7996-add-check-for-hostapd-config-he.patch @@ -0,0 +1,40 @@ +From 0c8717204e0b3a167d4310ad823238e611efb380 Mon Sep 17 00:00:00 2001 +From: "Allen.Ye" +Date: Thu, 8 Jun 2023 17:32:33 +0800 +Subject: [PATCH 1002/1044] mtk: wifi: mt76: mt7996: add check for hostapd + config he_ldpc + +Add check for hostapd config he_ldpc. +This capabilities is checked in mcu_beacon_check_caps in 7915. + +Add check for STA LDPC cap, if STA only have BCC we should not overwrite the phy_cap with config he_ldpc. + +Signed-off-by: Allen.Ye +--- + mt7996/mcu.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -1569,6 +1569,9 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *sk + struct ieee80211_link_sta *link_sta, + struct mt7996_vif_link *link) + { ++ struct mt7996_sta *msta = (struct mt7996_sta *)link_sta->sta->drv_priv; ++ struct ieee80211_vif *vif = container_of((void *)msta->vif, ++ struct ieee80211_vif, drv_priv); + struct ieee80211_he_cap_elem *elem = &link_sta->he_cap.he_cap_elem; + struct ieee80211_he_mcs_nss_supp mcs_map; + struct sta_rec_he_v2 *he; +@@ -1587,6 +1590,11 @@ mt7996_mcu_sta_he_tlv(struct sk_buff *sk + he->he_phy_cap[i] = elem->phy_cap_info[i]; + } + ++ if (vif->type == NL80211_IFTYPE_AP && ++ (elem->phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) ++ u8p_replace_bits(&he->he_phy_cap[1], vif->bss_conf.he_ldpc, ++ IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD); ++ + mcs_map = link_sta->he_cap.he_mcs_nss_supp; + switch (link_sta->bandwidth) { + case IEEE80211_STA_RX_BW_160: diff --git a/package/kernel/mt76/patches/smartrg-4000-1005-mtk-wifi-mt76-testmode-add-testmode-pre-calibration-.patch b/package/kernel/mt76/patches/smartrg-4000-1005-mtk-wifi-mt76-testmode-add-testmode-pre-calibration-.patch new file mode 100644 index 0000000000..d33a3551c2 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-1005-mtk-wifi-mt76-testmode-add-testmode-pre-calibration-.patch @@ -0,0 +1,261 @@ +From 7fa3c8e6ad7e3bc33db8dc9ea59504428f0450e5 Mon Sep 17 00:00:00 2001 +From: StanleyYP Wang +Date: Fri, 31 Mar 2023 11:27:24 +0800 +Subject: [PATCH 1005/1044] mtk: wifi: mt76: testmode: add testmode + pre-calibration support + +Signed-off-by: StanleyYP Wang +--- + mac80211.c | 21 --- + mt76.h | 22 +++ + mt76_connac_mcu.h | 2 + + mt7996/eeprom.c | 66 +++++++ + mt7996/eeprom.h | 47 +++++ + mt7996/mcu.c | 5 + + mt7996/mt7996.h | 7 + + mt7996/testmode.c | 437 ++++++++++++++++++++++++++++++++++++++++++++++ + mt7996/testmode.h | 20 ++- + testmode.c | 12 ++ + testmode.h | 8 + + tools/fields.c | 8 + + 12 files changed, 632 insertions(+), 23 deletions(-) + +--- a/mac80211.c ++++ b/mac80211.c +@@ -6,27 +6,6 @@ + #include + #include "mt76.h" + +-#define CHAN2G(_idx, _freq) { \ +- .band = NL80211_BAND_2GHZ, \ +- .center_freq = (_freq), \ +- .hw_value = (_idx), \ +- .max_power = 30, \ +-} +- +-#define CHAN5G(_idx, _freq) { \ +- .band = NL80211_BAND_5GHZ, \ +- .center_freq = (_freq), \ +- .hw_value = (_idx), \ +- .max_power = 30, \ +-} +- +-#define CHAN6G(_idx, _freq) { \ +- .band = NL80211_BAND_6GHZ, \ +- .center_freq = (_freq), \ +- .hw_value = (_idx), \ +- .max_power = 30, \ +-} +- + static const struct ieee80211_channel mt76_channels_2ghz[] = { + CHAN2G(1, 2412), + CHAN2G(2, 2417), +--- a/mt76.h ++++ b/mt76.h +@@ -29,6 +29,27 @@ + #include "util.h" + #include "testmode.h" + ++#define CHAN2G(_idx, _freq) { \ ++ .band = NL80211_BAND_2GHZ, \ ++ .center_freq = (_freq), \ ++ .hw_value = (_idx), \ ++ .max_power = 30, \ ++} ++ ++#define CHAN5G(_idx, _freq) { \ ++ .band = NL80211_BAND_5GHZ, \ ++ .center_freq = (_freq), \ ++ .hw_value = (_idx), \ ++ .max_power = 30, \ ++} ++ ++#define CHAN6G(_idx, _freq) { \ ++ .band = NL80211_BAND_6GHZ, \ ++ .center_freq = (_freq), \ ++ .hw_value = (_idx), \ ++ .max_power = 30, \ ++} ++ + #define MT_MCU_RING_SIZE 32 + #define MT_RX_BUF_SIZE 2048 + #define MT_SKB_HEAD_LEN 256 +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1072,9 +1072,11 @@ enum { + MCU_UNI_EVENT_ROC = 0x27, + MCU_UNI_EVENT_MBMC = 0x28, + MCU_UNI_EVENT_TX_DONE = 0x2d, ++ MCU_UNI_EVENT_BF = 0x33, + MCU_UNI_EVENT_THERMAL = 0x35, + MCU_UNI_EVENT_RSSI_MONITOR = 0x41, + MCU_UNI_EVENT_NIC_CAPAB = 0x43, ++ MCU_UNI_EVENT_TESTMODE_CTRL = 0x46, + MCU_UNI_EVENT_WED_RRO = 0x57, + MCU_UNI_EVENT_PER_STA_INFO = 0x6d, + MCU_UNI_EVENT_ALL_STA_INFO = 0x6e, +--- a/mt7996/eeprom.c ++++ b/mt7996/eeprom.c +@@ -7,6 +7,42 @@ + #include "mt7996.h" + #include "eeprom.h" + ++const struct ieee80211_channel dpd_2g_ch_list_bw20[] = { ++ CHAN2G(3, 2422), ++ CHAN2G(7, 2442), ++ CHAN2G(11, 2462) ++}; ++ ++const struct ieee80211_channel dpd_5g_ch_list_bw160[] = { ++ CHAN5G(50, 5250), ++ CHAN5G(114, 5570), ++ CHAN5G(163, 5815) ++}; ++ ++const struct ieee80211_channel dpd_6g_ch_list_bw160[] = { ++ CHAN6G(15, 6025), ++ CHAN6G(47, 6185), ++ CHAN6G(79, 6345), ++ CHAN6G(111, 6505), ++ CHAN6G(143, 6665), ++ CHAN6G(175, 6825), ++ CHAN6G(207, 6985) ++}; ++ ++const struct ieee80211_channel dpd_6g_ch_list_bw320[] = { ++ CHAN6G(31, 6105), ++ CHAN6G(63, 6265), ++ CHAN6G(95, 6425), ++ CHAN6G(127, 6585), ++ CHAN6G(159, 6745), ++ CHAN6G(191, 6905) ++}; ++ ++const u32 dpd_2g_bw20_ch_num = ARRAY_SIZE(dpd_2g_ch_list_bw20); ++const u32 dpd_5g_bw160_ch_num = ARRAY_SIZE(dpd_5g_ch_list_bw160); ++const u32 dpd_6g_bw160_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw160); ++const u32 dpd_6g_bw320_ch_num = ARRAY_SIZE(dpd_6g_ch_list_bw320); ++ + static int mt7996_check_eeprom(struct mt7996_dev *dev) + { + u8 *eeprom = dev->mt76.eeprom.data; +@@ -133,6 +169,36 @@ static bool mt7996_eeprom_variant_valid( + return true; + } + ++int ++mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band) ++{ ++ /* handle different sku */ ++ static const u8 band_to_idx[] = { ++ [NL80211_BAND_2GHZ] = MT_BAND0, ++ [NL80211_BAND_5GHZ] = MT_BAND1, ++ [NL80211_BAND_6GHZ] = MT_BAND2, ++ }; ++ struct mt7996_phy *phy = __mt7996_phy(dev, band_to_idx[band]); ++ struct mt76_phy *mphy; ++ int dpd_size; ++ ++ if (!phy) ++ return 0; ++ ++ mphy = phy->mt76; ++ ++ if (band == NL80211_BAND_2GHZ) ++ dpd_size = dpd_2g_bw20_ch_num * DPD_PER_CH_BW20_SIZE; ++ else if (band == NL80211_BAND_5GHZ) ++ dpd_size = mphy->sband_5g.sband.n_channels * DPD_PER_CH_BW20_SIZE + ++ dpd_5g_bw160_ch_num * DPD_PER_CH_GT_BW20_SIZE; ++ else ++ dpd_size = mphy->sband_6g.sband.n_channels * DPD_PER_CH_BW20_SIZE + ++ (dpd_6g_bw160_ch_num + dpd_6g_bw320_ch_num) * DPD_PER_CH_GT_BW20_SIZE; ++ ++ return dpd_size; ++} ++ + static int + mt7996_eeprom_check_or_use_default(struct mt7996_dev *dev, bool use_default) + { +--- a/mt7996/eeprom.h ++++ b/mt7996/eeprom.h +@@ -14,6 +14,7 @@ enum mt7996_eeprom_field { + MT_EE_MAC_ADDR = 0x004, + MT_EE_MAC_ADDR2 = 0x00a, + MT_EE_WIFI_CONF = 0x190, ++ MT_EE_DO_PRE_CAL = 0x1a5, + MT_EE_MAC_ADDR3 = 0x2c0, + MT_EE_RATE_DELTA_2G = 0x1400, + MT_EE_RATE_DELTA_5G = 0x147d, +@@ -30,6 +31,52 @@ enum mt7996_eeprom_field { + #define MT_EE_WIFI_CONF1_BAND_SEL GENMASK(5, 3) + #define MT_EE_WIFI_CONF2_BAND_SEL GENMASK(2, 0) + ++#define MT_EE_WIFI_CAL_GROUP_2G BIT(0) ++#define MT_EE_WIFI_CAL_GROUP_5G BIT(1) ++#define MT_EE_WIFI_CAL_GROUP_6G BIT(2) ++#define MT_EE_WIFI_CAL_GROUP GENMASK(2, 0) ++#define MT_EE_WIFI_CAL_DPD_2G BIT(3) ++#define MT_EE_WIFI_CAL_DPD_5G BIT(4) ++#define MT_EE_WIFI_CAL_DPD_6G BIT(5) ++#define MT_EE_WIFI_CAL_DPD GENMASK(5, 3) ++ ++#define MT_EE_CAL_UNIT 1024 ++#define MT_EE_CAL_GROUP_SIZE_2G (4 * MT_EE_CAL_UNIT) ++#define MT_EE_CAL_GROUP_SIZE_5G (45 * MT_EE_CAL_UNIT) ++#define MT_EE_CAL_GROUP_SIZE_6G (125 * MT_EE_CAL_UNIT) ++#define MT_EE_CAL_ADCDCOC_SIZE_2G (4 * 4) ++#define MT_EE_CAL_ADCDCOC_SIZE_5G (4 * 4) ++#define MT_EE_CAL_ADCDCOC_SIZE_6G (4 * 5) ++#define MT_EE_CAL_GROUP_SIZE (MT_EE_CAL_GROUP_SIZE_2G + \ ++ MT_EE_CAL_GROUP_SIZE_5G + \ ++ MT_EE_CAL_GROUP_SIZE_6G + \ ++ MT_EE_CAL_ADCDCOC_SIZE_2G + \ ++ MT_EE_CAL_ADCDCOC_SIZE_5G + \ ++ MT_EE_CAL_ADCDCOC_SIZE_6G) ++ ++#define DPD_PER_CH_LEGACY_SIZE (4 * MT_EE_CAL_UNIT) ++#define DPD_PER_CH_MEM_SIZE (13 * MT_EE_CAL_UNIT) ++#define DPD_PER_CH_OTFG0_SIZE (2 * MT_EE_CAL_UNIT) ++#define DPD_PER_CH_BW20_SIZE (DPD_PER_CH_LEGACY_SIZE + DPD_PER_CH_OTFG0_SIZE) ++#define DPD_PER_CH_GT_BW20_SIZE (DPD_PER_CH_MEM_SIZE + DPD_PER_CH_OTFG0_SIZE) ++#define MT_EE_CAL_DPD_SIZE (780 * MT_EE_CAL_UNIT) ++ ++extern const struct ieee80211_channel dpd_2g_ch_list_bw20[]; ++extern const u32 dpd_2g_bw20_ch_num; ++extern const struct ieee80211_channel dpd_5g_ch_list_bw160[]; ++extern const u32 dpd_5g_bw160_ch_num; ++extern const struct ieee80211_channel dpd_6g_ch_list_bw160[]; ++extern const u32 dpd_6g_bw160_ch_num; ++extern const struct ieee80211_channel dpd_6g_ch_list_bw320[]; ++extern const u32 dpd_6g_bw320_ch_num; ++ ++#define RF_DPD_FLAT_CAL BIT(28) ++#define RF_PRE_CAL BIT(29) ++#define RF_DPD_FLAT_5G_CAL GENMASK(29, 28) ++#define RF_DPD_FLAT_5G_MEM_CAL (BIT(30) | BIT(28)) ++#define RF_DPD_FLAT_6G_CAL GENMASK(30, 28) ++#define RF_DPD_FLAT_6G_MEM_CAL (BIT(31) | BIT(28)) ++ + #define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3) + #define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0) + #define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3) +--- a/mt7996/mt7996.h ++++ b/mt7996/mt7996.h +@@ -519,6 +519,9 @@ struct mt7996_dev { + struct dentry *debugfs_dir; + struct rchan *relay_fwlog; + ++ void *cal; ++ u32 cur_prek_offset; ++ + struct { + u16 table_mask; + u8 n_agrt; +@@ -712,6 +715,7 @@ int mt7996_eeprom_get_target_power(struc + struct ieee80211_channel *chan); + s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band); + bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev); ++int mt7996_get_dpd_per_band_size(struct mt7996_dev *dev, enum nl80211_band band); + int mt7996_dma_init(struct mt7996_dev *dev); + void mt7996_dma_reset(struct mt7996_dev *dev, bool force); + void mt7996_dma_prefetch(struct mt7996_dev *dev); diff --git a/package/kernel/mt76/patches/smartrg-4000-1006-mtk-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-d.patch b/package/kernel/mt76/patches/smartrg-4000-1006-mtk-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-d.patch new file mode 100644 index 0000000000..b2cab85a8c --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-1006-mtk-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-d.patch @@ -0,0 +1,304 @@ +From 31635ddf23d7a951aa3896e8f4055bc1e52569a1 Mon Sep 17 00:00:00 2001 +From: Howard Hsu +Date: Mon, 8 May 2023 09:03:50 +0800 +Subject: [PATCH 1006/1044] mtk: wifi: mt76: mt7996: enable SCS feature for + mt7996 driver + +Enable Smart Carrier Sense algorithn by default to improve performance +in a noisy environment. + +Signed-off-by: Howard Hsu +--- + mt76_connac_mcu.h | 1 + + mt7996/init.c | 1 + + mt7996/mac.c | 2 + + mt7996/main.c | 7 +++ + mt7996/mcu.c | 105 +++++++++++++++++++++++++++++++++++++++++++ + mt7996/mcu.h | 6 +++ + mt7996/mt7996.h | 15 +++++++ + mt7996/mtk_debugfs.c | 11 +++++ + 8 files changed, 148 insertions(+) + +--- a/mt76_connac_mcu.h ++++ b/mt76_connac_mcu.h +@@ -1303,6 +1303,7 @@ enum { + MCU_UNI_CMD_GET_STAT_INFO = 0x23, + MCU_UNI_CMD_SNIFFER = 0x24, + MCU_UNI_CMD_SR = 0x25, ++ MCU_UNI_CMD_SCS = 0x26, + MCU_UNI_CMD_ROC = 0x27, + MCU_UNI_CMD_SET_DBDC_PARMS = 0x28, + MCU_UNI_CMD_TXPOWER = 0x2b, +--- a/mt7996/init.c ++++ b/mt7996/init.c +@@ -1740,6 +1740,7 @@ int mt7996_register_device(struct mt7996 + dev->mt76.phy.priv = &dev->phy; + INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work); + INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work); ++ INIT_DELAYED_WORK(&dev->scs_work, mt7996_mcu_scs_sta_poll); + INIT_LIST_HEAD(&dev->sta_rc_list); + INIT_LIST_HEAD(&dev->twt_list); + +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -2430,6 +2430,7 @@ mt7996_mac_full_reset(struct mt7996_dev + cancel_work_sync(&dev->wed_rro.work); + mt7996_for_each_phy(dev, phy) + cancel_delayed_work_sync(&phy->mt76->mac_work); ++ cancel_delayed_work_sync(&dev->scs_work); + + mt76_abort_scan(&dev->mt76); + +--- a/mt7996/main.c ++++ b/mt7996/main.c +@@ -39,11 +39,17 @@ int mt7996_run(struct mt7996_phy *phy) + if (ret) + return ret; + ++ ret = mt7996_mcu_set_scs(phy, SCS_ENABLE); ++ if (ret) ++ return ret; ++ + set_bit(MT76_STATE_RUNNING, &phy->mt76->state); + + ieee80211_queue_delayed_work(dev->mphy.hw, &phy->mt76->mac_work, + MT7996_WATCHDOG_TIME); + ++ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); ++ + if (!phy->counter_reset) { + mt7996_mac_reset_counters(phy); + phy->counter_reset = true; +@@ -81,6 +87,7 @@ static void mt7996_stop_phy(struct mt799 + dev = phy->dev; + + cancel_delayed_work_sync(&phy->mt76->mac_work); ++ cancel_delayed_work_sync(&dev->scs_work); + + mutex_lock(&dev->mt76.mutex); + +@@ -2505,6 +2512,8 @@ mt7996_reconfig_complete(struct ieee8021 + mt7996_for_each_phy(dev, phy) + ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, + MT7996_WATCHDOG_TIME); ++ ++ ieee80211_queue_delayed_work(hw, &dev->scs_work, HZ); + } + + static int +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -5610,3 +5610,116 @@ int mt7996_mcu_set_pp_en(struct mt7996_p + return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(PP), + &req, sizeof(req), false); + } ++ ++static int mt7996_mcu_set_scs_stats(struct mt7996_phy *phy) ++{ ++ struct mt7996_scs_ctrl ctrl = phy->scs_ctrl; ++ struct { ++ u8 band_idx; ++ u8 _rsv[3]; ++ ++ __le16 tag; ++ __le16 len; ++ ++ u8 _rsv2[6]; ++ s8 min_rssi; ++ u8 _rsv3; ++ } __packed req = { ++ .band_idx = phy->mt76->band_idx, ++ .tag = cpu_to_le16(UNI_CMD_SCS_SEND_DATA), ++ .len = cpu_to_le16(sizeof(req) - 4), ++ ++ .min_rssi = ctrl.sta_min_rssi, ++ }; ++ ++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS), ++ &req, sizeof(req), false); ++} ++ ++static void mt7996_sta_rssi_work(void *data, struct ieee80211_sta *sta) ++{ ++ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; ++ struct mt7996_sta_link *msta_link; ++ struct mt7996_phy *poll_phy = (struct mt7996_phy *)data; ++ ++ mutex_lock(&poll_phy->dev->mt76.mutex); ++ msta_link = mt76_dereference(msta->link[0], &poll_phy->dev->mt76); ++ if (!msta_link) ++ goto out; ++ ++ if (poll_phy->scs_ctrl.sta_min_rssi > msta_link->ack_signal) ++ poll_phy->scs_ctrl.sta_min_rssi = msta_link->ack_signal; ++out: ++ mutex_unlock(&poll_phy->dev->mt76.mutex); ++} ++ ++void mt7996_mcu_scs_sta_poll(struct work_struct *work) ++{ ++ struct mt7996_dev *dev = container_of(work, struct mt7996_dev, ++ scs_work.work); ++ bool scs_enable_flag = false; ++ u8 i; ++ ++ for (i = 0; i < __MT_MAX_BAND; i++) { ++ struct mt7996_phy *phy; ++ ++ switch (i) { ++ case MT_BAND0: ++ phy = dev->mphy.priv; ++ break; ++ case MT_BAND1: ++ phy = mt7996_phy2(dev); ++ break; ++ case MT_BAND2: ++ phy = mt7996_phy3(dev); ++ break; ++ default: ++ phy = NULL; ++ break; ++ } ++ ++ if (!phy || !test_bit(MT76_STATE_RUNNING, &phy->mt76->state) || ++ !phy->scs_ctrl.scs_enable) ++ continue; ++ ++ ieee80211_iterate_stations_atomic(phy->mt76->hw, ++ mt7996_sta_rssi_work, phy); ++ ++ scs_enable_flag = true; ++ if (mt7996_mcu_set_scs_stats(phy)) ++ dev_err(dev->mt76.dev, "Failed to send scs mcu cmd\n"); ++ phy->scs_ctrl.sta_min_rssi = 0; ++ } ++ ++ if (scs_enable_flag) ++ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); ++} ++ ++ ++int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable) ++{ ++ struct mt7996_dev *dev = phy->dev; ++ struct { ++ u8 band_idx; ++ u8 _rsv[3]; ++ ++ __le16 tag; ++ __le16 len; ++ ++ u8 scs_enable; ++ u8 _rsv2[3]; ++ } __packed req = { ++ .band_idx = phy->mt76->band_idx, ++ .tag = cpu_to_le16(UNI_CMD_SCS_ENABLE), ++ .len = cpu_to_le16(sizeof(req) - 4), ++ .scs_enable = enable, ++ }; ++ ++ phy->scs_ctrl.scs_enable = enable; ++ ++ if (enable == SCS_ENABLE) ++ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->scs_work, HZ); ++ ++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(SCS), ++ &req, sizeof(req), false); ++} +--- a/mt7996/mcu.h ++++ b/mt7996/mcu.h +@@ -1081,6 +1081,12 @@ enum pp_mode { + PP_USR_MODE, + }; + ++enum { ++ UNI_CMD_SCS_SEND_DATA, ++ UNI_CMD_SCS_SET_PD_THR_RANGE = 2, ++ UNI_CMD_SCS_ENABLE, ++}; ++ + #define MT7996_PATCH_SEC GENMASK(31, 24) + #define MT7996_PATCH_SCRAMBLE_KEY GENMASK(15, 8) + #define MT7996_PATCH_AES_KEY GENMASK(7, 0) +--- a/mt7996/mt7996.h ++++ b/mt7996/mt7996.h +@@ -321,6 +321,16 @@ struct mt7996_hif { + enum pcie_link_width width; + }; + ++struct mt7996_scs_ctrl { ++ u8 scs_enable; ++ s8 sta_min_rssi; ++}; ++ ++enum { ++ SCS_DISABLE = 0, ++ SCS_ENABLE, ++}; ++ + #define WED_RRO_ADDR_SIGNATURE_MASK GENMASK(31, 24) + #define WED_RRO_ADDR_COUNT_MASK GENMASK(14, 4) + #define WED_RRO_ADDR_HEAD_HIGH_MASK GENMASK(3, 0) +@@ -409,6 +419,8 @@ struct mt7996_phy { + + u8 pp_mode; + u16 punct_bitmap; ++ ++ struct mt7996_scs_ctrl scs_ctrl; + }; + + struct mt7996_dev { +@@ -445,6 +457,7 @@ struct mt7996_dev { + struct work_struct rc_work; + struct work_struct dump_work; + struct work_struct reset_work; ++ struct delayed_work scs_work; + wait_queue_head_t reset_wait; + struct { + u32 state; +@@ -975,6 +988,8 @@ u32 mt7996_wed_init_buf(void *ptr, dma_a + int mt7996_mtk_init_debugfs(struct mt7996_dev *dev, struct dentry *dir); + int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val); + #endif ++int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable); ++void mt7996_mcu_scs_sta_poll(struct work_struct *work); + + int mt7996_dma_rro_init(struct mt7996_dev *dev); + void mt7996_dma_rro_start(struct mt7996_dev *dev); +--- a/mt7996/mtk_debugfs.c ++++ b/mt7996/mtk_debugfs.c +@@ -2344,8 +2344,19 @@ static int mt7996_sta_info(struct seq_fi + return 0; + } + ++static int ++mt7996_scs_enable_set(void *data, u64 val) ++{ ++ struct mt7996_phy *phy = data; ++ ++ return mt7996_mcu_set_scs(phy, (u8) val); ++} ++DEFINE_DEBUGFS_ATTRIBUTE(fops_scs_enable, NULL, ++ mt7996_scs_enable_set, "%lld\n"); ++ + int mt7996_mtk_init_debugfs(struct mt7996_dev *dev, struct dentry *dir) + { ++ struct ieee80211_hw *hw = mt76_hw(dev); + u32 device_id = (dev->mt76.rev) >> 16; + int i = 0; + static const struct mt7996_dbg_reg_desc dbg_reg_s[] = { +@@ -2408,6 +2419,14 @@ int mt7996_mtk_init_debugfs(struct mt799 + + debugfs_create_u8("sku_disable", 0600, dir, &dev->dbg.sku_disable); + ++ for (i = 0; i < hw->wiphy->n_radio; i++) { ++ char buf[32]; ++ struct mt7996_phy *phy = dev->radio_phy[i]; ++ ++ snprintf(buf, sizeof(buf), "scs_enable%d", i); ++ debugfs_create_file(buf, 0200, dir, phy, &fops_scs_enable); ++ } ++ + return 0; + } + diff --git a/package/kernel/mt76/patches/smartrg-4000-1018-mtk-wifi-mt76-mt7996-add-support-for-runtime-set-in-.patch b/package/kernel/mt76/patches/smartrg-4000-1018-mtk-wifi-mt76-mt7996-add-support-for-runtime-set-in-.patch new file mode 100644 index 0000000000..47c6f7740d --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-1018-mtk-wifi-mt76-mt7996-add-support-for-runtime-set-in-.patch @@ -0,0 +1,39 @@ +From 87640cadc55b8baf82dfb9db81bf7718da595f77 Mon Sep 17 00:00:00 2001 +From: MeiChia Chiu +Date: Tue, 6 Jun 2023 16:57:10 +0800 +Subject: [PATCH 1018/1044] mtk: wifi: mt76: mt7996: add support for runtime + set in-band discovery + +with this patch, AP can runtime set inband discovery via hostapd_cli + +Usage: +Enable FILS: hostapd_cli -i [interface] inband_discovery 2 20 +Enable UBPR: hostapd_cli -i [interface] inband_discovery 1 20 +Disable inband discovery: hostapd_cli -i [interface] inband_discovery 0 0 + +Signed-off-by: MeiChia Chiu +--- + mt7996/mcu.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -3298,8 +3298,7 @@ int mt7996_mcu_beacon_inband_discov(stru + if (IS_ERR(rskb)) + return PTR_ERR(rskb); + +- if (changed & BSS_CHANGED_FILS_DISCOVERY && +- link_conf->fils_discovery.max_interval) { ++ if (changed & BSS_CHANGED_FILS_DISCOVERY) { + interval = link_conf->fils_discovery.max_interval; + skb = ieee80211_get_fils_discovery_tmpl(hw, vif); + } else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP && +@@ -3334,7 +3333,7 @@ int mt7996_mcu_beacon_inband_discov(stru + discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY); + discov->tx_interval = interval; + discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len); +- discov->enable = true; ++ discov->enable = !!(interval); + discov->wcid = cpu_to_le16(MT7996_WTBL_RESERVED); + + buf = (u8 *)tlv + sizeof(*discov); diff --git a/package/kernel/mt76/patches/smartrg-4000-1021-mtk-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch b/package/kernel/mt76/patches/smartrg-4000-1021-mtk-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch new file mode 100644 index 0000000000..2a4b4d9711 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-4000-1021-mtk-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch @@ -0,0 +1,20 @@ +From 8652100545c84c1db5f59840ba34c08615f1e572 Mon Sep 17 00:00:00 2001 +From: MeiChia Chiu +Date: Tue, 1 Aug 2023 16:02:28 +0800 +Subject: [PATCH 1021/1044] mtk: wifi: mt76: mt7996: Establish BA in VO queue + +--- + mt7996/mac.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -1221,8 +1221,6 @@ mt7996_tx_check_aggr(struct ieee80211_li + return; + + tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; +- if (tid >= 6) /* skip VO queue */ +- return; + + if (is_8023) { + fc = IEEE80211_FTYPE_DATA | diff --git a/package/kernel/mt76/patches/smartrg-9500-wifi-mt76-mt7915-fix-ch144-dpd-frequency-index.patch b/package/kernel/mt76/patches/smartrg-9500-wifi-mt76-mt7915-fix-ch144-dpd-frequency-index.patch new file mode 100644 index 0000000000..ea8818ac6d --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9500-wifi-mt76-mt7915-fix-ch144-dpd-frequency-index.patch @@ -0,0 +1,12 @@ +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -3160,6 +3160,9 @@ static int mt7915_dpd_freq_idx(struct mt + return idx; + } + ++ if (is_mt7915(&dev->mt76)) ++ freq = (freq == 5720) ? 5700: freq; ++ + return mt7915_find_freq_idx(freq_list, n_freqs, freq); + } + diff --git a/package/kernel/mt76/patches/smartrg-9504-wifi-mt76-mt7915-ignore-duplicate-radar-events.patch b/package/kernel/mt76/patches/smartrg-9504-wifi-mt76-mt7915-ignore-duplicate-radar-events.patch new file mode 100644 index 0000000000..c3bdcd51b4 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9504-wifi-mt76-mt7915-ignore-duplicate-radar-events.patch @@ -0,0 +1,86 @@ +From: Chad Monroe +Date: Wed, 22 Jan 2025 13:14:08 -0800 +Subject: [PATCH] wifi: mt76: mt7915: ignore duplicate radar events + +If a radar event is triggered while mac80211 is in the middle of +a CSA from a prior event, some channel switch parameters can get +overwritten. When this happens the radio will fail to start after +moving to the new channel. + +It seems like it would be better for mac80211 to protect itself +against this but I couldn't find a clean way to do it. + +Signed-off-by: Chad Monroe +--- + mt7915/mac.c | 2 ++ + mt7915/mcu.c | 19 +++++++++++++++++-- + mt7915/mt7915.h | 1 + + 3 files changed, 20 insertions(+), 2 deletions(-) + +--- a/mt7915/mcu.c ++++ b/mt7915/mcu.c +@@ -332,6 +332,8 @@ static void + mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) + { + struct mt76_phy *mphy = &dev->mt76.phy; ++ struct mt7915_phy *phy; ++ struct cfg80211_chan_def *chandef; + struct mt7915_mcu_rdd_report *r; + u32 sku; + +@@ -361,18 +363,31 @@ mt7915_mcu_rx_radar_detected(struct mt79 + if (!mphy) + return; + ++ phy = (struct mt7915_phy *)mphy->priv; ++ chandef = &phy->mt76->chandef; ++ ++ if (phy->rdd_hw_value == chandef->chan->hw_value) { ++ dev_info(dev->mt76.dev, ++ "%s: radar detection for channel=%u in progress, ignore r->rdd_idx=%d\n", ++ __func__, phy->rdd_hw_value, r->rdd_idx); ++ return; ++ } ++ + dev_info(dev->mt76.dev, "%s: RADAR DETECTED r->rdd_idx=%d\n", __func__, r->rdd_idx); + dev_dbg(dev->mt76.dev, "%s: long_detected=%u constant_prf_detected=%u staggered_prf_detected=%u\n", + __func__, r->long_detected, r->constant_prf_detected, r->staggered_prf_detected); + dev_dbg(dev->mt76.dev, "%s: radar_type_idx=%u periodic_pulse_num=%u long_pulse_num=%u hw_pulse_num=%u\n", + __func__, r->radar_type_idx, r->periodic_pulse_num, r->long_pulse_num, r->hw_pulse_num); + +- if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) ++ if (r->rdd_idx == MT_RDD_IDX_BACKGROUND) { + cfg80211_background_radar_event(mphy->hw->wiphy, + &dev->rdd2_chandef, + GFP_ATOMIC); +- else ++ } else { ++ phy->rdd_hw_value = chandef->chan->hw_value; + ieee80211_radar_detected(mphy->hw, NULL); ++ } ++ + dev->hw_pattern++; + } + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -2290,6 +2290,8 @@ int mt7915_dfs_init_radar_detector(struc + enum mt76_dfs_state dfs_state, prev_state; + int err, rdd_idx = mt7915_get_rdd_idx(phy, false); + ++ phy->rdd_hw_value = 0; ++ + prev_state = phy->mt76->dfs_state; + dfs_state = mt76_phy_dfs_state(phy->mt76); + +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -237,6 +237,8 @@ struct mt7915_phy { + s16 coverage_class; + u8 slottime; + ++ u16 rdd_hw_value; ++ + u32 trb_ts; + + u32 rx_ampdu_ts; diff --git a/package/kernel/mt76/patches/smartrg-9504-wifi-mt76-mt7996-ignore-duplicate-radar-events.patch b/package/kernel/mt76/patches/smartrg-9504-wifi-mt76-mt7996-ignore-duplicate-radar-events.patch new file mode 100644 index 0000000000..6df78a0fa0 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9504-wifi-mt76-mt7996-ignore-duplicate-radar-events.patch @@ -0,0 +1,77 @@ +From: Chad Monroe +Date: Wed, 22 Jan 2025 13:14:18 -0800 +Subject: [PATCH] wifi: mt76: mt7996: ignore duplicate radar events + +If a radar event is triggered while mac80211 is in the middle of +a CSA from a prior event, some channel switch parameters can get +overwritten. When this happens the radio will fail to start after +moving to the new channel. + +It seems like it would be better for mac80211 to protect itself +against this but I couldn't find a clean way to do it. + +Signed-off-by: Chad Monroe +--- + mt7996/mac.c | 2 ++ + mt7996/mcu.c | 13 +++++++++++++ + mt7996/mt7996.h | 1 + + 3 files changed, 16 insertions(+) + +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -526,6 +526,8 @@ static void + mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) + { + struct mt76_phy *mphy = &dev->mt76.phy; ++ struct mt7996_phy *phy; ++ struct cfg80211_chan_def *chandef; + struct mt7996_mcu_rdd_report *r; + + r = (struct mt7996_mcu_rdd_report *)skb->data; +@@ -549,6 +551,16 @@ mt7996_mcu_rx_radar_detected(struct mt79 + if (!mphy) + goto err; + ++ phy = (struct mt7996_phy *)mphy->priv; ++ chandef = &phy->mt76->chandef; ++ ++ if (phy->rdd_hw_value == chandef->chan->hw_value) { ++ dev_info(dev->mt76.dev, ++ "%s: radar detection for channel=%u in progress, ignore r->rdd_idx=%d\n", ++ __func__, phy->rdd_hw_value, r->rdd_idx); ++ return; ++ } ++ + dev_info(dev->mt76.dev, "%s: RADAR DETECTED r->rdd_idx=%d\n", __func__, r->rdd_idx); + dev_dbg(dev->mt76.dev, "%s: long_detected=%u constant_prf_detected=%u staggered_prf_detected=%u\n", + __func__, r->long_detected, r->constant_prf_detected, r->staggered_prf_detected); +@@ -563,6 +575,7 @@ mt7996_mcu_rx_radar_detected(struct mt79 + } else { + struct mt7996_phy *phy = mphy->priv; + ++ phy->rdd_hw_value = chandef->chan->hw_value; + phy->rdd_tx_paused = true; + ieee80211_radar_detected(mphy->hw, NULL); + } +--- a/mt7996/mt7996.h ++++ b/mt7996/mt7996.h +@@ -401,6 +401,8 @@ struct mt7996_phy { + s16 coverage_class; + u8 slottime; + ++ u16 rdd_hw_value; ++ + u16 beacon_rate; + + u32 rx_ampdu_ts; +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -3054,6 +3054,8 @@ int mt7996_dfs_init_radar_detector(struc + enum mt76_dfs_state dfs_state, prev_state; + int err, rdd_idx = mt7996_get_rdd_idx(phy, false); + ++ phy->rdd_hw_value = 0; ++ + prev_state = phy->mt76->dfs_state; + dfs_state = mt76_phy_dfs_state(phy->mt76); + diff --git a/package/kernel/mt76/patches/smartrg-9506-wifi-mt76-mt7996-fix-station-stats-crash.patch b/package/kernel/mt76/patches/smartrg-9506-wifi-mt76-mt7996-fix-station-stats-crash.patch new file mode 100644 index 0000000000..584598f050 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9506-wifi-mt76-mt7996-fix-station-stats-crash.patch @@ -0,0 +1,18 @@ +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -674,6 +674,7 @@ mt7996_mcu_rx_all_sta_info_event(struct + + res = (struct mt7996_mcu_all_sta_info_event *)skb->data; + ++ rcu_read_lock(); + for (i = 0; i < le16_to_cpu(res->sta_num); i++) { + u8 ac; + u16 wlan_idx; +@@ -720,6 +721,7 @@ mt7996_mcu_rx_all_sta_info_event(struct + break; + } + } ++ rcu_read_unlock(); + } + + static void diff --git a/package/kernel/mt76/patches/smartrg-9513-mt76-mt7915-fix-GENMASK-for-chain-3-RSSI-in-mt7915_mac_sta_poll.patch b/package/kernel/mt76/patches/smartrg-9513-mt76-mt7915-fix-GENMASK-for-chain-3-RSSI-in-mt7915_mac_sta_poll.patch new file mode 100644 index 0000000000..57ae17f021 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9513-mt76-mt7915-fix-GENMASK-for-chain-3-RSSI-in-mt7915_mac_sta_poll.patch @@ -0,0 +1,40 @@ +From dda490f9aa1dd8b93bc4d2daaae50d436882005e Mon Sep 17 00:00:00 2001 +From: Ankit Dange +Date: Wed, 29 Apr 2026 00:52:28 +0530 +Subject: [PATCH] wifi: mt76: mt7915: fix GENMASK for chain 3 RSSI in + mt7915_mac_sta_poll() + +The RCPI values of response frames are stored as four consecutive +bytes in WTBL DW30. The bitmask for extracting chain 3 RCPI uses +GENMASK(31, 14) which is an 18-bit field overlapping with chains 1 +and 2. Fix it to GENMASK(31, 24) to correctly extract the 8-bit +RCPI value for chain 3. + +On devices with fewer than 4 antenna chains this bug is masked +because mt76_rx_signal() skips chains not present in antenna_mask. +On 4x4 configurations the corrupted chain 3 value feeds into the +combined ACK signal strength calculation. + +Tested on Yuncore AX820 (MT7915, 2x2) by reading raw DW30 register +values and comparing FIELD_GET results for both masks. With +GENMASK(31, 14), chain 3 produces garbage values (e.g., -112 dBm +from a register value of 0xFFFF4248 where the correct result is ++17, indicating an unused chain). No regression on 2x2 operation. + +Fixes: 94b335fa88e1 ("wifi: mt76: mt7915: add ack signal support") +Signed-off-by: Ankit Dange +--- + mt7915/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -201,7 +201,7 @@ static void mt7915_mac_sta_poll(struct m + rssi[0] = to_rssi(GENMASK(7, 0), val); + rssi[1] = to_rssi(GENMASK(15, 8), val); + rssi[2] = to_rssi(GENMASK(23, 16), val); +- rssi[3] = to_rssi(GENMASK(31, 14), val); ++ rssi[3] = to_rssi(GENMASK(31, 24), val); + + msta->ack_signal = + mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi); diff --git a/package/kernel/mt76/patches/smartrg-9514-wifi-mt76-mt7915-fix-recovery.patch b/package/kernel/mt76/patches/smartrg-9514-wifi-mt76-mt7915-fix-recovery.patch new file mode 100644 index 0000000000..8f37f2a553 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9514-wifi-mt76-mt7915-fix-recovery.patch @@ -0,0 +1,25 @@ +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1373,9 +1373,10 @@ static void + mt7915_mac_full_reset(struct mt7915_dev *dev) + { + struct mt76_phy *ext_phy; +- struct mt7915_phy *phy2; ++ struct mt7915_phy *phy, *phy2; + int i; + ++ phy = &dev->phy; + ext_phy = dev->mt76.phys[MT_BAND1]; + phy2 = ext_phy ? ext_phy->priv : NULL; + +@@ -1411,6 +1412,10 @@ mt7915_mac_full_reset(struct mt7915_dev + INIT_LIST_HEAD(&dev->sta_rc_list); + INIT_LIST_HEAD(&dev->twt_list); + ++ INIT_LIST_HEAD(&phy->stats_list); ++ if (phy2) ++ INIT_LIST_HEAD(&phy2->stats_list); ++ + i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); + dev->mt76.global_wcid.idx = i; + dev->recovery.hw_full_reset = false; diff --git a/package/kernel/mt76/patches/smartrg-9515-wifi-mt76-mt7915-disable-coredump.patch b/package/kernel/mt76/patches/smartrg-9515-wifi-mt76-mt7915-disable-coredump.patch new file mode 100644 index 0000000000..949ad3a9d1 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9515-wifi-mt76-mt7915-disable-coredump.patch @@ -0,0 +1,11 @@ +--- a/mt7915/coredump.c ++++ b/mt7915/coredump.c +@@ -351,6 +351,8 @@ static struct mt7915_coredump *mt7915_co + unsigned char *buf; + bool exception; + ++ return NULL; ++ + len = hdr_len; + + if (coredump_memdump && crash_data->memdump_buf_len) diff --git a/package/kernel/mt76/patches/smartrg-9517-wifi-mt76-add-dma_rx_process-len-check.patch b/package/kernel/mt76/patches/smartrg-9517-wifi-mt76-add-dma_rx_process-len-check.patch new file mode 100644 index 0000000000..c95c2acae5 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9517-wifi-mt76-add-dma_rx_process-len-check.patch @@ -0,0 +1,25 @@ +From 142444baea281daabf8b39e38aa1f83b30e58ddb Mon Sep 17 00:00:00 2001 +From: Rany Hany +Date: Sun, 7 Jul 2024 19:52:45 +0000 +Subject: [PATCH] mt76: dma: add len check in mt76_dma_rx_process to drop + garbage frames + +Ref: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/9b805e58a26443d4d59349dfb4629f3f4986127a/autobuild_mac80211_release/mt7988_mt7996_mac80211_mlo/package/kernel/mt76/patches/0063-mtk-wifi-mt76-mt7915-wed-find-rx-token-by-physical-a.patch + +No other change in dma.c required (earlier rework WED flow just +changed some variable names for that part of the code so that +patch can't apply cleanly). + +Signed-off-by: Rany Hany +--- +--- a/dma.c ++++ b/dma.c +@@ -1018,7 +1018,7 @@ mt76_dma_rx_process(struct mt76_dev *dev + continue; + } + +- if (drop) ++ if (drop || (len == 0)) + goto free_frag; + + if (q->rx_head) diff --git a/package/kernel/mt76/patches/smartrg-9519-wifi-mt76-mt7915-trigger-L1-SER-on-PLE-MDP-RIOC-hang.patch b/package/kernel/mt76/patches/smartrg-9519-wifi-mt76-mt7915-trigger-L1-SER-on-PLE-MDP-RIOC-hang.patch new file mode 100644 index 0000000000..5f4afd3018 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9519-wifi-mt76-mt7915-trigger-L1-SER-on-PLE-MDP-RIOC-hang.patch @@ -0,0 +1,67 @@ +From: Chad Monroe +Date: Wed, 14 Jan 2026 17:10:41 -0800 +Subject: [PATCH] mt76: mt7915: trigger L1 SER on PLE MDP RIOC hang + +WM firmware can enter a partial failure state where RX is hung. + +Detect this condition by monitoring SER_PLE_ERR_1 for MDP_RIOC_HANG_ERR +and trigger L1 SER to restore operation. Use transition detection on the +error bit to fire only once per new occurrence, preventing an infinite +SER loop when the bit remains set across checks. + +Signed-off-by: Chad Monroe +--- + mt7915/mac.c | 12 +++++++++++- + mt7915/mt7915.h | 1 + + mt7915/regs.h | 1 + + 3 files changed, 13 insertions(+), 1 deletion(-) + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1933,7 +1933,7 @@ void mt7915_mac_update_stats(struct mt79 + static void mt7915_mac_severe_check(struct mt7915_phy *phy) + { + struct mt7915_dev *dev = phy->dev; +- u32 trb; ++ u32 trb, ple_err; + + if (!phy->omac_mask) + return; +@@ -1953,6 +1953,17 @@ static void mt7915_mac_severe_check(stru + phy->mt76->band_idx); + + phy->trb_ts = trb; ++ ++ ple_err = mt76_rr(dev, MT_SWDEF_PLE1_STATS); ++ if ((ple_err & MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR) && ++ !(dev->ple1_sts & MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR)) { ++ dev_warn(dev->mt76.dev, ++ "band%d: PLE error 0x%x detected, triggering L1 SER\n", ++ phy->mt76->band_idx, ple_err); ++ mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L1, ++ phy->mt76->band_idx); ++ } ++ dev->ple1_sts = ple_err; + } + + static void mt7915_mac_sta_stats_work(struct mt7915_phy *phy) +--- a/mt7915/regs.h ++++ b/mt7915/regs.h +@@ -1080,6 +1080,7 @@ enum offs_rev { + #define MT_SWDEF_SER_STATS MT_SWDEF(0x040) + #define MT_SWDEF_PLE_STATS MT_SWDEF(0x044) + #define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048) ++#define MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR BIT(3) + #define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04C) + #define MT_SWDEF_PSE_STATS MT_SWDEF(0x050) + #define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054) +--- a/mt7915/mt7915.h ++++ b/mt7915/mt7915.h +@@ -325,6 +325,7 @@ struct mt7915_dev { + spinlock_t reg_lock; + + u32 hw_pattern; ++ u32 ple1_sts; + + bool limited_wtbl_size; + bool dbdc_support; diff --git a/package/kernel/mt76/patches/smartrg-9520-wifi-mt76-mt7915-increase-txq-memory-limit.patch b/package/kernel/mt76/patches/smartrg-9520-wifi-mt76-mt7915-increase-txq-memory-limit.patch new file mode 100644 index 0000000000..092fb56fa3 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9520-wifi-mt76-mt7915-increase-txq-memory-limit.patch @@ -0,0 +1,26 @@ +From: Chad Monroe +Date: Fri, 18 Apr 2025 09:41:44 -0700 +Subject: [PATCH] mt76: mt7915: set appropriate txq memory limits + +MT7986 is DBDC and would fall back to the mac80211 default of 16MB +or if the radio does not support VHT (2G/6G) then 4MB. Set all radios +to 32MB except MT7915 DBDC where 16MB is adequate. + +Signed-off-by: Chad Monroe +--- + mt7915/init.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/mt7915/init.c ++++ b/mt7915/init.c +@@ -417,7 +417,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy + + hw->max_tx_fragments = 4; + +- if (!phy->dev->dbdc_support) ++ if (phy->dev->dbdc_support && is_mt7915(&dev->mt76)) ++ wiphy->txq_memory_limit = 16 << 20; /* 16 MiB */ ++ else + wiphy->txq_memory_limit = 32 << 20; /* 32 MiB */ + + if (phy->mt76->cap.has_2ghz) { diff --git a/package/kernel/mt76/patches/smartrg-9521-wifi-mt76-mt7996-disable-UNI_BSS_INFO_PROTECT_INFO-for-mt7996.patch b/package/kernel/mt76/patches/smartrg-9521-wifi-mt76-mt7996-disable-UNI_BSS_INFO_PROTECT_INFO-for-mt7996.patch new file mode 100644 index 0000000000..06f12a6198 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9521-wifi-mt76-mt7996-disable-UNI_BSS_INFO_PROTECT_INFO-for-mt7996.patch @@ -0,0 +1,30 @@ +From: Ryder Lee +Date: Wed, 25 Mar 2026 10:17:23 -0700 +Subject: [PATCH v2] wifi: mt76: mt7996: disable UNI_BSS_INFO_PROTECT_INFO for + mt7996 + +The current MT7996 firmware causes TX failure and need further +investigation, so it is temporarily disabled. + +MT7992 and MT7990 are working normally. + +Signed-off-by: Ryder Lee +--- +v2 - add a comment to describe why this check is required. +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/mt7996/mcu.c ++++ b/mt7996/mcu.c +@@ -1381,6 +1381,10 @@ int mt7996_mcu_set_protection(struct mt7 + if (is_mt7996(&dev->mt76)) + return 0; + ++ /* The current firmware causes TX failure. Need further investigation */ ++ if (is_mt7996(&dev->mt76)) ++ return 0; ++ + skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76, + MT7996_BSS_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) diff --git a/package/kernel/mt76/patches/smartrg-9530-wifi-mt76-mt7996-add-debug-log-for-SER-flow.patch b/package/kernel/mt76/patches/smartrg-9530-wifi-mt76-mt7996-add-debug-log-for-SER-flow.patch new file mode 100644 index 0000000000..96a0092e90 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9530-wifi-mt76-mt7996-add-debug-log-for-SER-flow.patch @@ -0,0 +1,92 @@ +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -2513,7 +2513,7 @@ void mt7996_mac_reset_work(struct work_s + if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) + return; + +- dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.", ++ dev_info(dev->mt76.dev,"==== %s L1 SER recovery start ====", + wiphy_name(hw->wiphy)); + + if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) +@@ -2525,6 +2525,9 @@ void mt7996_mac_reset_work(struct work_s + mt7996_npu_hw_stop(dev); + ieee80211_stop_queues(mt76_hw(dev)); + ++ dev_info(dev->mt76.dev,"%s L1 SER queue stop done", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + mt76_abort_scan(&dev->mt76); +@@ -2538,6 +2541,10 @@ void mt7996_mac_reset_work(struct work_s + } + + mt76_worker_disable(&dev->mt76.tx_worker); ++ ++ dev_info(dev->mt76.dev,"%s L1 SER disable tx_work done", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + mt76_for_each_q_rx(&dev->mt76, i) { + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && + mt76_queue_is_wed_rro(&dev->mt76.q_rx[i])) +@@ -2556,14 +2563,30 @@ void mt7996_mac_reset_work(struct work_s + + mutex_lock(&dev->mt76.mutex); + ++ dev_info(dev->mt76.dev,"%s L1 SER napi disable done", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); + ++ dev_info(dev->mt76.dev,"%s L1 SER dma stop done", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { + mt7996_dma_reset(dev, false); + ++ dev_info(dev->mt76.dev,"%s L1 SER dma reset done", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + mt7996_tx_token_put(dev); ++ ++ dev_info(dev->mt76.dev,"%s L1 SER token put done", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + idr_init(&dev->mt76.token); + ++ dev_info(dev->mt76.dev,"%s L1 SER idr init done", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); + mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); + } +@@ -2596,6 +2619,9 @@ void mt7996_mac_reset_work(struct work_s + + __mt7996_npu_hw_init(dev); + ++ dev_info(dev->mt76.dev,"%s L1 SER dma start done", ++ wiphy_name(dev->mt76.hw->wiphy)); ++ + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + mt7996_for_each_phy(dev, phy) + clear_bit(MT76_RESET, &phy->mt76->state); +@@ -2635,7 +2661,7 @@ void mt7996_mac_reset_work(struct work_s + mt7996_for_each_phy(dev, phy) + ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, + MT7996_WATCHDOG_TIME); +- dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.", ++ dev_info(dev->mt76.dev,"==== %s L1 SER recovery completed ====", + wiphy_name(dev->mt76.hw->wiphy)); + } + +@@ -2710,6 +2736,9 @@ skip_coredump: + + void mt7996_reset(struct mt7996_dev *dev) + { ++ dev_info(dev->mt76.dev, "%s SER recovery state: 0x%08x\n", ++ wiphy_name(dev->mt76.hw->wiphy), READ_ONCE(dev->recovery.state)); ++ + if (!dev->recovery.hw_init_done) + return; + diff --git a/package/kernel/mt76/patches/smartrg-9531-wifi-mt76-mt7996-release-scan-lock-during-recovery.patch b/package/kernel/mt76/patches/smartrg-9531-wifi-mt76-mt7996-release-scan-lock-during-recovery.patch new file mode 100644 index 0000000000..cd92803a9d --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9531-wifi-mt76-mt7996-release-scan-lock-during-recovery.patch @@ -0,0 +1,50 @@ +From: Chad Monroe +Date: Tue, 27 Jan 2026 10:22:04 -0800 +Subject: [PATCH] wifi: mt76: mt7996: release scan lock during MCU recovery + +MCU reset during an active scan leaves mac80211's scan lock held +blocking all future scan requests. + +Also clear stale MCU reset bits when recovery returns to normal. + +Signed-off-by: Chad Monroe +--- + mt7996/mac.c | 14 +++++++++++++- + scan.c | 2 +- + 2 files changed, 14 insertions(+), 2 deletions(-) + +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -2510,8 +2510,20 @@ void mt7996_mac_reset_work(struct work_s + return; + } + +- if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) ++ if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA)) { ++ u32 state = READ_ONCE(dev->recovery.state); ++ ++ if (test_bit(MT76_MCU_RESET, &dev->mphy.state) && ++ (state & MT_MCU_CMD_NORMAL_STATE)) { ++ clear_bit(MT76_MCU_RESET, &dev->mphy.state); ++ mt7996_for_each_phy(dev, phy) ++ clear_bit(MT76_RESET, &phy->mt76->state); ++ dev_info(dev->mt76.dev, ++ "%s cleared stale MCU reset bit after recovery state normal (0x%08x)\n", ++ wiphy_name(dev->mt76.hw->wiphy), state); ++ } + return; ++ } + + dev_info(dev->mt76.dev,"==== %s L1 SER recovery start ====", + wiphy_name(hw->wiphy)); +--- a/scan.c ++++ b/scan.c +@@ -23,7 +23,7 @@ static void mt76_scan_complete(struct mt + } + mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink); + memset(&dev->scan, 0, sizeof(dev->scan)); +- if (!test_bit(MT76_MCU_RESET, &dev->phy.state)) ++ if (!test_bit(MT76_MCU_RESET, &dev->phy.state) || abort) + ieee80211_scan_completed(phy->hw, &info); + } + diff --git a/package/kernel/mt76/patches/smartrg-9532-wifi-mt76-mt7996-abort-scan-during-full-reset.patch b/package/kernel/mt76/patches/smartrg-9532-wifi-mt76-mt7996-abort-scan-during-full-reset.patch new file mode 100644 index 0000000000..8d56a4e3f4 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9532-wifi-mt76-mt7996-abort-scan-during-full-reset.patch @@ -0,0 +1,33 @@ +From: Chad Monroe +Date: Mon, 27 Jan 2026 16:45:00 -0800 +Subject: [PATCH] wifi: mt76: mt7996: abort scan/ROC before mutex in full reset + +Full reset acquires mutex before aborting scan, but scan_work needs +that mutex for mt76_set_channel(). Deadlock occurs when +ieee80211_restart_hw() waits for scan completion. + +Mirror L1 SER ordering: abort scan/ROC before mutex acquisition. + +Signed-off-by: Chad Monroe +--- + mt7996/mac.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -2426,8 +2426,14 @@ mt7996_mac_full_reset(struct mt7996_dev + ieee80211_stop_queues(hw); + + cancel_work_sync(&dev->wed_rro.work); +- mt7996_for_each_phy(dev, phy) ++ ++ set_bit(MT76_MCU_RESET, &dev->mphy.state); ++ mt76_abort_scan(&dev->mt76); ++ mt7996_for_each_phy(dev, phy) { ++ mt76_abort_roc(phy->mt76); ++ set_bit(MT76_RESET, &phy->mt76->state); + cancel_delayed_work_sync(&phy->mt76->mac_work); ++ } + cancel_delayed_work_sync(&dev->scs_work); + + mt76_abort_scan(&dev->mt76); diff --git a/package/kernel/mt76/patches/smartrg-9533-wifi-mt76-fix-stuck-queues-after-SER-with-no-active-interfaces.patch b/package/kernel/mt76/patches/smartrg-9533-wifi-mt76-fix-stuck-queues-after-SER-with-no-active-interfaces.patch new file mode 100644 index 0000000000..d91792e124 --- /dev/null +++ b/package/kernel/mt76/patches/smartrg-9533-wifi-mt76-fix-stuck-queues-after-SER-with-no-active-interfaces.patch @@ -0,0 +1,40 @@ +From: Chad Monroe +Date: Mon, 23 Mar 2026 15:57:14 -0700 +Subject: [PATCH] wifi: mt76: fix stuck TX queues after SER with no + active interfaces + +When a firmware watchdog triggers full SER recovery before any VAPs +are up, mac80211 skips drv_reconfig_complete() because open_count is +zero. This leaves the DRIVER queue stop reason set permanently, +blocking all TX when interfaces eventually start. + +Signed-off-by: Chad Monroe +--- + mt7915/mac.c | 4 ++++ + mt7996/mac.c | 2 ++ + 2 files changed, 6 insertions(+) + +--- a/mt7915/mac.c ++++ b/mt7915/mac.c +@@ -1422,6 +1422,10 @@ mt7915_mac_full_reset(struct mt7915_dev + + mutex_unlock(&dev->mt76.mutex); + ++ ieee80211_wake_queues(mt76_hw(dev)); ++ if (ext_phy) ++ ieee80211_wake_queues(ext_phy->hw); ++ + ieee80211_restart_hw(mt76_hw(dev)); + if (ext_phy) + ieee80211_restart_hw(ext_phy->hw); +--- a/mt7996/mac.c ++++ b/mt7996/mac.c +@@ -2478,6 +2478,8 @@ mt7996_mac_full_reset(struct mt7996_dev + + mutex_unlock(&dev->mt76.mutex); + ++ ieee80211_wake_queues(mt76_hw(dev)); ++ + ieee80211_restart_hw(mt76_hw(dev)); + } + diff --git a/package/kmod-amneziawg b/package/kmod-amneziawg new file mode 120000 index 0000000000..5df2d19726 --- /dev/null +++ b/package/kmod-amneziawg @@ -0,0 +1 @@ +../submodules/awg-openwrt/kmod-amneziawg \ No newline at end of file diff --git a/package/luci-proto-amneziawg b/package/luci-proto-amneziawg new file mode 120000 index 0000000000..24e7fcf451 --- /dev/null +++ b/package/luci-proto-amneziawg @@ -0,0 +1 @@ +../submodules/awg-openwrt/luci-proto-amneziawg \ No newline at end of file diff --git a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc index 7104357f39..1a6ecc3858 100644 --- a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc +++ b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc @@ -36,6 +36,9 @@ function set_fixed_freq(data, config) { if (wildcard(data.htmode, 'VHT*')) set_default(config, 'vht', 1); + + if (config.mode in [ 'sta', 'adhoc', 'mesh' ]) + set_default(config, 'noscan', true); } export function ratestr(rate) { @@ -169,9 +172,12 @@ function setup_sta(data, config) { } - if (config.wpa_pairwise == 'GCMP') { - config.pairwise = 'GCMP'; - config.group = 'GCMP'; + if (config.wpa_pairwise) { + config.pairwise = config.wpa_pairwise; + + if (wildcard(config.wpa_pairwise, '*GCMP*') || + wildcard(config.wpa_pairwise, '*CCMP-256*')) + config.group = config.wpa_pairwise; } config.key_mgmt ??= 'NONE'; diff --git a/package/network/config/wifi-scripts/files/lib/netifd/hostapd.sh b/package/network/config/wifi-scripts/files/lib/netifd/hostapd.sh index 2536a31539..d1c8be9d85 100644 --- a/package/network/config/wifi-scripts/files/lib/netifd/hostapd.sh +++ b/package/network/config/wifi-scripts/files/lib/netifd/hostapd.sh @@ -1609,9 +1609,14 @@ wpa_supplicant_add_network() { ;; esac - [ "$wpa_cipher" = GCMP ] && { - append network_data "pairwise=GCMP" "$N$T" - append network_data "group=GCMP" "$N$T" + [ -n "$wpa_cipher" ] && { + append network_data "pairwise=$wpa_cipher" "$N$T" + + case "$wpa_cipher" in + *GCMP*|*CCMP-256*) + append network_data "group=$wpa_cipher" "$N$T" + ;; + esac } [ "$mode" = mesh ] || { diff --git a/submodules/awg-openwrt b/submodules/awg-openwrt new file mode 160000 index 0000000000..d95099d6f4 --- /dev/null +++ b/submodules/awg-openwrt @@ -0,0 +1 @@ +Subproject commit d95099d6f4d8c4ec8eaea8d9896136b0c6bfa6cc diff --git a/tests/test_invariant_drv_mei_cpe.c b/tests/test_invariant_drv_mei_cpe.c new file mode 100644 index 0000000000..85ebc27460 --- /dev/null +++ b/tests/test_invariant_drv_mei_cpe.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +/* Test invariant: Buffer reads never exceed declared length. + * The CMVMSG buffer is 24 bytes; with offset 4, only 20 bytes are safe. + * Size parameter masked with 0xf allows up to 15, multiplied by 2 = 30 bytes. + * This test verifies that oversized inputs are either rejected or truncated. + */ + +START_TEST(test_cmvmsg_buffer_overflow_prevention) +{ + /* Payloads: exploit case (size=15 → 30 bytes), boundary (size=10 → 20 bytes safe), + * valid (size=5 → 10 bytes safe), and edge cases */ + struct { + uint32_t size; + const char *description; + } test_cases[] = { + {15, "exploit: max masked size (30 bytes into 20-byte space)"}, + {10, "boundary: 20 bytes (fills safe space exactly)"}, + {5, "valid: 10 bytes (well within bounds)"}, + {20, "overflow: size > 15 (should be masked or rejected)"}, + {0, "edge: zero size"} + }; + + int num_cases = sizeof(test_cases) / sizeof(test_cases[0]); + + for (int i = 0; i < num_cases; i++) { + uint32_t size = test_cases[i].size; + uint32_t masked_size = size & 0xf; /* Simulate the mask from vulnerable code */ + uint32_t bytes_to_copy = masked_size * 2; + + /* Invariant: bytes_to_copy must not exceed 20 (24 - 4 offset) */ + ck_assert_msg( + bytes_to_copy <= 20, + "Buffer overflow detected: size=%u, masked=%u, bytes=%u exceeds safe limit of 20. Case: %s", + size, masked_size, bytes_to_copy, test_cases[i].description + ); + } +} +END_TEST + +Suite *security_suite(void) +{ + Suite *s; + TCase *tc_core; + + s = suite_create("Security"); + tc_core = tcase_create("Core"); + + tcase_add_test(tc_core, test_cmvmsg_buffer_overflow_prevention); + suite_add_tcase(s, tc_core); + + return s; +} + +int main(void) +{ + int number_failed; + Suite *s; + SRunner *sr; + + s = security_suite(); + sr = srunner_create(s); + + srunner_run_all(sr, CK_NORMAL); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} \ No newline at end of file