From f80275632a4cb6b84e64fc0d991554ce1a80ff1f Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Wed, 20 May 2026 17:43:54 +0000 Subject: [PATCH 01/11] amneziawg: add AmneziaWG packages Signed-off-by: Rany Hany --- .gitmodules | 3 +++ package/amneziawg-tools | 1 + package/kmod-amneziawg | 1 + package/luci-proto-amneziawg | 1 + submodules/awg-openwrt | 1 + 5 files changed, 7 insertions(+) create mode 100644 .gitmodules create mode 120000 package/amneziawg-tools create mode 120000 package/kmod-amneziawg create mode 120000 package/luci-proto-amneziawg create mode 160000 submodules/awg-openwrt 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/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/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 From c02344d3034b325b6ed0c8e2332acf357fbda7b9 Mon Sep 17 00:00:00 2001 From: Omar Avelar Date: Sun, 29 Mar 2026 14:09:16 +0000 Subject: [PATCH 02/11] wifi-scripts: restore noscan handling for sta/adhoc/mesh The mac80211 shell implementation explicitly enabled noscan for station, adhoc and mesh interfaces when operating on a fixed frequency: for_each_interface "sta adhoc mesh" mac80211_set_noscan During the migration from the shell scripts to ucode, this logic was not carried over into supplicant.uc. As a result, wpa_supplicant would continue to perform scans even when fixed_freq is set, preventing reliable HT40/HE40 operation on 2.4 GHz and causing mesh links to fallback to 20 MHz. Restore the original behavior by setting noscan when fixed_freq is enabled for sta, adhoc and mesh modes. This matches the legacy mac80211.sh behavior and ensures correct channel width operation for fixed-frequency links. No functional change for non-fixed-frequency configurations. Signed-off-by: Omar Avelar Signed-off-by: Rany Hany --- .../files-ucode/usr/share/ucode/wifi/supplicant.uc | 3 +++ 1 file changed, 3 insertions(+) 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..3ec0adf0f8 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) { From ae969885eebb300b5f7ed167b650de83722971dc Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Sat, 20 Jun 2026 15:29:26 +0300 Subject: [PATCH 03/11] wifi-scripts: fix cipher pinning in client mode For anything other than plain GCMP, we were not setting pairwise/group to the configured cipher. Now we always pin pairwise to ${config.wpa_pairwise} and also do so for group cipher except in the CCMP case as the group cipher might be set to TKIP on the AP's end in the mixed-mode case. This makes CCMP-256 and GCMP-256 work for the supplicant in both WPA2 and WPA3, and also fixes the default WPA3 cipher on HE/EHT radios which previously fell back to CCMP only. Signed-off-by: Rany Hany --- .../files-ucode/usr/share/ucode/wifi/supplicant.uc | 9 ++++++--- .../config/wifi-scripts/files/lib/netifd/hostapd.sh | 11 ++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) 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 3ec0adf0f8..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 @@ -172,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 ] || { From eaf719ee957c6f419421339e2e8e9d7f49774589 Mon Sep 17 00:00:00 2001 From: Andrea Covelli <34921854+AndreaCovelli@users.noreply.github.com> Date: Sat, 2 May 2026 17:18:26 +0200 Subject: [PATCH 04/11] 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 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 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, and upload them to the driver once the station is associated. Keep the later AUTHORIZED transition as an extra retry point. This is proposed as an OpenWrt-local fix for now and keeps the behavioral change scoped to AP/AP_VLAN pairwise keys. Signed-off-by: AndreaCovelli Signed-off-by: Rany Hany --- ...mac80211-defer-ap-side-ft-key-upload.patch | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 package/kernel/mac80211/patches/subsys/390-mac80211-defer-ap-side-ft-key-upload.patch 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) From 0c0457af225cda2a9ae1f47725401bfbb04afe25 Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Tue, 2 Jun 2026 13:32:57 +0000 Subject: [PATCH 05/11] mt76: update to Git HEAD (2026-06-02) git log --no-merges --pretty=oneline --abbrev-commit 018f60316d4dd6b4e741874eda40e2dfaa29df3b..2ab649809db7d7c4220ce4229573fc72a48ecf4d 2ab64980 wifi: mt76: add wcid publish check in mt76_sta_add 02934c3d wifi: mt76: mt7996: remove redundant pdev->bus check in probe 1ba5cc4b wifi: mt76: mt7925: drop redundant chandef.chan NULL check in MT7927 path 934f6471 wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add() 1e7ac9bf Revert "wifi: mt76: mt7996: avoid memset overwriting tx_info->control.flags" f5f14a01 Revert "wifi: mt76: disable rx napi before queue cleanup" 652740d6 wifi: mt76: mt7996: Fix possible NULL pointer dereference in mt7996_mac_write_txwi_80211() d8fc8629 wifi: mt76: mt7996: Fix possible token leak in mt7996_tx_prepare_skb() 2802466a wifi: mt76: mt7915: validate skb length in txpower SKU query e588dc48 wifi: mt76: mt7925: validate skb length in testmode query 3e54e1c8 wifi: mt76: mt792x: skip MLD header rewrite for 802.3 encap TX f142a553 wifi: mt76: mt7925: program BA state on active links 6cdcb480 wifi: mt76: mt7925: pass WCID explicitly to mt7925_mcu_sta_ba() 4ed65179 wifi: mt76: mt7925: keep TX BA state in the primary WCID 62956aec wifi: mt76: mt7925: add MT7927 USB support 8a7d31ac wifi: mt76: mt7925: add MT7927 PCIe support 049633e3 wifi: mt76: mt792x: enable CNM ops for MT7927 b8e20dc9 wifi: mt76: mt7925: add MBMC event handling 3e55b659 wifi: mt76: mt7925: sync MT7927 BSS band assignment 79e061f3 wifi: mt76: mt792x: add MT7927-specific PCIe DMA support 903f8b3b wifi: mt76: mt7925: switch DMA init to common mt792x queue helpers b81028de wifi: mt76: mt792x: factor out common DMA queue allocation d045c72b wifi: mt76: mt792x: add MT7927 WFSYS reset support 3969bb11 wifi: mt76: connac: tolerate inactive BSS deactivation 9342a017 wifi: mt76: mt7925: use link-specific removal for non-MLD STA 1f91523c wifi: mt76: connac: replace is_mt7925() with is_connac3() f698c7f2 wifi: mt76: mt7925: disable ASPM and runtime PM for MT7927 8175695d wifi: mt76: mt7925: use irq_map for chip-specific interrupt handling 6e5802e9 wifi: mt76: mt7925: add MT7927 firmware paths fda04bb4 wifi: mt76: mt7925: add MT7927 chip ID helpers 70bfd49d wifi: mt76: mt7925: advertise EHT 320MHz capabilities for 6GHz band 06277d86 wifi: mt76: mt7925: populate EHT 320MHz MCS map in sta_rec b1f7e240 wifi: mt76: mt7925: handle 320MHz bandwidth in RXV and TXS 3c575281 wifi: mt76: mt7925: add 320MHz bandwidth to bss_rlm_tlv bd493e29 wifi: mt76: mt7925: fix stale pointer comparisons in change_vif_links 58331e62 wifi: mt76: mt7996: Fix NULL pointer dereference in mt7996_init_tx_queues() 756b1c67 wifi: mt76: mt7925: add Netgear A8500 USB device ID 5c94494f dma.h: add missing variable initialization 0aca66c1 wifi: mt76: mt792xu: drop redundant device reference 52071e88 wifi: mt76x2u: drop redundant device reference a4f3781d wifi: mt76x0u: drop redundant device reference 49a0aa65 wifi: mt76: drop redundant device reference 97fc0e78 wifi: mt76: mt7921: fix uninitialized variable warning fe0555fe wifi: mt76: use kfree_rcu for offchannel link in mt76_put_vif_phy_link 0753cf18 wifi: mt76: mt7925: don't disable AP BSS when removing TDLS peer 6ae6f2b5 wifi: mt76: route TDLS-peer frames as 3-addr non-DS in HW encap dd1459c0 wifi: mt76: mt7921/mt7925: fix NULL dereference in CSA beacon d463ed94 wifi: mt76: mt7921: fix resource leak in probe error path 381582f2 wifi: mt76: mt7996: avoid memset overwriting tx_info->control.flags 4ab8f212 wifi: mt76: disable rx napi before queue cleanup 34064bd5 wifi: mt76: mt7925: clean up DMA on probe failure b0af99f2 wifi: mt76: mt7996: handle UNI PS sync events 9e613fb0 wifi: mt76: mt7915: handle MCU PS sync events 9a46d8d2 wifi: mt76: add PS buffering support for HW-managed TIM drivers d2b01fbc mt76: pass LED define via ccflags-y 012e52ae wifi: mt76: use hrtimer_setup() in mt76x02u beacon init Signed-off-by: Rany Hany --- package/kernel/mt76/Makefile | 6 ++-- ...rtimer_setup-in-mt76x02u-beacon-init.patch | 33 ------------------- .../003-pass-LED-define-via-ccflags-y.patch | 26 --------------- 3 files changed, 3 insertions(+), 62 deletions(-) delete mode 100644 package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch delete mode 100644 package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index c2e3a199fc..7ba20ef7c4 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-02 +PKG_SOURCE_VERSION:=2ab649809db7d7c4220ce4229573fc72a48ecf4d +PKG_MIRROR_HASH:=b6e11b43752b1c1ae2ca5f8ebd5b6d061df47cb28298caee6f002d193c67f5cd 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 From a91773a881de81b323bec9e9140c66f60d4b0a62 Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Tue, 9 Jun 2026 17:13:02 +0000 Subject: [PATCH 06/11] mt76: update to Git HEAD (2026-06-09) git log --no-merges --pretty=oneline --abbrev-commit 2ab649809db7d7c4220ce4229573fc72a48ecf4d..72d8dc8574430210e782857c3f50ceddf355432c 72d8dc85 wifi: mt76: Drop unneeded mt76_register_debugfs_fops() return checks a3bf7dac wifi: mt76: mt7921: assert sniffer on chanctx change 9f60dd01 wifi: mt76: mt7996: fix potential tx_retries underflow e791fb66 wifi: mt76: mt7925: fix potential tx_retries underflow ee2bb333 wifi: mt76: mt7921: fix potential tx_retries underflow 748311fa wifi: mt76: mt7915: fix potential tx_retries underflow 4fb4a076 wifi: mt76: mt7921: disable auto regd changes after user set 06d1ccbe wifi: mt76: mt7921: add auto regdomain switch support cd3d2a68 wifi: mt76: mt7921: refactor regulatory notifier flow 1ec0abf5 wifi: mt76: mt7921: refactor CLC support check flow fc890d5b wifi: mt76: mt7921: refactor regulatory domain handling to regd.[ch] cd931f9e wifi: mt76: mt7996: disable UNI_BSS_INFO_PROTECT_INFO for mt7996 03644ac1 wifi: mt76: fix argument to ieee80211_is_first_frag() 91f19ba3 wifi: mt76: mt7921u: escalate broken USB transport to device reset 600dbf12 wifi: mt76: mt792x: add common USB transport reset helpers 994443de wifi: mt76: mt792x: report txpower for the requested vif link 1e05654e wifi: mt76: connac: factor out rate power limit calculation 761478b9 wifi: mt76: connac: use a helper to cache txpower_cur e640565e wifi: mt76: mt7996: limit work in set_bitrate_mask c0e41eb5 wifi: mt76: mt7996: reduce phy work in set_coverage 7825972b wifi: mt76: transform aspm_conf for pci_disable_link_state Signed-off-by: Rany Hany --- package/kernel/mt76/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 7ba20ef7c4..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-06-02 -PKG_SOURCE_VERSION:=2ab649809db7d7c4220ce4229573fc72a48ecf4d -PKG_MIRROR_HASH:=b6e11b43752b1c1ae2ca5f8ebd5b6d061df47cb28298caee6f002d193c67f5cd +PKG_SOURCE_DATE:=2026-06-09 +PKG_SOURCE_VERSION:=72d8dc8574430210e782857c3f50ceddf355432c +PKG_MIRROR_HASH:=36d263dc212c45de62d74dd2823834cd0c6734e3d6bb0242ff8e3ca26fa8be39 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 From 9e75134d8e67cfe1590504525d92135cefbd02aa Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Wed, 3 Jun 2026 15:51:39 +0000 Subject: [PATCH 07/11] mt76: pass LED define via ccflags-y for submodules This is needed for submodules as well. Signed-off-by: Rany Hany --- ...p-mt76-pass-LED-define-via-ccflags-y.patch | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 package/kernel/mt76/patches/005-fixup-mt76-pass-LED-define-via-ccflags-y.patch 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 + From 3654c59823eeefb947fc11aecd411c3af0aef94f Mon Sep 17 00:00:00 2001 From: David Bauer Date: Tue, 2 Dec 2025 01:25:42 +0100 Subject: [PATCH 08/11] mt76: 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 Signed-off-by: Rany Hany --- ...15-detect-and-purge-stuck-PLE-queues.patch | 299 ++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 package/kernel/mt76/patches/010-mt7915-detect-and-purge-stuck-PLE-queues.patch 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)) From ed6a8becf7693d1da03237f12a4056146b2070c1 Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Mon, 22 Jun 2026 14:11:13 +0000 Subject: [PATCH 09/11] mt76: add SmartRG patches (rev: b2fb3e619ed714602301be23686f1d94) Import patches from the SmartRG tree using the following command: for f in ~/projects/feed-wifi-master/mt76/patches/*; do cp $f smartrg-$(basename $f); done Dropped patches due to issues: - smartrg-1017-wifi-mt76-mt7915-fix-key-used-after-free-issue.patch (Causes 802.11s to stop working if both nodes have the same patch installed) Excluded patches (unwanted/unneeded): - smartrg-0006-mt76-pass-LED-define-via-ccflags-y.patch - smartrg-0012-mt76-mt7615-disable-160mhz.patch - smartrg-1032-wifi-mt76-mt7915-remove-BW160-support.patch Excluded patches (skipped to avoid refreshing): - smartrg-0018-wifi-mt76-mt7915-fix-tx-retry-and-failure-counting.patch - smartrg-1000-wifi-mt76-mt7915-add-mtk-internal-debug-tools-for-mt.patch - smartrg-1001-wifi-mt76-mt7915-csi-implement-csi-support.patch - smartrg-1002-wifi-mt76-mt7915-air-monitor-support.patch - smartrg-1012-wifi-mt76-testmode-add-ZWDFS-test-mode-support.patch - smartrg-1018-wifi-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable.patch - smartrg-1019-wifi-mt76-mt7915-implement-bin-file-mode.patch - smartrg-1024-wifi-mt76-mt7915-support-on-off-SW-ACI-through-debug.patch - smartrg-1028-wifi-mt76-mt7915-add-vendor-cmd-to-get-available-col.patch - smartrg-1036-wifi-mt76-mt7915-Disable-RegDB-when-enable-single-sk.patch - smartrg-1038-wifi-mt76-update-debugfs-knob-to-dump-token-pending-.patch - smartrg-1039-wifi-mt76-mt7915-support-enable-disable-spatial-reus.patch - smartrg-1045-wifi-mt76-mt7915-support-scs-feature.patch - smartrg-1046-wifi-mt76-mt7915-support-thermal-recal-debug-commnad.patch - smartrg-1047-wifi-mt76-mt7915-Add-support-for-lpi-and-duplicate-m.patch - smartrg-2000-wifi-mt76-mt7915-sync-lpi-support-with-mt7996.patch - smartrg-4000-0029-mtk-wifi-mt76-mt7996-rework-chainmask.patch - smartrg-4000-0030-mtk-wifi-mt76-mt7996-support-txpower-backoff-table.patch - smartrg-4000-0044-mtk-wifi-mt76-mt7996-rework-statistics-report-for-mt7996.patch - smartrg-4000-0063-mtk-wifi-mt76-mt7996-add-5th-chain-RX-RSSI-support.patch - smartrg-4000-0066-mtk-wifi-mt76-mt7996-update-agg-session-time-when-receivi.patch - smartrg-4000-1007-mtk-wifi-mt76-mt7996-add-txpower-debug-support.patch - smartrg-4000-1009-mtk-wifi-mt76-mt7996-add-binfile-mode-support.patch - smartrg-4000-1010-mtk-wifi-mt76-mt7996-add-normal-mode-pre-calibration.patch - smartrg-4000-1012-mtk-wifi-mt76-mt7996-add-mu-vendor-command-support.patch - smartrg-4000-1015-mtk-wifi-mt76-mt7996-add-vendor-cmd-to-get-available.patch - smartrg-4000-1019-mtk-wifi-mt76-mt7996-add-vendor-subcmd-EDCCA-ctrl-en.patch - smartrg-4000-1020-mtk-wifi-mt76-mt7996-add-support-spatial-reuse-debug.patch - smartrg-4000-1022-mtk-wifi-mt76-mt7996-add-eagle-iFEM-HWITS-ZWDFS-SW-w.patch - smartrg-4000-1036-mtk-wifi-mt76-testmode-add-channel-68-96.patch - smartrg-4000-1037-mtk-wifi-mt76-mt7996-support-enable-disable-pp-featu.patch - smartrg-4000-1038-mtk-wifi-mt76-testmode-add-kite-testmode-support.patch - smartrg-4000-1042-mtk-wifi-mt7996-add-Eagle-2adie-TBTC-BE14000-support.patch - smartrg-4000-1044-mtk-mt76-mt7996-Add-lpi-support-with-sku_idx-and-enh.patch - smartrg-4000-2138-mtk-wifi-mt76-mt7996-fix-MT7992-precal-layout-issue.patch - smartrg-9501-wifi-mt76-mt7915-fix-single-sku-power-limits.patch - smartrg-9501-wifi-mt76-mt7996-fix-single-sku-power-limits.patch - smartrg-9503-wifi-mt76-mt7996-remove-channel-68-96.patch - smartrg-9505-wifi-mt76-mt7996-make-precal-mcu-command-synchronous.patch - smartrg-9507-wifi-mt76-mt7996-fix-BE14000-6G-precal-size.patch - smartrg-9508-wifi-mt76-mt7996-skip-precal-unless-needed.patch - smartrg-9509-wifi-mt76-mt7996-add-mcu-set-tx-power-ctrl.patch - smartrg-9510-wifi-mt76-mt7915-get-airtime-from-mcu.patch - smartrg-9511-wifi-mt76-mt7915-guard-airtime-counters-against-overflow.patch - smartrg-9512-wifi-mt76-mt7996-guard-airtime-counters-against-overflow.patch - smartrg-9516-wifi-mt76-mt7996-add-device-tree-EDCCA-threshold-configuration.patch - smartrg-9518-wifi-mt76-mt7996-fix-tx-retry-and-failure-counting.patch Signed-off-by: Rany Hany --- .../smartrg-0001-mt76-add-dfs-debugs.patch | 56 + ...default-rate-if-rate-info-is-missing.patch | 36 + ...rg-0003-mt76-eeprom-add-nvmem-debugs.patch | 11 + ...-reset-channel-state-during-scanning.patch | 37 + ...ant-survey-update-in-mt76_get_survey.patch | 23 + ...-efuse-data-and-cache-to-otp-for-sys.patch | 67 + ...make-pre-cal-mcu-command-synchronous.patch | 21 + ...t7915-fix-use-after-free-in-sta-poll.patch | 34 + ...0014-mt76-mt7915-print-hwrev-at-boot.patch | 11 + ...0015-mt76-mt7915-rdd-antenna-support.patch | 98 + ...d-debugging-for-MCU-command-timeouts.patch | 62 + ...15-enable-PPDU-TXS-for-tx-statistics.patch | 197 + ...mgmt-frames-for-inactive-sta-to-altx.patch | 48 + ...mt76-mt7996-add-per-band-token-limit.patch | 290 + ...t7996-add-debugsfs-to-dump-tx-tokens.patch | 95 + ...i-mt76-fix-incorrect-HE-TX-GI-report.patch | 489 ++ ...-add-pc-stack-dump-for-WM-s-coredump.patch | 626 ++ ...-move-temperature-margin-check-to-mt.patch | 49 + ...-wifi-mt76-mt7915-fix-txpower-issues.patch | 103 + ...-add-post-channel-switch-for-DFS-cha.patch | 49 + ...-remove-redundant-argument-in-add_be.patch | 71 + ...17-wifi-mt76-mt7915-adjust-rx-filter.patch | 53 + ...mt76-mt7915-update-power-on-sequence.patch | 134 + ...tmode-rework-testmode-init-registers.patch | 455 ++ ...76-mt7915-refine-twt-mcu-update-flow.patch | 85 + ...7915-add-cal-free-data-merge-support.patch | 260 + ...6-mt7915-add-debugfs-for-fw-coredump.patch | 162 + ...mt7915-add-txpower-info-dump-support.patch | 138 + ...mt76-mt7915-Establish-BA-in-VO-queue.patch | 20 + ...76-mt7915-add-debug-log-for-SER-flow.patch | 42 + ...-add-additional-chain-signal-info-to.patch | 22 + ...15-add-mt7981-efuse-variants-support.patch | 71 + ...-remove-unnecessary-register-setting.patch | 136 + ...-set-channel-after-sta-is-associated.patch | 61 + ...tk-wifi-mt76-mt7996-enable-ser-query.patch | 24 + ...7996-add-preamble-puncture-support-f.patch | 111 + ...7996-add-sanity-check-for-NAPI-sched.patch | 33 + ...6-flush-stale-per-station-PLE-tokens.patch | 218 + ...-trigger-channel-calibration-for-DFS.patch | 86 + ...refactor-mcu-commands-flow-for-stati.patch | 71 + ...-mtk-wifi-mt76-mt7996-add-debug-tool.patch | 5116 +++++++++++++++++ ...7996-add-check-for-hostapd-config-he.patch | 40 + ...stmode-add-testmode-pre-calibration-.patch | 261 + ...7996-enable-SCS-feature-for-mt7996-d.patch | 304 + ...7996-add-support-for-runtime-set-in-.patch | 39 + ...mt76-mt7996-Establish-BA-in-VO-queue.patch | 20 + ...mt7915-fix-ch144-dpd-frequency-index.patch | 12 + ...mt7915-ignore-duplicate-radar-events.patch | 86 + ...mt7996-ignore-duplicate-radar-events.patch | 77 + ...-mt76-mt7996-fix-station-stats-crash.patch | 18 + ...-chain-3-RSSI-in-mt7915_mac_sta_poll.patch | 40 + ...g-9514-wifi-mt76-mt7915-fix-recovery.patch | 25 + ...15-wifi-mt76-mt7915-disable-coredump.patch | 11 + ...fi-mt76-add-dma_rx_process-len-check.patch | 25 + ...-trigger-L1-SER-on-PLE-MDP-RIOC-hang.patch | 67 + ...t76-mt7915-increase-txq-memory-limit.patch | 26 + ...UNI_BSS_INFO_PROTECT_INFO-for-mt7996.patch | 30 + ...76-mt7996-add-debug-log-for-SER-flow.patch | 92 + ...96-release-scan-lock-during-recovery.patch | 50 + ...-mt7996-abort-scan-during-full-reset.patch | 33 + ...-after-SER-with-no-active-interfaces.patch | 40 + 61 files changed, 11067 insertions(+) create mode 100644 package/kernel/mt76/patches/smartrg-0001-mt76-add-dfs-debugs.patch create mode 100644 package/kernel/mt76/patches/smartrg-0002-mt76-set-sane-default-rate-if-rate-info-is-missing.patch create mode 100644 package/kernel/mt76/patches/smartrg-0003-mt76-eeprom-add-nvmem-debugs.patch create mode 100644 package/kernel/mt76/patches/smartrg-0004-mt76-reset-channel-state-during-scanning.patch create mode 100644 package/kernel/mt76/patches/smartrg-0005-mt76-remove-redundant-survey-update-in-mt76_get_survey.patch create mode 100644 package/kernel/mt76/patches/smartrg-0010-mt76-mt7915-read-efuse-data-and-cache-to-otp-for-sys.patch create mode 100644 package/kernel/mt76/patches/smartrg-0011-mt76-mt7915-make-pre-cal-mcu-command-synchronous.patch create mode 100644 package/kernel/mt76/patches/smartrg-0013-mt76-mt7915-fix-use-after-free-in-sta-poll.patch create mode 100644 package/kernel/mt76/patches/smartrg-0014-mt76-mt7915-print-hwrev-at-boot.patch create mode 100644 package/kernel/mt76/patches/smartrg-0015-mt76-mt7915-rdd-antenna-support.patch create mode 100644 package/kernel/mt76/patches/smartrg-0016-mt76-mt7915-add-debugging-for-MCU-command-timeouts.patch create mode 100644 package/kernel/mt76/patches/smartrg-0017-wifi-mt76-mt7915-enable-PPDU-TXS-for-tx-statistics.patch create mode 100644 package/kernel/mt76/patches/smartrg-0020-wifi-mt76-route-mgmt-frames-for-inactive-sta-to-altx.patch create mode 100644 package/kernel/mt76/patches/smartrg-0120-wifi-mt76-mt7996-add-per-band-token-limit.patch create mode 100644 package/kernel/mt76/patches/smartrg-0121-wifi-mt76-mt7996-add-debugsfs-to-dump-tx-tokens.patch create mode 100644 package/kernel/mt76/patches/smartrg-0901-wifi-mt76-fix-incorrect-HE-TX-GI-report.patch create mode 100644 package/kernel/mt76/patches/smartrg-0902-wifi-mt76-mt7915-add-pc-stack-dump-for-WM-s-coredump.patch create mode 100644 package/kernel/mt76/patches/smartrg-0903-wifi-mt76-mt7915-move-temperature-margin-check-to-mt.patch create mode 100644 package/kernel/mt76/patches/smartrg-0904-wifi-mt76-mt7915-fix-txpower-issues.patch create mode 100644 package/kernel/mt76/patches/smartrg-0907-wifi-mt76-mt7915-add-post-channel-switch-for-DFS-cha.patch create mode 100644 package/kernel/mt76/patches/smartrg-0909-wifi-mt76-mt7915-remove-redundant-argument-in-add_be.patch create mode 100644 package/kernel/mt76/patches/smartrg-0917-wifi-mt76-mt7915-adjust-rx-filter.patch create mode 100644 package/kernel/mt76/patches/smartrg-0918-wifi-mt76-mt7915-update-power-on-sequence.patch create mode 100644 package/kernel/mt76/patches/smartrg-1008-wifi-mt76-testmode-rework-testmode-init-registers.patch create mode 100644 package/kernel/mt76/patches/smartrg-1016-wifi-mt76-mt7915-refine-twt-mcu-update-flow.patch create mode 100644 package/kernel/mt76/patches/smartrg-1023-wifi-mt76-mt7915-add-cal-free-data-merge-support.patch create mode 100644 package/kernel/mt76/patches/smartrg-1031-wifi-mt76-mt7915-add-debugfs-for-fw-coredump.patch create mode 100644 package/kernel/mt76/patches/smartrg-1033-wifi-mt76-mt7915-add-txpower-info-dump-support.patch create mode 100644 package/kernel/mt76/patches/smartrg-1035-wifi-mt76-mt7915-Establish-BA-in-VO-queue.patch create mode 100644 package/kernel/mt76/patches/smartrg-1040-wifi-mt76-mt7915-add-debug-log-for-SER-flow.patch create mode 100644 package/kernel/mt76/patches/smartrg-1041-wifi-mt76-mt7915-add-additional-chain-signal-info-to.patch create mode 100644 package/kernel/mt76/patches/smartrg-1044-wifi-mt76-mt7915-add-mt7981-efuse-variants-support.patch create mode 100644 package/kernel/mt76/patches/smartrg-1052-wifi-mt76-mt7915-remove-unnecessary-register-setting.patch create mode 100644 package/kernel/mt76/patches/smartrg-1054-wifi-mt76-mt7915-set-channel-after-sta-is-associated.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-0008-mtk-wifi-mt76-mt7996-enable-ser-query.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-0016-mtk-wifi-mt76-mt7996-add-preamble-puncture-support-f.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-0017-mtk-wifi-mt76-mt7996-add-sanity-check-for-NAPI-sched.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-0045-mtk-wifi-mt76-mt7996-flush-stale-per-station-PLE-tokens.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-0056-mtk-wifi-mt76-mt7996-trigger-channel-calibration-for-DFS.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-0102-mtk-wifi-mt76-mt7996-refactor-mcu-commands-flow-for-stati.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-1000-mtk-wifi-mt76-mt7996-add-debug-tool.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-1002-mtk-wifi-mt76-mt7996-add-check-for-hostapd-config-he.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-1005-mtk-wifi-mt76-testmode-add-testmode-pre-calibration-.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-1006-mtk-wifi-mt76-mt7996-enable-SCS-feature-for-mt7996-d.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-1018-mtk-wifi-mt76-mt7996-add-support-for-runtime-set-in-.patch create mode 100644 package/kernel/mt76/patches/smartrg-4000-1021-mtk-wifi-mt76-mt7996-Establish-BA-in-VO-queue.patch create mode 100644 package/kernel/mt76/patches/smartrg-9500-wifi-mt76-mt7915-fix-ch144-dpd-frequency-index.patch create mode 100644 package/kernel/mt76/patches/smartrg-9504-wifi-mt76-mt7915-ignore-duplicate-radar-events.patch create mode 100644 package/kernel/mt76/patches/smartrg-9504-wifi-mt76-mt7996-ignore-duplicate-radar-events.patch create mode 100644 package/kernel/mt76/patches/smartrg-9506-wifi-mt76-mt7996-fix-station-stats-crash.patch create mode 100644 package/kernel/mt76/patches/smartrg-9513-mt76-mt7915-fix-GENMASK-for-chain-3-RSSI-in-mt7915_mac_sta_poll.patch create mode 100644 package/kernel/mt76/patches/smartrg-9514-wifi-mt76-mt7915-fix-recovery.patch create mode 100644 package/kernel/mt76/patches/smartrg-9515-wifi-mt76-mt7915-disable-coredump.patch create mode 100644 package/kernel/mt76/patches/smartrg-9517-wifi-mt76-add-dma_rx_process-len-check.patch create mode 100644 package/kernel/mt76/patches/smartrg-9519-wifi-mt76-mt7915-trigger-L1-SER-on-PLE-MDP-RIOC-hang.patch create mode 100644 package/kernel/mt76/patches/smartrg-9520-wifi-mt76-mt7915-increase-txq-memory-limit.patch create mode 100644 package/kernel/mt76/patches/smartrg-9521-wifi-mt76-mt7996-disable-UNI_BSS_INFO_PROTECT_INFO-for-mt7996.patch create mode 100644 package/kernel/mt76/patches/smartrg-9530-wifi-mt76-mt7996-add-debug-log-for-SER-flow.patch create mode 100644 package/kernel/mt76/patches/smartrg-9531-wifi-mt76-mt7996-release-scan-lock-during-recovery.patch create mode 100644 package/kernel/mt76/patches/smartrg-9532-wifi-mt76-mt7996-abort-scan-during-full-reset.patch create mode 100644 package/kernel/mt76/patches/smartrg-9533-wifi-mt76-fix-stuck-queues-after-SER-with-no-active-interfaces.patch 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)); + } + From 409ad5bee3657850460e81a4aba8bb4bb01276bb Mon Sep 17 00:00:00 2001 From: orbisai0security Date: Mon, 22 Jun 2026 20:51:31 +0000 Subject: [PATCH 10/11] fix: V-004 security vulnerability Automated security fix generated by OrbisAI Security --- package/kernel/lantiq/ltq-adsl-mei/src/drv_mei_cpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; } From 70a99bf6b040cca259213c4514fc1264b5fb9f52 Mon Sep 17 00:00:00 2001 From: orbisai0security Date: Mon, 22 Jun 2026 20:52:11 +0000 Subject: [PATCH 11/11] fix: add buffer-length check in drv_mei_cpe.c The Lantiq ADSL MEI kernel driver copies user data into a fixed-size CMVMSG buffer using memcpy() without adequate bounds checking --- tests/test_invariant_drv_mei_cpe.c | 72 ++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/test_invariant_drv_mei_cpe.c 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