summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authordragonn2021-09-18 10:01:44 +0200
committerdragonn2021-09-18 10:01:44 +0200
commit825d71ed713c470164cb24131dd6af6fcb19664e (patch)
tree2422ae50eb0bf5fec3e80d533425293bf1a57730
parent8f5e12722e0aa4ead0854037a38ff6dbb1981a6b (diff)
downloadaur-825d71ed713c470164cb24131dd6af6fcb19664e.tar.gz
5.14.5
-rw-r--r--.SRCINFO62
-rw-r--r--.gitignore5
-rw-r--r--PKGBUILD53
-rw-r--r--config1
-rw-r--r--sys-kernel_arch-sources-g14_files-0006-fix-tigerlake-pin-mapping.patch54
-rw-r--r--sys-kernel_arch-sources-g14_files-0034-btusb-mediatek.patch145
-rw-r--r--sys-kernel_arch-sources-g14_files-0035-backport-from-5.14-s0ix-enablement-no-d3hot-2021-06-30.patch1308
-rw-r--r--sys-kernel_arch-sources-g14_files-0036-PCI-quirks-Quirk-PCI-d3hot-delay-for-AMD-xhci.patch30
-rw-r--r--sys-kernel_arch-sources-g14_files-0037-ACPI-PM-Only-mark-EC-GPE-for-wakeup-on-Intel-systems.patch171
-rw-r--r--sys-kernel_arch-sources-g14_files-0037-platform-x86-amd-pmc-Use-return-code-on-suspend.patch135
-rw-r--r--sys-kernel_arch-sources-g14_files-0040-asus-wmi-Add-dgpu-disable-method.patch182
-rw-r--r--sys-kernel_arch-sources-g14_files-0041-asus-wmi-Add-egpu-enable-method.patch169
-rw-r--r--sys-kernel_arch-sources-g14_files-0042-HID-asus-Remove-check-for-same-LED-brightness-on-set.patch30
-rw-r--r--sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch840
-rw-r--r--sys-kernel_arch-sources-g14_files-8001-x86-amd_nb-Add-AMD-family-19h-model-50h-PCI-ids.patch59
-rw-r--r--sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Add-support-for-Lite-On-Mediatek-Chi.patch74
-rw-r--r--sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Enable-MSFT-extension-for-Mediatek-Chip-MT7921.patch34
-rw-r--r--sys-kernel_arch-sources-g14_files-8011-mt76-mt7921-fix-stupid-mediatek-wth-a-hammer.patch6575
-rw-r--r--sys-kernel_arch-sources-g14_files-8012-mt76-mt7915-send-EAPOL-frames-at-lowest-rate.patch31
-rw-r--r--sys-kernel_arch-sources-g14_files-8012-mt76-mt7921-continue-to-probe-driver-when-fw-already.patch41
-rw-r--r--sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-robustify-hardware-initialization-flow.patch125
-rw-r--r--sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-fix-retrying-release-semaphore-without-end.patch38
-rw-r--r--sys-kernel_arch-sources-g14_files-8015-mt76-mt7921-send-EAPOL-frames-at-lowest-rate.patch31
-rw-r--r--sys-kernel_arch-sources-g14_files-8016-mt76-mt7921-Add-mt7922-support.patch (renamed from sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-Add-mt7922-support.patch)0
-rw-r--r--sys-kernel_arch-sources-g14_files-8017-mt76-mt7921-enable-VO-tx-aggregation.patch40
-rw-r--r--sys-kernel_arch-sources-g14_files-8018-mt76-mt7921-fix-dma-hang-in-rmmod.patch55
-rw-r--r--sys-kernel_arch-sources-g14_files-8019-mt76-mt7921-fix-firmware-usage-of-RA-info-using-legacy-rates.patch72
-rw-r--r--sys-kernel_arch-sources-g14_files-8020-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch (renamed from sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch)0
-rw-r--r--sys-kernel_arch-sources-g14_files-8021-mt76-mt7921-fix-the-inconsistent-state-between-bind-and-unbind.patch46
-rw-r--r--sys-kernel_arch-sources-g14_files-8022-mt76-mt7921-report-HE-MU-radiotap.patch187
-rw-r--r--sys-kernel_arch-sources-g14_files-8023-v2-mt76-mt7921-fix-kernel-warning-from-cfg80211_calculate_bitrate.patch99
-rw-r--r--sys-kernel_arch-sources-g14_files-9001-v5.13.13-s0ix-patch-2021-08-28.patch1081
-rw-r--r--sys-kernel_arch-sources-g14_files-9001-v5.13.14-s0ix-patch-2021-09-03.patch1293
-rw-r--r--sys-kernel_arch-sources-g14_files-9001-v5.14.1-s0ix-patch-2021-09-03.patch766
-rw-r--r--sys-kernel_arch-sources-g14_files-9001-v5.14.4-s0ix-patch-2021-09-15.patch342
-rw-r--r--sys-kernel_arch-sources-g14_files-9002-amd-pmc-delay-test.patch44
-rw-r--r--sys-kernel_arch-sources-g14_files-9002-amd-pmc-smu-register-dump-for-diagnostics.patch26
-rw-r--r--sys-kernel_arch-sources-g14_files-9003-ACPI-PM-s2idle-Invert-Microsoft-UUID-entry-and-exit.patch48
-rw-r--r--sys-kernel_arch-sources-g14_files-9007-s2idle-call-multiple-methods-test.patch128
-rw-r--r--sys-kernel_arch-sources-g14_files-9009-amd-pstate-sqashed.patch2880
-rw-r--r--sys-kernel_arch-sources-g14_files-9010-amd-apci-allow-c3.patch34
41 files changed, 2959 insertions, 14375 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 8b8364aa0b91..7f17cbc77e22 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = linux-g14
pkgdesc = Linux
- pkgver = 5.13.13.arch1
+ pkgver = 5.14.5.arch1
pkgrel = 1
url = https://lab.retarded.farm/zappel/asus-rog-zephyrus-g14/
arch = x86_64
@@ -16,58 +16,76 @@ pkgbase = linux-g14
makedepends = git
makedepends = gcc>=11.0
options = !strip
- source = archlinux-linux::git+https://github.com/archlinux/linux?signed#tag=v5.13.13-arch1
+ source = archlinux-linux::git+https://github.com/archlinux/linux?signed#tag=v5.14.5-arch1
source = config
source = choose-gcc-optimization.sh
source = sys-kernel_arch-sources-g14_files-0004-5.8+--more-uarches-for-kernel.patch::https://raw.githubusercontent.com/graysky2/kernel_compiler_patch/a8d200f422f4b2abeaa6cfcfa37136b308e6e33e/more-uarches-for-kernel-5.8%2B.patch
source = sys-kernel_arch-sources-g14_files-0005-lru-multi-generational.patch
source = https://gitlab.com/asus-linux/fedora-kernel/-/archive/e087e6d70c49c685b4d7cc7364496ade3aed3609/fedora-kernel-e087e6d70c49c685b4d7cc7364496ade3aed3609.zip
- source = sys-kernel_arch-sources-g14_files-0034-btusb-mediatek.patch
source = sys-kernel_arch-sources-g14_files-0039-asus-wmi-Add-panel-overdrive-functionality.patch
- source = sys-kernel_arch-sources-g14_files-0042-HID-asus-Remove-check-for-same-LED-brightness-on-set.patch
source = sys-kernel_arch-sources-g14_files-0043-ALSA-hda-realtek-Fix-speakers-not-working-on-Asus-Fl.patch
source = sys-kernel_arch-sources-g14_files-0044-claymore.patch
source = sys-kernel_arch-sources-g14_files-0045-v5-asus-wmi-Add-support-for-platform_profile.patch
source = sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch
- source = sys-kernel_arch-sources-g14_files-8001-x86-amd_nb-Add-AMD-family-19h-model-50h-PCI-ids.patch
source = sys-kernel_arch-sources-g14_files-8002-hwmon-k10temp-support-Zen3-APUs.patch
- source = sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Add-support-for-Lite-On-Mediatek-Chi.patch
- source = sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch
- source = sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-Add-mt7922-support.patch
- source = sys-kernel_arch-sources-g14_files-9001-v5.13.13-s0ix-patch-2021-08-28.patch
- source = sys-kernel_arch-sources-g14_files-9002-amd-pmc-delay-test.patch
- source = sys-kernel_arch-sources-g14_files-9002-amd-pmc-smu-register-dump-for-diagnostics.patch
+ source = sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Enable-MSFT-extension-for-Mediatek-Chip-MT7921.patch
+ source = sys-kernel_arch-sources-g14_files-8012-mt76-mt7915-send-EAPOL-frames-at-lowest-rate.patch
+ source = sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-robustify-hardware-initialization-flow.patch
+ source = sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-fix-retrying-release-semaphore-without-end.patch
+ source = sys-kernel_arch-sources-g14_files-8015-mt76-mt7921-send-EAPOL-frames-at-lowest-rate.patch
+ source = sys-kernel_arch-sources-g14_files-8016-mt76-mt7921-Add-mt7922-support.patch
+ source = sys-kernel_arch-sources-g14_files-8017-mt76-mt7921-enable-VO-tx-aggregation.patch
+ source = sys-kernel_arch-sources-g14_files-8018-mt76-mt7921-fix-dma-hang-in-rmmod.patch
+ source = sys-kernel_arch-sources-g14_files-8019-mt76-mt7921-fix-firmware-usage-of-RA-info-using-legacy-rates.patch
+ source = sys-kernel_arch-sources-g14_files-8020-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch
+ source = sys-kernel_arch-sources-g14_files-8021-mt76-mt7921-fix-the-inconsistent-state-between-bind-and-unbind.patch
+ source = sys-kernel_arch-sources-g14_files-8022-mt76-mt7921-report-HE-MU-radiotap.patch
+ source = sys-kernel_arch-sources-g14_files-8023-v2-mt76-mt7921-fix-kernel-warning-from-cfg80211_calculate_bitrate.patch
+ source = sys-kernel_arch-sources-g14_files-9001-v5.14.4-s0ix-patch-2021-09-15.patch
source = sys-kernel_arch-sources-g14_files-9004-HID-asus-Reduce-object-size-by-consolidating-calls.patch
source = sys-kernel_arch-sources-g14_files-9005-acpi-battery-Always-read-fresh-battery-state-on-update.patch
source = sys-kernel_arch-sources-g14_files-9006-amd-c3-entry.patch
+ source = sys-kernel_arch-sources-g14_files-9007-squashed-net-tcp_bbr-bbr2-for-5.14.y.patch
+ source = sys-kernel_arch-sources-g14_files-9008-fix-cpu-hotplug.patch
+ source = sys-kernel_arch-sources-g14_files-9009-amd-pstate-sqashed.patch
+ source = sys-kernel_arch-sources-g14_files-9010-amd-apci-allow-c3.patch
validpgpkeys = ABAF11C65A2970B130ABE3C479BE3E4300411886
validpgpkeys = 647F28654894E3BD457199BE38DBBDC86092693E
validpgpkeys = A2FF3A36AAA56654109064AB19802F8B0D70FC30
validpgpkeys = C7E7849466FE2358343588377258734B41C31549
sha256sums = SKIP
- sha256sums = 761427cf8dbeed10fd3149023bc83d0a2319e70a5cbfdcdda50e7a49e8d2b198
+ sha256sums = aa50b2ec33ce304f9b99ce80555a17ea18b1005dae147a560587acbdae00546f
sha256sums = 1ac18cad2578df4a70f9346f7c6fccbb62f042a0ee0594817fdef9f2704904ee
sha256sums = fa6cee9527d8e963d3398085d1862edc509a52e4540baec463edb8a9dd95bee0
- sha256sums = 9327ac3edacbc60a023928147f9439789527fad62cef66945f35a9165108e30d
+ sha256sums = 69ecf5456468935958f2cbf35691c2533a56344005537902b6051b6323ffff1f
sha256sums = 6806c034b7480245a0b9eec448bd79042ff5ff3f9f5efbf2af78227bc56004a8
- sha256sums = 0c515951db1c3dfc847e9b4777249c09be520ac140feb015a39c29e0531a89e6
sha256sums = 1ab75535772c63567384eb2ac74753e4d5db2f3317cb265aedf6151b9f18c6c2
- sha256sums = 96bf4c0fb920a876d7ec1ed25123bab8a0a43db5f363823e83e14707083d8501
sha256sums = 32bbcde83406810f41c9ed61206a7596eb43707a912ec9d870fd94f160d247c1
sha256sums = e2d312ea95d18e91801d131a2b5d03cf2175d3088cac6f84a19410078a5b6b14
sha256sums = 4ef12029ea73ca924b6397e1de4911e84d9e77ddaccdab1ef579823d848524e8
- sha256sums = 6fe5fe83e06d552f541bdca55d0d9e2cd6e70dd3047c01da749a0ff57fe706cc
- sha256sums = ed28a8051514f8c228717a5cdd13191b1c58181e0228d972fbe2af5ee1d013d7
+ sha256sums = 9d799be6d01a7438ca9999a10137be8fd95348610545c135c6dc9ce2b5afbe29
sha256sums = de8c9747637768c4356c06aa65c3f157c526aa420f21fdd5edd0ed06f720a62e
- sha256sums = 67ebf477b2ecbf367ea3fee1568eeb3de59de7185ef5ed66b81ae73108f6693c
- sha256sums = 2163cb2e394a013042a40cd3b00dae788603284b20d71e262995366c5534e480
+ sha256sums = 9f6b8c3ea6e1c285e0a7efda4d743dbae343bc6ee7ad599a4ab7d380c750bc83
+ sha256sums = 4bfbff4eba07fc9de2ce78097a4a269509468ba0e24c15a82905cd94e093ad55
+ sha256sums = c368cc4eefff20b7ae904eec686b7e72b46ff02b32c8a4fbd6bd4039f087e7ba
+ sha256sums = 1a8639167a1ee1b66f580c0c6f8304e6ef359a68cfa3eb869d9200a9f0234098
+ sha256sums = 021f8539ab2fb722b46937b95fdab22a2308236a24ecc1a9ea8db4853721dd39
sha256sums = a01cf700d79b983807e2285be1b30df6e02db6adfd9c9027fe2dfa8ca5a74bc9
- sha256sums = 41d7a48f113b3924595d327ea3031d1b14c611835e111c46438b9d85219cd76c
- sha256sums = d8dd84c26a44af618c6d1b68723e3bf0f8f50165af04fe090256afb0f931713e
- sha256sums = 6e629d4a032165f39202a702ad518a050c9305f911595a43bc34ce0c1d45d36b
+ sha256sums = 1ce9fd988201c4d2e48794c58acda5b768ec0fea1d29555e99d35cd2712281e4
+ sha256sums = e7e37c7c433c58e2f5a79e2a7724823bef1dccaa01e857584397b4e3c837d991
+ sha256sums = f075ac354acfd65dff4db49dc9798747cb9b7a3dd9839987bc46495bdbbd22dc
+ sha256sums = 2163cb2e394a013042a40cd3b00dae788603284b20d71e262995366c5534e480
+ sha256sums = 1770fec49335bc93194e9e55ced49e1cb67f2df4bf6948e80712a0b2ba50fa49
+ sha256sums = 6da4010f86a74125969fd3dbc953da7b45209d33ff3d216474c3399e82e893ff
+ sha256sums = eb391b6d1ebf7ef99ece00b23609b94180a1f3c0149bcf05f6bbeb74d0b724c7
+ sha256sums = 041214e202be4a6e90f00724e87ed787b39db148b24efd5fb03fcf23577601c1
sha256sums = 544464bf0807b324120767d55867f03014a9fda4e1804768ca341be902d7ade4
sha256sums = f7a4bf6293912bfc4a20743e58a5a266be8c4dbe3c1862d196d3a3b45f2f7c90
sha256sums = ee8794a551e33226900654d5c806183bf3b9b2e06f64fdc322987215d233d399
+ sha256sums = 2d854fc70297bb52bbc27dbf35ca019800530e40565be9740704d7f81bc4c763
+ sha256sums = 1cec0be41732a23c709e66d4a67e71bc5a75c77a3e4b73faafb5d7bfd3fafc0f
+ sha256sums = e62cbe1cb1577b1d80095fbb566d0516592e6174e7740e61a340164aff9bf2ec
+ sha256sums = bcb5966742921cdc772f163f6cbf0998e22cb1527d5a82b7b71eab4d605243dd
pkgname = linux-g14
pkgdesc = The Linux kernel and modules
diff --git a/.gitignore b/.gitignore
index 30c1b03f4b98..c8af6bbfe8e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,7 @@ archlinux-linux
xanmod-rog-PKGBUILD
linux
test
-fedora-kernel-*.zip \ No newline at end of file
+fedora-kernel-*.zip
+old
+old-mediatek
+new-mediatek \ No newline at end of file
diff --git a/PKGBUILD b/PKGBUILD
index b63e3d743d2e..64906cb082b0 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,7 +1,7 @@
# Maintainer: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
pkgbase=linux-g14
-pkgver=5.14.2.arch1
+pkgver=5.14.5.arch1
pkgrel=1
pkgdesc='Linux'
_srctag=v${pkgver%.*}-${pkgver##*.}
@@ -47,14 +47,23 @@ source=(
# mediatek mt7921 bt/wifi patches
- "sys-kernel_arch-sources-g14_files-8011-mt76-mt7921-fix-stupid-mediatek-wth-a-hammer.patch"
- #"sys-kernel_arch-sources-g14_files-8012-mt76-mt7921-continue-to-probe-driver-when-fw-already.patch"
- "sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch"
- "sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-Add-mt7922-support.patch"
+ "sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Enable-MSFT-extension-for-Mediatek-Chip-MT7921.patch"
+ "sys-kernel_arch-sources-g14_files-8012-mt76-mt7915-send-EAPOL-frames-at-lowest-rate.patch"
+ "sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-robustify-hardware-initialization-flow.patch"
+ "sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-fix-retrying-release-semaphore-without-end.patch"
+ "sys-kernel_arch-sources-g14_files-8015-mt76-mt7921-send-EAPOL-frames-at-lowest-rate.patch"
+ "sys-kernel_arch-sources-g14_files-8016-mt76-mt7921-Add-mt7922-support.patch"
+ "sys-kernel_arch-sources-g14_files-8017-mt76-mt7921-enable-VO-tx-aggregation.patch"
+ "sys-kernel_arch-sources-g14_files-8018-mt76-mt7921-fix-dma-hang-in-rmmod.patch"
+ "sys-kernel_arch-sources-g14_files-8019-mt76-mt7921-fix-firmware-usage-of-RA-info-using-legacy-rates.patch"
+ "sys-kernel_arch-sources-g14_files-8020-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch"
+ "sys-kernel_arch-sources-g14_files-8021-mt76-mt7921-fix-the-inconsistent-state-between-bind-and-unbind.patch"
+ "sys-kernel_arch-sources-g14_files-8022-mt76-mt7921-report-HE-MU-radiotap.patch"
+ "sys-kernel_arch-sources-g14_files-8023-v2-mt76-mt7921-fix-kernel-warning-from-cfg80211_calculate_bitrate.patch"
# squashed s0ix enablement through 2021-09-03
- "sys-kernel_arch-sources-g14_files-9001-v5.14.1-s0ix-patch-2021-09-03.patch"
- "sys-kernel_arch-sources-g14_files-9002-amd-pmc-delay-test.patch"
+ "sys-kernel_arch-sources-g14_files-9001-v5.14.4-s0ix-patch-2021-09-15.patch"
+ #"sys-kernel_arch-sources-g14_files-9002-amd-pmc-delay-test.patch"
# a small amd_pmc SMU debugging patch per Mario Limonciello @AMD
#"sys-kernel_arch-sources-g14_files-9002-amd-pmc-smu-register-dump-for-diagnostics.patch"
@@ -67,7 +76,7 @@ source=(
"sys-kernel_arch-sources-g14_files-9008-fix-cpu-hotplug.patch"
"sys-kernel_arch-sources-g14_files-9009-amd-pstate-sqashed.patch"
-
+ "sys-kernel_arch-sources-g14_files-9010-amd-apci-allow-c3.patch"
)
validpgpkeys=(
@@ -78,7 +87,7 @@ validpgpkeys=(
)
sha256sums=('SKIP'
- 'b6ec10132a4d0a656aa65c7c11686dc5d80fce396e761b398506b364e3529e30'
+ 'aa50b2ec33ce304f9b99ce80555a17ea18b1005dae147a560587acbdae00546f'
'1ac18cad2578df4a70f9346f7c6fccbb62f042a0ee0594817fdef9f2704904ee'
'fa6cee9527d8e963d3398085d1862edc509a52e4540baec463edb8a9dd95bee0'
'69ecf5456468935958f2cbf35691c2533a56344005537902b6051b6323ffff1f'
@@ -87,17 +96,29 @@ sha256sums=('SKIP'
'32bbcde83406810f41c9ed61206a7596eb43707a912ec9d870fd94f160d247c1'
'e2d312ea95d18e91801d131a2b5d03cf2175d3088cac6f84a19410078a5b6b14'
'4ef12029ea73ca924b6397e1de4911e84d9e77ddaccdab1ef579823d848524e8'
- '6fe5fe83e06d552f541bdca55d0d9e2cd6e70dd3047c01da749a0ff57fe706cc'
+ '9d799be6d01a7438ca9999a10137be8fd95348610545c135c6dc9ce2b5afbe29'
'de8c9747637768c4356c06aa65c3f157c526aa420f21fdd5edd0ed06f720a62e'
- '63b3c3b2a016209cbbea1b327dd3e977f74943821f65c04c0efb2fe967741bb1'
- '2163cb2e394a013042a40cd3b00dae788603284b20d71e262995366c5534e480'
+ '9f6b8c3ea6e1c285e0a7efda4d743dbae343bc6ee7ad599a4ab7d380c750bc83'
+ '4bfbff4eba07fc9de2ce78097a4a269509468ba0e24c15a82905cd94e093ad55'
+ 'c368cc4eefff20b7ae904eec686b7e72b46ff02b32c8a4fbd6bd4039f087e7ba'
+ '1a8639167a1ee1b66f580c0c6f8304e6ef359a68cfa3eb869d9200a9f0234098'
+ '021f8539ab2fb722b46937b95fdab22a2308236a24ecc1a9ea8db4853721dd39'
'a01cf700d79b983807e2285be1b30df6e02db6adfd9c9027fe2dfa8ca5a74bc9'
- '3d6d1e6374688c5f1abbc40b15c03c62f695e9d04d790556c57f8ec5d0d6a3f9'
- 'd8dd84c26a44af618c6d1b68723e3bf0f8f50165af04fe090256afb0f931713e'
+ '1ce9fd988201c4d2e48794c58acda5b768ec0fea1d29555e99d35cd2712281e4'
+ 'e7e37c7c433c58e2f5a79e2a7724823bef1dccaa01e857584397b4e3c837d991'
+ 'f075ac354acfd65dff4db49dc9798747cb9b7a3dd9839987bc46495bdbbd22dc'
+ '2163cb2e394a013042a40cd3b00dae788603284b20d71e262995366c5534e480'
+ '1770fec49335bc93194e9e55ced49e1cb67f2df4bf6948e80712a0b2ba50fa49'
+ '6da4010f86a74125969fd3dbc953da7b45209d33ff3d216474c3399e82e893ff'
+ 'eb391b6d1ebf7ef99ece00b23609b94180a1f3c0149bcf05f6bbeb74d0b724c7'
+ '041214e202be4a6e90f00724e87ed787b39db148b24efd5fb03fcf23577601c1'
'544464bf0807b324120767d55867f03014a9fda4e1804768ca341be902d7ade4'
'f7a4bf6293912bfc4a20743e58a5a266be8c4dbe3c1862d196d3a3b45f2f7c90'
'ee8794a551e33226900654d5c806183bf3b9b2e06f64fdc322987215d233d399'
- '2d854fc70297bb52bbc27dbf35ca019800530e40565be9740704d7f81bc4c763')
+ '2d854fc70297bb52bbc27dbf35ca019800530e40565be9740704d7f81bc4c763'
+ '1cec0be41732a23c709e66d4a67e71bc5a75c77a3e4b73faafb5d7bfd3fafc0f'
+ 'e62cbe1cb1577b1d80095fbb566d0516592e6174e7740e61a340164aff9bf2ec'
+ 'bcb5966742921cdc772f163f6cbf0998e22cb1527d5a82b7b71eab4d605243dd')
# notable microarch levels:
#
@@ -152,7 +173,7 @@ prepare() {
src="${src%%::*}"
src="${src##*/}"
[[ $src = *.patch ]] || continue
- echo "Applying patch $src..."
+ warning "Applying patch $src..."
patch -Np1 < "../$src"
done
diff --git a/config b/config
index e77024f1202f..3ba5f19a1f4b 100644
--- a/config
+++ b/config
@@ -636,6 +636,7 @@ CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
# CPU frequency scaling drivers
#
CONFIG_X86_INTEL_PSTATE=y
+CONFIG_X86_AMD_PSTATE=y
CONFIG_X86_PCC_CPUFREQ=m
CONFIG_X86_ACPI_CPUFREQ=m
CONFIG_X86_ACPI_CPUFREQ_CPB=y
diff --git a/sys-kernel_arch-sources-g14_files-0006-fix-tigerlake-pin-mapping.patch b/sys-kernel_arch-sources-g14_files-0006-fix-tigerlake-pin-mapping.patch
deleted file mode 100644
index d047f370409a..000000000000
--- a/sys-kernel_arch-sources-g14_files-0006-fix-tigerlake-pin-mapping.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-@@ -, +, @@
- software
----
- drivers/pinctrl/intel/pinctrl-tigerlake.c | 26 +++++++++++------------
- 1 file changed, 13 insertions(+), 13 deletions(-)
---- a/drivers/pinctrl/intel/pinctrl-tigerlake.c
-+++ a/drivers/pinctrl/intel/pinctrl-tigerlake.c
-@@ -701,32 +701,32 @@ static const struct pinctrl_pin_desc tglh_pins[] = {
-
- static const struct intel_padgroup tglh_community0_gpps[] = {
- TGL_GPP(0, 0, 24, 0), /* GPP_A */
-- TGL_GPP(1, 25, 44, 128), /* GPP_R */
-- TGL_GPP(2, 45, 70, 32), /* GPP_B */
-- TGL_GPP(3, 71, 78, INTEL_GPIO_BASE_NOMAP), /* vGPIO_0 */
-+ TGL_GPP(1, 25, 44, 32), /* GPP_R */
-+ TGL_GPP(2, 45, 70, 64), /* GPP_B */
-+ TGL_GPP(3, 71, 78, 96), /* vGPIO_0 */
- };
-
- static const struct intel_padgroup tglh_community1_gpps[] = {
-- TGL_GPP(0, 79, 104, 96), /* GPP_D */
-- TGL_GPP(1, 105, 128, 64), /* GPP_C */
-- TGL_GPP(2, 129, 136, 160), /* GPP_S */
-- TGL_GPP(3, 137, 153, 192), /* GPP_G */
-- TGL_GPP(4, 154, 180, 224), /* vGPIO */
-+ TGL_GPP(0, 79, 104, 128), /* GPP_D */
-+ TGL_GPP(1, 105, 128, 160), /* GPP_C */
-+ TGL_GPP(2, 129, 136, 192), /* GPP_S */
-+ TGL_GPP(3, 137, 153, 224), /* GPP_G */
-+ TGL_GPP(4, 154, 180, 256), /* vGPIO */
- };
-
- static const struct intel_padgroup tglh_community3_gpps[] = {
-- TGL_GPP(0, 181, 193, 256), /* GPP_E */
-- TGL_GPP(1, 194, 217, 288), /* GPP_F */
-+ TGL_GPP(0, 181, 193, 288), /* GPP_E */
-+ TGL_GPP(1, 194, 217, 320), /* GPP_F */
- };
-
- static const struct intel_padgroup tglh_community4_gpps[] = {
-- TGL_GPP(0, 218, 241, 320), /* GPP_H */
-+ TGL_GPP(0, 218, 241, 352), /* GPP_H */
- TGL_GPP(1, 242, 251, 384), /* GPP_J */
-- TGL_GPP(2, 252, 266, 352), /* GPP_K */
-+ TGL_GPP(2, 252, 266, 416), /* GPP_K */
- };
-
- static const struct intel_padgroup tglh_community5_gpps[] = {
-- TGL_GPP(0, 267, 281, 416), /* GPP_I */
-+ TGL_GPP(0, 267, 281, 448), /* GPP_I */
- TGL_GPP(1, 282, 290, INTEL_GPIO_BASE_NOMAP), /* JTAG */
- };
-
---
diff --git a/sys-kernel_arch-sources-g14_files-0034-btusb-mediatek.patch b/sys-kernel_arch-sources-g14_files-0034-btusb-mediatek.patch
deleted file mode 100644
index e107052b62c0..000000000000
--- a/sys-kernel_arch-sources-g14_files-0034-btusb-mediatek.patch
+++ /dev/null
@@ -1,145 +0,0 @@
-From 393dc5d19c825906f955210f10ee3befc39854f7 Mon Sep 17 00:00:00 2001
-From: "mark-yw.chen" <mark-yw.chen@mediatek.com>
-Date: Mon, 12 Apr 2021 23:06:27 +0800
-Subject: [PATCH] Bluetooth: btusb: Add support for Lite-On Mediatek Chip
-
-Add support for Lite-On Mediatek Chip (MT7921)
-Lite On VID = 04CA.
-
-* /sys/kernel/debug/usb/devices
-T: Bus=01 Lev=03 Prnt=04 Port=01 Cnt=02 Dev#= 8 Spd=480 MxCh= 0
-D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
-P: Vendor=04ca ProdID=3802 Rev= 1.00
-S: Manufacturer=MediaTek Inc.
-S: Product=Wireless_Device
-S: SerialNumber=000000000
-C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=100mA
-A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
-I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
-E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
-E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
-I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
-I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
-I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
-I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
-I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
-I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
-I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
-I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
-E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
-E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
-I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
-E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
-E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
-
-Signed-off-by: mark-yw.chen <mark-yw.chen@mediatek.com>
-Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
----
- drivers/bluetooth/btusb.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
-index 99fd88f7653d4f..cb18d63a948d89 100644
---- a/drivers/bluetooth/btusb.c
-+++ b/drivers/bluetooth/btusb.c
-@@ -408,6 +408,11 @@ static const struct usb_device_id blacklist_table[] = {
- /* Additional MediaTek MT7615E Bluetooth devices */
- { USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
-
-+ /* Additional MediaTek MT7921 Bluetooth devices */
-+ { USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
-+ BTUSB_WIDEBAND_SPEECH |
-+ BTUSB_VALID_LE_STATES },
-+
- /* Additional Realtek 8723AE Bluetooth devices */
- { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
- { USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK },
-
-
-From 0ea78370d7cad1efe7e014d7b7433073153c1ada Mon Sep 17 00:00:00 2001
-From: Wai Paulo Valerio Wang <waicool20@gmail.com>
-Date: Thu, 8 Jul 2021 03:28:56 +0800
-Subject: [PATCH] Bluetooth: btusb: Add support for IMC Networks Mediatek Chip
-
-This add supports for IMC Networks Wireless_Device Media Chip
-which contains the MT7921 chipset.
-
-Bus 001 Device 004: ID 13d3:3563 IMC Networks Wireless_Device
-
-T: Bus=01 Lev=01 Prnt=01 Port=03 Cnt=03 Dev#= 4 Spd=480 MxCh= 0
-D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
-P: Vendor=13d3 ProdID=3563 Rev= 1.00
-S: Manufacturer=MediaTek Inc.
-S: Product=Wireless_Device
-S: SerialNumber=000000000
-C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=100mA
-A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
-I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
-E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
-E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
-I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
-I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
-I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
-I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
-I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
-I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
-I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
-I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
-E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
-E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
-I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
-E: Ad=8a(I) Atr=03(Int.) MxPS= 512 Ivl=125us
-E: Ad=0a(O) Atr=03(Int.) MxPS= 512 Ivl=125us
-
-Signed-off-by: Wai Paulo Valerio Wang <waicool20@gmail.com>
----
- drivers/bluetooth/btusb.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
-index a9855a2dd561..edfa5a31a529 100644
---- a/drivers/bluetooth/btusb.c
-+++ b/drivers/bluetooth/btusb.c
-@@ -414,6 +414,9 @@ static const struct usb_device_id blacklist_table[] = {
- { USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
- BTUSB_WIDEBAND_SPEECH |
- BTUSB_VALID_LE_STATES },
-+ { USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK |
-+ BTUSB_WIDEBAND_SPEECH |
-+ BTUSB_VALID_LE_STATES },
-
- /* Additional Realtek 8723AE Bluetooth devices */
- { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
---
-2.32.0
-
diff --git a/sys-kernel_arch-sources-g14_files-0035-backport-from-5.14-s0ix-enablement-no-d3hot-2021-06-30.patch b/sys-kernel_arch-sources-g14_files-0035-backport-from-5.14-s0ix-enablement-no-d3hot-2021-06-30.patch
deleted file mode 100644
index 882d4af32dd4..000000000000
--- a/sys-kernel_arch-sources-g14_files-0035-backport-from-5.14-s0ix-enablement-no-d3hot-2021-06-30.patch
+++ /dev/null
@@ -1,1308 +0,0 @@
-From 42b2e2ffb3a9e421050893c8a3786210fb541ae1 Mon Sep 17 00:00:00 2001
-From: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Thu, 8 Jul 2021 03:24:48 -0700
-Subject: [PATCH] Squashed commit of the following:
-
-all mainline s0ix support up to 2021-06-30:
- 11 s0ix patches, including EC GPE patch
- 7 amd_pmc v5 patchset diagnostics
-
-Does not include AMD XHCI D3hot Quirk
-
-commit 2b513555a462fc9233355d44789833a9be300a2f
-Merge: ebf1d8bcad36 b072ea5d76db
-Author: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Thu Jul 8 03:16:14 2021 -0700
-
- Merge branch 'patchwork-amd-pmc-logging-v5' into TEMP-s0ix-on-5.13
-
-commit ebf1d8bcad366f451d54bda9e15943f173003551
-Merge: 62fb9874f5da 35f01a4422b1
-Author: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Thu Jul 8 03:15:32 2021 -0700
-
- Merge branch 'DO-NOT-USE-backport-from-5.14-s0ix-no-d3hot' into HEAD
-
-commit 35f01a4422b180806c6106b5696ab9626b5dac41
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 30 14:46:06 2021 -0500
-
- ACPI: PM: Only mark EC GPE for wakeup on Intel systems
-
- When using s2idle on a variety of AMD notebook systems, they are
- experiencing spurious events that the EC or SMU are in the wrong
- state leading to a hard time waking up or higher than expected
- power consumption.
-
- These events only occur when the EC GPE is inadvertently set as a wakeup
- source. Originally the EC GPE was only set as a wakeup source when using
- the intel-vbtn or intel-hid drivers in commit 10a08fd65ec1 ("ACPI: PM:
- Set up EC GPE for system wakeup from drivers that need it") but during
- testing a reporter discovered that this was not enough for their ASUS
- Zenbook UX430UNR/i7-8550U to wakeup by lid event or keypress.
- Marking the EC GPE for wakeup universally resolved this for that
- reporter in commit b90ff3554aa3 ("ACPI: PM: s2idle: Always set up EC GPE
- for system wakeup").
-
- However this behavior has lead to a number of problems:
-
- * On both Lenovo T14 and P14s the keyboard wakeup doesn't work, and
- sometimes the power button event doesn't work.
- * On HP 635 G7 detaching or attaching AC during suspend will cause
- the system not to wakeup
- * On Asus vivobook to prevent detaching AC causing resume problems
- * On Lenovo 14ARE05 to prevent detaching AC causing resume problems
- * On HP ENVY x360 to prevent detaching AC causing resume problems
-
- As there may be other Intel systems besides ASUS Zenbook UX430UNR/i7-8550U
- that don't use intel-vbtn or intel-hid avoid these problems by only
- universally marking the EC GPE wakesource on non-AMD systems.
-
- Link: https://patchwork.kernel.org/project/linux-pm/cover/5997740.FPbUVk04hV@kreacher/#22825489
- Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1230
- Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1629
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Acked-by: Alex Deucher <alexander.deucher@amd.com>
-
-commit 5032c30b7d44b5b9d68f7a8d3bbcb6238484b2a6
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Thu Jun 17 11:42:12 2021 -0500
-
- ACPI: PM: Adjust behavior for field problems on AMD systems
-
- Some AMD Systems with uPEP _HID AMD004/AMDI005 have an off by one bug
- in their function mask return. This means that they will call entrance
- but not exit for matching functions.
-
- Other AMD systems with this HID should use the Microsoft generic UUID.
-
- AMD systems with uPEP HID AMDI006 should be using the Microsoft method.
-
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-
-commit 6ad8efa21132a0c53372a615c91f5f24b6e2ed63
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:11 2021 -0500
-
- ACPI: PM: s2idle: Add support for new Microsoft UUID
-
- This adds supports for _DSM notifications to the Microsoft UUID
- described by Microsoft documentation for s2idle.
-
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby-firmware-notifications
- Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit 1c22e7dec26ea42a98b0c87d97a150a415978ec1
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:10 2021 -0500
-
- ACPI: PM: s2idle: Add support for multiple func mask
-
- Required for follow-up patch adding new UUID
- needing new function mask.
-
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit aa430a0319ce9ac4629735ac6a5b86bd48517dff
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:09 2021 -0500
-
- ACPI: PM: s2idle: Refactor common code
-
- Refactor common code to prepare for upcoming changes.
- * Remove unused struct.
- * Print error before returning.
- * Frees ACPI obj if _DSM type is not as expected.
- * Treat lps0_dsm_func_mask as an integer rather than character
- * Remove extra out_obj
- * Move rev_id
-
- Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit a71e52e9ea22c0b976014a6f7eb2ed93f65aa4ca
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:08 2021 -0500
-
- ACPI: PM: s2idle: Use correct revision id
-
- AMD spec mentions only revision 0. With this change,
- device constraint list is populated properly.
-
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit e5b15e24f169d15b231581cccb2bfa9820225cff
-Author: Alex Deucher <alexander.deucher@amd.com>
-Date: Wed May 5 09:20:32 2021 -0400
-
- ACPI: PM: s2idle: Add missing LPS0 functions for AMD
-
- These are supposedly not required for AMD platforms,
- but at least some HP laptops seem to require it to
- properly turn off the keyboard backlight.
-
- Based on a patch from Marcin Bachry <hegel666@gmail.com>.
-
- Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1230
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
- Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-
-commit 526bf2ffedece1257d3742a2ad633e00bb1778a7
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 9 13:40:18 2021 -0500
-
- ACPI: Add quirks for AMD Renoir/Lucienne CPUs to force the D3 hint
-
- AMD systems from Renoir and Lucienne require that the NVME controller
- is put into D3 over a Modern Standby / suspend-to-idle
- cycle. This is "typically" accomplished using the `StorageD3Enable`
- property in the _DSD, but this property was introduced after many
- of these systems launched and most OEM systems don't have it in
- their BIOS.
-
- On AMD Renoir without these drives going into D3 over suspend-to-idle
- the resume will fail with the NVME controller being reset and a trace
- like this in the kernel logs:
- ```
- [ 83.556118] nvme nvme0: I/O 161 QID 2 timeout, aborting
- [ 83.556178] nvme nvme0: I/O 162 QID 2 timeout, aborting
- [ 83.556187] nvme nvme0: I/O 163 QID 2 timeout, aborting
- [ 83.556196] nvme nvme0: I/O 164 QID 2 timeout, aborting
- [ 95.332114] nvme nvme0: I/O 25 QID 0 timeout, reset controller
- [ 95.332843] nvme nvme0: Abort status: 0x371
- [ 95.332852] nvme nvme0: Abort status: 0x371
- [ 95.332856] nvme nvme0: Abort status: 0x371
- [ 95.332859] nvme nvme0: Abort status: 0x371
- [ 95.332909] PM: dpm_run_callback(): pci_pm_resume+0x0/0xe0 returns -16
- [ 95.332936] nvme 0000:03:00.0: PM: failed to resume async: error -16
- ```
-
- The Microsoft documentation for StorageD3Enable mentioned that Windows has
- a hardcoded allowlist for D3 support, which was used for these platforms.
- Introduce quirks to hardcode them for Linux as well.
-
- As this property is now "standardized", OEM systems using AMD Cezanne and
- newer APU's have adopted this property, and quirks like this should not be
- necessary.
-
- CC: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
- CC: Alexander Deucher <Alexander.Deucher@amd.com>
- CC: Prike Liang <prike.liang@amd.com>
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
- Tested-by: Julian Sikorski <belegdol@gmail.com>
- Signed-off-by: Christoph Hellwig <hch@lst.de>
-
-commit 8b763d23606ce256a5ec9db81d8177ad5e90bbf9
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 9 13:40:17 2021 -0500
-
- ACPI: Check StorageD3Enable _DSD property in ACPI code
-
- Although first implemented for NVME, this check may be usable by
- other drivers as well. Microsoft's specification explicitly mentions
- that is may be usable by SATA and AHCI devices. Google also indicates
- that they have used this with SDHCI in a downstream kernel tree that
- a user can plug a storage device into.
-
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
- Suggested-by: Keith Busch <kbusch@kernel.org>
- CC: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
- CC: Alexander Deucher <Alexander.Deucher@amd.com>
- CC: Rafael J. Wysocki <rjw@rjwysocki.net>
- CC: Prike Liang <prike.liang@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
- Signed-off-by: Christoph Hellwig <hch@lst.de>
-
-commit b12b48eb29c8a392f4093898877a02f271b93355
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Fri May 28 11:02:34 2021 -0500
-
- nvme-pci: look for StorageD3Enable on companion ACPI device instead
-
- The documentation around the StorageD3Enable property hints that it
- should be made on the PCI device. This is where newer AMD systems set
- the property and it's required for S0i3 support.
-
- So rather than look for nodes of the root port only present on Intel
- systems, switch to the companion ACPI device for all systems.
- David Box from Intel indicated this should work on Intel as well.
-
- Link: https://lore.kernel.org/linux-nvme/YK6gmAWqaRmvpJXb@google.com/T/#m900552229fa455867ee29c33b854845fce80ba70
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
- Fixes: df4f9bc4fb9c ("nvme-pci: add support for ACPI StorageD3Enable property")
- Suggested-by: Liang Prike <Prike.Liang@amd.com>
- Acked-by: Raul E Rangel <rrangel@chromium.org>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Reviewed-by: David E. Box <david.e.box@linux.intel.com>
- Signed-off-by: Christoph Hellwig <hch@lst.de>
-
-commit e54f80e62f9d3412a7add7f3753c7c2604cbfe78
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed May 12 17:15:14 2021 -0500
-
- ACPI: processor idle: Fix up C-state latency if not ordered
-
- Generally, the C-state latency is provided by the _CST method or
- FADT, but some OEM platforms using AMD Picasso, Renoir, Van Gogh,
- and Cezanne set the C2 latency greater than C3's which causes the
- C2 state to be skipped.
-
- That will block the core entering PC6, which prevents S0ix working
- properly on Linux systems.
-
- In other operating systems, the latency values are not validated and
- this does not cause problems by skipping states.
-
- To avoid this issue on Linux, detect when latencies are not an
- arithmetic progression and sort them.
-
- Link: https://gitlab.freedesktop.org/agd5f/linux/-/commit/026d186e4592c1ee9c1cb44295912d0294508725
- Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1230#note_712174
- Suggested-by: Prike Liang <Prike.Liang@amd.com>
- Suggested-by: Alex Deucher <alexander.deucher@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- [ rjw: Subject and changelog edits ]
- Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-
-commit b072ea5d76db90c1316aa04a15f77744ac1bafa1
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:03 2021 +0530
-
- platform/x86: amd-pmc: Add new acpi id for future PMC controllers
-
- The upcoming PMC controller would have a newer acpi id, add that to
- the supported acpid device list.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit 4f025bcec084eb0624b3a34a03b0ff00a14a2fa0
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:02 2021 +0530
-
- platform/x86: amd-pmc: Add support for ACPI ID AMDI0006
-
- Some newer BIOSes have added another ACPI ID for the uPEP device.
- SMU statistics behave identically on this device.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit a3ccb3605aac3f650732a55adea7e666d9df24c5
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:01 2021 +0530
-
- amd-pmc: Add support for logging s0ix counters
-
- Even the FCH SSC registers provides certain level of information
- about the s0ix entry and exit times which comes handy when the SMU
- fails to report the statistics via the mailbox communication.
-
- This information is captured via a new debugfs file "s0ix_stats".
- A non-zero entry in this counters would mean that the system entered
- the s0ix state.
-
- If s0ix entry time and exit time don't change during suspend to idle,
- the silicon has not entered the deepest state.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit 826b61ec6a7785614435fcdeb951290981eff6f1
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:00 2021 +0530
-
- platform/x86: amd-pmc: Add support for logging SMU metrics
-
- SMU provides a way to dump the s0ix debug statistics in the form of a
- metrics table via a of set special mailbox commands.
-
- Add support to the driver which can send these commands to SMU and expose
- the information received via debugfs. The information contains the s0ix
- entry/exit, active time of each IP block etc.
-
- As a side note, SMU subsystem logging is not supported on Picasso based
- SoC's.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit dd120f506eea9bee584cf0f7d737631554ba17a3
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:17:59 2021 +0530
-
- platform/x86: amd-pmc: call dump registers only once
-
- Currently amd_pmc_dump_registers() routine is being called at
- multiple places. The best to call it is after command submission
- to SMU.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-
-commit 87390ff9f263e0aa586d9a33198e79b47e5f85d1
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:17:58 2021 +0530
-
- platform/x86: amd-pmc: Fix SMU firmware reporting mechanism
-
- It was lately understood that the current mechanism available in the
- driver to get SMU firmware info works only on internal SMU builds and
- there is a separate way to get all the SMU logging counters (addressed
- in the next patch). Hence remove all the smu info shown via debugfs as it
- is no more useful.
-
- Fixes: 156ec4731cb2 ("platform/x86: amd-pmc: Add AMD platform support for S2Idle")
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-
-commit 65581db92e5e4d5fa941cc6bb91e702e3ed97b74
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:17:57 2021 +0530
-
- platform/x86: amd-pmc: Fix command completion code
-
- The protocol to submit a job request to SMU is to wait for
- AMD_PMC_REGISTER_RESPONSE to return 1,meaning SMU is ready to take
- requests. PMC driver has to make sure that the response code is always
- AMD_PMC_RESULT_OK before making any command submissions.
-
- When we submit a message to SMU, we have to wait until it processes
- the request. Adding a read_poll_timeout() check as this was missing in
- the existing code.
-
- Also, add a mutex to protect amd_pmc_send_cmd() calls to SMU.
-
- Fixes: 156ec4731cb2 ("platform/x86: amd-pmc: Add AMD platform support for S2Idle")
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Acked-by: Raul E Rangel <rrangel@chromium.org>
----
- drivers/acpi/device_pm.c | 32 +++++
- drivers/acpi/internal.h | 9 ++
- drivers/acpi/processor_idle.c | 40 ++++++
- drivers/acpi/x86/s2idle.c | 157 ++++++++++++++-------
- drivers/acpi/x86/utils.c | 25 ++++
- drivers/nvme/host/pci.c | 50 +------
- drivers/platform/x86/amd-pmc.c | 244 ++++++++++++++++++++++++++++++---
- include/linux/acpi.h | 5 +
- 8 files changed, 443 insertions(+), 119 deletions(-)
-
-diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
-index d260bc1f3e6e..6dd9bd64903e 100644
---- a/drivers/acpi/device_pm.c
-+++ b/drivers/acpi/device_pm.c
-@@ -1340,4 +1340,36 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
- return 1;
- }
- EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
-+
-+/**
-+ * acpi_storage_d3 - Check if D3 should be used in the suspend path
-+ * @dev: Device to check
-+ *
-+ * Return %true if the platform firmware wants @dev to be programmed
-+ * into D3hot or D3cold (if supported) in the suspend path, or %false
-+ * when there is no specific preference. On some platforms, if this
-+ * hint is ignored, @dev may remain unresponsive after suspending the
-+ * platform as a whole.
-+ *
-+ * Although the property has storage in the name it actually is
-+ * applied to the PCIe slot and plugging in a non-storage device the
-+ * same platform restrictions will likely apply.
-+ */
-+bool acpi_storage_d3(struct device *dev)
-+{
-+ struct acpi_device *adev = ACPI_COMPANION(dev);
-+ u8 val;
-+
-+ if (force_storage_d3())
-+ return true;
-+
-+ if (!adev)
-+ return false;
-+ if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
-+ &val))
-+ return false;
-+ return val == 1;
-+}
-+EXPORT_SYMBOL_GPL(acpi_storage_d3);
-+
- #endif /* CONFIG_PM */
-diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
-index e21611c9a170..7ac01b03ba67 100644
---- a/drivers/acpi/internal.h
-+++ b/drivers/acpi/internal.h
-@@ -236,6 +236,15 @@ static inline int suspend_nvs_save(void) { return 0; }
- static inline void suspend_nvs_restore(void) {}
- #endif
-
-+#ifdef CONFIG_X86
-+bool force_storage_d3(void);
-+#else
-+static inline bool force_storage_d3(void)
-+{
-+ return false;
-+}
-+#endif
-+
- /*--------------------------------------------------------------------------
- Device properties
- -------------------------------------------------------------------------- */
-diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
-index 45a019619e4a..095c8aca141e 100644
---- a/drivers/acpi/processor_idle.c
-+++ b/drivers/acpi/processor_idle.c
-@@ -16,6 +16,7 @@
- #include <linux/acpi.h>
- #include <linux/dmi.h>
- #include <linux/sched.h> /* need_resched() */
-+#include <linux/sort.h>
- #include <linux/tick.h>
- #include <linux/cpuidle.h>
- #include <linux/cpu.h>
-@@ -384,10 +385,37 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
- return;
- }
-
-+static int acpi_cst_latency_cmp(const void *a, const void *b)
-+{
-+ const struct acpi_processor_cx *x = a, *y = b;
-+
-+ if (!(x->valid && y->valid))
-+ return 0;
-+ if (x->latency > y->latency)
-+ return 1;
-+ if (x->latency < y->latency)
-+ return -1;
-+ return 0;
-+}
-+static void acpi_cst_latency_swap(void *a, void *b, int n)
-+{
-+ struct acpi_processor_cx *x = a, *y = b;
-+ u32 tmp;
-+
-+ if (!(x->valid && y->valid))
-+ return;
-+ tmp = x->latency;
-+ x->latency = y->latency;
-+ y->latency = tmp;
-+}
-+
- static int acpi_processor_power_verify(struct acpi_processor *pr)
- {
- unsigned int i;
- unsigned int working = 0;
-+ unsigned int last_latency = 0;
-+ unsigned int last_type = 0;
-+ bool buggy_latency = false;
-
- pr->power.timer_broadcast_on_state = INT_MAX;
-
-@@ -411,12 +439,24 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
- }
- if (!cx->valid)
- continue;
-+ if (cx->type >= last_type && cx->latency < last_latency)
-+ buggy_latency = true;
-+ last_latency = cx->latency;
-+ last_type = cx->type;
-
- lapic_timer_check_state(i, pr, cx);
- tsc_check_state(cx->type);
- working++;
- }
-
-+ if (buggy_latency) {
-+ pr_notice("FW issue: working around C-state latencies out of order\n");
-+ sort(&pr->power.states[1], max_cstate,
-+ sizeof(struct acpi_processor_cx),
-+ acpi_cst_latency_cmp,
-+ acpi_cst_latency_swap);
-+ }
-+
- lapic_timer_propagate_broadcast(pr);
-
- return (working);
-diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
-index 2b69536cdccb..1c507804fb10 100644
---- a/drivers/acpi/x86/s2idle.c
-+++ b/drivers/acpi/x86/s2idle.c
-@@ -32,6 +32,9 @@ static const struct acpi_device_id lps0_device_ids[] = {
- {"", },
- };
-
-+/* Microsoft platform agnostic UUID */
-+#define ACPI_LPS0_DSM_UUID_MICROSOFT "11e00d56-ce64-47ce-837b-1f898f9aa461"
-+
- #define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
-
- #define ACPI_LPS0_GET_DEVICE_CONSTRAINTS 1
-@@ -39,15 +42,22 @@ static const struct acpi_device_id lps0_device_ids[] = {
- #define ACPI_LPS0_SCREEN_ON 4
- #define ACPI_LPS0_ENTRY 5
- #define ACPI_LPS0_EXIT 6
-+#define ACPI_LPS0_MS_ENTRY 7
-+#define ACPI_LPS0_MS_EXIT 8
-
- /* AMD */
- #define ACPI_LPS0_DSM_UUID_AMD "e3f32452-febc-43ce-9039-932122d37721"
-+#define ACPI_LPS0_ENTRY_AMD 2
-+#define ACPI_LPS0_EXIT_AMD 3
- #define ACPI_LPS0_SCREEN_OFF_AMD 4
- #define ACPI_LPS0_SCREEN_ON_AMD 5
-
- static acpi_handle lps0_device_handle;
- static guid_t lps0_dsm_guid;
--static char lps0_dsm_func_mask;
-+static int lps0_dsm_func_mask;
-+
-+static guid_t lps0_dsm_guid_microsoft;
-+static int lps0_dsm_func_mask_microsoft;
-
- /* Device constraint entry structure */
- struct lpi_device_info {
-@@ -68,15 +78,7 @@ struct lpi_constraints {
- int min_dstate;
- };
-
--/* AMD */
--/* Device constraint entry structure */
--struct lpi_device_info_amd {
-- int revision;
-- int count;
-- union acpi_object *package;
--};
--
--/* Constraint package structure */
-+/* AMD Constraint package structure */
- struct lpi_device_constraint_amd {
- char *name;
- int enabled;
-@@ -94,15 +96,15 @@ static void lpi_device_get_constraints_amd(void)
- int i, j, k;
-
- out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
-- 1, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
-+ rev_id, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
- NULL, ACPI_TYPE_PACKAGE);
-
-- if (!out_obj)
-- return;
--
- acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
- out_obj ? "successful" : "failed");
-
-+ if (!out_obj)
-+ return;
-+
- for (i = 0; i < out_obj->package.count; i++) {
- union acpi_object *package = &out_obj->package.elements[i];
-
-@@ -315,14 +317,15 @@ static void lpi_check_constraints(void)
- }
- }
-
--static void acpi_sleep_run_lps0_dsm(unsigned int func)
-+static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, guid_t dsm_guid)
- {
- union acpi_object *out_obj;
-
-- if (!(lps0_dsm_func_mask & (1 << func)))
-+ if (!(func_mask & (1 << func)))
- return;
-
-- out_obj = acpi_evaluate_dsm(lps0_device_handle, &lps0_dsm_guid, rev_id, func, NULL);
-+ out_obj = acpi_evaluate_dsm(lps0_device_handle, &dsm_guid,
-+ rev_id, func, NULL);
- ACPI_FREE(out_obj);
-
- acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n",
-@@ -334,11 +337,33 @@ static bool acpi_s2idle_vendor_amd(void)
- return boot_cpu_data.x86_vendor == X86_VENDOR_AMD;
- }
-
-+static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *dsm_guid)
-+{
-+ union acpi_object *obj;
-+ int ret = -EINVAL;
-+
-+ guid_parse(uuid, dsm_guid);
-+ obj = acpi_evaluate_dsm(handle, dsm_guid, rev, 0, NULL);
-+
-+ /* Check if the _DSM is present and as expected. */
-+ if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length == 0 ||
-+ obj->buffer.length > sizeof(u32)) {
-+ acpi_handle_debug(handle,
-+ "_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev);
-+ goto out;
-+ }
-+
-+ ret = *(int *)obj->buffer.pointer;
-+ acpi_handle_debug(handle, "_DSM UUID %s rev %d function mask: 0x%x\n", uuid, rev, ret);
-+
-+out:
-+ ACPI_FREE(obj);
-+ return ret;
-+}
-+
- static int lps0_device_attach(struct acpi_device *adev,
- const struct acpi_device_id *not_used)
- {
-- union acpi_object *out_obj;
--
- if (lps0_device_handle)
- return 0;
-
-@@ -346,28 +371,36 @@ static int lps0_device_attach(struct acpi_device *adev,
- return 0;
-
- if (acpi_s2idle_vendor_amd()) {
-- guid_parse(ACPI_LPS0_DSM_UUID_AMD, &lps0_dsm_guid);
-- out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 0, 0, NULL);
-+ /* AMD0004, AMDI0005:
-+ * - Should use rev_id 0x0
-+ * - function mask > 0x3: Should use AMD method, but has off by one bug
-+ * - function mask = 0x3: Should use Microsoft method
-+ * AMDI0006:
-+ * - should use rev_id 0x0
-+ * - function mask = 0x3: Should use Microsoft method
-+ */
-+ const char *hid = acpi_device_hid(adev);
- rev_id = 0;
-+ lps0_dsm_func_mask = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid);
-+ lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID_MICROSOFT, rev_id,
-+ &lps0_dsm_guid_microsoft);
-+ if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") ||
-+ !strcmp(hid, "AMDI0005"))) {
-+ lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
-+ acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
-+ ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
-+ }
- } else {
-- guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid);
-- out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL);
- rev_id = 1;
-+ lps0_dsm_func_mask = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid);
-+ lps0_dsm_func_mask_microsoft = -EINVAL;
- }
-
-- /* Check if the _DSM is present and as expected. */
-- if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) {
-- acpi_handle_debug(adev->handle,
-- "_DSM function 0 evaluation failed\n");
-- return 0;
-- }
--
-- lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer;
--
-- ACPI_FREE(out_obj);
--
-- acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
-- lps0_dsm_func_mask);
-+ if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0)
-+ return 0; //function evaluation failed
-
- lps0_device_handle = adev->handle;
-
-@@ -384,11 +417,15 @@ static int lps0_device_attach(struct acpi_device *adev,
- mem_sleep_current = PM_SUSPEND_TO_IDLE;
-
- /*
-- * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
-- * EC GPE to be enabled while suspended for certain wakeup devices to
-- * work, so mark it as wakeup-capable.
-+ * Some Intel based LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U don't
-+ * use intel-hid or intel-vbtn but require the EC GPE to be enabled while
-+ * suspended for certain wakeup devices to work, so mark it as wakeup-capable.
-+ *
-+ * Only enable on !AMD as enabling this universally causes problems for a number
-+ * of AMD based systems.
- */
-- acpi_ec_mark_gpe_for_wake();
-+ if (!acpi_s2idle_vendor_amd())
-+ acpi_ec_mark_gpe_for_wake();
-
- return 0;
- }
-@@ -406,11 +443,23 @@ int acpi_s2idle_prepare_late(void)
- if (pm_debug_messages_on)
- lpi_check_constraints();
-
-- if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD);
-+ if (lps0_dsm_func_mask_microsoft > 0) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ } else if (acpi_s2idle_vendor_amd()) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- }
-
- return 0;
-@@ -421,11 +470,23 @@ void acpi_s2idle_restore_early(void)
- if (!lps0_device_handle || sleep_no_lps0)
- return;
-
-- if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD);
-+ if (lps0_dsm_func_mask_microsoft > 0) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ } else if (acpi_s2idle_vendor_amd()) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT_AMD,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- }
- }
-
-diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
-index bdc1ba00aee9..f22f23933063 100644
---- a/drivers/acpi/x86/utils.c
-+++ b/drivers/acpi/x86/utils.c
-@@ -135,3 +135,28 @@ bool acpi_device_always_present(struct acpi_device *adev)
-
- return ret;
- }
-+
-+/*
-+ * AMD systems from Renoir and Lucienne *require* that the NVME controller
-+ * is put into D3 over a Modern Standby / suspend-to-idle cycle.
-+ *
-+ * This is "typically" accomplished using the `StorageD3Enable`
-+ * property in the _DSD that is checked via the `acpi_storage_d3` function
-+ * but this property was introduced after many of these systems launched
-+ * and most OEM systems don't have it in their BIOS.
-+ *
-+ * The Microsoft documentation for StorageD3Enable mentioned that Windows has
-+ * a hardcoded allowlist for D3 support, which was used for these platforms.
-+ *
-+ * This allows quirking on Linux in a similar fashion.
-+ */
-+static const struct x86_cpu_id storage_d3_cpu_ids[] = {
-+ X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 96, NULL), /* Renoir */
-+ X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 104, NULL), /* Lucienne */
-+ {}
-+};
-+
-+bool force_storage_d3(void)
-+{
-+ return x86_match_cpu(storage_d3_cpu_ids);
-+}
-diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
-index a29b170701fc..8fbc4c87a0d8 100644
---- a/drivers/nvme/host/pci.c
-+++ b/drivers/nvme/host/pci.c
-@@ -2828,54 +2828,6 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
- return 0;
- }
-
--#ifdef CONFIG_ACPI
--static bool nvme_acpi_storage_d3(struct pci_dev *dev)
--{
-- struct acpi_device *adev;
-- struct pci_dev *root;
-- acpi_handle handle;
-- acpi_status status;
-- u8 val;
--
-- /*
-- * Look for _DSD property specifying that the storage device on the port
-- * must use D3 to support deep platform power savings during
-- * suspend-to-idle.
-- */
-- root = pcie_find_root_port(dev);
-- if (!root)
-- return false;
--
-- adev = ACPI_COMPANION(&root->dev);
-- if (!adev)
-- return false;
--
-- /*
-- * The property is defined in the PXSX device for South complex ports
-- * and in the PEGP device for North complex ports.
-- */
-- status = acpi_get_handle(adev->handle, "PXSX", &handle);
-- if (ACPI_FAILURE(status)) {
-- status = acpi_get_handle(adev->handle, "PEGP", &handle);
-- if (ACPI_FAILURE(status))
-- return false;
-- }
--
-- if (acpi_bus_get_device(handle, &adev))
-- return false;
--
-- if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
-- &val))
-- return false;
-- return val == 1;
--}
--#else
--static inline bool nvme_acpi_storage_d3(struct pci_dev *dev)
--{
-- return false;
--}
--#endif /* CONFIG_ACPI */
--
- static void nvme_async_probe(void *data, async_cookie_t cookie)
- {
- struct nvme_dev *dev = data;
-@@ -2925,7 +2877,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-
- quirks |= check_vendor_combination_bug(pdev);
-
-- if (!noacpi && nvme_acpi_storage_d3(pdev)) {
-+ if (!noacpi && acpi_storage_d3(&pdev->dev)) {
- /*
- * Some systems use a bios work around to ask for D3 on
- * platforms that support kernel managed suspend.
-diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
-index b9da58ee9b1e..d2f9a62e1166 100644
---- a/drivers/platform/x86/amd-pmc.c
-+++ b/drivers/platform/x86/amd-pmc.c
-@@ -46,34 +46,79 @@
- #define AMD_PMC_RESULT_CMD_UNKNOWN 0xFE
- #define AMD_PMC_RESULT_FAILED 0xFF
-
-+/* FCH SSC Registers */
-+#define FCH_S0I3_ENTRY_TIME_L_OFFSET 0x30
-+#define FCH_S0I3_ENTRY_TIME_H_OFFSET 0x34
-+#define FCH_S0I3_EXIT_TIME_L_OFFSET 0x38
-+#define FCH_S0I3_EXIT_TIME_H_OFFSET 0x3C
-+#define FCH_SSC_MAPPING_SIZE 0x800
-+#define FCH_BASE_PHY_ADDR_LOW 0xFED81100
-+#define FCH_BASE_PHY_ADDR_HIGH 0x00000000
-+
-+/* SMU Message Definations */
-+#define SMU_MSG_GETSMUVERSION 0x02
-+#define SMU_MSG_LOG_GETDRAM_ADDR_HI 0x04
-+#define SMU_MSG_LOG_GETDRAM_ADDR_LO 0x05
-+#define SMU_MSG_LOG_START 0x06
-+#define SMU_MSG_LOG_RESET 0x07
-+#define SMU_MSG_LOG_DUMP_DATA 0x08
-+#define SMU_MSG_GET_SUP_CONSTRAINTS 0x09
- /* List of supported CPU ids */
- #define AMD_CPU_ID_RV 0x15D0
- #define AMD_CPU_ID_RN 0x1630
- #define AMD_CPU_ID_PCO AMD_CPU_ID_RV
- #define AMD_CPU_ID_CZN AMD_CPU_ID_RN
-+#define AMD_CPU_ID_YC 0x14B5
-
--#define AMD_SMU_FW_VERSION 0x0
- #define PMC_MSG_DELAY_MIN_US 100
- #define RESPONSE_REGISTER_LOOP_MAX 200
-
-+#define SOC_SUBSYSTEM_IP_MAX 12
-+#define DELAY_MIN_US 2000
-+#define DELAY_MAX_US 3000
- enum amd_pmc_def {
- MSG_TEST = 0x01,
- MSG_OS_HINT_PCO,
- MSG_OS_HINT_RN,
- };
-
-+struct amd_pmc_bit_map {
-+ const char *name;
-+ u32 bit_mask;
-+};
-+
-+static const struct amd_pmc_bit_map soc15_ip_blk[] = {
-+ {"DISPLAY", BIT(0)},
-+ {"CPU", BIT(1)},
-+ {"GFX", BIT(2)},
-+ {"VDD", BIT(3)},
-+ {"ACP", BIT(4)},
-+ {"VCN", BIT(5)},
-+ {"ISP", BIT(6)},
-+ {"NBIO", BIT(7)},
-+ {"DF", BIT(8)},
-+ {"USB0", BIT(9)},
-+ {"USB1", BIT(10)},
-+ {"LAPIC", BIT(11)},
-+ {}
-+};
-+
- struct amd_pmc_dev {
- void __iomem *regbase;
-- void __iomem *smu_base;
-+ void __iomem *smu_virt_addr;
-+ void __iomem *fch_virt_addr;
- u32 base_addr;
- u32 cpu_id;
-+ u32 active_ips;
- struct device *dev;
-+ struct mutex lock; /* generic mutex lock */
- #if IS_ENABLED(CONFIG_DEBUG_FS)
- struct dentry *dbgfs_dir;
- #endif /* CONFIG_DEBUG_FS */
- };
-
- static struct amd_pmc_dev pmc;
-+static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg, bool ret);
-
- static inline u32 amd_pmc_reg_read(struct amd_pmc_dev *dev, int reg_offset)
- {
-@@ -85,18 +130,76 @@ static inline void amd_pmc_reg_write(struct amd_pmc_dev *dev, int reg_offset, u3
- iowrite32(val, dev->regbase + reg_offset);
- }
-
-+struct smu_metrics {
-+ u32 table_version;
-+ u32 hint_count;
-+ u32 s0i3_cyclecount;
-+ u32 timein_s0i2;
-+ u64 timeentering_s0i3_lastcapture;
-+ u64 timeentering_s0i3_totaltime;
-+ u64 timeto_resume_to_os_lastcapture;
-+ u64 timeto_resume_to_os_totaltime;
-+ u64 timein_s0i3_lastcapture;
-+ u64 timein_s0i3_totaltime;
-+ u64 timein_swdrips_lastcapture;
-+ u64 timein_swdrips_totaltime;
-+ u64 timecondition_notmet_lastcapture[SOC_SUBSYSTEM_IP_MAX];
-+ u64 timecondition_notmet_totaltime[SOC_SUBSYSTEM_IP_MAX];
-+} __packed;
-+
- #ifdef CONFIG_DEBUG_FS
- static int smu_fw_info_show(struct seq_file *s, void *unused)
- {
- struct amd_pmc_dev *dev = s->private;
-- u32 value;
-+ struct smu_metrics table;
-+ int idx;
-+
-+ if (dev->cpu_id == AMD_CPU_ID_PCO)
-+ return -EINVAL;
-+
-+ memcpy_fromio(&table, dev->smu_virt_addr, sizeof(struct smu_metrics));
-+
-+ seq_puts(s, "\n=== SMU Statistics ===\n");
-+ seq_printf(s, "Table Version: %d\n", table.table_version);
-+ seq_printf(s, "Hint Count: %d\n", table.hint_count);
-+ seq_printf(s, "S0i3 Cycle Count: %d\n", table.s0i3_cyclecount);
-+ seq_printf(s, "Time (in us) to S0i3: %lld\n", table.timeentering_s0i3_lastcapture);
-+ seq_printf(s, "Time (in us) in S0i3: %lld\n", table.timein_s0i3_lastcapture);
-+
-+ seq_puts(s, "\n=== Active time (in us) ===\n");
-+ for (idx = 0 ; idx < SOC_SUBSYSTEM_IP_MAX ; idx++) {
-+ if (soc15_ip_blk[idx].bit_mask & dev->active_ips)
-+ seq_printf(s, "%-8s : %lld\n", soc15_ip_blk[idx].name,
-+ table.timecondition_notmet_lastcapture[idx]);
-+ }
-
-- value = ioread32(dev->smu_base + AMD_SMU_FW_VERSION);
-- seq_printf(s, "SMU FW Info: %x\n", value);
- return 0;
- }
- DEFINE_SHOW_ATTRIBUTE(smu_fw_info);
-
-+static int s0ix_stats_show(struct seq_file *s, void *unused)
-+{
-+ struct amd_pmc_dev *dev = s->private;
-+ u64 entry_time, exit_time, residency;
-+
-+ entry_time = ioread32(dev->fch_virt_addr + FCH_S0I3_ENTRY_TIME_H_OFFSET);
-+ entry_time = entry_time << 32 | ioread32(dev->fch_virt_addr + FCH_S0I3_ENTRY_TIME_L_OFFSET);
-+
-+ exit_time = ioread32(dev->fch_virt_addr + FCH_S0I3_EXIT_TIME_H_OFFSET);
-+ exit_time = exit_time << 32 | ioread32(dev->fch_virt_addr + FCH_S0I3_EXIT_TIME_L_OFFSET);
-+
-+ /* It's in 48MHz. We need to convert it */
-+ residency = (exit_time - entry_time) / 48;
-+
-+ seq_puts(s, "=== S0ix statistics ===\n");
-+ seq_printf(s, "S0ix Entry Time: %lld\n", entry_time);
-+ seq_printf(s, "S0ix Exit Time: %lld\n", exit_time);
-+ seq_printf(s, "Residency Time: %lld\n", residency);
-+
-+ return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(s0ix_stats);
-+
- static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
- {
- debugfs_remove_recursive(dev->dbgfs_dir);
-@@ -107,6 +210,8 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
- dev->dbgfs_dir = debugfs_create_dir("amd_pmc", NULL);
- debugfs_create_file("smu_fw_info", 0644, dev->dbgfs_dir, dev,
- &smu_fw_info_fops);
-+ debugfs_create_file("s0ix_stats", 0644, dev->dbgfs_dir, dev,
-+ &s0ix_stats_fops);
- }
- #else
- static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
-@@ -118,6 +223,32 @@ static inline void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
- }
- #endif /* CONFIG_DEBUG_FS */
-
-+static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
-+{
-+ u32 phys_addr_low, phys_addr_hi;
-+ u64 smu_phys_addr;
-+
-+ if (dev->cpu_id == AMD_CPU_ID_PCO)
-+ return -EINVAL;
-+
-+ /* Get Active devices list from SMU */
-+ amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, 1);
-+
-+ /* Get dram address */
-+ amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, 1);
-+ amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, 1);
-+ smu_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
-+
-+ dev->smu_virt_addr = devm_ioremap(dev->dev, smu_phys_addr, sizeof(struct smu_metrics));
-+ if (!dev->smu_virt_addr)
-+ return -ENOMEM;
-+
-+ /* Start the logging */
-+ amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, 0);
-+
-+ return 0;
-+}
-+
- static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
- {
- u32 value;
-@@ -132,15 +263,15 @@ static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
- dev_dbg(dev->dev, "AMD_PMC_REGISTER_MESSAGE:%x\n", value);
- }
-
--static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
-+static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg, bool ret)
- {
- int rc;
-- u8 msg;
- u32 val;
-
-+ mutex_lock(&dev->lock);
- /* Wait until we get a valid response */
- rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
-- val, val > 0, PMC_MSG_DELAY_MIN_US,
-+ val, val != 0, PMC_MSG_DELAY_MIN_US,
- PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX);
- if (rc) {
- dev_err(dev->dev, "failed to talk to SMU\n");
-@@ -154,21 +285,74 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_ARGUMENT, set);
-
- /* Write message ID to message ID register */
-- msg = (dev->cpu_id == AMD_CPU_ID_RN) ? MSG_OS_HINT_RN : MSG_OS_HINT_PCO;
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_MESSAGE, msg);
-- return 0;
-+
-+ /* Wait until we get a valid response */
-+ rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
-+ val, val != 0, PMC_MSG_DELAY_MIN_US,
-+ PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX);
-+ if (rc) {
-+ dev_err(dev->dev, "SMU response timed out\n");
-+ goto out_unlock;
-+ }
-+
-+ switch (val) {
-+ case AMD_PMC_RESULT_OK:
-+ if (ret) {
-+ /* PMFW may take longer time to return back the data */
-+ usleep_range(DELAY_MIN_US, 10 * DELAY_MAX_US);
-+ *data = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_ARGUMENT);
-+ }
-+ break;
-+ case AMD_PMC_RESULT_CMD_REJECT_BUSY:
-+ dev_err(dev->dev, "SMU not ready. err: 0x%x\n", val);
-+ rc = -EBUSY;
-+ goto out_unlock;
-+ case AMD_PMC_RESULT_CMD_UNKNOWN:
-+ dev_err(dev->dev, "SMU cmd unknown. err: 0x%x\n", val);
-+ rc = -EINVAL;
-+ goto out_unlock;
-+ case AMD_PMC_RESULT_CMD_REJECT_PREREQ:
-+ case AMD_PMC_RESULT_FAILED:
-+ default:
-+ dev_err(dev->dev, "SMU cmd failed. err: 0x%x\n", val);
-+ rc = -EIO;
-+ goto out_unlock;
-+ }
-+
-+out_unlock:
-+ mutex_unlock(&dev->lock);
-+ amd_pmc_dump_registers(dev);
-+ return rc;
-+}
-+
-+static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev)
-+{
-+ switch (dev->cpu_id) {
-+ case AMD_CPU_ID_PCO:
-+ return MSG_OS_HINT_PCO;
-+ case AMD_CPU_ID_RN:
-+ case AMD_CPU_ID_YC:
-+ return MSG_OS_HINT_RN;
-+ }
-+ return -EINVAL;
- }
-
- static int __maybe_unused amd_pmc_suspend(struct device *dev)
- {
- struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
- int rc;
-+ u8 msg;
-
-- rc = amd_pmc_send_cmd(pdev, 1);
-+ /* Reset and Start SMU logging - to monitor the s0i3 stats */
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_RESET, 0);
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_START, 0);
-+
-+ msg = amd_pmc_get_os_hint(pdev);
-+ rc = amd_pmc_send_cmd(pdev, 1, NULL, msg, 0);
- if (rc)
- dev_err(pdev->dev, "suspend failed\n");
-
-- amd_pmc_dump_registers(pdev);
- return 0;
- }
-
-@@ -176,12 +360,16 @@ static int __maybe_unused amd_pmc_resume(struct device *dev)
- {
- struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
- int rc;
-+ u8 msg;
-
-- rc = amd_pmc_send_cmd(pdev, 0);
-+ /* Let SMU know that we are looking for stats */
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0);
-+
-+ msg = amd_pmc_get_os_hint(pdev);
-+ rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, 0);
- if (rc)
- dev_err(pdev->dev, "resume failed\n");
-
-- amd_pmc_dump_registers(pdev);
- return 0;
- }
-
-@@ -190,6 +378,7 @@ static const struct dev_pm_ops amd_pmc_pm_ops = {
- };
-
- static const struct pci_device_id pmc_pci_ids[] = {
-+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_YC) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_CZN) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RN) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) },
-@@ -201,9 +390,8 @@ static int amd_pmc_probe(struct platform_device *pdev)
- {
- struct amd_pmc_dev *dev = &pmc;
- struct pci_dev *rdev;
-- u32 base_addr_lo;
-- u32 base_addr_hi;
-- u64 base_addr;
-+ u32 base_addr_lo, base_addr_hi;
-+ u64 base_addr, fch_phys_addr;
- int err;
- u32 val;
-
-@@ -248,16 +436,25 @@ static int amd_pmc_probe(struct platform_device *pdev)
- pci_dev_put(rdev);
- base_addr = ((u64)base_addr_hi << 32 | base_addr_lo);
-
-- dev->smu_base = devm_ioremap(dev->dev, base_addr, AMD_PMC_MAPPING_SIZE);
-- if (!dev->smu_base)
-- return -ENOMEM;
--
- dev->regbase = devm_ioremap(dev->dev, base_addr + AMD_PMC_BASE_ADDR_OFFSET,
- AMD_PMC_MAPPING_SIZE);
- if (!dev->regbase)
- return -ENOMEM;
-
-- amd_pmc_dump_registers(dev);
-+ mutex_init(&dev->lock);
-+
-+ /* Use FCH registers to get the S0ix stats */
-+ base_addr_lo = FCH_BASE_PHY_ADDR_LOW;
-+ base_addr_hi = FCH_BASE_PHY_ADDR_HIGH;
-+ fch_phys_addr = ((u64)base_addr_hi << 32 | base_addr_lo);
-+ dev->fch_virt_addr = devm_ioremap(dev->dev, fch_phys_addr, FCH_SSC_MAPPING_SIZE);
-+ if (!dev->fch_virt_addr)
-+ return -ENOMEM;
-+
-+ /* Use SMU to get the s0i3 debug stats */
-+ err = amd_pmc_setup_smu_logging(dev);
-+ if (err)
-+ dev_err(dev->dev, "SMU debugging info not supported on this platform\n");
-
- platform_set_drvdata(pdev, dev);
- amd_pmc_dbgfs_register(dev);
-@@ -269,11 +466,14 @@ static int amd_pmc_remove(struct platform_device *pdev)
- struct amd_pmc_dev *dev = platform_get_drvdata(pdev);
-
- amd_pmc_dbgfs_unregister(dev);
-+ mutex_destroy(&dev->lock);
- return 0;
- }
-
- static const struct acpi_device_id amd_pmc_acpi_ids[] = {
- {"AMDI0005", 0},
-+ {"AMDI0006", 0},
-+ {"AMDI0007", 0},
- {"AMD0004", 0},
- { }
- };
-diff --git a/include/linux/acpi.h b/include/linux/acpi.h
-index c60745f657e9..dd0dafd21e33 100644
---- a/include/linux/acpi.h
-+++ b/include/linux/acpi.h
-@@ -1004,6 +1004,7 @@ int acpi_dev_resume(struct device *dev);
- int acpi_subsys_runtime_suspend(struct device *dev);
- int acpi_subsys_runtime_resume(struct device *dev);
- int acpi_dev_pm_attach(struct device *dev, bool power_on);
-+bool acpi_storage_d3(struct device *dev);
- #else
- static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
- static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
-@@ -1011,6 +1012,10 @@ static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
- {
- return 0;
- }
-+static inline bool acpi_storage_d3(struct device *dev)
-+{
-+ return false;
-+}
- #endif
-
- #if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP)
---
-2.32.0
-
diff --git a/sys-kernel_arch-sources-g14_files-0036-PCI-quirks-Quirk-PCI-d3hot-delay-for-AMD-xhci.patch b/sys-kernel_arch-sources-g14_files-0036-PCI-quirks-Quirk-PCI-d3hot-delay-for-AMD-xhci.patch
deleted file mode 100644
index a6797595b45a..000000000000
--- a/sys-kernel_arch-sources-g14_files-0036-PCI-quirks-Quirk-PCI-d3hot-delay-for-AMD-xhci.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 6e4c0295938e21c52d86502da5c454204617f9a8 Mon Sep 17 00:00:00 2001
-From: Marcin Bachry <hegel666@gmail.com>
-Date: Tue, 16 Mar 2021 15:28:51 -0400
-Subject: [PATCH] PCI: quirks: Quirk PCI d3hot delay for AMD xhci
-
-Renoir needs a similar delay.
-
-Signed-off-by: Marcin Bachry <hegel666@gmail.com>
-Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
----
- drivers/pci/quirks.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
-index 98851d00dc4d..8c929b7d335e 100644
---- a/drivers/pci/quirks.c
-+++ b/drivers/pci/quirks.c
-@@ -1904,6 +1904,9 @@ static void quirk_ryzen_xhci_d3hot(struct pci_dev *dev)
- }
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e0, quirk_ryzen_xhci_d3hot);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e1, quirk_ryzen_xhci_d3hot);
-+/* Renoir XHCI requires longer delay when transitioning from D0 to
-+ * D3hot */
-+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1639, quirk_ryzen_xhci_d3hot);
-
- #ifdef CONFIG_X86_IO_APIC
- static int dmi_disable_ioapicreroute(const struct dmi_system_id *d)
---
-GitLab
-
diff --git a/sys-kernel_arch-sources-g14_files-0037-ACPI-PM-Only-mark-EC-GPE-for-wakeup-on-Intel-systems.patch b/sys-kernel_arch-sources-g14_files-0037-ACPI-PM-Only-mark-EC-GPE-for-wakeup-on-Intel-systems.patch
deleted file mode 100644
index c4081389ae10..000000000000
--- a/sys-kernel_arch-sources-g14_files-0037-ACPI-PM-Only-mark-EC-GPE-for-wakeup-on-Intel-systems.patch
+++ /dev/null
@@ -1,171 +0,0 @@
-From patchwork Wed Jun 30 19:46:06 2021
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Mario Limonciello <Mario.Limonciello@amd.com>
-X-Patchwork-Id: 12352783
-Return-Path: <linux-acpi-owner@kernel.org>
-X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
- aws-us-west-2-korg-lkml-1.web.codeaurora.org
-X-Spam-Level:
-X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
- DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,
- INCLUDES_PATCH,MAILING_LIST_MULTI,MSGID_FROM_MTA_HEADER,SPF_HELO_NONE,
- SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no
- version=3.4.0
-Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
- by smtp.lore.kernel.org (Postfix) with ESMTP id BEC31C11F65
- for <linux-acpi@archiver.kernel.org>; Wed, 30 Jun 2021 19:46:21 +0000 (UTC)
-Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
- by mail.kernel.org (Postfix) with ESMTP id 975CB61461
- for <linux-acpi@archiver.kernel.org>; Wed, 30 Jun 2021 19:46:21 +0000 (UTC)
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
- id S233693AbhF3Tsu (ORCPT <rfc822;linux-acpi@archiver.kernel.org>);
- Wed, 30 Jun 2021 15:48:50 -0400
-Received: from mail-dm6nam12on2075.outbound.protection.outlook.com
- ([40.107.243.75]:62305
- "EHLO NAM12-DM6-obe.outbound.protection.outlook.com"
- rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP
- id S229700AbhF3Tst (ORCPT <rfc822;linux-acpi@vger.kernel.org>);
- Wed, 30 Jun 2021 15:48:49 -0400
-ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
- b=JmnIG3cU0NKjlEyAHpokY/WgKor19FW41t1CEzkuIT/kUl9VGPGypwN9mKeLezFefiSeFdFXfz3gJHE/df1wLTomZJTjJ9pQXBnqsUxqpneeFAvqGgU9DKuHrp8cWXQZ+t39GRNUWWswzJzFpTBhQinUoKfJ7fYE/4PdtHGS3QbCvSJCrY2SO20VOhIcB0KSGJDOuLJvGdflN3dkPp8pogdC2sW5kpRU9KgrI5lGdPsUCdPyH8KO+6Pu6ApVA3EQkQIIOmCVBc0xo2s9r+cNERiCc7JeSq+sp8UPLkDahg2KiNE6t1J1ODajt2t7eENIQ/FV6Jjf+sfdGOBkl9UitQ==
-ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
- s=arcselector9901;
- h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
- bh=f9Nm9L3mznSJPWBuxu6jYs8p6of3ysIGVMyMt5nG3l0=;
- b=hTXEccprTsnbVP53d0vaEr4m4JhYYpDFqkv16OdFXj4yLaEBeElYu+8VYKDssd2dr3SrjyFCNg/7+bhWBSvdCCgL3a7BnZ4tyflMFImUPcDs3NEoYIdVc0JlyncRMa60Zyk8ZhKLd4jSbG7Fzm+nnzJqvIig3yQS7XhCeh98DrXfgOApH7+ocqBdfDK6kO51zhdmdpBb4ut/p1to3RVHw9QIaHBeN02C8kTcGQp9GkTpsEXTqbyOp8TlNLfo6I1vW3mfNNfk/P2I+3ch3mFuKBHryDDqbUIFaLbaPtPtVCL8XT26YMrdR+Uz1f5Xx9gFlg1sUoJBDvOsm23EpAYR+Q==
-ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
- smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass
- header.d=amd.com; arc=none
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1;
- h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
- bh=f9Nm9L3mznSJPWBuxu6jYs8p6of3ysIGVMyMt5nG3l0=;
- b=yPRB01odGvmaAW9iH0mvZaLxj5hRiZGy261M6i7zuJ06z+zZTtV/VTv8CKAuJjdOdiWbwoUHvkqLMGUGywQ+yh9gyN8rF27RGzQsrTOoLsq6bC9woEaxIt8KuUSo6zViHztZe+q15wEbTYwlSFZvoq/LeO1jEBqoxLHX9T+srdo=
-Authentication-Results: rjwysocki.net; dkim=none (message not signed)
- header.d=none;rjwysocki.net; dmarc=none action=none header.from=amd.com;
-Received: from SA0PR12MB4510.namprd12.prod.outlook.com (2603:10b6:806:94::8)
- by SA0PR12MB4592.namprd12.prod.outlook.com (2603:10b6:806:9b::16) with
- Microsoft SMTP Server (version=TLS1_2,
- cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4264.20; Wed, 30 Jun
- 2021 19:46:18 +0000
-Received: from SA0PR12MB4510.namprd12.prod.outlook.com
- ([fe80::9c16:2794:cd04:2be0]) by SA0PR12MB4510.namprd12.prod.outlook.com
- ([fe80::9c16:2794:cd04:2be0%6]) with mapi id 15.20.4264.026; Wed, 30 Jun 2021
- 19:46:18 +0000
-From: Mario Limonciello <mario.limonciello@amd.com>
-To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
- Len Brown <lenb@kernel.org>, linux-acpi@vger.kernel.org
-Cc: Julian Sikorski <belegdol@gmail.com>,
- Mario Limonciello <mario.limonciello@amd.com>,
- Alex Deucher <alexander.deucher@amd.com>
-Subject: [PATCH] ACPI: PM: Only mark EC GPE for wakeup on Intel systems
-Date: Wed, 30 Jun 2021 14:46:06 -0500
-Message-Id: <20210630194606.530-1-mario.limonciello@amd.com>
-X-Mailer: git-send-email 2.25.1
-X-Originating-IP: [165.204.77.1]
-X-ClientProxiedBy: SA0PR11CA0078.namprd11.prod.outlook.com
- (2603:10b6:806:d2::23) To SA0PR12MB4510.namprd12.prod.outlook.com
- (2603:10b6:806:94::8)
-MIME-Version: 1.0
-X-MS-Exchange-MessageSentRepresentingType: 1
-Received: from AUS-LX-MLIMONCI.amd.com (165.204.77.1) by
- SA0PR11CA0078.namprd11.prod.outlook.com (2603:10b6:806:d2::23) with Microsoft
- SMTP Server (version=TLS1_2,
- cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4287.22 via Frontend
- Transport; Wed, 30 Jun 2021 19:46:18 +0000
-X-MS-PublicTrafficType: Email
-X-MS-Office365-Filtering-Correlation-Id: a6884916-0dc0-4350-1182-08d93bffbad5
-X-MS-TrafficTypeDiagnostic: SA0PR12MB4592:
-X-MS-Exchange-Transport-Forked: True
-X-Microsoft-Antispam-PRVS:
- <SA0PR12MB45924771257AAAE21B3805E3E2019@SA0PR12MB4592.namprd12.prod.outlook.com>
-X-MS-Oob-TLC-OOBClassifiers: OLM:4502;
-X-MS-Exchange-SenderADCheck: 1
-X-Microsoft-Antispam: BCL:0;
-X-Microsoft-Antispam-Message-Info:
- sTNyRB8bq24xGmK+WSQ6EkvpaYmKUZAlhgGSljfEX7NiUdg5hZoYOJRQdBY63i6+bALFnzUPr+ZpmP71tYzSYUpV26yXlnrq2j3BSmYP1NJUsgpAPCve4iKGH100fNRImf73rPvc8PZOAFPQizoYOnMmIc34HCdFwwtdcg1Fe7YscTJBR9Hr3h1HTOk2Kn9JGaGHdpG8BVqYbQ5h63kzWPxn9I7x8FpW8iNcspSocBu/4Do+kT/RTEGbC4T4GHnj4thlAIUQ+6J17TAfDav9yf2elKEOxQalN2SvTgzNJyfRRXghrocv9+7Z/qDcr1lrPsLBUGhdozlxS+5YpoGxkBCM6Brcj8Ipej8xSHKLlD2xmHeNNtLCjZvCBeL26JMA8OwEM8Fpyq/m8A5x5fLw52h5Pu8+0FxHCkkS3YYjr/L8PKMezB7590sVNBLvAr2tj/FL8uT/4u4OaIGWV12RQmKRrAwso1HLPqOi4jJclanwUQOOFtWR3iCcUS5+cKqN5/ReBWeaXliDJioSwGJ8JVxjhqBdm8nWZGeb8QchWZZi7gjmpOV23u/4QpXI8/RGL60bBOeAK1rMoDkGF6gF/LagqwQZFfYQggSBO9CIF0S6U8+9i3JKuQwlfqhzudML83TsnegZLMgpGrf/hnh6n8gwGbMqIjPS9aKpPlfVHfGsAs/3mEo2SmxxxA03lMZ8S66pbN3EL5a/cI9lM0nhJSLsyAusJ4UvOyMRJTbFXQyERUNWw8qCBK8TKULU8lbK/sHbm0iJvOX82wjz/EjdeC+yIYgmwbGb7wKWzR18ieMwl9IRNPCIU6coFi7YuWThfnHmy1lL5Dtt88jtCdjxRQ==
-X-Forefront-Antispam-Report:
- CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SA0PR12MB4510.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(376002)(39860400002)(366004)(346002)(136003)(396003)(66556008)(966005)(66476007)(7696005)(52116002)(5660300002)(36756003)(186003)(8676002)(16526019)(2906002)(38100700002)(38350700002)(54906003)(44832011)(6666004)(316002)(6486002)(26005)(86362001)(83380400001)(110136005)(478600001)(956004)(66946007)(4326008)(2616005)(8936002)(1076003);DIR:OUT;SFP:1101;
-X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1
-X-MS-Exchange-AntiSpam-MessageData-0:
- Q2VMa7+27RuNEDKB8gbF7BfJMOCHBmQM8yI9OkbM9jOm3bZDMMZaTtlmhwIPD6zZ1CRxRi1s12CDZJDADpP6gX5y0/o/axPNOfsS1PrzFsualk8cP+0NOw+cigWohi0/W8wu+gBtrpTOSYTKTOF82H2X1et8jWUTuID7FCWgice4lT95yQzarHqKJadraT9Z8hSEsrDJaVs6/oABV1IMvrYVwoB3nkE9iT/fm7wmMd0i1vRFZ/WZwlCwIeOrjHu5fREwRoYtWj2tGAKBlbcYKapzdIHG0t5F/gOdW51cXCibOcN0xfGVGMGXeYGN+XjXRwxAKB/4LN4lXO/GCmJAMPuFRmlexK8sNDibFf3BOquffu3ggZ9VYLAwE2whAfAb1B/+txBs5Z4uN9G1uTScmNmyRQfmLXr9anLrMpLvPULZfDRIIBP2rs6prCjOP4sdk3zZ6H1HRFhuZJZpHKpNahgc4tqTBxlu3cTjEGUHzzM1mju6ABnqXuRHxyWfi1iiuCTIlcB2yQod9g7oi9y59LIfkwXHCJxw8idX+2jxp0EgY10ZkO33DUgCWgNhpUpC0DHv93HzWTcbJCoujMVi37i0cjaGnMOxiY/F87M1G9VfCPTum6ZXTxW4srbkq1cqiv5qXCOX28hHPisTZmXxWClBeL9crsK4udkoNzX60W5J53VV6gf7V/ZC59Cnfn0Ux/meIT2YZedYmYszau0ZqC5qJYQLaYtrzDoToXunWFVjfhls2zqiXV86PAZ9iogkjztA4PUM4A0PfA4WSFnOPmN3CwPQTnLZmvJNL0K1QV3N8QtYy+Dk1TrRSzLZAVc7gZTm3izrcd+dO271YDDasvzW2jKLbwvMOSILAHyshwfMYPVwU75Ocuu+aPlk33pA18iwAFEfElqdHw6VxKQhEzVORDoVwp6eH7zKEeoH36zjy8AZnMmruvwap3NbzRuJFnjPvmy87Kjge1oBq2wCX/+cveHiJoQPHdSk4bZue/EbWB2K70RCVR2wr42DVa/74Pb8QpZ1Rnpp4XDZ6DxLaHCXUjlpJS7hqsGW0/2Vf6IvRyChvfEQCLw659oe8vwnRxWKDF2e8/tuEHsvGPJ9OKHXAXRU/9JDeRN2eqdKdsxea8jV06ySh2BB3jxEG5hnHyDPKIWY5kV0evNPiK4PN2QkXA4UewR2StSbb8K6IYoxUI9kxIZJ4/zxjDqgn4LxIeNE6VUMZPO0z7wvqNtSdCzXSqcJNS2wtdQNaDV654FJp93h8peSqlnMVfo+gNguR2Eb25rV74+VNcIo2TlFU4RjCQWFQSwf86lBSgVzNYsFXaQs/ByUsrE+a1aY2ka+
-X-OriginatorOrg: amd.com
-X-MS-Exchange-CrossTenant-Network-Message-Id:
- a6884916-0dc0-4350-1182-08d93bffbad5
-X-MS-Exchange-CrossTenant-AuthSource: SA0PR12MB4510.namprd12.prod.outlook.com
-X-MS-Exchange-CrossTenant-AuthAs: Internal
-X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Jun 2021 19:46:18.8503
- (UTC)
-X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
-X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d
-X-MS-Exchange-CrossTenant-MailboxType: HOSTED
-X-MS-Exchange-CrossTenant-UserPrincipalName:
- dZD13ysT7xcV+BQUi/R10P8OP1E49HUQyvzNXH87rAzc7mjqBSdKPCAe3tW3LJK0/UtZNwlqjS2xSjrywZ9rNA==
-X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA0PR12MB4592
-Precedence: bulk
-List-ID: <linux-acpi.vger.kernel.org>
-X-Mailing-List: linux-acpi@vger.kernel.org
-
-When using s2idle on a variety of AMD notebook systems, they are
-experiencing spurious events that the EC or SMU are in the wrong
-state leading to a hard time waking up or higher than expected
-power consumption.
-
-These events only occur when the EC GPE is inadvertently set as a wakeup
-source. Originally the EC GPE was only set as a wakeup source when using
-the intel-vbtn or intel-hid drivers in commit 10a08fd65ec1 ("ACPI: PM:
-Set up EC GPE for system wakeup from drivers that need it") but during
-testing a reporter discovered that this was not enough for their ASUS
-Zenbook UX430UNR/i7-8550U to wakeup by lid event or keypress.
-Marking the EC GPE for wakeup universally resolved this for that
-reporter in commit b90ff3554aa3 ("ACPI: PM: s2idle: Always set up EC GPE
-for system wakeup").
-
-However this behavior has lead to a number of problems:
-
-* On both Lenovo T14 and P14s the keyboard wakeup doesn't work, and
-sometimes the power button event doesn't work.
-* On HP 635 G7 detaching or attaching AC during suspend will cause
-the system not to wakeup
-* On Asus vivobook to prevent detaching AC causing resume problems
-* On Lenovo 14ARE05 to prevent detaching AC causing resume problems
-* On HP ENVY x360 to prevent detaching AC causing resume problems
-
-As there may be other Intel systems besides ASUS Zenbook UX430UNR/i7-8550U
-that don't use intel-vbtn or intel-hid avoid these problems by only
-universally marking the EC GPE wakesource on non-AMD systems.
-
-Link: https://patchwork.kernel.org/project/linux-pm/cover/5997740.FPbUVk04hV@kreacher/#22825489
-Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1230
-Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1629
-Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-Acked-by: Alex Deucher <alexander.deucher@amd.com>
----
- drivers/acpi/x86/s2idle.c | 12 ++++++++----
- 1 file changed, 8 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
-index 816bf2c34b7a..1c507804fb10 100644
---- a/drivers/acpi/x86/s2idle.c
-+++ b/drivers/acpi/x86/s2idle.c
-@@ -417,11 +417,15 @@ static int lps0_device_attach(struct acpi_device *adev,
- mem_sleep_current = PM_SUSPEND_TO_IDLE;
-
- /*
-- * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
-- * EC GPE to be enabled while suspended for certain wakeup devices to
-- * work, so mark it as wakeup-capable.
-+ * Some Intel based LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U don't
-+ * use intel-hid or intel-vbtn but require the EC GPE to be enabled while
-+ * suspended for certain wakeup devices to work, so mark it as wakeup-capable.
-+ *
-+ * Only enable on !AMD as enabling this universally causes problems for a number
-+ * of AMD based systems.
- */
-- acpi_ec_mark_gpe_for_wake();
-+ if (!acpi_s2idle_vendor_amd())
-+ acpi_ec_mark_gpe_for_wake();
-
- return 0;
- }
diff --git a/sys-kernel_arch-sources-g14_files-0037-platform-x86-amd-pmc-Use-return-code-on-suspend.patch b/sys-kernel_arch-sources-g14_files-0037-platform-x86-amd-pmc-Use-return-code-on-suspend.patch
deleted file mode 100644
index b35a5323f78f..000000000000
--- a/sys-kernel_arch-sources-g14_files-0037-platform-x86-amd-pmc-Use-return-code-on-suspend.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-From patchwork Wed Jul 7 14:16:47 2021
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Mario Limonciello <Mario.Limonciello@amd.com>
-X-Patchwork-Id: 12362721
-Return-Path: <platform-driver-x86-owner@kernel.org>
-X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
- aws-us-west-2-korg-lkml-1.web.codeaurora.org
-X-Spam-Level:
-X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED,
- DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,
- INCLUDES_PATCH,MAILING_LIST_MULTI,MSGID_FROM_MTA_HEADER,SPF_HELO_NONE,
- SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0
-Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
- by smtp.lore.kernel.org (Postfix) with ESMTP id 60140C07E95
- for <platform-driver-x86@archiver.kernel.org>;
- Wed, 7 Jul 2021 14:17:02 +0000 (UTC)
-Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
- by mail.kernel.org (Postfix) with ESMTP id 4272D61CBF
- for <platform-driver-x86@archiver.kernel.org>;
- Wed, 7 Jul 2021 14:17:02 +0000 (UTC)
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
- id S231787AbhGGOTm (ORCPT
- <rfc822;platform-driver-x86@archiver.kernel.org>);
- Wed, 7 Jul 2021 10:19:42 -0400
-Received: from mail-dm6nam12on2040.outbound.protection.outlook.com
- ([40.107.243.40]:30812
- "EHLO NAM12-DM6-obe.outbound.protection.outlook.com"
- rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP
- id S231718AbhGGOTl (ORCPT
- <rfc822;platform-driver-x86@vger.kernel.org>);
- Wed, 7 Jul 2021 10:19:41 -0400
-ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
- b=k0W2C0lXK5509UfwTN6QtRX27ElZ9tFDgWkZpvHpZ7kJamBn+4F6lzgWMNZNY6ly+yppN1kLlMt2dcnyQozx/XWD4xUW1o79yh4idMsSmz9kqnskW5hq178yMvYYxjkwvPWLB/NBXLb/TEz1N38rMSrcRbNR5IbXm3lVuphd1y9bZHxQeUEAXgf/3mAMClHqP3ya7uUtBPuf2+oSk7O1oHaqcZcHDcuU43rbnbTmKApJ+JR/XUpPWIBnr9V+nY3ODLi7BLRfZdXbytzcsj4gj7lL//U2tX6pN/5LOEbJwwGqHQlxLIr9Nif7FCMe/fEtYS3pRjyxlAQIKceam1Mqgg==
-ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
- s=arcselector9901;
- h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
- bh=isGCQcbhgntdb/xokuLHsVWJtEX5YAh+fg/NJ0ex46M=;
- b=h3tD5XHOjJ0S/zbEn14A/Ub5QHOKFJgT2p5H2SoXUQPwLF6lmbrNbcJp6eesHkHDw/Vbo0Gm/j3CMzzpo3rAPBdHqbjzswyUm4iRMed0hIoJ2EEQCB1nhGZgoObTHjpQcZf7HKcFPnOfX2YYS9z5XDZBP4Fz4LK+h5YKRoNvZtDOwDePDI6p9gsoToAP6NYy+I72mLn6cRnRwhUrGKZJVFfEyjYRptL3oc4S7rxpXC5YguvAwk/Te2wPSUJSNFwYVkTJwPmfWu9pmlBv8iTyQFuwssKc98h2H5ikLRLf7YpOiI/XfQfjOz+aElCkfWBuUsYRA7KLePtRZl97VkhI1A==
-ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
- smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass
- header.d=amd.com; arc=none
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1;
- h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
- bh=isGCQcbhgntdb/xokuLHsVWJtEX5YAh+fg/NJ0ex46M=;
- b=roJQ8gko57Hb8CaBE/EYLru6ickefCtnfAsBOjh2/C14etws0Smk5RcCiPG9lsbuyZg1E2w1uicNVKCFEqKm1rgbIHQ6OTJ/RaWVg2bxjPosYH1K6MS1yLjsRpwFINQIpbkDyhzSgfwk4/myP5xRk+YbxOZ1R74zDemr2Pu7TnQ=
-Authentication-Results: redhat.com; dkim=none (message not signed)
- header.d=none;redhat.com; dmarc=none action=none header.from=amd.com;
-Received: from SA0PR12MB4510.namprd12.prod.outlook.com (2603:10b6:806:94::8)
- by SN6PR12MB2767.namprd12.prod.outlook.com (2603:10b6:805:75::23) with
- Microsoft SMTP Server (version=TLS1_2,
- cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4287.33; Wed, 7 Jul
- 2021 14:17:00 +0000
-Received: from SA0PR12MB4510.namprd12.prod.outlook.com
- ([fe80::c05f:7a93:601b:9861]) by SA0PR12MB4510.namprd12.prod.outlook.com
- ([fe80::c05f:7a93:601b:9861%6]) with mapi id 15.20.4287.033; Wed, 7 Jul 2021
- 14:17:00 +0000
-From: Mario Limonciello <mario.limonciello@amd.com>
-To: Hans de Goede <hdegoede@redhat.com>,
- Mark Gross <mgross@linux.intel.com>,
- platform-driver-x86@vger.kernel.org (open list:X86 PLATFORM DRIVERS)
-Cc: Mario Limonciello <mario.limonciello@amd.com>,
- Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Subject: [PATCH] platform/x86: amd-pmc: Use return code on suspend
-Date: Wed, 7 Jul 2021 09:16:47 -0500
-Message-Id: <20210707141647.8871-1-mario.limonciello@amd.com>
-X-Mailer: git-send-email 2.25.1
-X-ClientProxiedBy: SN4PR0501CA0042.namprd05.prod.outlook.com
- (2603:10b6:803:41::19) To SA0PR12MB4510.namprd12.prod.outlook.com
- (2603:10b6:806:94::8)
-MIME-Version: 1.0
-X-MS-Exchange-MessageSentRepresentingType: 1
-Received: from AUS-LX-MLIMONCI.amd.com (165.204.77.1) by
- SN4PR0501CA0042.namprd05.prod.outlook.com (2603:10b6:803:41::19) with
- Microsoft SMTP Server (version=TLS1_2,
- cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4308.8 via Frontend
- Transport; Wed, 7 Jul 2021 14:16:59 +0000
-X-MS-PublicTrafficType: Email
-X-MS-Office365-Filtering-Correlation-Id: a19b1585-ba5f-4bec-bce4-08d94151e29d
-X-MS-TrafficTypeDiagnostic: SN6PR12MB2767:
-X-MS-Exchange-Transport-Forked: True
-X-Microsoft-Antispam-PRVS:
- <SN6PR12MB2767D71FF0391027D193AADCE21A9@SN6PR12MB2767.namprd12.prod.outlook.com>
-X-MS-Oob-TLC-OOBClassifiers: OLM:3044;
-X-MS-Exchange-SenderADCheck: 1
-X-Microsoft-Antispam: BCL:0;
-X-Microsoft-Antispam-Message-Info:
- 6AhBzvacjkr9Cck62JDESL5RE3LYrtbTWbODIt7/jXGKkb+Wmr1c+sXbUB0R+RJnwf6gmW/qwBOpPRyU2r7PZ5bpd99awOkBLJpG99BL71brvzsKHQXi4Af+Ftom1dtpZItZtBK3XkhswauUupbSSM7JFtpL7hB6GzE5Nttb7Fjk5Tj+ixR5hKeZiitlXrW5gLZww8jCR6bPP+OUzHesAqBm9yjOqnxSBFIx1019kPJo3EAc4ilVX6kj/9b2ICU1AAtgI5PJ05xIURxODGWQuRXtwLKP/gfZKSrecCGULGZdksIyUJfjfBFLiqKUGH8lrzNHIwMwDptgK1vdhvZtahkeRXOKZi5PqohKdLi61fHOKDR2KKQQk1BYS+Zc43AJpuQSTg7n8BexHUkW4pkYuFlgOXwk5IZIwYYLp0OXyLR7pQ0BskHhZ2+r5vSG4VpYGVdl8AxXMfSmroAjQqSIICIrNB/IQ0VT9x1YylzX1y43o+G1SaYshv/d1hhos8evRnHxRwWnIzOqw074GnS6RETf9EguaM+7x2SXR/8ePRoOgj9tiXRk4WYSIYCXZCS72sHGHELYBIiSUFXCn2sC9weSVW5apespetuZzyW5kCtdF8ljiS9N1ycwejjZF+VSVKvQ87cl63k7w9WSLaAV+B67PeZ/85Y6jN2KO+Y/D1p9SfVius/QKiFX9JtsGl1VytgbXjVLIvaHeTZ64moeag==
-X-Forefront-Antispam-Report:
- CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SA0PR12MB4510.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(136003)(366004)(396003)(346002)(376002)(39860400002)(15650500001)(478600001)(8676002)(5660300002)(7696005)(44832011)(4744005)(36756003)(8936002)(956004)(66476007)(66946007)(110136005)(2906002)(54906003)(83380400001)(66556008)(316002)(38350700002)(1076003)(186003)(2616005)(86362001)(26005)(38100700002)(52116002)(4326008)(6666004)(6486002);DIR:OUT;SFP:1101;
-X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1
-X-MS-Exchange-AntiSpam-MessageData-0:
- GRYYR8rjMIz7s6ETrmtKfGQRdFU5uBK2V3x+PvQn1DuKHLsuubpERiwqkqY5eq5hG3QPZoYGj5kni8d0vlsok1rw4ZdQ7hMKlZILbx2lwojEwzaYlKIq8R4etvy1N6S7r/4ejmV16+uezsegm0qQWbSg724GtrGXe2ZZInIiHSjT1+DCimO4eE1WbRoeR8jtsw7Q+9XZTo4FSjdTlFu7UWOwk4Nlvj8HUFtVkfJJNGQHLY+HlVEwchRSaIGShF8235o/Wwt1abwmabOEWhHIBKXJlVEFIXsJJBm5wQjaxQhCEExsHu57ttDKUs4lT7b5d7YZHDYHCCIW3i2V0vKtqHkysPbIKIzt7Tk/8r4UEsVx7iIpFl2oFh41JwhafzDiZhWT9Pzxp4GxfbCCIGl39uBoyz+j6uV+Vp+nEQqbpSWOVMNBk/sE0HNsx6kl3t+ojvSCb1qN4/TrQFVDT7c4HRDTymo81n7eKVwUjy+heQmrq9KKrDPwe7pFyJs7NrqQWuJYjGtfdsEHVGX8KmiSMcyUjchK+ECRrD5E0IPpv9csjj5My9PjKxBnXc7nUoQ2oB+gAkZCQTUJLGjPgRXUTpM9K88qF08RTP7t6hzoH2oOWtDkasYBEgK8Vh7OFrDwJo3zdop11IYWXuU1EhOTN4obY0hYOck0mdI46VTZeji13cX7X4LuvvYBRyx/XpmdhRcvS6niUjp+iaFyPQlj39isqz9JN8j1FfISy1y8v29/Dux46l879EC+OTMoBmb+GABwg1y/LzzaUcLoE3Hfy3fjtwoVyrQT4jahLesqfCD0SgNEX6lReHBdldxi2zqwUpqFTyQ4CRuDB3g60tljlmgbAGa38B8xo7uL9xiHzXks1792DRzZ7SC6kO/YQAuPw3idjws2HmXyQdqsLCdg1eiLwaCC+YhJccehsLfoWpAU1HcmohGB+EIExmcChun2OrmCzKNGk/VdXWcAn35F/fXUUMRovtFZ8D0r9Cp7nDCTUrhzqRW3cILRlVt0nwaIVYWmiS2DBGl2WYn6TT7S9fBIQll2ApKYs4xMw4QIJX/YS3YCUpebhqnmqVwsn3FNi+IPrMsV9Jm3Snr5UpTBixhLhudYP1rzb9DX/xSaxxskz1TC2VKXHqg7dkpnkDOfsSkZK6Caec0GTUAoBVoBKRAem/zwMYd0u22CfqpI7U5lnp8wgpkWAH63TH9Vxg1f3SLW9jKDrLRkLoF64MEJKRlhr7z03D5EA4Apl+Mrn1QWIM2ywAomaDfKICj8iG+gWngAsTk+YI0q0l3GsoH5OKFiqE3/GB+fu+mxMEcft39cb+Z1LhXZDH9/nPX/636R
-X-OriginatorOrg: amd.com
-X-MS-Exchange-CrossTenant-Network-Message-Id:
- a19b1585-ba5f-4bec-bce4-08d94151e29d
-X-MS-Exchange-CrossTenant-AuthSource: SA0PR12MB4510.namprd12.prod.outlook.com
-X-MS-Exchange-CrossTenant-AuthAs: Internal
-X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Jul 2021 14:17:00.0905
- (UTC)
-X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
-X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d
-X-MS-Exchange-CrossTenant-MailboxType: HOSTED
-X-MS-Exchange-CrossTenant-UserPrincipalName:
- Ca0ndGjyAnWX69uDR8h2RlVWpnGzyjbhvqx7Gpv45yyGfXDhs9seNOPoHUS+QcO3WV0CMN7tZBe+3BooTd9Xvg==
-X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR12MB2767
-Precedence: bulk
-List-ID: <platform-driver-x86.vger.kernel.org>
-X-Mailing-List: platform-driver-x86@vger.kernel.org
-
-Right now the driver will still return success even if the OS_HINT
-command failed to send to the SMU. In the rare event of a failure,
-the suspend should really be aborted here so that relevant logs
-can may be captured.
-
-Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
----
- drivers/platform/x86/amd-pmc.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
-index d2f9a62e1166..680f94c7e075 100644
---- a/drivers/platform/x86/amd-pmc.c
-+++ b/drivers/platform/x86/amd-pmc.c
-@@ -353,7 +353,7 @@ static int __maybe_unused amd_pmc_suspend(struct device *dev)
- if (rc)
- dev_err(pdev->dev, "suspend failed\n");
-
-- return 0;
-+ return rc;
- }
-
- static int __maybe_unused amd_pmc_resume(struct device *dev)
diff --git a/sys-kernel_arch-sources-g14_files-0040-asus-wmi-Add-dgpu-disable-method.patch b/sys-kernel_arch-sources-g14_files-0040-asus-wmi-Add-dgpu-disable-method.patch
deleted file mode 100644
index 415590fd6094..000000000000
--- a/sys-kernel_arch-sources-g14_files-0040-asus-wmi-Add-dgpu-disable-method.patch
+++ /dev/null
@@ -1,182 +0,0 @@
-From de08016c5ef567c853dcf2ff8d9c9b352af253b6 Mon Sep 17 00:00:00 2001
-From: "Luke D. Jones" <luke@ljones.dev>
-Date: Sat, 17 Jul 2021 20:13:22 +1200
-Subject: [PATCH 102/103] asus-wmi: Add dgpu disable method
-
-In Windows the ASUS Armory Crate program can enable or disable the
-dGPU via a WMI call. This functions much the same as various Linux
-methods in software where the dGPU is removed from the device tree.
-
-However the WMI call saves the state of dGPU (enabled or not) and
-this then changes the dGPU visibility in Linux with no way for
-Linux users to re-enable it. We expose the WMI method so users can
-see and change the dGPU ACPI state.
-
-Signed-off-by: Luke D. Jones <luke@ljones.dev>
----
- drivers/platform/x86/asus-wmi.c | 99 ++++++++++++++++++++++
- include/linux/platform_data/x86/asus-wmi.h | 3 +
- 2 files changed, 102 insertions(+)
-
-diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
-index cd881443bc2f..02762a60d27a 100644
---- a/drivers/platform/x86/asus-wmi.c
-+++ b/drivers/platform/x86/asus-wmi.c
-@@ -210,6 +210,9 @@ struct asus_wmi {
- u8 fan_boost_mode_mask;
- u8 fan_boost_mode;
-
-+ bool dgpu_disable_available;
-+ bool dgpu_disable;
-+
- bool throttle_thermal_policy_available;
- u8 throttle_thermal_policy_mode;
-
-@@ -427,6 +430,94 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus)
- }
- }
-
-+/* dGPU ********************************************************************/
-+static int dgpu_disable_check_present(struct asus_wmi *asus)
-+{
-+ u32 result;
-+ int err;
-+
-+ asus->dgpu_disable_available = false;
-+
-+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_DGPU, &result);
-+ if (err) {
-+ if (err == -ENODEV)
-+ return 0;
-+ return err;
-+ }
-+
-+ if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
-+ asus->dgpu_disable_available = true;
-+ asus->dgpu_disable = result & ASUS_WMI_DSTS_STATUS_BIT;
-+ }
-+
-+ return 0;
-+}
-+
-+static int dgpu_disable_write(struct asus_wmi *asus)
-+{
-+ int err;
-+ u8 value;
-+ u32 retval;
-+
-+ value = asus->dgpu_disable;
-+
-+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, value, &retval);
-+
-+ if (err) {
-+ pr_warn("Failed to set dgpu disable: %d\n", err);
-+ return err;
-+ }
-+
-+ if (retval > 1 || retval < 0) {
-+ pr_warn("Failed to set dgpu disable (retval): 0x%x\n", retval);
-+ return -EIO;
-+ }
-+
-+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "dgpu_disable");
-+
-+ return 0;
-+}
-+
-+static ssize_t dgpu_disable_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ bool mode = asus->dgpu_disable;
-+
-+ return sysfs_emit(buf, "%d\n", mode);
-+}
-+
-+static ssize_t dgpu_disable_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ int result;
-+ bool disable;
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+
-+ result = kstrtobool(buf, &disable);
-+ if (result == -EINVAL)
-+ return result;
-+
-+ asus->dgpu_disable = disable;
-+ /*
-+ * The ACPI call used does not save the mode unless the call is run twice.
-+ * Once to disable, then once to check status and save - this is two code
-+ * paths in the method in the ACPI dumps.
-+ */
-+ result = dgpu_disable_write(asus);
-+ if (result != 0)
-+ return result;
-+
-+ result = dgpu_disable_write(asus);
-+ if (result != 0)
-+ return result;
-+
-+ return count;
-+}
-+
-+static DEVICE_ATTR_RW(dgpu_disable);
-+
- /* Battery ********************************************************************/
-
- /* The battery maximum charging percentage */
-@@ -2411,6 +2502,7 @@ static struct attribute *platform_attributes[] = {
- &dev_attr_camera.attr,
- &dev_attr_cardr.attr,
- &dev_attr_touchpad.attr,
-+ &dev_attr_dgpu_disable.attr,
- &dev_attr_lid_resume.attr,
- &dev_attr_als_enable.attr,
- &dev_attr_fan_boost_mode.attr,
-@@ -2437,6 +2529,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
- devid = ASUS_WMI_DEVID_LID_RESUME;
- else if (attr == &dev_attr_als_enable.attr)
- devid = ASUS_WMI_DEVID_ALS_ENABLE;
-+ else if (attr == &dev_attr_dgpu_disable.attr)
-+ ok = asus->dgpu_disable_available;
- else if (attr == &dev_attr_fan_boost_mode.attr)
- ok = asus->fan_boost_mode_available;
- else if (attr == &dev_attr_throttle_thermal_policy.attr)
-@@ -2698,6 +2792,10 @@ static int asus_wmi_add(struct platform_device *pdev)
- if (err)
- goto fail_platform;
-
-+ err = dgpu_disable_check_present(asus);
-+ if (err)
-+ goto fail_dgpu_disable;
-+
- err = fan_boost_mode_check_present(asus);
- if (err)
- goto fail_fan_boost_mode;
-@@ -2798,6 +2896,7 @@ static int asus_wmi_add(struct platform_device *pdev)
- fail_sysfs:
- fail_throttle_thermal_policy:
- fail_fan_boost_mode:
-+fail_dgpu_disable:
- fail_platform:
- fail_panel_od:
- kfree(asus);
-diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
-index 428aea701c7b..a528f9d0e4b7 100644
---- a/include/linux/platform_data/x86/asus-wmi.h
-+++ b/include/linux/platform_data/x86/asus-wmi.h
-@@ -90,6 +90,9 @@
- /* Keyboard dock */
- #define ASUS_WMI_DEVID_KBD_DOCK 0x00120063
-
-+/* dgpu on/off */
-+#define ASUS_WMI_DEVID_DGPU 0x00090020
-+
- /* DSTS masks */
- #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001
- #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002
---
-2.32.0
-
diff --git a/sys-kernel_arch-sources-g14_files-0041-asus-wmi-Add-egpu-enable-method.patch b/sys-kernel_arch-sources-g14_files-0041-asus-wmi-Add-egpu-enable-method.patch
deleted file mode 100644
index 13804605dc37..000000000000
--- a/sys-kernel_arch-sources-g14_files-0041-asus-wmi-Add-egpu-enable-method.patch
+++ /dev/null
@@ -1,169 +0,0 @@
-From 49872973ce89a5778cd57094eb2eebba530b1244 Mon Sep 17 00:00:00 2001
-From: "Luke D. Jones" <luke@ljones.dev>
-Date: Sat, 17 Jul 2021 20:13:23 +1200
-Subject: [PATCH 103/103] asus-wmi: Add egpu enable method
-
-The X13 Flow laptops can utilise an external GPU. This requires
-toggling an ACPI method which will first disable the internal
-dGPU, and then enable the eGPU.
-
-Signed-off-by: Luke D. Jones <luke@ljones.dev>
----
- drivers/platform/x86/asus-wmi.c | 91 ++++++++++++++++++++++
- include/linux/platform_data/x86/asus-wmi.h | 3 +
- 2 files changed, 94 insertions(+)
-
-diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
-index 02762a60d27a..ee5d8656641e 100644
---- a/drivers/platform/x86/asus-wmi.c
-+++ b/drivers/platform/x86/asus-wmi.c
-@@ -210,6 +210,9 @@ struct asus_wmi {
- u8 fan_boost_mode_mask;
- u8 fan_boost_mode;
-
-+ bool egpu_enable_available; // 0 = enable
-+ bool egpu_enable;
-+
- bool dgpu_disable_available;
- bool dgpu_disable;
-
-@@ -430,6 +433,86 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus)
- }
- }
-
-+/* eGPU ********************************************************************/
-+static int egpu_enable_check_present(struct asus_wmi *asus)
-+{
-+ u32 result;
-+ int err;
-+
-+ asus->egpu_enable_available = false;
-+
-+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_EGPU, &result);
-+ if (err) {
-+ if (err == -ENODEV)
-+ return 0;
-+ return err;
-+ }
-+
-+ if (result & ASUS_WMI_DSTS_PRESENCE_BIT) {
-+ asus->egpu_enable_available = true;
-+ asus->egpu_enable = result & ASUS_WMI_DSTS_STATUS_BIT;
-+ }
-+
-+ return 0;
-+}
-+
-+static int egpu_enable_write(struct asus_wmi *asus)
-+{
-+ int err;
-+ u8 value;
-+ u32 retval;
-+
-+ value = asus->egpu_enable;
-+
-+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, value, &retval);
-+
-+ if (err) {
-+ pr_warn("Failed to set egpu disable: %d\n", err);
-+ return err;
-+ }
-+
-+ if (retval > 1 || retval < 0) {
-+ pr_warn("Failed to set egpu disable (retval): 0x%x\n", retval);
-+ return -EIO;
-+ }
-+
-+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "egpu_enable");
-+
-+ return 0;
-+}
-+
-+static ssize_t egpu_enable_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ bool mode = asus->egpu_enable;
-+
-+ return sysfs_emit(buf, "%d\n", mode);
-+}
-+
-+static ssize_t egpu_enable_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ int result;
-+ bool disable;
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+
-+ result = kstrtobool(buf, &disable);
-+ if (result == -EINVAL)
-+ return result;
-+
-+ asus->egpu_enable = disable;
-+
-+ result = egpu_enable_write(asus);
-+ if (result != 0)
-+ return result;
-+
-+ return count;
-+}
-+
-+static DEVICE_ATTR_RW(egpu_enable);
-+
- /* dGPU ********************************************************************/
- static int dgpu_disable_check_present(struct asus_wmi *asus)
- {
-@@ -2502,6 +2585,7 @@ static struct attribute *platform_attributes[] = {
- &dev_attr_camera.attr,
- &dev_attr_cardr.attr,
- &dev_attr_touchpad.attr,
-+ &dev_attr_egpu_enable.attr,
- &dev_attr_dgpu_disable.attr,
- &dev_attr_lid_resume.attr,
- &dev_attr_als_enable.attr,
-@@ -2529,6 +2613,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
- devid = ASUS_WMI_DEVID_LID_RESUME;
- else if (attr == &dev_attr_als_enable.attr)
- devid = ASUS_WMI_DEVID_ALS_ENABLE;
-+ else if (attr == &dev_attr_egpu_enable.attr)
-+ ok = asus->egpu_enable_available;
- else if (attr == &dev_attr_dgpu_disable.attr)
- ok = asus->dgpu_disable_available;
- else if (attr == &dev_attr_fan_boost_mode.attr)
-@@ -2792,6 +2878,10 @@ static int asus_wmi_add(struct platform_device *pdev)
- if (err)
- goto fail_platform;
-
-+ err = egpu_enable_check_present(asus);
-+ if (err)
-+ goto fail_egpu_enable;
-+
- err = dgpu_disable_check_present(asus);
- if (err)
- goto fail_dgpu_disable;
-@@ -2896,6 +2986,7 @@ static int asus_wmi_add(struct platform_device *pdev)
- fail_sysfs:
- fail_throttle_thermal_policy:
- fail_fan_boost_mode:
-+fail_egpu_enable:
- fail_dgpu_disable:
- fail_platform:
- fail_panel_od:
-diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
-index a528f9d0e4b7..17dc5cb6f3f2 100644
---- a/include/linux/platform_data/x86/asus-wmi.h
-+++ b/include/linux/platform_data/x86/asus-wmi.h
-@@ -90,6 +90,9 @@
- /* Keyboard dock */
- #define ASUS_WMI_DEVID_KBD_DOCK 0x00120063
-
-+/* dgpu on/off */
-+#define ASUS_WMI_DEVID_EGPU 0x00090019
-+
- /* dgpu on/off */
- #define ASUS_WMI_DEVID_DGPU 0x00090020
-
---
-2.32.0
-
diff --git a/sys-kernel_arch-sources-g14_files-0042-HID-asus-Remove-check-for-same-LED-brightness-on-set.patch b/sys-kernel_arch-sources-g14_files-0042-HID-asus-Remove-check-for-same-LED-brightness-on-set.patch
deleted file mode 100644
index 65bee17ead27..000000000000
--- a/sys-kernel_arch-sources-g14_files-0042-HID-asus-Remove-check-for-same-LED-brightness-on-set.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From ed4bd51509d971f5cc0d1ddffa30acbe4c65969c Mon Sep 17 00:00:00 2001
-From: "Luke D. Jones" <luke@ljones.dev>
-Date: Sun, 6 Jun 2021 11:03:33 +1200
-Subject: [PATCH] HID: asus: Remove check for same LED brightness on set
-
-Remove the early return on LED brightness set. This is required
-because many ASUS ROG keyboards will default to max brightness on
-laptop resume if the LEDs were set to off before sleep.
-
-Signed-off-by: Luke D Jones <luke@ljones.dev>
----
- drivers/hid/hid-asus.c | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
-index 60606c11bdaf..19da81d2a910 100644
---- a/drivers/hid/hid-asus.c
-+++ b/drivers/hid/hid-asus.c
-@@ -486,9 +486,6 @@ static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
- {
- struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
- cdev);
-- if (led->brightness == brightness)
-- return;
--
- led->brightness = brightness;
- schedule_work(&led->work);
- }
---
-2.31.1
diff --git a/sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch b/sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch
index aa6919698f41..ce6665e3db5d 100644
--- a/sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch
+++ b/sys-kernel_arch-sources-g14_files-0046-fan-curvers.patch
@@ -1,59 +1,60 @@
-From 094c3ed89ed4a86933f69838679f4222ba288aa4 Mon Sep 17 00:00:00 2001
+From cfd3291fa2a77bf1029646da5945d83d1021609a Mon Sep 17 00:00:00 2001
From: "Luke D. Jones" <luke@ljones.dev>
Date: Sun, 29 Aug 2021 13:21:23 +1200
-Subject: [PATCH v6] asus-wmi: Add support for custom fan curves
+Subject: [PATCH v14 1/1] asus-wmi: Add support for custom fan curves
Add support for custom fan curves found on some ASUS ROG laptops.
These laptops have the ability to set a custom curve for the CPU
-and GPU fans via an ACPI method call. This patch enables this,
-additionally enabling custom fan curves per-profile, where profile
-here means each of the 3 levels of "throttle_thermal_policy".
+and GPU fans via two ACPI methods.
-The format for input fan curves is
-"30:1,49:2,59:3,69:4,79:31,89:49,99:56,109:58"
-where each block of "30:1," is one point on the curve, and 30c, 1%
-of fan RPM up to 100%. This follows the internal WMI format. This
-format was chosen as it is used heavily by pre-existing utilities
-that were based on using the acpi_call module. Further, each pair
-can be defined as "T[ c:]P[ %,]" resulting in "30c:1%,", "30c1 "
-or similar with a max of two chars between values.
+This patch adds two pwm<N> attributes to the hwmon sysfs,
+pwm1 for CPU fan, pwm2 for GPU fan. Both are under the hwmon of the
+name `asus_custom_fan_curve`. There is no safety check of the set
+fan curves - this must be done in userspace.
+
+The fans have settings [1,2,3] under pwm<N>_enable:
+1. Enable and write settings out
+2. Disable and use factory fan mode
+3. Same as 2, additionally restoring default factory curve.
+
+Use of 2 means that the curve the user has set is still stored and
+won't be erased, but the laptop will be using its default auto-fan
+mode. Re-enabling the manual mode then activates the curves again.
+
+Notes:
+- pwm<N>_enable = 0 is an invalid setting.
+- pwm is actually a percentage and is scaled on writing to device.
Signed-off-by: Luke D. Jones <luke@ljones.dev>
---
- drivers/platform/x86/asus-wmi.c | 488 ++++++++++++++++++++-
+ drivers/platform/x86/asus-wmi.c | 611 ++++++++++++++++++++-
include/linux/platform_data/x86/asus-wmi.h | 2 +
- 2 files changed, 488 insertions(+), 2 deletions(-)
+ 2 files changed, 605 insertions(+), 8 deletions(-)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
-index cc5811844012..dccdd41917ff 100644
+index e14fb5fa7324..7569f34bac3e 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
-@@ -106,8 +106,23 @@ module_param(fnlock_default, bool, 0444);
+@@ -106,8 +106,17 @@ module_param(fnlock_default, bool, 0444);
#define WMI_EVENT_MASK 0xFFFF
-+/* The number of ASUS_THROTTLE_THERMAL_POLICY_* available */
-+#define NUM_FAN_CURVE_PROFILES 3
-+#define NUM_FAN_CURVE_POINTS 8
-+#define NUM_FAN_CURVE_DATA (NUM_FAN_CURVE_POINTS * 2)
++#define FAN_CURVE_POINTS 8
++#define FAN_CURVE_BUF_LEN (FAN_CURVE_POINTS * 2)
++#define FAN_CURVE_DEV_CPU 0x00
++#define FAN_CURVE_DEV_GPU 0x01
++/* Mask to determine if setting temperature or percentage */
++#define FAN_CURVE_PWM_MASK 0x04
+
static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
-+/*
-+ * The order here matters, index positions reflect
-+ * ASUS_THROTTLE_THERMAL_POLICY_<name>
-+ */
-+static const char * const fan_curve_names[] = {
-+ "balanced", "performance", "quiet"
-+};
-+
+static int throttle_thermal_policy_write(struct asus_wmi *);
+
static bool ashs_present(void)
{
int i = 0;
-@@ -122,7 +137,8 @@ struct bios_args {
+@@ -122,7 +131,8 @@ struct bios_args {
u32 arg0;
u32 arg1;
u32 arg2; /* At least TUF Gaming series uses 3 dword input buffer. */
@@ -63,49 +64,38 @@ index cc5811844012..dccdd41917ff 100644
u32 arg5;
} __packed;
-@@ -173,6 +189,29 @@ enum fan_type {
+@@ -173,6 +183,19 @@ enum fan_type {
FAN_TYPE_SPEC83, /* starting in Spec 8.3, use CPU_FAN_CTRL */
};
-+enum fan_device {
-+ FAN_DEVICE_CPU = 0,
-+ FAN_DEVICE_GPU,
-+};
-+
-+/*
-+ * Each temps[n] is paired with percents[n]
-+ */
-+struct fan_curve {
-+ u8 temps[NUM_FAN_CURVE_POINTS];
-+ u8 percents[NUM_FAN_CURVE_POINTS];
-+};
-+
+/*
+ * The related ACPI method for testing availability also returns the factory
+ * default fan curves. We save them here so that a user can reset custom
+ * settings if required.
+ */
+struct fan_curve_data {
-+ struct fan_curve custom;
-+ struct fan_curve defaults;
++ bool enabled;
++ u8 temps[FAN_CURVE_POINTS];
++ u8 percents[FAN_CURVE_POINTS];
++ u8 default_temps[FAN_CURVE_POINTS];
++ u8 default_percents[FAN_CURVE_POINTS];
+};
+
struct asus_wmi {
int dsts_id;
int spec;
-@@ -220,6 +259,11 @@ struct asus_wmi {
+@@ -220,6 +243,10 @@ struct asus_wmi {
bool throttle_thermal_policy_available;
u8 throttle_thermal_policy_mode;
+ bool cpu_fan_curve_available;
+ bool gpu_fan_curve_available;
-+ bool fan_curves_enabled[NUM_FAN_CURVE_PROFILES];
-+ struct fan_curve_data throttle_fan_curves[NUM_FAN_CURVE_PROFILES][2];
++ struct fan_curve_data custom_fan_curves[2];
+
struct platform_profile_handler platform_profile_handler;
bool platform_profile_support;
-@@ -285,6 +329,84 @@ int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval)
+@@ -285,6 +312,103 @@ int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval)
}
EXPORT_SYMBOL_GPL(asus_wmi_evaluate_method);
@@ -151,7 +141,7 @@ index cc5811844012..dccdd41917ff 100644
+ * means that the method called is unsupported.
+ */
+static int asus_wmi_evaluate_method_buf(u32 method_id,
-+ u32 arg0, u32 arg1, u8 *ret_buffer)
++ u32 arg0, u32 arg1, u8 *ret_buffer, size_t size)
+{
+ struct bios_args args = {
+ .arg0 = arg0,
@@ -162,7 +152,7 @@ index cc5811844012..dccdd41917ff 100644
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+ acpi_status status;
+ union acpi_object *obj;
-+ u32 int_tmp = 0;
++ int err = 0;
+
+ status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,
+ &input, &output);
@@ -172,182 +162,228 @@ index cc5811844012..dccdd41917ff 100644
+
+ obj = (union acpi_object *)output.pointer;
+
-+ if (obj && obj->type == ACPI_TYPE_INTEGER) {
-+ int_tmp = (u32) obj->integer.value;
-+ if (int_tmp == ASUS_WMI_UNSUPPORTED_METHOD)
-+ return -ENODEV;
-+ return int_tmp;
-+ }
++ switch (obj->type) {
++ case ACPI_TYPE_BUFFER:
++ if (obj->buffer.length > size)
++ err = -ENOSPC;
++ if (obj->buffer.length == 0)
++ err = -ENODATA;
+
-+ if (obj && obj->type == ACPI_TYPE_BUFFER)
+ memcpy(ret_buffer, obj->buffer.pointer, obj->buffer.length);
++ break;
++ case ACPI_TYPE_INTEGER:
++ err = (u32)obj->integer.value;
++
++ if (err == ASUS_WMI_UNSUPPORTED_METHOD)
++ err = -ENODEV;
++ /*
++ * At least one method returns a 0 with no buffer if no arg
++ * is provided, such as ASUS_WMI_DEVID_CPU_FAN_CURVE
++ */
++ if (err == 0)
++ err = -ENODATA;
++ break;
++ default:
++ err = -ENODATA;
++ break;
++ }
+
+ kfree(obj);
+
++ if (err)
++ return err;
++
+ return 0;
+}
+
static int asus_wmi_evaluate_method_agfn(const struct acpi_buffer args)
{
struct acpi_buffer input;
-@@ -2043,6 +2165,330 @@ static ssize_t fan_boost_mode_store(struct device *dev,
+@@ -1806,6 +1930,13 @@ static ssize_t pwm1_enable_store(struct device *dev,
+ }
+
+ asus->fan_pwm_mode = state;
++
++ /* Must set to disabled if mode is toggled */
++ if (asus->cpu_fan_curve_available)
++ asus->custom_fan_curves[FAN_CURVE_DEV_CPU].enabled = false;
++ if (asus->gpu_fan_curve_available)
++ asus->custom_fan_curves[FAN_CURVE_DEV_GPU].enabled = false;
++
+ return count;
+ }
+
+@@ -1953,9 +2084,9 @@ static int fan_boost_mode_check_present(struct asus_wmi *asus)
+
+ static int fan_boost_mode_write(struct asus_wmi *asus)
+ {
+- int err;
+- u8 value;
+ u32 retval;
++ u8 value;
++ int err;
+
+ value = asus->fan_boost_mode;
+
+@@ -2013,10 +2144,10 @@ static ssize_t fan_boost_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- int result;
+- u8 new_mode;
+ struct asus_wmi *asus = dev_get_drvdata(dev);
+ u8 mask = asus->fan_boost_mode_mask;
++ u8 new_mode;
++ int result;
+
+ result = kstrtou8(buf, 10, &new_mode);
+ if (result < 0) {
+@@ -2043,6 +2174,458 @@ static ssize_t fan_boost_mode_store(struct device *dev,
// Fan boost mode: 0 - normal, 1 - overboost, 2 - silent
static DEVICE_ATTR_RW(fan_boost_mode);
+/* Custom fan curves per-profile **********************************************/
+
-+static void copy_fan_curve_buf(struct fan_curve *data, u8 *buf)
++static void fan_curve_copy_from_buf(struct fan_curve_data *data, u8 *buf)
+{
+ int i;
+
-+ for (i = 0; i < NUM_FAN_CURVE_POINTS; i++)
++ for (i = 0; i < FAN_CURVE_POINTS; i++) {
+ data->temps[i] = buf[i];
++ data->default_temps[i] = buf[i];
++ }
+
-+ for (i = 0; i < NUM_FAN_CURVE_POINTS; i++)
-+ data->percents[i] = buf[i + 8];
++ for (i = 0; i < FAN_CURVE_POINTS; i++) {
++ data->percents[i] =
++ 255 * buf[i + FAN_CURVE_POINTS] / 100;
++ data->default_percents[i] =
++ 255 * buf[i + FAN_CURVE_POINTS] / 100;
++ }
+}
+
-+static void init_fan_curve(struct fan_curve_data *curves,
-+ u8 *buf, u32 dev)
++static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev)
+{
-+ copy_fan_curve_buf(&curves->custom, buf);
-+ copy_fan_curve_buf(&curves->defaults, buf);
++ struct fan_curve_data *curves;
++ u8 buf[FAN_CURVE_BUF_LEN];
++ int fan_idx = 0;
++ u8 mode = 0;
++ int err;
++
++ if (asus->throttle_thermal_policy_available)
++ mode = asus->throttle_thermal_policy_mode;
++ /* DEVID_<C/G>PU_FAN_CURVE is switched for OVERBOOST vs SILENT */
++ if (mode == 2)
++ mode = 1;
++ else if (mode == 1)
++ mode = 2;
++
++ if (fan_dev == ASUS_WMI_DEVID_GPU_FAN_CURVE)
++ fan_idx = FAN_CURVE_DEV_GPU;
++
++ curves = &asus->custom_fan_curves[fan_idx];
++ err = asus_wmi_evaluate_method_buf(asus->dsts_id, fan_dev, mode, buf,
++ FAN_CURVE_BUF_LEN);
++ if (err)
++ return err;
++
++ fan_curve_copy_from_buf(curves, buf);
++
++ return 0;
+}
+
+/*
-+ * Check if the ability to set fan curves on either fan exists, and store the
-+ * defaults for recall later plus to provide users with a starting point.
-+ *
-+ * "dev" is either CPU_FAN_CURVE or GPU_FAN_CURVE.
++ * Check if capability exists, and populate defaults.
+ */
-+static int custom_fan_check_present(struct asus_wmi *asus,
-+ bool *available, u32 dev)
++static int fan_curve_check_present(struct asus_wmi *asus, bool *available,
++ u32 fan_dev)
+{
-+ struct fan_curve_data *curves;
-+ u8 buf[NUM_FAN_CURVE_DATA];
-+ int fan_idx = 0;
+ int err;
+
+ *available = false;
-+ if (dev == ASUS_WMI_DEVID_GPU_FAN_CURVE)
-+ fan_idx = 1;
+
-+ /* Balanced default */
-+ curves =
-+ &asus->throttle_fan_curves[ASUS_THROTTLE_THERMAL_POLICY_DEFAULT][fan_idx];
-+ err = asus_wmi_evaluate_method_buf(asus->dsts_id, dev, 0, buf);
++ err = fan_curve_get_factory_default(asus, fan_dev);
+ if (err) {
+ if (err == -ENODEV)
+ return 0;
+ return err;
+ }
-+ init_fan_curve(curves, buf, dev);
-+
-+ /*
-+ * Quiet default. The index num for ACPI method does not match the
-+ * throttle_thermal number, same for Performance.
-+ */
-+ curves =
-+ &asus->throttle_fan_curves[ASUS_THROTTLE_THERMAL_POLICY_SILENT][fan_idx];
-+ err = asus_wmi_evaluate_method_buf(asus->dsts_id, dev, 1, buf);
-+ if (err) {
-+ if (err == -ENODEV)
-+ return 0;
-+ return err;
-+ }
-+ init_fan_curve(curves, buf, dev);
-+
-+ /* Performance default */
-+ curves =
-+ &asus->throttle_fan_curves[ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST][fan_idx];
-+ err = asus_wmi_evaluate_method_buf(asus->dsts_id, dev, 2, buf);
-+ if (err) {
-+ if (err == -ENODEV)
-+ return 0;
-+ return err;
-+ }
-+ init_fan_curve(curves, buf, dev);
+
+ *available = true;
+ return 0;
+}
+
++static struct fan_curve_data *fan_curve_data_select(struct asus_wmi *asus,
++ struct device_attribute *attr)
++{
++ /* Determine which fan the attribute is for */
++ int nr = to_sensor_dev_attr_2(attr)->nr;
++ int fan = nr & FAN_CURVE_DEV_GPU;
++
++ return &asus->custom_fan_curves[fan];
++}
++
+static ssize_t fan_curve_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
++ struct device_attribute *attr, char *buf)
+{
+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ /* index maps to ASUS_THROTTLE_THERMAL_POLICY_DEFAULT */
++ /* Determine if temperature or pwm */
+ int nr = to_sensor_dev_attr_2(attr)->nr;
-+ /* dev maps to ASUS_WMI_DEVID_[C/G]PU_FAN_CURVE */
-+ int index = to_sensor_dev_attr_2(attr)->index;
++ struct fan_curve_data *data;
++ int value, index;
+
-+ struct fan_curve *dat = &asus->throttle_fan_curves[nr][index].custom;
-+ int len = 0;
-+ int i = 0;
++ data = fan_curve_data_select(asus, attr);
++ index = to_sensor_dev_attr_2(attr)->index;
+
-+ for (i = 0; i < NUM_FAN_CURVE_POINTS; i++) {
-+ len += sysfs_emit_at(buf, len, "%dc:%d%%",
-+ dat->temps[i], dat->percents[i]);
-+ if (i < NUM_FAN_CURVE_POINTS - 1)
-+ len += sysfs_emit_at(buf, len, ",");
-+ }
-+ len += sysfs_emit_at(buf, len, "\n");
-+ return len;
++ if (nr & FAN_CURVE_PWM_MASK)
++ value = data->percents[index];
++ else
++ value = data->temps[index];
++
++ return sysfs_emit(buf, "%d\n", value);
+}
+
+/*
-+ * "dev" is the related WMI method such as ASUS_WMI_DEVID_CPU_FAN_CURVE.
++ * "fan_dev" is the related WMI method such as ASUS_WMI_DEVID_CPU_FAN_CURVE.
+ */
-+static int fan_curve_write(struct asus_wmi *asus, u32 dev,
-+ struct fan_curve *curve)
++static int fan_curve_write(struct asus_wmi *asus,
++ struct device_attribute *attr, u32 fan_dev)
+{
-+ int ret;
-+ u32 arg1, arg2, arg3, arg4;
-+
-+ arg1 = curve->temps[0];
-+ arg2 = curve->temps[4];
-+ arg1 += curve->temps[1] << 8;
-+ arg2 += curve->temps[5] << 8;
-+ arg1 += curve->temps[2] << 16;
-+ arg2 += curve->temps[6] << 16;
-+ arg1 += curve->temps[3] << 24;
-+ arg2 += curve->temps[7] << 24;
-+
-+
-+ arg3 = curve->percents[0];
-+ arg4 = curve->percents[4];
-+ arg3 += curve->percents[1] << 8;
-+ arg4 += curve->percents[5] << 8;
-+ arg3 += curve->percents[2] << 16;
-+ arg4 += curve->percents[6] << 16;
-+ arg3 += curve->percents[3] << 24;
-+ arg4 += curve->percents[7] << 24;
-+
-+ return asus_wmi_evaluate_method5(ASUS_WMI_METHODID_DEVS, dev,
-+ arg1, arg2, arg3, arg4, &ret);
++ struct fan_curve_data *data = fan_curve_data_select(asus, attr);
++ u32 arg1 = 0, arg2 = 0, arg3 = 0, arg4 = 0;
++ u8 *percents = data->percents;
++ u8 *temps = data->temps;
++ int ret, i, shift = 0;
++
++ for (i = 0; i < FAN_CURVE_POINTS / 2; i++) {
++ arg1 += (temps[i]) << shift;
++ arg2 += (temps[i + 4]) << shift;
++ /* Scale to percentage for device */
++ arg3 += (100 * percents[i] / 255) << shift;
++ arg4 += (100 * percents[i + 4] / 255) << shift;
++ shift += 8;
++ }
++
++ return asus_wmi_evaluate_method5(ASUS_WMI_METHODID_DEVS, fan_dev, arg1,
++ arg2, arg3, arg4, &ret);
+}
+
+/*
-+ * Called only by throttle_thermal_policy_write()
++ * Called on curve enable/disable. This should be the only way to write out the
++ * fan curves. This avoids potential lockups on write to ACPI for every change.
+ */
-+static int fan_curve_write_data(struct asus_wmi *asus)
++static int fan_curve_write_data(struct asus_wmi *asus,
++ struct device_attribute *attr)
+{
-+ struct fan_curve_data *cpu;
-+ struct fan_curve_data *gpu;
-+ int err, mode;
-+
-+ mode = asus->throttle_thermal_policy_mode;
-+ cpu = &asus->throttle_fan_curves[mode][FAN_DEVICE_CPU];
-+ gpu = &asus->throttle_fan_curves[mode][FAN_DEVICE_GPU];
++ int err;
+
-+ if (asus->fan_curves_enabled[mode]) {
-+ err = fan_curve_write(asus, ASUS_WMI_DEVID_CPU_FAN_CURVE, &cpu->custom);
++ if (asus->cpu_fan_curve_available) {
++ err = fan_curve_write(asus, attr, ASUS_WMI_DEVID_CPU_FAN_CURVE);
+ if (err)
+ return err;
+ }
+
-+ if (asus->fan_curves_enabled[mode]) {
-+ err = fan_curve_write(asus, ASUS_WMI_DEVID_GPU_FAN_CURVE, &gpu->custom);
++ if (asus->gpu_fan_curve_available) {
++ err = fan_curve_write(asus, attr, ASUS_WMI_DEVID_GPU_FAN_CURVE);
+ if (err)
+ return err;
+ }
@@ -355,221 +391,337 @@ index cc5811844012..dccdd41917ff 100644
+ return 0;
+}
+
-+/*
-+ * The expected input is 8 sets of number pairs, where "53c30%" temperacture
-+ * and fan RPM percentage. The pair can be of the format "T[ c:]P[ %,]".
-+ *
-+ */
+static ssize_t fan_curve_store(struct device *dev,
-+ struct device_attribute *attr, const char *buf, size_t count)
++ struct device_attribute *attr, const char *buf,
++ size_t count)
+{
+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ u8 temps[NUM_FAN_CURVE_POINTS];
-+ u8 percents[NUM_FAN_CURVE_POINTS];
-+ /* tmp1 and tmp2 exist only to allow matching to succeed */
-+ char *tmp1;
-+ char *tmp2;
++ struct fan_curve_data *data;
++ u8 value;
+ int err;
+
-+ /* index maps to ASUS_THROTTLE_THERMAL_POLICY_DEFAULT */
-+ int nr = to_sensor_dev_attr_2(attr)->nr;
-+ /* dev maps to ASUS_WMI_DEVID_[C/G]PU_FAN_CURVE */
+ int index = to_sensor_dev_attr_2(attr)->index;
-+ /* Variable format, values must at least be separated by these */
-+ char part[] = "%d%2[ c:]%d%2[ %%,\n]%n";
-+ u32 prev_percent = 0;
-+ u32 prev_temp = 0;
-+ u32 percent = 0;
-+ u32 temp = 0;
-+ int len = 0;
-+ int idx = 0;
-+ int at = 0;
-+
-+ struct fan_curve_data *curve = &asus->throttle_fan_curves[nr][index];
-+
-+ /* Allow a user to write "" or " " to erase a curve setting */
-+ if (strlen(buf) <= 1 || strcmp(buf, "\n") == 0) {
-+ memcpy(&curve->custom, &curve->defaults, NUM_FAN_CURVE_DATA);
-+ err = throttle_thermal_policy_write(asus);
-+ if (err)
-+ return err;
-+ return count;
-+ }
++ int nr = to_sensor_dev_attr_2(attr)->nr;
++ int pwm = nr & FAN_CURVE_PWM_MASK;
+
-+ /* parse the buf */
-+ while (sscanf(&buf[at], part, &temp, &tmp1, &percent, &tmp2, &len) == 4) {
-+ if (temp < prev_temp || percent < prev_percent) {
-+ pr_info("Fan curve invalid: a value is sequentially lower");
-+ return -EINVAL;
-+ }
-+
-+ if (percent > 100) {
-+ pr_info("Fan curve invalid: percentage > 100");
-+ return -EINVAL;
-+ }
-+
-+ prev_temp = temp;
-+ prev_percent = percent;
-+
-+ temps[idx] = temp;
-+ percents[idx] = percent;
-+ at += len;
-+ idx += 1;
-+ }
++ data = fan_curve_data_select(asus, attr);
+
-+ if (idx != NUM_FAN_CURVE_POINTS) {
-+ pr_info("Fan curve invalid: incomplete string: %d", idx);
-+ return -EINVAL;
-+ }
++ err = kstrtou8(buf, 10, &value);
++ if (err < 0)
++ return err;
+
-+ memcpy(&curve->custom.temps, &temps, NUM_FAN_CURVE_POINTS);
-+ memcpy(&curve->custom.percents, &percents, NUM_FAN_CURVE_POINTS);
++ if (pwm) {
++ data->percents[index] = value;
++ } else {
++ data->temps[index] = value;
++ }
+
-+ /* Maybe activate fan curve if in associated mode */
-+ err = throttle_thermal_policy_write(asus);
-+ if (err)
-+ return err;
++ /*
++ * Mark as disabled so the user has to explicitly enable to apply a
++ * changed fan curve. This prevents potential lockups from writing out
++ * many changes as one-write-per-change.
++ */
++ data->enabled = false;
+
+ return count;
+}
+
-+static SENSOR_DEVICE_ATTR_2_RW(cpu_fan_curve_balanced, fan_curve,
-+ ASUS_THROTTLE_THERMAL_POLICY_DEFAULT,
-+ FAN_DEVICE_CPU);
-+static SENSOR_DEVICE_ATTR_2_RW(cpu_fan_curve_performance, fan_curve,
-+ ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST,
-+ FAN_DEVICE_CPU);
-+static SENSOR_DEVICE_ATTR_2_RW(cpu_fan_curve_quiet, fan_curve,
-+ ASUS_THROTTLE_THERMAL_POLICY_SILENT,
-+ FAN_DEVICE_CPU);
-+
-+static SENSOR_DEVICE_ATTR_2_RW(gpu_fan_curve_balanced, fan_curve,
-+ ASUS_THROTTLE_THERMAL_POLICY_DEFAULT,
-+ FAN_DEVICE_GPU);
-+static SENSOR_DEVICE_ATTR_2_RW(gpu_fan_curve_performance, fan_curve,
-+ ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST,
-+ FAN_DEVICE_GPU);
-+static SENSOR_DEVICE_ATTR_2_RW(gpu_fan_curve_quiet, fan_curve,
-+ ASUS_THROTTLE_THERMAL_POLICY_SILENT,
-+ FAN_DEVICE_GPU);
-+
-+/*
-+ * Profiles with enabled fan curve setting
-+ */
-+
-+static int enabled_fan_curve_profiles_write(struct asus_wmi *asus,
-+ const char *names)
++static ssize_t fan_curve_enable_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
+{
-+ char *buf, *set, *set_end;
-+ int err, index;
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++ struct fan_curve_data *data = fan_curve_data_select(asus, attr);
++ int out = 2;
+
-+ buf = set_end = kstrdup(names, GFP_KERNEL);
++ if (data->enabled)
++ out = 1;
+
-+ /* Reset before checking */
-+ asus->fan_curves_enabled[ASUS_THROTTLE_THERMAL_POLICY_DEFAULT] = false;
-+ asus->fan_curves_enabled[ASUS_THROTTLE_THERMAL_POLICY_SILENT] = false;
-+ asus->fan_curves_enabled[ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST] = false;
++ return sysfs_emit(buf, "%d\n", out);
++}
+
-+ while ((set = strsep(&set_end, " ")) != NULL) {
-+ index = sysfs_match_string(fan_curve_names, set);
-+ if (index >= 0)
-+ asus->fan_curves_enabled[index] = true;
-+ }
++static int fan_curve_set_default(struct asus_wmi *asus)
++{
++ int err;
+
-+ err = throttle_thermal_policy_write(asus);
++ err = fan_curve_get_factory_default(
++ asus, ASUS_WMI_DEVID_CPU_FAN_CURVE);
+ if (err)
+ return err;
+
-+ kfree(buf);
-+
++ err = fan_curve_get_factory_default(
++ asus, ASUS_WMI_DEVID_GPU_FAN_CURVE);
++ if (err)
++ return err;
+ return 0;
+}
+
-+static ssize_t enabled_fan_curve_profiles_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
++static ssize_t fan_curve_enable_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
+{
+ struct asus_wmi *asus = dev_get_drvdata(dev);
-+ int i, len = 0;
++ struct fan_curve_data *data;
++ int value;
++ int err;
++
++ data = fan_curve_data_select(asus, attr);
++
++ err = kstrtoint(buf, 10, &value);
++ if (err < 0)
++ return err;
++
++ switch (value) {
++ case 1:
++ data->enabled = true;
++ break;
++ case 2:
++ data->enabled = false;
++ break;
++ /*
++ * Auto + reset the fan curve data to defaults. Make it an explicit
++ * option so that users don't accidentally overwrite a set fan curve.
++ */
++ case 3:
++ err = fan_curve_set_default(asus);
++ if (err)
++ return err;
++ data->enabled = false;
++ break;
++ default:
++ return -EINVAL;
++ };
++
++ /*
++ * For machines with throttle this is the only way to reset fans to
++ * default mode of operation (does not erase curve data).
++ */
++ if (asus->throttle_thermal_policy_available && !data->enabled) {
++ err = throttle_thermal_policy_write(asus);
++ if (err)
++ return err;
++ }
++ /* Similar is true for laptops with this fan */
++ if (asus->fan_type == FAN_TYPE_SPEC83) {
++ err = asus_fan_set_auto(asus);
++ if (err)
++ return err;
++ }
++ /*
++ * Machines without either need to write their defaults back always.
++ * This is more of a safeguard against ASUS faulty ACPI tables.
++ */
++ if (!asus->throttle_thermal_policy_available
++ && asus->fan_type != FAN_TYPE_SPEC83 && !data->enabled) {
++ err = fan_curve_set_default(asus);
++ if (err)
++ return err;
++ err = fan_curve_write_data(asus, attr);
++ if (err)
++ return err;
++ }
+
-+ for (i = 0; i < NUM_FAN_CURVE_PROFILES; i++) {
-+ if (asus->fan_curves_enabled[i]) {
-+ len += sysfs_emit_at(buf, len, fan_curve_names[i]);
-+ len += sysfs_emit_at(buf, len, " ");
-+ }
++ if (data->enabled) {
++ err = fan_curve_write_data(asus, attr);
++ if (err)
++ return err;
+ }
+
-+ len += sysfs_emit_at(buf, len, "\n");
-+ return len;
++ return count;
+}
+
-+static ssize_t enabled_fan_curve_profiles_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
++/* CPU */
++static SENSOR_DEVICE_ATTR_RW(pwm1_enable, fan_curve_enable, FAN_CURVE_DEV_CPU);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point1_temp, fan_curve,
++ FAN_CURVE_DEV_CPU, 0);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_temp, fan_curve,
++ FAN_CURVE_DEV_CPU, 1);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point3_temp, fan_curve,
++ FAN_CURVE_DEV_CPU, 2);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point4_temp, fan_curve,
++ FAN_CURVE_DEV_CPU, 3);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point5_temp, fan_curve,
++ FAN_CURVE_DEV_CPU, 4);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point6_temp, fan_curve,
++ FAN_CURVE_DEV_CPU, 5);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point7_temp, fan_curve,
++ FAN_CURVE_DEV_CPU, 6);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point8_temp, fan_curve,
++ FAN_CURVE_DEV_CPU, 7);
++
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point1_pwm, fan_curve,
++ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 0);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_pwm, fan_curve,
++ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 1);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point3_pwm, fan_curve,
++ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 2);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point4_pwm, fan_curve,
++ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 3);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point5_pwm, fan_curve,
++ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 4);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point6_pwm, fan_curve,
++ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 5);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point7_pwm, fan_curve,
++ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 6);
++static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point8_pwm, fan_curve,
++ FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 7);
++
++/* GPU */
++static SENSOR_DEVICE_ATTR_RW(pwm2_enable, fan_curve_enable, FAN_CURVE_DEV_GPU);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_temp, fan_curve,
++ FAN_CURVE_DEV_GPU, 0);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_temp, fan_curve,
++ FAN_CURVE_DEV_GPU, 1);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point3_temp, fan_curve,
++ FAN_CURVE_DEV_GPU, 2);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point4_temp, fan_curve,
++ FAN_CURVE_DEV_GPU, 3);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point5_temp, fan_curve,
++ FAN_CURVE_DEV_GPU, 4);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point6_temp, fan_curve,
++ FAN_CURVE_DEV_GPU, 5);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point7_temp, fan_curve,
++ FAN_CURVE_DEV_GPU, 6);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point8_temp, fan_curve,
++ FAN_CURVE_DEV_GPU, 7);
++
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_pwm, fan_curve,
++ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 0);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_pwm, fan_curve,
++ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 1);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point3_pwm, fan_curve,
++ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 2);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point4_pwm, fan_curve,
++ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 3);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point5_pwm, fan_curve,
++ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 4);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point6_pwm, fan_curve,
++ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 5);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point7_pwm, fan_curve,
++ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 6);
++static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point8_pwm, fan_curve,
++ FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 7);
++
++static struct attribute *asus_fan_curve_attr[] = {
++ /* CPU */
++ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point7_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point8_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point7_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm1_auto_point8_pwm.dev_attr.attr,
++ /* GPU */
++ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point5_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point6_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point7_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point8_temp.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point5_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point6_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point7_pwm.dev_attr.attr,
++ &sensor_dev_attr_pwm2_auto_point8_pwm.dev_attr.attr,
++ NULL
++};
++
++static umode_t asus_fan_curve_is_visible(struct kobject *kobj,
++ struct attribute *attr, int idx)
+{
-+ struct asus_wmi *asus = dev_get_drvdata(dev);
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct asus_wmi *asus = dev_get_drvdata(dev->parent);
++
++ if (asus->cpu_fan_curve_available)
++ return 0644;
++
++ if (asus->gpu_fan_curve_available)
++ return 0644;
++
++ return 0;
++}
++
++static const struct attribute_group asus_fan_curve_attr_group = {
++ .is_visible = asus_fan_curve_is_visible,
++ .attrs = asus_fan_curve_attr,
++};
++__ATTRIBUTE_GROUPS(asus_fan_curve_attr);
++
++/*
++ * Must be initialised after throttle_thermal_policy_check_present() as
++ * we check the status of throttle_thermal_policy_available during init.
++ */
++static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
++{
++ struct device *dev = &asus->platform_device->dev;
++ struct device *hwmon;
+ int err;
+
-+ err = enabled_fan_curve_profiles_write(asus, buf);
++ err = fan_curve_check_present(asus, &asus->cpu_fan_curve_available,
++ ASUS_WMI_DEVID_CPU_FAN_CURVE);
+ if (err)
+ return err;
+
-+ return count;
-+}
++ err = fan_curve_check_present(asus, &asus->gpu_fan_curve_available,
++ ASUS_WMI_DEVID_GPU_FAN_CURVE);
++ if (err)
++ return err;
+
-+static DEVICE_ATTR_RW(enabled_fan_curve_profiles);
++ hwmon = devm_hwmon_device_register_with_groups(
++ dev, "asus_custom_fan_curve", asus, asus_fan_curve_attr_groups);
++
++ if (IS_ERR(hwmon)) {
++ dev_err(dev,
++ "Could not register asus_custom_fan_curve device\n");
++ return PTR_ERR(hwmon);
++ }
++
++ return 0;
++}
+
/* Throttle thermal policy ****************************************************/
static int throttle_thermal_policy_check_present(struct asus_wmi *asus)
-@@ -2092,6 +2538,12 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
+@@ -2053,8 +2636,8 @@ static int throttle_thermal_policy_check_present(struct asus_wmi *asus)
+ asus->throttle_thermal_policy_available = false;
+
+ err = asus_wmi_get_devstate(asus,
+- ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY,
+- &result);
++ ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY,
++ &result);
+ if (err) {
+ if (err == -ENODEV)
+ return 0;
+@@ -2092,6 +2675,12 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
return -EIO;
}
-+ if (asus->cpu_fan_curve_available || asus->gpu_fan_curve_available) {
-+ err = fan_curve_write_data(asus);
-+ if (err)
-+ return err;
-+ }
++ /* Must set to disabled if mode is toggled */
++ if (asus->cpu_fan_curve_available)
++ asus->custom_fan_curves[FAN_CURVE_DEV_CPU].enabled = false;
++ if (asus->gpu_fan_curve_available)
++ asus->custom_fan_curves[FAN_CURVE_DEV_GPU].enabled = false;
+
return 0;
}
-@@ -2711,6 +3163,13 @@ static struct attribute *platform_attributes[] = {
- &dev_attr_als_enable.attr,
- &dev_attr_fan_boost_mode.attr,
- &dev_attr_throttle_thermal_policy.attr,
-+ &sensor_dev_attr_cpu_fan_curve_balanced.dev_attr.attr,
-+ &sensor_dev_attr_cpu_fan_curve_performance.dev_attr.attr,
-+ &sensor_dev_attr_cpu_fan_curve_quiet.dev_attr.attr,
-+ &sensor_dev_attr_gpu_fan_curve_balanced.dev_attr.attr,
-+ &sensor_dev_attr_gpu_fan_curve_performance.dev_attr.attr,
-+ &sensor_dev_attr_gpu_fan_curve_quiet.dev_attr.attr,
-+ &dev_attr_enabled_fan_curve_profiles.attr,
- &dev_attr_panel_od.attr,
- NULL
- };
-@@ -2741,6 +3200,20 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
- ok = asus->fan_boost_mode_available;
- else if (attr == &dev_attr_throttle_thermal_policy.attr)
- ok = asus->throttle_thermal_policy_available;
-+ else if (attr == &sensor_dev_attr_cpu_fan_curve_balanced.dev_attr.attr)
-+ ok = asus->cpu_fan_curve_available;
-+ else if (attr == &sensor_dev_attr_cpu_fan_curve_performance.dev_attr.attr)
-+ ok = asus->cpu_fan_curve_available;
-+ else if (attr == &sensor_dev_attr_cpu_fan_curve_quiet.dev_attr.attr)
-+ ok = asus->cpu_fan_curve_available;
-+ else if (attr == &sensor_dev_attr_gpu_fan_curve_balanced.dev_attr.attr)
-+ ok = asus->gpu_fan_curve_available;
-+ else if (attr == &sensor_dev_attr_gpu_fan_curve_performance.dev_attr.attr)
-+ ok = asus->gpu_fan_curve_available;
-+ else if (attr == &sensor_dev_attr_gpu_fan_curve_quiet.dev_attr.attr)
-+ ok = asus->gpu_fan_curve_available;
-+ else if (attr == &dev_attr_enabled_fan_curve_profiles.attr)
-+ ok = asus->cpu_fan_curve_available || asus->gpu_fan_curve_available;
- else if (attr == &dev_attr_panel_od.attr)
- ok = asus->panel_overdrive_available;
-
-@@ -2904,7 +3377,7 @@ static int show_call(struct seq_file *m, void *data)
+@@ -2901,7 +3490,7 @@ static int show_call(struct seq_file *m, void *data)
if (ACPI_FAILURE(status))
return -EIO;
@@ -578,24 +730,18 @@ index cc5811844012..dccdd41917ff 100644
if (obj && obj->type == ACPI_TYPE_INTEGER)
seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,
asus->debug.dev_id, asus->debug.ctrl_param,
-@@ -3016,6 +3489,16 @@ static int asus_wmi_add(struct platform_device *pdev)
- else
- throttle_thermal_policy_set_default(asus);
+@@ -3035,6 +3624,10 @@ static int asus_wmi_add(struct platform_device *pdev)
+ if (err)
+ goto fail_hwmon;
-+ err = custom_fan_check_present(asus, &asus->cpu_fan_curve_available,
-+ ASUS_WMI_DEVID_CPU_FAN_CURVE);
-+ if (err)
-+ goto fail_custom_fan_curve;
-+
-+ err = custom_fan_check_present(asus, &asus->gpu_fan_curve_available,
-+ ASUS_WMI_DEVID_GPU_FAN_CURVE);
++ err = asus_wmi_custom_fan_curve_init(asus);
+ if (err)
+ goto fail_custom_fan_curve;
+
- err = platform_profile_setup(asus);
+ err = asus_wmi_led_init(asus);
if (err)
- goto fail_platform_profile_setup;
-@@ -3109,6 +3592,7 @@ static int asus_wmi_add(struct platform_device *pdev)
+ goto fail_leds;
+@@ -3106,6 +3699,7 @@ static int asus_wmi_add(struct platform_device *pdev)
asus_wmi_sysfs_exit(asus->platform_device);
fail_sysfs:
fail_throttle_thermal_policy:
@@ -603,6 +749,14 @@ index cc5811844012..dccdd41917ff 100644
fail_platform_profile_setup:
if (asus->platform_profile_support)
platform_profile_remove();
+@@ -3131,6 +3725,7 @@ static int asus_wmi_remove(struct platform_device *device)
+ asus_wmi_debugfs_exit(asus);
+ asus_wmi_sysfs_exit(asus->platform_device);
+ asus_fan_set_auto(asus);
++ throttle_thermal_policy_set_default(asus);
+ asus_wmi_battery_exit(asus);
+
+ if (asus->platform_profile_support)
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index 17dc5cb6f3f2..a571b47ff362 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
@@ -617,5 +771,5 @@ index 17dc5cb6f3f2..a571b47ff362 100644
/* Power */
#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
--
-2.31.1
+2.32.0
diff --git a/sys-kernel_arch-sources-g14_files-8001-x86-amd_nb-Add-AMD-family-19h-model-50h-PCI-ids.patch b/sys-kernel_arch-sources-g14_files-8001-x86-amd_nb-Add-AMD-family-19h-model-50h-PCI-ids.patch
deleted file mode 100644
index 65e85b859729..000000000000
--- a/sys-kernel_arch-sources-g14_files-8001-x86-amd_nb-Add-AMD-family-19h-model-50h-PCI-ids.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From 2ade8fc65076095460e3ea1ca65a8f619d7d9a3a Mon Sep 17 00:00:00 2001
-From: David Bartley <andareed@gmail.com>
-Date: Thu, 20 May 2021 10:41:30 -0700
-Subject: x86/amd_nb: Add AMD family 19h model 50h PCI ids
-
-This is required to support Zen3 APUs in k10temp.
-
-Signed-off-by: David Bartley <andareed@gmail.com>
-Signed-off-by: Borislav Petkov <bp@suse.de>
-Acked-by: Wei Huang <wei.huang2@amd.com>
-Link: https://lkml.kernel.org/r/20210520174130.94954-1-andareed@gmail.com
----
- arch/x86/kernel/amd_nb.c | 3 +++
- include/linux/pci_ids.h | 1 +
- 2 files changed, 4 insertions(+)
-
-diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
-index 09083094eb575..23dda362dc0f3 100644
---- a/arch/x86/kernel/amd_nb.c
-+++ b/arch/x86/kernel/amd_nb.c
-@@ -25,6 +25,7 @@
- #define PCI_DEVICE_ID_AMD_17H_M60H_DF_F4 0x144c
- #define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4 0x1444
- #define PCI_DEVICE_ID_AMD_19H_DF_F4 0x1654
-+#define PCI_DEVICE_ID_AMD_19H_M50H_DF_F4 0x166e
-
- /* Protect the PCI config register pairs used for SMN and DF indirect access. */
- static DEFINE_MUTEX(smn_mutex);
-@@ -57,6 +58,7 @@ static const struct pci_device_id amd_nb_misc_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) },
-+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F3) },
- {}
- };
-
-@@ -72,6 +74,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F4) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F4) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F4) },
-+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F4) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
- {}
- };
-diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index 4c3fa5293d763..5356ccf1c275b 100644
---- a/include/linux/pci_ids.h
-+++ b/include/linux/pci_ids.h
-@@ -555,6 +555,7 @@
- #define PCI_DEVICE_ID_AMD_17H_M60H_DF_F3 0x144b
- #define PCI_DEVICE_ID_AMD_17H_M70H_DF_F3 0x1443
- #define PCI_DEVICE_ID_AMD_19H_DF_F3 0x1653
-+#define PCI_DEVICE_ID_AMD_19H_M50H_DF_F3 0x166d
- #define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703
- #define PCI_DEVICE_ID_AMD_LANCE 0x2000
- #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001
---
-cgit 1.2.3-1.el7
-
diff --git a/sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Add-support-for-Lite-On-Mediatek-Chi.patch b/sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Add-support-for-Lite-On-Mediatek-Chi.patch
deleted file mode 100644
index a2c1f335cde0..000000000000
--- a/sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Add-support-for-Lite-On-Mediatek-Chi.patch
+++ /dev/null
@@ -1,74 +0,0 @@
-From d2ee0adeb66389140bc7c84ba8ebc109420b74f3 Mon Sep 17 00:00:00 2001
-From: "mark-yw.chen" <mark-yw.chen@mediatek.com>
-Date: Mon, 12 Apr 2021 23:06:27 +0800
-Subject: [PATCH 8011/8014] Bluetooth: btusb: Add support for Lite-On Mediatek
- Chip
-
-Add support for Lite-On Mediatek Chip (MT7921)
-Lite On VID = 04CA.
-
-* /sys/kernel/debug/usb/devices
-T: Bus=01 Lev=03 Prnt=04 Port=01 Cnt=02 Dev#= 8 Spd=480 MxCh= 0
-D: Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
-P: Vendor=04ca ProdID=3802 Rev= 1.00
-S: Manufacturer=MediaTek Inc.
-S: Product=Wireless_Device
-S: SerialNumber=000000000
-C:* #Ifs= 3 Cfg#= 1 Atr=e0 MxPwr=100mA
-A: FirstIf#= 0 IfCount= 3 Cls=e0(wlcon) Sub=01 Prot=01
-I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us
-E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
-E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
-I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
-I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
-I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
-I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
-I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
-I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
-I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
-E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
-E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
-I:* If#= 2 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
-E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
-E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
-I: If#= 2 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none)
-E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=125us
-E: Ad=0a(O) Atr=03(Int.) MxPS= 64 Ivl=125us
-
-Signed-off-by: mark-yw.chen <mark-yw.chen@mediatek.com>
----
- drivers/bluetooth/btusb.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
-index 99fd88f7653d..cb18d63a948d 100644
---- a/drivers/bluetooth/btusb.c
-+++ b/drivers/bluetooth/btusb.c
-@@ -408,6 +408,11 @@ static const struct usb_device_id blacklist_table[] = {
- /* Additional MediaTek MT7615E Bluetooth devices */
- { USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
-
-+ /* Additional MediaTek MT7921 Bluetooth devices */
-+ { USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
-+ BTUSB_WIDEBAND_SPEECH |
-+ BTUSB_VALID_LE_STATES },
-+
- /* Additional Realtek 8723AE Bluetooth devices */
- { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
- { USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK },
---
-2.32.0
-
diff --git a/sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Enable-MSFT-extension-for-Mediatek-Chip-MT7921.patch b/sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Enable-MSFT-extension-for-Mediatek-Chip-MT7921.patch
new file mode 100644
index 000000000000..c13ab0806638
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8011-Bluetooth-btusb-Enable-MSFT-extension-for-Mediatek-Chip-MT7921.patch
@@ -0,0 +1,34 @@
+From: <mark-yw.chen@mediatek.com>
+To: <marcel@holtmann.org>, <johan.hedberg@gmail.com>
+CC: <chris.lu@mediatek.com>, <will-cy.lee@mediatek.com>,
+ <sean.wang@mediatek.com>, <linux-bluetooth@vger.kernel.org>,
+ <linux-mediatek@lists.infradead.org>, <linux-kernel@vger.kernel.org>,
+ <michaelfsun@google.com>, <shawnku@google.com>, <jemele@google.com>,
+ <apusaka@google.com>, mark-yw.chen <mark-yw.chen@mediatek.com>
+Subject: [PATCH 1/1] Bluetooth: btusb: Enable MSFT extension for Mediatek Chip
+ (MT7921)
+Date: Mon, 2 Aug 2021 20:59:41 +0800
+
+From: "mark-yw.chen" <mark-yw.chen@mediatek.com>
+
+The Mdiatek MT7921(7961) support MSFT HCI extensions, we are using
+0xFD30 for VsMsftOpCode.
+
+Signed-off-by: mark-yw.chen <mark-yw.chen@mediatek.com>
+---
+ drivers/bluetooth/btusb.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index fec798dadd99..b1a05bb9f4bf 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -3775,6 +3775,8 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
+ bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+ return err;
+ }
++
++ hci_set_msft_opcode(hdev, 0xFD30);
+ goto done;
+ default:
+ bt_dev_err(hdev, "Unsupported hardware variant (%08x)",
diff --git a/sys-kernel_arch-sources-g14_files-8011-mt76-mt7921-fix-stupid-mediatek-wth-a-hammer.patch b/sys-kernel_arch-sources-g14_files-8011-mt76-mt7921-fix-stupid-mediatek-wth-a-hammer.patch
deleted file mode 100644
index b573e0fe6ac6..000000000000
--- a/sys-kernel_arch-sources-g14_files-8011-mt76-mt7921-fix-stupid-mediatek-wth-a-hammer.patch
+++ /dev/null
@@ -1,6575 +0,0 @@
-diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
-index 5e1c1506a4c6..e5c324dd24f9 100644
---- a/drivers/net/wireless/mediatek/mt76/dma.c
-+++ b/drivers/net/wireless/mediatek/mt76/dma.c
-@@ -191,7 +191,6 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
-
- q->entry[idx].txwi = txwi;
- q->entry[idx].skb = skb;
-- q->entry[idx].wcid = 0xffff;
-
- return idx;
- }
-diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
-index d03aedc3286b..03fe62837557 100644
---- a/drivers/net/wireless/mediatek/mt76/mac80211.c
-+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
-@@ -83,22 +83,6 @@ static const struct ieee80211_tpt_blink mt76_tpt_blink[] = {
- { .throughput = 300 * 1024, .blink_time = 50 },
- };
-
--struct ieee80211_rate mt76_rates[] = {
-- CCK_RATE(0, 10),
-- CCK_RATE(1, 20),
-- CCK_RATE(2, 55),
-- CCK_RATE(3, 110),
-- OFDM_RATE(11, 60),
-- OFDM_RATE(15, 90),
-- OFDM_RATE(10, 120),
-- OFDM_RATE(14, 180),
-- OFDM_RATE(9, 240),
-- OFDM_RATE(13, 360),
-- OFDM_RATE(8, 480),
-- OFDM_RATE(12, 540),
--};
--EXPORT_SYMBOL_GPL(mt76_rates);
--
- static int mt76_led_init(struct mt76_dev *dev)
- {
- struct device_node *np = dev->dev->of_node;
-@@ -331,6 +315,17 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
- ieee80211_hw_set(hw, MFP_CAPABLE);
- ieee80211_hw_set(hw, AP_LINK_PS);
- ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
-+
-+ wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
-+ wiphy->interface_modes =
-+ BIT(NL80211_IFTYPE_STATION) |
-+ BIT(NL80211_IFTYPE_AP) |
-+#ifdef CONFIG_MAC80211_MESH
-+ BIT(NL80211_IFTYPE_MESH_POINT) |
-+#endif
-+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
-+ BIT(NL80211_IFTYPE_P2P_GO) |
-+ BIT(NL80211_IFTYPE_ADHOC);
- }
-
- struct mt76_phy *
-@@ -351,17 +346,6 @@ mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
- phy->hw = hw;
- phy->priv = hw->priv + phy_size;
-
-- hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
-- hw->wiphy->interface_modes =
-- BIT(NL80211_IFTYPE_STATION) |
-- BIT(NL80211_IFTYPE_AP) |
--#ifdef CONFIG_MAC80211_MESH
-- BIT(NL80211_IFTYPE_MESH_POINT) |
--#endif
-- BIT(NL80211_IFTYPE_P2P_CLIENT) |
-- BIT(NL80211_IFTYPE_P2P_GO) |
-- BIT(NL80211_IFTYPE_ADHOC);
--
- return phy;
- }
- EXPORT_SYMBOL_GPL(mt76_alloc_phy);
-@@ -444,17 +428,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
- mutex_init(&dev->mcu.mutex);
- dev->tx_worker.fn = mt76_tx_worker;
-
-- hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
-- hw->wiphy->interface_modes =
-- BIT(NL80211_IFTYPE_STATION) |
-- BIT(NL80211_IFTYPE_AP) |
--#ifdef CONFIG_MAC80211_MESH
-- BIT(NL80211_IFTYPE_MESH_POINT) |
--#endif
-- BIT(NL80211_IFTYPE_P2P_CLIENT) |
-- BIT(NL80211_IFTYPE_P2P_GO) |
-- BIT(NL80211_IFTYPE_ADHOC);
--
- spin_lock_init(&dev->token_lock);
- idr_init(&dev->token);
-
-@@ -659,19 +632,20 @@ void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time)
- }
- EXPORT_SYMBOL_GPL(mt76_update_survey_active_time);
-
--void mt76_update_survey(struct mt76_phy *phy)
-+void mt76_update_survey(struct mt76_dev *dev)
- {
-- struct mt76_dev *dev = phy->dev;
- ktime_t cur_time;
-
- if (dev->drv->update_survey)
-- dev->drv->update_survey(phy);
-+ dev->drv->update_survey(dev);
-
- cur_time = ktime_get_boottime();
-- mt76_update_survey_active_time(phy, cur_time);
-+ mt76_update_survey_active_time(&dev->phy, cur_time);
-+ if (dev->phy2)
-+ mt76_update_survey_active_time(dev->phy2, cur_time);
-
- if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) {
-- struct mt76_channel_state *state = phy->chan_state;
-+ struct mt76_channel_state *state = dev->phy.chan_state;
-
- spin_lock_bh(&dev->cc_lock);
- state->cc_bss_rx += dev->cur_cc_bss_rx;
-@@ -690,7 +664,7 @@ void mt76_set_channel(struct mt76_phy *phy)
- int timeout = HZ / 5;
-
- wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout);
-- mt76_update_survey(phy);
-+ mt76_update_survey(dev);
-
- phy->chandef = *chandef;
- phy->chan_state = mt76_channel_state(phy, chandef->chan);
-@@ -715,7 +689,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx,
-
- mutex_lock(&dev->mutex);
- if (idx == 0 && dev->drv->update_survey)
-- mt76_update_survey(phy);
-+ mt76_update_survey(dev);
-
- sband = &phy->sband_2g;
- if (idx >= sband->sband.n_channels) {
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
-index 25c5ceef5257..0c23edbfbdbb 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
-@@ -336,7 +336,6 @@ enum {
- struct mt76_hw_cap {
- bool has_2ghz;
- bool has_5ghz;
-- bool has_6ghz;
- };
-
- #define MT_DRV_TXWI_NO_FREE BIT(0)
-@@ -353,7 +352,7 @@ struct mt76_driver_ops {
- u16 token_size;
- u8 mcs_rates;
-
-- void (*update_survey)(struct mt76_phy *phy);
-+ void (*update_survey)(struct mt76_dev *dev);
-
- int (*tx_prepare_skb)(struct mt76_dev *dev, void *txwi_ptr,
- enum mt76_txq_id qid, struct mt76_wcid *wcid,
-@@ -755,21 +754,6 @@ enum mt76_phy_type {
- MT_PHY_TYPE_HE_MU,
- };
-
--#define CCK_RATE(_idx, _rate) { \
-- .bitrate = _rate, \
-- .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
-- .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \
-- .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + _idx), \
--}
--
--#define OFDM_RATE(_idx, _rate) { \
-- .bitrate = _rate, \
-- .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-- .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
--}
--
--extern struct ieee80211_rate mt76_rates[12];
--
- #define __mt76_rr(dev, ...) (dev)->bus->rr((dev), __VA_ARGS__)
- #define __mt76_wr(dev, ...) (dev)->bus->wr((dev), __VA_ARGS__)
- #define __mt76_rmw(dev, ...) (dev)->bus->rmw((dev), __VA_ARGS__)
-@@ -1063,7 +1047,7 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw,
- bool more_data);
- bool mt76_has_tx_pending(struct mt76_phy *phy);
- void mt76_set_channel(struct mt76_phy *phy);
--void mt76_update_survey(struct mt76_phy *phy);
-+void mt76_update_survey(struct mt76_dev *dev);
- void mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time);
- int mt76_get_survey(struct ieee80211_hw *hw, int idx,
- struct survey_info *survey);
-@@ -1088,14 +1072,7 @@ struct sk_buff *mt76_tx_status_skb_get(struct mt76_dev *dev,
- struct sk_buff_head *list);
- void mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb,
- struct sk_buff_head *list);
--void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid, struct sk_buff *skb,
-- struct list_head *free_list);
--static inline void
--mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid, struct sk_buff *skb)
--{
-- __mt76_tx_complete_skb(dev, wcid, skb, NULL);
--}
--
-+void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid, struct sk_buff *skb);
- void mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid,
- bool flush);
- int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-@@ -1292,15 +1269,4 @@ mt76_token_put(struct mt76_dev *dev, int token)
-
- return txwi;
- }
--
--static inline int
--mt76_get_next_pkt_id(struct mt76_wcid *wcid)
--{
-- wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
-- if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
-- wcid->packet_id == MT_PACKET_ID_NO_SKB)
-- wcid->packet_id = MT_PACKET_ID_FIRST;
--
-- return wcid->packet_id;
--}
- #endif
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
-index 031d39a48a55..e1b2cfa56074 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c
-@@ -304,6 +304,34 @@ mt7603_init_hardware(struct mt7603_dev *dev)
- return 0;
- }
-
-+#define CCK_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
-+ .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + _idx), \
-+}
-+
-+#define OFDM_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+}
-+
-+static struct ieee80211_rate mt7603_rates[] = {
-+ CCK_RATE(0, 10),
-+ CCK_RATE(1, 20),
-+ CCK_RATE(2, 55),
-+ CCK_RATE(3, 110),
-+ OFDM_RATE(11, 60),
-+ OFDM_RATE(15, 90),
-+ OFDM_RATE(10, 120),
-+ OFDM_RATE(14, 180),
-+ OFDM_RATE(9, 240),
-+ OFDM_RATE(13, 360),
-+ OFDM_RATE(8, 480),
-+ OFDM_RATE(12, 540),
-+};
-+
- static const struct ieee80211_iface_limit if_limits[] = {
- {
- .max = 1,
-@@ -541,8 +569,8 @@ int mt7603_register_device(struct mt7603_dev *dev)
-
- wiphy->reg_notifier = mt7603_regd_notifier;
-
-- ret = mt76_register_device(&dev->mt76, true, mt76_rates,
-- ARRAY_SIZE(mt76_rates));
-+ ret = mt76_register_device(&dev->mt76, true, mt7603_rates,
-+ ARRAY_SIZE(mt7603_rates));
- if (ret)
- return ret;
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
-index 3972c56136a2..3aa7483e929f 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
-@@ -1226,7 +1226,7 @@ mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid,
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
- if (!mt7603_fill_txs(dev, sta, info, txs_data)) {
-- info->status.rates[0].count = 0;
-+ ieee80211_tx_info_clear_status(info);
- info->status.rates[0].idx = -1;
- }
-
-@@ -1597,12 +1597,12 @@ mt7603_watchdog_check(struct mt7603_dev *dev, u8 *counter,
- return true;
- }
-
--void mt7603_update_channel(struct mt76_phy *mphy)
-+void mt7603_update_channel(struct mt76_dev *mdev)
- {
-- struct mt7603_dev *dev = container_of(mphy->dev, struct mt7603_dev, mt76);
-+ struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
- struct mt76_channel_state *state;
-
-- state = mphy->chan_state;
-+ state = mdev->phy.chan_state;
- state->cc_busy += mt76_rr(dev, MT_MIB_STAT_CCA);
- }
-
-@@ -1819,7 +1819,7 @@ void mt7603_mac_work(struct work_struct *work)
- mutex_lock(&dev->mt76.mutex);
-
- dev->mphy.mac_work_count++;
-- mt76_update_survey(&dev->mphy);
-+ mt76_update_survey(&dev->mt76);
- mt7603_edcca_check(dev);
-
- for (i = 0, idx = 0; i < 2; i++) {
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
-index 0fd46d907638..1df5b9fed2bb 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h
-@@ -256,7 +256,7 @@ void mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-
- void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t);
-
--void mt7603_update_channel(struct mt76_phy *mphy);
-+void mt7603_update_channel(struct mt76_dev *mdev);
-
- void mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val);
- void mt7603_cca_stats_reset(struct mt7603_dev *dev);
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile
-index 83f9861ff522..e8fc4a7ae9bc 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile
-@@ -1,4 +1,4 @@
--# SPDX-License-Identifier: ISC
-+#SPDX-License-Identifier: ISC
-
- obj-$(CONFIG_MT7615_COMMON) += mt7615-common.o
- obj-$(CONFIG_MT7615E) += mt7615e.o
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
-index cb4659771fd9..676bb22726d6 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
-@@ -75,7 +75,7 @@ mt7615_pm_set(void *data, u64 val)
- if (!mt7615_wait_for_mcu_init(dev))
- return 0;
-
-- if (!mt7615_firmware_offload(dev) || mt76_is_usb(&dev->mt76))
-+ if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76))
- return -EOPNOTSUPP;
-
- if (val == pm->enable)
-@@ -319,6 +319,24 @@ mt7615_radio_read(struct seq_file *s, void *data)
- return 0;
- }
-
-+static int mt7615_read_temperature(struct seq_file *s, void *data)
-+{
-+ struct mt7615_dev *dev = dev_get_drvdata(s->private);
-+ int temp;
-+
-+ if (!mt7615_wait_for_mcu_init(dev))
-+ return 0;
-+
-+ /* cpu */
-+ mt7615_mutex_acquire(dev);
-+ temp = mt7615_mcu_get_temperature(dev, 0);
-+ mt7615_mutex_release(dev);
-+
-+ seq_printf(s, "Temperature: %d\n", temp);
-+
-+ return 0;
-+}
-+
- static int
- mt7615_queues_acq(struct seq_file *s, void *data)
- {
-@@ -548,6 +566,8 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
-
- debugfs_create_file("reset_test", 0200, dir, dev,
- &fops_reset_test);
-+ debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir,
-+ mt7615_read_temperature);
- debugfs_create_file("ext_mac_addr", 0600, dir, dev, &fops_ext_mac_addr);
-
- debugfs_create_u32("rf_wfidx", 0600, dir, &dev->debugfs_rf_wf);
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
-index 00aefea1bf61..8004ae5c16a9 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c
-@@ -81,7 +81,7 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget)
- if (napi_complete(napi))
- mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev));
-
-- mt76_connac_pm_unref(&dev->mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
-
- return 0;
- }
-@@ -99,7 +99,7 @@ static int mt7615_poll_rx(struct napi_struct *napi, int budget)
- return 0;
- }
- done = mt76_dma_rx_poll(napi, budget);
-- mt76_connac_pm_unref(&dev->mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
-
- return done;
- }
-@@ -222,9 +222,14 @@ void mt7615_dma_start(struct mt7615_dev *dev)
- int mt7615_dma_init(struct mt7615_dev *dev)
- {
- int rx_ring_size = MT7615_RX_RING_SIZE;
-+ int rx_buf_size = MT_RX_BUF_SIZE;
- u32 mask;
- int ret;
-
-+ /* Increase buffer size to receive large VHT MPDUs */
-+ if (dev->mphy.cap.has_5ghz)
-+ rx_buf_size *= 2;
-+
- mt76_dma_attach(&dev->mt76);
-
- mt76_wr(dev, MT_WPDMA_GLO_CFG,
-@@ -265,7 +270,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
-
- /* init rx queues */
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
-- MT7615_RX_MCU_RING_SIZE, MT_RX_BUF_SIZE,
-+ MT7615_RX_MCU_RING_SIZE, rx_buf_size,
- MT_RX_RING_BASE);
- if (ret)
- return ret;
-@@ -274,7 +279,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
- rx_ring_size /= 2;
-
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0,
-- rx_ring_size, MT_RX_BUF_SIZE, MT_RX_RING_BASE);
-+ rx_ring_size, rx_buf_size, MT_RX_RING_BASE);
- if (ret)
- return ret;
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
-index 2f1ac644e018..0d01fd3c77b5 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
-@@ -8,61 +8,11 @@
- */
-
- #include <linux/etherdevice.h>
--#include <linux/hwmon.h>
--#include <linux/hwmon-sysfs.h>
- #include "mt7615.h"
- #include "mac.h"
- #include "mcu.h"
- #include "eeprom.h"
-
--static ssize_t mt7615_thermal_show_temp(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct mt7615_dev *mdev = dev_get_drvdata(dev);
-- int temperature;
--
-- if (!mt7615_wait_for_mcu_init(mdev))
-- return 0;
--
-- mt7615_mutex_acquire(mdev);
-- temperature = mt7615_mcu_get_temperature(mdev);
-- mt7615_mutex_release(mdev);
--
-- if (temperature < 0)
-- return temperature;
--
-- /* display in millidegree celcius */
-- return sprintf(buf, "%u\n", temperature * 1000);
--}
--
--static SENSOR_DEVICE_ATTR(temp1_input, 0444, mt7615_thermal_show_temp,
-- NULL, 0);
--
--static struct attribute *mt7615_hwmon_attrs[] = {
-- &sensor_dev_attr_temp1_input.dev_attr.attr,
-- NULL,
--};
--ATTRIBUTE_GROUPS(mt7615_hwmon);
--
--int mt7615_thermal_init(struct mt7615_dev *dev)
--{
-- struct wiphy *wiphy = mt76_hw(dev)->wiphy;
-- struct device *hwmon;
--
-- if (!IS_REACHABLE(CONFIG_HWMON))
-- return 0;
--
-- hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev,
-- wiphy_name(wiphy), dev,
-- mt7615_hwmon_groups);
-- if (IS_ERR(hwmon))
-- return PTR_ERR(hwmon);
--
-- return 0;
--}
--EXPORT_SYMBOL_GPL(mt7615_thermal_init);
--
- static void
- mt7615_phy_init(struct mt7615_dev *dev)
- {
-@@ -224,6 +174,35 @@ bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev)
- }
- EXPORT_SYMBOL_GPL(mt7615_wait_for_mcu_init);
-
-+#define CCK_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
-+ .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)), \
-+}
-+
-+#define OFDM_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+}
-+
-+struct ieee80211_rate mt7615_rates[] = {
-+ CCK_RATE(0, 10),
-+ CCK_RATE(1, 20),
-+ CCK_RATE(2, 55),
-+ CCK_RATE(3, 110),
-+ OFDM_RATE(11, 60),
-+ OFDM_RATE(15, 90),
-+ OFDM_RATE(10, 120),
-+ OFDM_RATE(14, 180),
-+ OFDM_RATE(9, 240),
-+ OFDM_RATE(13, 360),
-+ OFDM_RATE(8, 480),
-+ OFDM_RATE(12, 540),
-+};
-+EXPORT_SYMBOL_GPL(mt7615_rates);
-+
- static const struct ieee80211_iface_limit if_limits[] = {
- {
- .max = 1,
-@@ -493,8 +472,8 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
- for (i = 0; i <= MT_TXQ_PSD ; i++)
- mphy->q_tx[i] = dev->mphy.q_tx[i];
-
-- ret = mt76_register_phy(mphy, true, mt76_rates,
-- ARRAY_SIZE(mt76_rates));
-+ ret = mt76_register_phy(mphy, true, mt7615_rates,
-+ ARRAY_SIZE(mt7615_rates));
- if (ret)
- ieee80211_free_hw(mphy->hw);
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
-index ff3f85e4087c..4873154d082e 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
-@@ -20,7 +20,7 @@
- #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
-
- static const struct mt7615_dfs_radar_spec etsi_radar_specs = {
-- .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
-+ .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 },
- .radar_pattern = {
- [5] = { 1, 0, 6, 32, 28, 0, 17, 990, 5010, 1, 1 },
- [6] = { 1, 0, 9, 32, 28, 0, 27, 615, 5010, 1, 1 },
-@@ -34,7 +34,7 @@ static const struct mt7615_dfs_radar_spec etsi_radar_specs = {
- };
-
- static const struct mt7615_dfs_radar_spec fcc_radar_specs = {
-- .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
-+ .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 },
- .radar_pattern = {
- [0] = { 1, 0, 9, 32, 28, 0, 13, 508, 3076, 1, 1 },
- [1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 },
-@@ -45,7 +45,7 @@ static const struct mt7615_dfs_radar_spec fcc_radar_specs = {
- };
-
- static const struct mt7615_dfs_radar_spec jp_radar_specs = {
-- .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
-+ .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 },
- .radar_pattern = {
- [0] = { 1, 0, 8, 32, 28, 0, 13, 508, 3076, 1, 1 },
- [1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 },
-@@ -1102,7 +1102,7 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
- idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
- addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
-
-- mt76_rmw(dev, addr, MT_LPON_TCR_MODE, MT_LPON_TCR_READ); /* TSF read */
-+ mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */
- sta->rate_set_tsf = mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0);
- sta->rate_set_tsf |= rd.rateset;
-
-@@ -1429,7 +1429,7 @@ static bool mt7615_mac_add_txs_skb(struct mt7615_dev *dev,
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
- if (!mt7615_fill_txs(dev, sta, info, txs_data)) {
-- info->status.rates[0].count = 0;
-+ ieee80211_tx_info_clear_status(info);
- info->status.rates[0].idx = -1;
- }
-
-@@ -1859,41 +1859,43 @@ mt7615_phy_update_channel(struct mt76_phy *mphy, int idx)
- state->noise = -(phy->noise >> 4);
- }
-
--static void mt7615_update_survey(struct mt7615_dev *dev)
-+static void __mt7615_update_channel(struct mt7615_dev *dev)
- {
- struct mt76_dev *mdev = &dev->mt76;
-- ktime_t cur_time;
--
-- /* MT7615 can only update both phys simultaneously
-- * since some reisters are shared across bands.
-- */
-
- mt7615_phy_update_channel(&mdev->phy, 0);
- if (mdev->phy2)
- mt7615_phy_update_channel(mdev->phy2, 1);
-
-- cur_time = ktime_get_boottime();
--
-- mt76_update_survey_active_time(&mdev->phy, cur_time);
-- if (mdev->phy2)
-- mt76_update_survey_active_time(mdev->phy2, cur_time);
--
- /* reset obss airtime */
- mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR);
- }
-
--void mt7615_update_channel(struct mt76_phy *mphy)
-+void mt7615_update_channel(struct mt76_dev *mdev)
- {
-- struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76);
-+ struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
-
- if (mt76_connac_pm_wake(&dev->mphy, &dev->pm))
- return;
-
-- mt7615_update_survey(dev);
-+ __mt7615_update_channel(dev);
- mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
- }
- EXPORT_SYMBOL_GPL(mt7615_update_channel);
-
-+static void mt7615_update_survey(struct mt7615_dev *dev)
-+{
-+ struct mt76_dev *mdev = &dev->mt76;
-+ ktime_t cur_time;
-+
-+ __mt7615_update_channel(dev);
-+ cur_time = ktime_get_boottime();
-+
-+ mt76_update_survey_active_time(&mdev->phy, cur_time);
-+ if (mdev->phy2)
-+ mt76_update_survey_active_time(mdev->phy2, cur_time);
-+}
-+
- static void
- mt7615_mac_update_mib_stats(struct mt7615_phy *phy)
- {
-@@ -1942,26 +1944,15 @@ void mt7615_pm_wake_work(struct work_struct *work)
- mphy = dev->phy.mt76;
-
- if (!mt7615_mcu_set_drv_ctrl(dev)) {
-- struct mt76_dev *mdev = &dev->mt76;
- int i;
-
-- if (mt76_is_sdio(mdev)) {
-- mt76_worker_schedule(&mdev->sdio.txrx_worker);
-- } else {
-- mt76_for_each_q_rx(mdev, i)
-- napi_schedule(&mdev->napi[i]);
-- mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
-- mt76_queue_tx_cleanup(dev, mdev->q_mcu[MT_MCUQ_WM],
-- false);
-- }
--
-- if (test_bit(MT76_STATE_RUNNING, &mphy->state)) {
-- unsigned long timeout;
--
-- timeout = mt7615_get_macwork_timeout(dev);
-+ mt76_for_each_q_rx(&dev->mt76, i)
-+ napi_schedule(&dev->mt76.napi[i]);
-+ mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
-+ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
-+ if (test_bit(MT76_STATE_RUNNING, &mphy->state))
- ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
-- timeout);
-- }
-+ MT7615_WATCHDOG_TIME);
- }
-
- ieee80211_wake_queues(mphy->hw);
-@@ -1996,7 +1987,6 @@ void mt7615_mac_work(struct work_struct *work)
- {
- struct mt7615_phy *phy;
- struct mt76_phy *mphy;
-- unsigned long timeout;
-
- mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
- mac_work.work);
-@@ -2015,9 +2005,8 @@ void mt7615_mac_work(struct work_struct *work)
- mt7615_mutex_release(phy->dev);
-
- mt76_tx_status_check(mphy->dev, NULL, false);
--
-- timeout = mt7615_get_macwork_timeout(phy->dev);
-- ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, timeout);
-+ ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
-+ MT7615_WATCHDOG_TIME);
- }
-
- void mt7615_tx_token_put(struct mt7615_dev *dev)
-@@ -2098,12 +2087,14 @@ mt7615_dfs_init_radar_specs(struct mt7615_phy *phy)
- {
- const struct mt7615_dfs_radar_spec *radar_specs;
- struct mt7615_dev *dev = phy->dev;
-- int err, i, lpn = 500;
-+ int err, i;
-
- switch (dev->mt76.region) {
- case NL80211_DFS_FCC:
- radar_specs = &fcc_radar_specs;
-- lpn = 8;
-+ err = mt7615_mcu_set_fcc5_lpn(dev, 8);
-+ if (err < 0)
-+ return err;
- break;
- case NL80211_DFS_ETSI:
- radar_specs = &etsi_radar_specs;
-@@ -2115,11 +2106,6 @@ mt7615_dfs_init_radar_specs(struct mt7615_phy *phy)
- return -EINVAL;
- }
-
-- /* avoid FCC radar detection in non-FCC region */
-- err = mt7615_mcu_set_fcc5_lpn(dev, lpn);
-- if (err < 0)
-- return err;
--
- for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) {
- err = mt7615_mcu_set_radar_th(dev, i,
- &radar_specs->radar_pattern[i]);
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
-index dada43d6d879..39733b351ac4 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
-@@ -28,7 +28,6 @@ static int mt7615_start(struct ieee80211_hw *hw)
- {
- struct mt7615_dev *dev = mt7615_hw_dev(hw);
- struct mt7615_phy *phy = mt7615_hw_phy(hw);
-- unsigned long timeout;
- bool running;
- int ret;
-
-@@ -79,8 +78,8 @@ static int mt7615_start(struct ieee80211_hw *hw)
-
- set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
-
-- timeout = mt7615_get_macwork_timeout(dev);
-- ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, timeout);
-+ ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
-+ MT7615_WATCHDOG_TIME);
-
- if (!running)
- mt7615_mac_reset_counters(dev);
-@@ -241,6 +240,8 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
- }
-
- ret = mt7615_mcu_add_dev_info(phy, vif, true);
-+ if (ret)
-+ goto out;
- out:
- mt7615_mutex_release(dev);
-
-@@ -351,12 +352,10 @@ int mt7615_set_channel(struct mt7615_phy *phy)
- mt7615_mutex_release(dev);
-
- mt76_worker_schedule(&dev->mt76.tx_worker);
-- if (!mt76_testmode_enabled(phy->mt76)) {
-- unsigned long timeout = mt7615_get_macwork_timeout(dev);
--
-+ if (!mt76_testmode_enabled(phy->mt76))
- ieee80211_queue_delayed_work(phy->mt76->hw,
-- &phy->mt76->mac_work, timeout);
-- }
-+ &phy->mt76->mac_work,
-+ MT7615_WATCHDOG_TIME);
-
- return ret;
- }
-@@ -696,7 +695,7 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw,
- msta->n_rates = i;
- if (mt76_connac_pm_ref(phy->mt76, &dev->pm)) {
- mt7615_mac_set_rates(phy, msta, NULL, msta->rates);
-- mt76_connac_pm_unref(phy->mt76, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
- }
- spin_unlock_bh(&dev->mt76.lock);
- }
-@@ -712,7 +711,7 @@ void mt7615_tx_worker(struct mt76_worker *w)
- }
-
- mt76_tx_worker_run(&dev->mt76);
-- mt76_connac_pm_unref(&dev->mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
- }
-
- static void mt7615_tx(struct ieee80211_hw *hw,
-@@ -742,7 +741,7 @@ static void mt7615_tx(struct ieee80211_hw *hw,
-
- if (mt76_connac_pm_ref(mphy, &dev->pm)) {
- mt76_tx(mphy, control->sta, wcid, skb);
-- mt76_connac_pm_unref(mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
- return;
- }
-
-@@ -882,8 +881,7 @@ mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-
- mt7615_mutex_acquire(dev);
-
-- /* TSF read */
-- mt76_rmw(dev, reg, MT_LPON_TCR_MODE, MT_LPON_TCR_READ);
-+ mt76_set(dev, reg, MT_LPON_TCR_MODE); /* TSF read */
- tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0);
- tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1);
-
-@@ -913,33 +911,7 @@ mt7615_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- mt76_wr(dev, MT_LPON_UTTR0, tsf.t32[0]);
- mt76_wr(dev, MT_LPON_UTTR1, tsf.t32[1]);
- /* TSF software overwrite */
-- mt76_rmw(dev, reg, MT_LPON_TCR_MODE, MT_LPON_TCR_WRITE);
--
-- mt7615_mutex_release(dev);
--}
--
--static void
--mt7615_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-- s64 timestamp)
--{
-- struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
-- struct mt7615_dev *dev = mt7615_hw_dev(hw);
-- union {
-- u64 t64;
-- u32 t32[2];
-- } tsf = { .t64 = timestamp, };
-- u16 idx = mvif->mt76.omac_idx;
-- u32 reg;
--
-- idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
-- reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
--
-- mt7615_mutex_acquire(dev);
--
-- mt76_wr(dev, MT_LPON_UTTR0, tsf.t32[0]);
-- mt76_wr(dev, MT_LPON_UTTR1, tsf.t32[1]);
-- /* TSF software adjust*/
-- mt76_rmw(dev, reg, MT_LPON_TCR_MODE, MT_LPON_TCR_ADJUST);
-+ mt76_set(dev, reg, MT_LPON_TCR_WRITE);
-
- mt7615_mutex_release(dev);
- }
-@@ -1190,7 +1162,7 @@ static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw,
- else
- clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
-
-- mt7615_mcu_set_sta_decap_offload(dev, vif, sta);
-+ mt7615_mcu_sta_update_hdr_trans(dev, vif, sta);
- }
-
- #ifdef CONFIG_PM
-@@ -1228,7 +1200,6 @@ static int mt7615_resume(struct ieee80211_hw *hw)
- {
- struct mt7615_phy *phy = mt7615_hw_phy(hw);
- struct mt7615_dev *dev = mt7615_hw_dev(hw);
-- unsigned long timeout;
- bool running;
-
- mt7615_mutex_acquire(dev);
-@@ -1252,8 +1223,8 @@ static int mt7615_resume(struct ieee80211_hw *hw)
- mt76_connac_mcu_set_suspend_iter,
- phy->mt76);
-
-- timeout = mt7615_get_macwork_timeout(dev);
-- ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, timeout);
-+ ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
-+ MT7615_WATCHDOG_TIME);
-
- mt7615_mutex_release(dev);
-
-@@ -1307,7 +1278,6 @@ const struct ieee80211_ops mt7615_ops = {
- .get_stats = mt7615_get_stats,
- .get_tsf = mt7615_get_tsf,
- .set_tsf = mt7615_set_tsf,
-- .offset_tsf = mt7615_offset_tsf,
- .get_survey = mt76_get_survey,
- .get_antenna = mt76_get_antenna,
- .set_antenna = mt7615_set_antenna,
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
-index f8a09692d3e4..257a2c4ddf36 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
-@@ -430,10 +430,6 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb)
-
- r = (struct mt7615_mcu_rdd_report *)skb->data;
-
-- if (!dev->radar_pattern.n_pulses && !r->long_detected &&
-- !r->constant_prf_detected && !r->staggered_prf_detected)
-- return;
--
- if (r->band_idx && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
-
-@@ -1028,10 +1024,9 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
- if (IS_ERR(sskb))
- return PTR_ERR(sskb);
-
-- mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable, true);
-+ mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable);
- if (enable && sta)
-- mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0,
-- MT76_STA_INFO_STATE_ASSOC);
-+ mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0);
-
- wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
- WTBL_RESET_AND_SET, NULL,
-@@ -1045,8 +1040,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
- if (sta)
- mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,
- NULL, wtbl_hdr);
-- mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid,
-- NULL, wtbl_hdr);
-+ mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, &msta->wcid, NULL,
-+ wtbl_hdr);
- }
-
- cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE;
-@@ -1066,26 +1061,6 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
- return mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true);
- }
-
--static int
--mt7615_mcu_wtbl_update_hdr_trans(struct mt7615_dev *dev,
-- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta)
--{
-- struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
-- struct wtbl_req_hdr *wtbl_hdr;
-- struct sk_buff *skb = NULL;
--
-- wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
-- WTBL_SET, NULL, &skb);
-- if (IS_ERR(wtbl_hdr))
-- return PTR_ERR(wtbl_hdr);
--
-- mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, &msta->wcid, NULL,
-- wtbl_hdr);
-- return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE,
-- true);
--}
--
- static const struct mt7615_mcu_ops wtbl_update_ops = {
- .add_beacon_offload = mt7615_mcu_add_beacon_offload,
- .set_pm_state = mt7615_mcu_ctrl_pm_state,
-@@ -1096,7 +1071,6 @@ static const struct mt7615_mcu_ops wtbl_update_ops = {
- .sta_add = mt7615_mcu_wtbl_sta_add,
- .set_drv_ctrl = mt7615_mcu_drv_pmctrl,
- .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
-- .set_sta_decap_offload = mt7615_mcu_wtbl_update_hdr_trans,
- };
-
- static int
-@@ -1158,12 +1132,11 @@ __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif,
- .vif = vif,
- .offload_fw = offload_fw,
- .enable = enable,
-- .newly = true,
- .cmd = cmd,
- };
-
- info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid;
-- return mt76_connac_mcu_sta_cmd(phy, &info);
-+ return mt76_connac_mcu_add_sta_cmd(phy, &info);
- }
-
- static int
-@@ -1174,18 +1147,6 @@ mt7615_mcu_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif,
- MCU_EXT_CMD_STA_REC_UPDATE, false);
- }
-
--static int
--mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
-- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta)
--{
-- struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
--
-- return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,
-- vif, &msta->wcid,
-- MCU_EXT_CMD_STA_REC_UPDATE);
--}
--
- static const struct mt7615_mcu_ops sta_update_ops = {
- .add_beacon_offload = mt7615_mcu_add_beacon_offload,
- .set_pm_state = mt7615_mcu_ctrl_pm_state,
-@@ -1196,9 +1157,27 @@ static const struct mt7615_mcu_ops sta_update_ops = {
- .sta_add = mt7615_mcu_add_sta,
- .set_drv_ctrl = mt7615_mcu_drv_pmctrl,
- .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
-- .set_sta_decap_offload = mt7615_mcu_sta_update_hdr_trans,
- };
-
-+int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
-+{
-+ struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
-+ struct wtbl_req_hdr *wtbl_hdr;
-+ struct sk_buff *skb = NULL;
-+
-+ wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid,
-+ WTBL_SET, NULL, &skb);
-+ if (IS_ERR(wtbl_hdr))
-+ return PTR_ERR(wtbl_hdr);
-+
-+ mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, &msta->wcid, NULL, wtbl_hdr);
-+
-+ return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE,
-+ true);
-+}
-+
- static int
- mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)
- {
-@@ -1364,18 +1343,6 @@ mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev,
- MCU_UNI_CMD_STA_REC_UPDATE, true);
- }
-
--static int
--mt7615_mcu_sta_uni_update_hdr_trans(struct mt7615_dev *dev,
-- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta)
--{
-- struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
--
-- return mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76,
-- vif, &msta->wcid,
-- MCU_UNI_CMD_STA_REC_UPDATE);
--}
--
- static const struct mt7615_mcu_ops uni_update_ops = {
- .add_beacon_offload = mt7615_mcu_uni_add_beacon_offload,
- .set_pm_state = mt7615_mcu_uni_ctrl_pm_state,
-@@ -1386,7 +1353,6 @@ static const struct mt7615_mcu_ops uni_update_ops = {
- .sta_add = mt7615_mcu_uni_add_sta,
- .set_drv_ctrl = mt7615_mcu_lp_drv_pmctrl,
- .set_fw_ctrl = mt7615_mcu_fw_pmctrl,
-- .set_sta_decap_offload = mt7615_mcu_sta_uni_update_hdr_trans,
- };
-
- int mt7615_mcu_restart(struct mt76_dev *dev)
-@@ -2361,12 +2327,14 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
- return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);
- }
-
--int mt7615_mcu_get_temperature(struct mt7615_dev *dev)
-+int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index)
- {
- struct {
- u8 action;
- u8 rsv[3];
-- } req = {};
-+ } req = {
-+ .action = index,
-+ };
-
- return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req,
- sizeof(req), true);
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
-index 71719c787511..202ea235415e 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c
-@@ -229,7 +229,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
- GFP_KERNEL);
- if (!bus_ops) {
- ret = -ENOMEM;
-- goto err_free_dev;
-+ goto error;
- }
-
- bus_ops->rr = mt7615_rr;
-@@ -242,20 +242,17 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
- ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler,
- IRQF_SHARED, KBUILD_MODNAME, dev);
- if (ret)
-- goto err_free_dev;
-+ goto error;
-
- if (is_mt7663(mdev))
- mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1);
-
- ret = mt7615_register_device(dev);
- if (ret)
-- goto err_free_irq;
-+ goto error;
-
- return 0;
--
--err_free_irq:
-- devm_free_irq(pdev, irq, dev);
--err_free_dev:
-+error:
- mt76_free_device(&dev->mt76);
-
- return ret;
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
-index d0c64a9b09cf..989f05ed4377 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
-@@ -20,6 +20,7 @@
- MT7615_MAX_INTERFACES)
-
- #define MT7615_PM_TIMEOUT (HZ / 12)
-+#define MT7615_WATCHDOG_TIME (HZ / 10)
- #define MT7615_HW_SCAN_TIMEOUT (HZ / 10)
- #define MT7615_RESET_TIMEOUT (30 * HZ)
- #define MT7615_RATE_RETRY 2
-@@ -201,7 +202,6 @@ struct mt7615_phy {
- #define mt7615_mcu_set_pm(dev, ...) (dev)->mcu_ops->set_pm_state((dev), __VA_ARGS__)
- #define mt7615_mcu_set_drv_ctrl(dev) (dev)->mcu_ops->set_drv_ctrl((dev))
- #define mt7615_mcu_set_fw_ctrl(dev) (dev)->mcu_ops->set_fw_ctrl((dev))
--#define mt7615_mcu_set_sta_decap_offload(dev, ...) (dev)->mcu_ops->set_sta_decap_offload((dev), __VA_ARGS__)
- struct mt7615_mcu_ops {
- int (*add_tx_ba)(struct mt7615_dev *dev,
- struct ieee80211_ampdu_params *params,
-@@ -221,9 +221,6 @@ struct mt7615_mcu_ops {
- int (*set_pm_state)(struct mt7615_dev *dev, int band, int state);
- int (*set_drv_ctrl)(struct mt7615_dev *dev);
- int (*set_fw_ctrl)(struct mt7615_dev *dev);
-- int (*set_sta_decap_offload)(struct mt7615_dev *dev,
-- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta);
- };
-
- struct mt7615_dev {
-@@ -359,7 +356,6 @@ static inline int mt7622_wmac_init(struct mt7615_dev *dev)
- }
- #endif
-
--int mt7615_thermal_init(struct mt7615_dev *dev);
- int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
- int irq, const u32 *map);
- u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr);
-@@ -460,12 +456,6 @@ static inline u32 mt7615_tx_mcu_int_mask(struct mt7615_dev *dev)
- return MT_INT_TX_DONE(dev->mt76.q_mcu[MT_MCUQ_WM]->hw_idx);
- }
-
--static inline unsigned long
--mt7615_get_macwork_timeout(struct mt7615_dev *dev)
--{
-- return dev->pm.enable ? HZ / 3 : HZ / 10;
--}
--
- void mt7615_dma_reset(struct mt7615_dev *dev);
- void mt7615_scan_work(struct work_struct *work);
- void mt7615_roc_work(struct work_struct *work);
-@@ -476,7 +466,7 @@ int mt7615_set_channel(struct mt7615_phy *phy);
- void mt7615_init_work(struct mt7615_dev *dev);
-
- int mt7615_mcu_restart(struct mt76_dev *dev);
--void mt7615_update_channel(struct mt76_phy *mphy);
-+void mt7615_update_channel(struct mt76_dev *mdev);
- bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask);
- void mt7615_mac_reset_counters(struct mt7615_dev *dev);
- void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy);
-@@ -504,7 +494,7 @@ u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg);
- int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val);
- int mt7615_mcu_set_dbdc(struct mt7615_dev *dev);
- int mt7615_mcu_set_eeprom(struct mt7615_dev *dev);
--int mt7615_mcu_get_temperature(struct mt7615_dev *dev);
-+int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index);
- int mt7615_mcu_set_tx_power(struct mt7615_phy *phy);
- void mt7615_mcu_exit(struct mt7615_dev *dev);
- void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,
-@@ -528,6 +518,9 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- void mt7615_mac_work(struct work_struct *work);
- void mt7615_txp_skb_unmap(struct mt76_dev *dev,
- struct mt76_txwi_cache *txwi);
-+int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta);
- int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev);
- int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val);
- int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev,
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
-index a2465b49ecd0..ec8ec1a2033f 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c
-@@ -98,7 +98,7 @@ mt7615_led_set_config(struct led_classdev *led_cdev,
- addr = mt7615_reg_map(dev, MT_LED_CTRL);
- mt76_wr(dev, addr, val);
-
-- mt76_connac_pm_unref(&dev->mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
- }
-
- static int
-@@ -147,12 +147,8 @@ int mt7615_register_device(struct mt7615_dev *dev)
- if (ret)
- return ret;
-
-- ret = mt76_register_device(&dev->mt76, true, mt76_rates,
-- ARRAY_SIZE(mt76_rates));
-- if (ret)
-- return ret;
--
-- ret = mt7615_thermal_init(dev);
-+ ret = mt76_register_device(&dev->mt76, true, mt7615_rates,
-+ ARRAY_SIZE(mt7615_rates));
- if (ret)
- return ret;
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
-index da87c02a73eb..cc278d8cb888 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
-@@ -268,7 +268,6 @@ void mt7615_mac_reset_work(struct work_struct *work)
- struct mt7615_phy *phy2;
- struct mt76_phy *ext_phy;
- struct mt7615_dev *dev;
-- unsigned long timeout;
-
- dev = container_of(work, struct mt7615_dev, reset_work);
- ext_phy = dev->mt76.phy2;
-@@ -346,11 +345,11 @@ void mt7615_mac_reset_work(struct work_struct *work)
-
- mt7615_mutex_release(dev);
-
-- timeout = mt7615_get_macwork_timeout(dev);
- ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
-- timeout);
-+ MT7615_WATCHDOG_TIME);
- if (phy2)
- ieee80211_queue_delayed_work(ext_phy->hw,
-- &phy2->mt76->mac_work, timeout);
-+ &phy2->mt76->mac_work,
-+ MT7615_WATCHDOG_TIME);
-
- }
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h
-index 6712ad9faeaa..63c081bb04d0 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h
-@@ -463,9 +463,7 @@ enum mt7615_reg_base {
- #define MT_LPON_TCR0(_n) MT_LPON(0x010 + ((_n) * 4))
- #define MT_LPON_TCR2(_n) MT_LPON(0x0f8 + ((_n) - 2) * 4)
- #define MT_LPON_TCR_MODE GENMASK(1, 0)
--#define MT_LPON_TCR_READ GENMASK(1, 0)
- #define MT_LPON_TCR_WRITE BIT(0)
--#define MT_LPON_TCR_ADJUST BIT(1)
-
- #define MT_LPON_UTTR0 MT_LPON(0x018)
- #define MT_LPON_UTTR1 MT_LPON(0x01c)
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.h b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.h
-index 03877d89e152..05180971de84 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.h
-@@ -1,4 +1,4 @@
--/* SPDX-License-Identifier: ISC */
-+// SPDX-License-Identifier: ISC
- /* Copyright (C) 2020 MediaTek Inc.
- *
- * Author: Sean Wang <sean.wang@mediatek.com>
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c
-index 45c1cd3b9f49..d1be78b0711c 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c
-@@ -55,7 +55,6 @@ static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
- {
- struct sdio_func *func = dev->mt76.sdio.func;
- struct mt76_phy *mphy = &dev->mt76.phy;
-- struct mt76_connac_pm *pm = &dev->pm;
- u32 status;
- int ret;
-
-@@ -67,45 +66,37 @@ static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
- status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
- if (ret < 0) {
- dev_err(dev->mt76.dev, "Cannot get ownership from device");
-- } else {
-- clear_bit(MT76_STATE_PM, &mphy->state);
-+ set_bit(MT76_STATE_PM, &mphy->state);
-+ sdio_release_host(func);
-
-- pm->stats.last_wake_event = jiffies;
-- pm->stats.doze_time += pm->stats.last_wake_event -
-- pm->stats.last_doze_event;
-+ return ret;
- }
-+
- sdio_release_host(func);
-+ dev->pm.last_activity = jiffies;
-
-- return ret;
-+ return 0;
- }
-
- static int mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
- {
- struct mt76_phy *mphy = &dev->mt76.phy;
-- int ret = 0;
--
-- mutex_lock(&dev->pm.mutex);
-
-- if (test_bit(MT76_STATE_PM, &mphy->state))
-- ret = __mt7663s_mcu_drv_pmctrl(dev);
-+ if (test_and_clear_bit(MT76_STATE_PM, &mphy->state))
-+ return __mt7663s_mcu_drv_pmctrl(dev);
-
-- mutex_unlock(&dev->pm.mutex);
--
-- return ret;
-+ return 0;
- }
-
- static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)
- {
- struct sdio_func *func = dev->mt76.sdio.func;
- struct mt76_phy *mphy = &dev->mt76.phy;
-- struct mt76_connac_pm *pm = &dev->pm;
-- int ret = 0;
- u32 status;
-+ int ret;
-
-- mutex_lock(&pm->mutex);
--
-- if (mt76_connac_skip_fw_pmctrl(mphy, pm))
-- goto out;
-+ if (test_and_set_bit(MT76_STATE_PM, &mphy->state))
-+ return 0;
-
- sdio_claim_host(func);
-
-@@ -116,15 +107,9 @@ static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)
- if (ret < 0) {
- dev_err(dev->mt76.dev, "Cannot set ownership to device");
- clear_bit(MT76_STATE_PM, &mphy->state);
-- } else {
-- pm->stats.last_doze_event = jiffies;
-- pm->stats.awake_time += pm->stats.last_doze_event -
-- pm->stats.last_wake_event;
- }
-
- sdio_release_host(func);
--out:
-- mutex_unlock(&pm->mutex);
-
- return ret;
- }
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
-index 04f4c89b7499..4393dd21ebbb 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
-@@ -283,15 +283,9 @@ void mt7663s_txrx_worker(struct mt76_worker *w)
- {
- struct mt76_sdio *sdio = container_of(w, struct mt76_sdio,
- txrx_worker);
-- struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio);
-- struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
-+ struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio);
- int i, nframes, ret;
-
-- if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
-- queue_work(mdev->wq, &dev->pm.wake_work);
-- return;
-- }
--
- /* disable interrupt */
- sdio_claim_host(sdio->func);
- sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
-@@ -301,16 +295,16 @@ void mt7663s_txrx_worker(struct mt76_worker *w)
-
- /* tx */
- for (i = 0; i <= MT_TXQ_PSD; i++) {
-- ret = mt7663s_tx_run_queue(mdev, mdev->phy.q_tx[i]);
-+ ret = mt7663s_tx_run_queue(dev, dev->phy.q_tx[i]);
- if (ret > 0)
- nframes += ret;
- }
-- ret = mt7663s_tx_run_queue(mdev, mdev->q_mcu[MT_MCUQ_WM]);
-+ ret = mt7663s_tx_run_queue(dev, dev->q_mcu[MT_MCUQ_WM]);
- if (ret > 0)
- nframes += ret;
-
- /* rx */
-- ret = mt7663s_rx_handler(mdev);
-+ ret = mt7663s_rx_handler(dev);
- if (ret > 0)
- nframes += ret;
- } while (nframes > 0);
-@@ -318,8 +312,6 @@ void mt7663s_txrx_worker(struct mt76_worker *w)
- /* enable interrupt */
- sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
- sdio_release_host(sdio->func);
--
-- mt76_connac_pm_unref(&dev->mphy, &dev->pm);
- }
-
- void mt7663s_sdio_irq(struct sdio_func *func)
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c
-index f13d1b418742..be9a69fe1b38 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c
-@@ -31,6 +31,7 @@ int mt7622_wmac_init(struct mt7615_dev *dev)
-
- static int mt7622_wmac_probe(struct platform_device *pdev)
- {
-+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- void __iomem *mem_base;
- int irq;
-
-@@ -38,7 +39,7 @@ static int mt7622_wmac_probe(struct platform_device *pdev)
- if (irq < 0)
- return irq;
-
-- mem_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
-+ mem_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(mem_base))
- return PTR_ERR(mem_base);
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
-index 996d48cca18a..7010101f6b14 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
-@@ -123,7 +123,7 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,
- idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;
- addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);
-
-- mt76_rmw(dev, addr, MT_LPON_TCR_MODE, MT_LPON_TCR_READ); /* TSF read */
-+ mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */
- val = mt76_rr(dev, MT_LPON_UTTR0);
- sta->rate_set_tsf = (val & ~BIT(0)) | rate->rateset;
-
-@@ -324,8 +324,8 @@ int mt7663_usb_sdio_register_device(struct mt7615_dev *dev)
- hw->max_tx_fragments = 1;
- }
-
-- err = mt76_register_device(&dev->mt76, true, mt76_rates,
-- ARRAY_SIZE(mt76_rates));
-+ err = mt76_register_device(&dev->mt76, true, mt7615_rates,
-+ ARRAY_SIZE(mt7615_rates));
- if (err < 0)
- return err;
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
-index f49d97d0a1c5..75223b6e1c87 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
-@@ -46,7 +46,6 @@ enum {
-
- struct mt76_connac_pm {
- bool enable;
-- bool ds_enable;
- bool suspended;
-
- spinlock_t txq_lock;
-@@ -119,15 +118,11 @@ mt76_connac_pm_ref(struct mt76_phy *phy, struct mt76_connac_pm *pm)
- }
-
- static inline void
--mt76_connac_pm_unref(struct mt76_phy *phy, struct mt76_connac_pm *pm)
-+mt76_connac_pm_unref(struct mt76_connac_pm *pm)
- {
- spin_lock_bh(&pm->wake.lock);
--
-+ pm->wake.count--;
- pm->last_activity = jiffies;
-- if (--pm->wake.count == 0 &&
-- test_bit(MT76_STATE_MCU_RUNNING, &phy->state))
-- mt76_connac_power_save_sched(phy, pm);
--
- spin_unlock_bh(&pm->wake.lock);
- }
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
-index af43bcb54578..5f2705fbd680 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
-@@ -10,7 +10,7 @@ int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
- if (!pm->enable)
- return 0;
-
-- if (mt76_is_usb(dev))
-+ if (!mt76_is_mmio(dev))
- return 0;
-
- cancel_delayed_work_sync(&pm->ps_work);
-@@ -37,7 +37,7 @@ void mt76_connac_power_save_sched(struct mt76_phy *phy,
- {
- struct mt76_dev *dev = phy->dev;
-
-- if (mt76_is_usb(dev))
-+ if (!mt76_is_mmio(dev))
- return;
-
- if (!pm->enable)
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
-index 5c3a81e5f559..e5721603586f 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
-@@ -304,7 +304,7 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_alloc_wtbl_req);
- void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
-- bool enable, bool newly)
-+ bool enable)
- {
- struct sta_rec_basic *basic;
- struct tlv *tlv;
-@@ -316,8 +316,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
- basic->extra_info = cpu_to_le16(EXTRA_INFO_VER);
-
- if (enable) {
-- if (newly)
-- basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW);
-+ basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW);
- basic->conn_state = CONN_STATE_PORT_SECURE;
- } else {
- basic->conn_state = CONN_STATE_DISCONNECT;
-@@ -394,7 +393,6 @@ mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif,
- }
-
- void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
-- struct ieee80211_vif *vif,
- struct mt76_wcid *wcid,
- void *sta_wtbl, void *wtbl_tlv)
- {
-@@ -406,46 +404,9 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
- wtbl_tlv, sta_wtbl);
- htr = (struct wtbl_hdr_trans *)tlv;
- htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
--
-- if (vif->type == NL80211_IFTYPE_STATION)
-- htr->to_ds = true;
-- else
-- htr->from_ds = true;
--
-- if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {
-- htr->to_ds = true;
-- htr->from_ds = true;
-- }
- }
- EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv);
-
--int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
-- struct ieee80211_vif *vif,
-- struct mt76_wcid *wcid, int cmd)
--{
-- struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
-- struct wtbl_req_hdr *wtbl_hdr;
-- struct tlv *sta_wtbl;
-- struct sk_buff *skb;
--
-- skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);
-- if (IS_ERR(skb))
-- return PTR_ERR(skb);
--
-- sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
-- sizeof(struct tlv));
--
-- wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_SET,
-- sta_wtbl, &skb);
-- if (IS_ERR(wtbl_hdr))
-- return PTR_ERR(wtbl_hdr);
--
-- mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, sta_wtbl, wtbl_hdr);
--
-- return mt76_mcu_skb_send_msg(dev, skb, cmd, true);
--}
--EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_update_hdr_trans);
--
- void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev,
- struct sk_buff *skb,
- struct ieee80211_vif *vif,
-@@ -710,7 +671,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
- void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
- struct ieee80211_sta *sta,
- struct ieee80211_vif *vif,
-- u8 rcpi, u8 sta_state)
-+ u8 rcpi)
- {
- struct cfg80211_chan_def *chandef = &mphy->chandef;
- enum nl80211_band band = chandef->chan->band;
-@@ -775,7 +736,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
-
- tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_STATE, sizeof(*state));
- state = (struct sta_rec_state *)tlv;
-- state->state = sta_state;
-+ state->state = 2;
-
- if (sta->vht_cap.vht_supported) {
- state->vht_opmode = sta->bandwidth;
-@@ -867,8 +828,8 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
- }
- EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ht_tlv);
-
--int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
-- struct mt76_sta_cmd_info *info)
-+int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
-+ struct mt76_sta_cmd_info *info)
- {
- struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv;
- struct mt76_dev *dev = phy->dev;
-@@ -882,11 +843,10 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
-
- if (info->sta || !info->offload_fw)
- mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta,
-- info->enable, info->newly);
-+ info->enable);
- if (info->sta && info->enable)
- mt76_connac_mcu_sta_tlv(phy, skb, info->sta,
-- info->vif, info->rcpi,
-- info->state);
-+ info->vif, info->rcpi);
-
- sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
- sizeof(struct tlv));
-@@ -901,8 +861,6 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
- mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif,
- info->sta, sta_wtbl,
- wtbl_hdr);
-- mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, info->vif, info->wcid,
-- sta_wtbl, wtbl_hdr);
- if (info->sta)
- mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
- sta_wtbl, wtbl_hdr);
-@@ -910,7 +868,7 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
-
- return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
- }
--EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_cmd);
-+EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_sta_cmd);
-
- void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
- struct ieee80211_ampdu_params *params,
-@@ -939,10 +897,8 @@ void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
- ba->rst_ba_sb = 1;
- }
-
-- if (is_mt7921(dev)) {
-- ba->ba_winsize = enable ? cpu_to_le16(params->buf_size) : 0;
-+ if (is_mt7921(dev))
- return;
-- }
-
- if (enable && tx) {
- u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 };
-@@ -1317,7 +1273,6 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
- u8 pad[3];
- } __packed hdr;
- struct bss_info_uni_he he;
-- struct bss_info_uni_bss_color bss_color;
- } he_req = {
- .hdr = {
- .bss_idx = mvif->idx,
-@@ -1326,21 +1281,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
- .tag = cpu_to_le16(UNI_BSS_INFO_HE_BASIC),
- .len = cpu_to_le16(sizeof(struct bss_info_uni_he)),
- },
-- .bss_color = {
-- .tag = cpu_to_le16(UNI_BSS_INFO_BSS_COLOR),
-- .len = cpu_to_le16(sizeof(struct bss_info_uni_bss_color)),
-- .enable = 0,
-- .bss_color = 0,
-- },
- };
-
-- if (enable) {
-- he_req.bss_color.enable =
-- vif->bss_conf.he_bss_color.enabled;
-- he_req.bss_color.bss_color =
-- vif->bss_conf.he_bss_color.color;
-- }
--
- mt76_connac_mcu_uni_bss_he_tlv(phy, vif,
- (struct tlv *)&he_req.he);
- err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD_BSS_INFO_UPDATE,
-@@ -1523,16 +1465,14 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
- req->version = 1;
- req->seq_num = mvif->scan_seq_num | ext_phy << 7;
-
-- if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
-- u8 *addr = is_mt7663(phy->dev) ? req->mt7663.random_mac
-- : req->mt7921.random_mac;
--
-- req->scan_func = 1;
-- get_random_mask_addr(addr, sreq->mac_addr,
-+ if (is_mt7663(phy->dev) &&
-+ (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) {
-+ get_random_mask_addr(req->mt7663.random_mac, sreq->mac_addr,
- sreq->mac_addr_mask);
-- }
-- if (is_mt7921(phy->dev))
-+ req->scan_func = 1;
-+ } else if (is_mt7921(phy->dev)) {
- req->mt7921.bss_idx = mvif->idx;
-+ }
-
- req->ssids_num = sreq->n_ssids;
- for (i = 0; i < req->ssids_num; i++) {
-@@ -1618,26 +1558,6 @@ int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable)
- }
- EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_deep_sleep);
-
--int mt76_connac_sta_state_dp(struct mt76_dev *dev,
-- enum ieee80211_sta_state old_state,
-- enum ieee80211_sta_state new_state)
--{
-- if ((old_state == IEEE80211_STA_ASSOC &&
-- new_state == IEEE80211_STA_AUTHORIZED) ||
-- (old_state == IEEE80211_STA_NONE &&
-- new_state == IEEE80211_STA_NOTEXIST))
-- mt76_connac_mcu_set_deep_sleep(dev, true);
--
-- if ((old_state == IEEE80211_STA_NOTEXIST &&
-- new_state == IEEE80211_STA_NONE) ||
-- (old_state == IEEE80211_STA_AUTHORIZED &&
-- new_state == IEEE80211_STA_ASSOC))
-- mt76_connac_mcu_set_deep_sleep(dev, false);
--
-- return 0;
--}
--EXPORT_SYMBOL_GPL(mt76_connac_sta_state_dp);
--
- void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
- struct mt76_connac_coredump *coredump)
- {
-@@ -1652,60 +1572,6 @@ void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
- }
- EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event);
-
--int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy)
--{
-- struct mt76_connac_cap_hdr {
-- __le16 n_element;
-- u8 rsv[2];
-- } __packed * hdr;
-- struct sk_buff *skb;
-- int ret, i;
--
-- ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CMD_GET_NIC_CAPAB, NULL,
-- 0, true, &skb);
-- if (ret)
-- return ret;
--
-- hdr = (struct mt76_connac_cap_hdr *)skb->data;
-- if (skb->len < sizeof(*hdr)) {
-- ret = -EINVAL;
-- goto out;
-- }
--
-- skb_pull(skb, sizeof(*hdr));
--
-- for (i = 0; i < le16_to_cpu(hdr->n_element); i++) {
-- struct tlv_hdr {
-- __le32 type;
-- __le32 len;
-- } __packed * tlv = (struct tlv_hdr *)skb->data;
-- int len;
--
-- if (skb->len < sizeof(*tlv))
-- break;
--
-- skb_pull(skb, sizeof(*tlv));
--
-- len = le32_to_cpu(tlv->len);
-- if (skb->len < len)
-- break;
--
-- switch (le32_to_cpu(tlv->type)) {
-- case MT_NIC_CAP_6G:
-- phy->cap.has_6ghz = skb->data[0];
-- break;
-- default:
-- break;
-- }
-- skb_pull(skb, len);
-- }
--out:
-- dev_kfree_skb(skb);
--
-- return ret;
--}
--EXPORT_SYMBOL_GPL(mt76_connac_mcu_get_nic_capability);
--
- static void
- mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
- struct mt76_power_limits *limits,
-@@ -1768,15 +1634,12 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
- 142, 144, 149, 151, 153, 155, 157,
- 159, 161, 165
- };
-- int i, n_chan, batch_size, idx = 0, tx_power, last_ch;
- struct mt76_connac_sku_tlv sku_tlbv;
-+ int i, n_chan, batch_size, idx = 0;
- struct mt76_power_limits limits;
- const u8 *ch_list;
-
- sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
-- tx_power = 2 * phy->hw->conf.power_level;
-- if (!tx_power)
-- tx_power = 127;
-
- if (band == NL80211_BAND_2GHZ) {
- n_chan = ARRAY_SIZE(chan_list_2ghz);
-@@ -1787,48 +1650,39 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
- }
- batch_size = DIV_ROUND_UP(n_chan, batch_len);
-
-- if (!phy->cap.has_5ghz)
-- last_ch = chan_list_2ghz[n_chan - 1];
-- else
-- last_ch = chan_list_5ghz[n_chan - 1];
--
- for (i = 0; i < batch_size; i++) {
-+ bool last_msg = i == batch_size - 1;
-+ int num_ch = last_msg ? n_chan % batch_len : batch_len;
- struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {
- .band = band == NL80211_BAND_2GHZ ? 1 : 2,
-+ .n_chan = num_ch,
-+ .last_msg = last_msg,
- };
-- int j, err, msg_len, num_ch;
- struct sk_buff *skb;
-+ int j, err, msg_len;
-
-- num_ch = i == batch_size - 1 ? n_chan % batch_len : batch_len;
- msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv);
- skb = mt76_mcu_msg_alloc(dev, NULL, msg_len);
- if (!skb)
- return -ENOMEM;
-
-- skb_reserve(skb, sizeof(tx_power_tlv));
--
- BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(tx_power_tlv.alpha2));
- memcpy(tx_power_tlv.alpha2, dev->alpha2, sizeof(dev->alpha2));
-- tx_power_tlv.n_chan = num_ch;
-
-+ skb_put_data(skb, &tx_power_tlv, sizeof(tx_power_tlv));
- for (j = 0; j < num_ch; j++, idx++) {
- struct ieee80211_channel chan = {
- .hw_value = ch_list[idx],
- .band = band,
- };
-
-- mt76_get_rate_power_limits(phy, &chan, &limits,
-- tx_power);
-+ mt76_get_rate_power_limits(phy, &chan, &limits, 127);
-
-- tx_power_tlv.last_msg = ch_list[idx] == last_ch;
- sku_tlbv.channel = ch_list[idx];
--
- mt76_connac_mcu_build_sku(dev, sku_tlbv.pwr_limit,
- &limits, band);
- skb_put_data(skb, &sku_tlbv, sku_len);
- }
-- __skb_push(skb, sizeof(tx_power_tlv));
-- memcpy(skb->data, &tx_power_tlv, sizeof(tx_power_tlv));
-
- err = mt76_mcu_skb_send_msg(dev, skb,
- MCU_CMD_SET_RATE_TX_POWER, false);
-@@ -1843,20 +1697,11 @@ int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
- {
- int err;
-
-- if (phy->cap.has_2ghz) {
-- err = mt76_connac_mcu_rate_txpower_band(phy,
-- NL80211_BAND_2GHZ);
-- if (err < 0)
-- return err;
-- }
-- if (phy->cap.has_5ghz) {
-- err = mt76_connac_mcu_rate_txpower_band(phy,
-- NL80211_BAND_5GHZ);
-- if (err < 0)
-- return err;
-- }
-+ err = mt76_connac_mcu_rate_txpower_band(phy, NL80211_BAND_2GHZ);
-+ if (err < 0)
-+ return err;
-
-- return 0;
-+ return mt76_connac_mcu_rate_txpower_band(phy, NL80211_BAND_5GHZ);
- }
- EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
-index 1c73beb22677..facebed1e301 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
-@@ -559,7 +559,6 @@ enum {
- MCU_CMD_SET_RATE_TX_POWER = MCU_CE_PREFIX | 0x5d,
- MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61,
- MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62,
-- MCU_CMD_GET_NIC_CAPAB = MCU_CE_PREFIX | 0x8a,
- MCU_CMD_REG_WRITE = MCU_CE_PREFIX | 0xc0,
- MCU_CMD_REG_READ = MCU_CE_PREFIX | MCU_QUERY_MASK | 0xc0,
- MCU_CMD_CHIP_CONFIG = MCU_CE_PREFIX | 0xca,
-@@ -576,7 +575,6 @@ enum {
- enum {
- UNI_BSS_INFO_BASIC = 0,
- UNI_BSS_INFO_RLM = 2,
-- UNI_BSS_INFO_BSS_COLOR = 4,
- UNI_BSS_INFO_HE_BASIC = 5,
- UNI_BSS_INFO_BCN_CONTENT = 7,
- UNI_BSS_INFO_QBSS = 15,
-@@ -592,28 +590,6 @@ enum {
- UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
- };
-
--enum {
-- MT_NIC_CAP_TX_RESOURCE,
-- MT_NIC_CAP_TX_EFUSE_ADDR,
-- MT_NIC_CAP_COEX,
-- MT_NIC_CAP_SINGLE_SKU,
-- MT_NIC_CAP_CSUM_OFFLOAD,
-- MT_NIC_CAP_HW_VER,
-- MT_NIC_CAP_SW_VER,
-- MT_NIC_CAP_MAC_ADDR,
-- MT_NIC_CAP_PHY,
-- MT_NIC_CAP_MAC,
-- MT_NIC_CAP_FRAME_BUF,
-- MT_NIC_CAP_BEAM_FORM,
-- MT_NIC_CAP_LOCATION,
-- MT_NIC_CAP_MUMIMO,
-- MT_NIC_CAP_BUFFER_MODE_INFO,
-- MT_NIC_CAP_HW_ADIE_VERSION = 0x14,
-- MT_NIC_CAP_ANTSWP = 0x16,
-- MT_NIC_CAP_WFDMA_REALLOC,
-- MT_NIC_CAP_6G,
--};
--
- #define UNI_WOW_DETECT_TYPE_MAGIC BIT(0)
- #define UNI_WOW_DETECT_TYPE_ANY BIT(1)
- #define UNI_WOW_DETECT_TYPE_DISCONNECT BIT(2)
-@@ -802,9 +778,7 @@ struct mt76_connac_sched_scan_req {
- } mt7663;
- struct {
- u8 bss_idx;
-- u8 pad2[19];
-- u8 random_mac[ETH_ALEN];
-- u8 pad3[38];
-+ u8 pad2[63];
- } mt7921;
- };
- } __packed;
-@@ -815,14 +789,6 @@ struct mt76_connac_sched_scan_done {
- __le16 pad;
- } __packed;
-
--struct bss_info_uni_bss_color {
-- __le16 tag;
-- __le16 len;
-- u8 enable;
-- u8 bss_color;
-- u8 rsv[2];
--} __packed;
--
- struct bss_info_uni_he {
- __le16 tag;
- __le16 len;
-@@ -927,12 +893,6 @@ struct mt76_connac_suspend_tlv {
- u8 pad[5];
- } __packed;
-
--enum mt76_sta_info_state {
-- MT76_STA_INFO_STATE_NONE,
-- MT76_STA_INFO_STATE_AUTH,
-- MT76_STA_INFO_STATE_ASSOC
--};
--
- struct mt76_sta_cmd_info {
- struct ieee80211_sta *sta;
- struct mt76_wcid *wcid;
-@@ -941,10 +901,8 @@ struct mt76_sta_cmd_info {
-
- bool offload_fw;
- bool enable;
-- bool newly;
- int cmd;
- u8 rcpi;
-- u8 state;
- };
-
- #define MT_SKU_POWER_LIMIT 161
-@@ -1014,23 +972,18 @@ int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy);
- int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif);
- void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta, bool enable,
-- bool newly);
-+ struct ieee80211_sta *sta, bool enable);
- void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, void *sta_wtbl,
- void *wtbl_tlv);
- void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
-- struct ieee80211_vif *vif,
- struct mt76_wcid *wcid,
- void *sta_wtbl, void *wtbl_tlv);
--int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
-- struct ieee80211_vif *vif,
-- struct mt76_wcid *wcid, int cmd);
- void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
- struct ieee80211_sta *sta,
- struct ieee80211_vif *vif,
-- u8 rcpi, u8 state);
-+ u8 rcpi);
- void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
- struct ieee80211_sta *sta, void *sta_wtbl,
- void *wtbl_tlv);
-@@ -1052,8 +1005,8 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
- struct ieee80211_vif *vif,
- struct mt76_wcid *wcid,
- bool enable);
--int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
-- struct mt76_sta_cmd_info *info);
-+int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
-+ struct mt76_sta_cmd_info *info);
- void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac,
- struct ieee80211_vif *vif);
- int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band);
-@@ -1064,7 +1017,6 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
- int mt76_connac_mcu_start_patch(struct mt76_dev *dev);
- int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get);
- int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option);
--int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy);
-
- int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
- struct ieee80211_scan_request *scan_req);
-@@ -1085,9 +1037,6 @@ int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
- int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend);
- void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
- struct ieee80211_vif *vif);
--int mt76_connac_sta_state_dp(struct mt76_dev *dev,
-- enum ieee80211_sta_state old_state,
-- enum ieee80211_sta_state new_state);
- int mt76_connac_mcu_chip_config(struct mt76_dev *dev);
- int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable);
- void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
-index cea24213186c..dd66fd12a2e6 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
-@@ -68,7 +68,7 @@ static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
- nic_conf1 &= 0xff00;
-
- if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL)
-- dev_dbg(dev->mt76.dev,
-+ dev_err(dev->mt76.dev,
- "driver does not support HW RF ctrl\n");
-
- if (!mt76x02_field_valid(nic_conf0 >> 8))
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
-index c32e6dc68773..10d66775c391 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
-@@ -1022,12 +1022,12 @@ void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
- mt76_wr(dev, MT_TX_PROT_CFG6 + i * 4, vht_prot[i]);
- }
-
--void mt76x02_update_channel(struct mt76_phy *mphy)
-+void mt76x02_update_channel(struct mt76_dev *mdev)
- {
-- struct mt76x02_dev *dev = container_of(mphy->dev, struct mt76x02_dev, mt76);
-+ struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
- struct mt76_channel_state *state;
-
-- state = mphy->chan_state;
-+ state = mdev->phy.chan_state;
- state->cc_busy += mt76_rr(dev, MT_CH_BUSY);
-
- spin_lock_bh(&dev->mt76.cc_lock);
-@@ -1169,7 +1169,7 @@ void mt76x02_mac_work(struct work_struct *work)
-
- mutex_lock(&dev->mt76.mutex);
-
-- mt76_update_survey(&dev->mphy);
-+ mt76_update_survey(&dev->mt76);
- for (i = 0, idx = 0; i < 16; i++) {
- u32 val = mt76_rr(dev, MT_TX_AGG_CNT(i));
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
-index 5dc6c834111e..0cfbaca50210 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
-@@ -195,7 +195,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
- struct ieee80211_sta *sta, int len);
- void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq);
- void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
--void mt76x02_update_channel(struct mt76_phy *mphy);
-+void mt76x02_update_channel(struct mt76_dev *mdev);
- void mt76x02_mac_work(struct work_struct *work);
-
- void mt76x02_mac_cc_reset(struct mt76x02_dev *dev);
-diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
-index ccdbab341271..02db5d66735d 100644
---- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
-@@ -7,18 +7,24 @@
- #include <linux/module.h>
- #include "mt76x02.h"
-
--#define MT76x02_CCK_RATE(_idx, _rate) { \
-+#define CCK_RATE(_idx, _rate) { \
- .bitrate = _rate, \
- .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
- .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \
- .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + (_idx)), \
- }
-
-+#define OFDM_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+}
-+
- struct ieee80211_rate mt76x02_rates[] = {
-- MT76x02_CCK_RATE(0, 10),
-- MT76x02_CCK_RATE(1, 20),
-- MT76x02_CCK_RATE(2, 55),
-- MT76x02_CCK_RATE(3, 110),
-+ CCK_RATE(0, 10),
-+ CCK_RATE(1, 20),
-+ CCK_RATE(2, 55),
-+ CCK_RATE(3, 110),
- OFDM_RATE(0, 60),
- OFDM_RATE(1, 90),
- OFDM_RATE(2, 120),
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile
-index 80e49244348e..40c8061787e9 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile
-@@ -1,4 +1,4 @@
--# SPDX-License-Identifier: ISC
-+#SPDX-License-Identifier: ISC
-
- obj-$(CONFIG_MT7915E) += mt7915e.o
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
-index 64048243e34b..6a8ddeeecbe9 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
-@@ -3,7 +3,6 @@
-
- #include "mt7915.h"
- #include "eeprom.h"
--#include "mcu.h"
-
- /** global debugfs **/
-
-@@ -17,7 +16,7 @@ mt7915_implicit_txbf_set(void *data, u64 val)
-
- dev->ibf = !!val;
-
-- return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);
-+ return mt7915_mcu_set_txbf_type(dev);
- }
-
- static int
-@@ -148,9 +147,6 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
- {
- struct mt7915_dev *dev = s->private;
- bool ext_phy = phy != &dev->phy;
-- static const char * const bw[] = {
-- "BW20", "BW40", "BW80", "BW160"
-- };
- int cnt;
-
- if (!phy)
-@@ -168,16 +164,11 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s)
- seq_puts(s, "Tx Beamformer Rx feedback statistics: ");
-
- cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(ext_phy));
-- seq_printf(s, "All: %ld, HE: %ld, VHT: %ld, HT: %ld, ",
-+ seq_printf(s, "All: %ld, HE: %ld, VHT: %ld, HT: %ld\n",
- FIELD_GET(MT_ETBF_RX_FB_ALL, cnt),
- FIELD_GET(MT_ETBF_RX_FB_HE, cnt),
- FIELD_GET(MT_ETBF_RX_FB_VHT, cnt),
- FIELD_GET(MT_ETBF_RX_FB_HT, cnt));
-- cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(ext_phy));
-- seq_printf(s, "%s, NC: %ld, NR: %ld\n",
-- bw[FIELD_GET(MT_ETBF_RX_FB_BW, cnt)],
-- FIELD_GET(MT_ETBF_RX_FB_NC, cnt),
-- FIELD_GET(MT_ETBF_RX_FB_NR, cnt));
-
- /* Tx Beamformee Rx NDPA & Tx feedback report */
- cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy));
-@@ -213,7 +204,7 @@ mt7915_tx_stats_show(struct seq_file *file, void *data)
- mt7915_txbf_stat_read_phy(mt7915_ext_phy(dev), file);
-
- /* Tx amsdu info */
-- seq_puts(file, "Tx MSDU statistics:\n");
-+ seq_puts(file, "Tx MSDU stat:\n");
- for (i = 0, n = 0; i < ARRAY_SIZE(stat); i++) {
- stat[i] = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
- n += stat[i];
-@@ -233,6 +224,18 @@ mt7915_tx_stats_show(struct seq_file *file, void *data)
-
- DEFINE_SHOW_ATTRIBUTE(mt7915_tx_stats);
-
-+static int mt7915_read_temperature(struct seq_file *s, void *data)
-+{
-+ struct mt7915_dev *dev = dev_get_drvdata(s->private);
-+ int temp;
-+
-+ /* cpu */
-+ temp = mt7915_mcu_get_temperature(dev, 0);
-+ seq_printf(s, "Temperature: %d\n", temp);
-+
-+ return 0;
-+}
-+
- static int
- mt7915_queues_acq(struct seq_file *s, void *data)
- {
-@@ -304,23 +307,54 @@ mt7915_puts_rate_txpower(struct seq_file *s, struct mt7915_phy *phy)
- "RU26", "RU52", "RU106", "RU242/SU20",
- "RU484/SU40", "RU996/SU80", "RU2x996/SU160"
- };
-- s8 txpower[MT7915_SKU_RATE_NUM], *buf;
-- int i;
-+ struct mt7915_dev *dev = dev_get_drvdata(s->private);
-+ bool ext_phy = phy != &dev->phy;
-+ u32 reg_base;
-+ int i, idx = 0;
-
- if (!phy)
- return;
-
-- seq_printf(s, "\nBand %d\n", phy != &phy->dev->phy);
-+ reg_base = MT_TMAC_FP0R0(ext_phy);
-+ seq_printf(s, "\nBand %d\n", ext_phy);
-
-- mt7915_mcu_get_txpower_sku(phy, txpower, sizeof(txpower));
-- for (i = 0, buf = txpower; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
-- u8 mcs_num = mt7915_sku_group_len[i];
-+ for (i = 0; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
-+ u8 cnt, mcs_num = mt7915_sku_group_len[i];
-+ s8 txpower[12];
-+ int j;
-
-- if (i >= SKU_VHT_BW20 && i <= SKU_VHT_BW160)
-+ if (i == SKU_HT_BW20 || i == SKU_HT_BW40) {
-+ mcs_num = 8;
-+ } else if (i >= SKU_VHT_BW20 && i <= SKU_VHT_BW160) {
- mcs_num = 10;
-+ } else if (i == SKU_HE_RU26) {
-+ reg_base = MT_TMAC_FP0R18(ext_phy);
-+ idx = 0;
-+ }
-+
-+ for (j = 0, cnt = 0; j < DIV_ROUND_UP(mcs_num, 4); j++) {
-+ u32 val;
-+
-+ if (i == SKU_VHT_BW160 && idx == 60) {
-+ reg_base = MT_TMAC_FP0R15(ext_phy);
-+ idx = 0;
-+ }
-+
-+ val = mt76_rr(dev, reg_base + (idx / 4) * 4);
-+
-+ if (idx && idx % 4)
-+ val >>= (idx % 4) * 8;
-+
-+ while (val > 0 && cnt < mcs_num) {
-+ s8 pwr = FIELD_GET(MT_TMAC_FP_MASK, val);
-+
-+ txpower[cnt++] = pwr;
-+ val >>= 8;
-+ idx++;
-+ }
-+ }
-
-- mt76_seq_puts_array(s, sku_group_name[i], buf, mcs_num);
-- buf += mt7915_sku_group_len[i];
-+ mt76_seq_puts_array(s, sku_group_name[i], txpower, mcs_num);
- }
- }
-
-@@ -356,6 +390,8 @@ int mt7915_init_debugfs(struct mt7915_dev *dev)
- debugfs_create_file("radar_trigger", 0200, dir, dev,
- &fops_radar_trigger);
- debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger);
-+ debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir,
-+ mt7915_read_temperature);
- debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
- mt7915_read_rate_txpower);
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
-index 9182568f95c7..11d0b760abd7 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c
-@@ -19,6 +19,39 @@ int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc)
- return 0;
- }
-
-+void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
-+ struct sk_buff *skb)
-+{
-+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
-+ __le32 *rxd = (__le32 *)skb->data;
-+ enum rx_pkt_type type;
-+
-+ type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
-+
-+ switch (type) {
-+ case PKT_TYPE_TXRX_NOTIFY:
-+ mt7915_mac_tx_free(dev, skb);
-+ break;
-+ case PKT_TYPE_RX_EVENT:
-+ mt7915_mcu_rx_event(dev, skb);
-+ break;
-+#ifdef CONFIG_NL80211_TESTMODE
-+ case PKT_TYPE_TXRXV:
-+ mt7915_mac_fill_rx_vector(dev, skb);
-+ break;
-+#endif
-+ case PKT_TYPE_NORMAL:
-+ if (!mt7915_mac_fill_rx(dev, skb)) {
-+ mt76_rx(&dev->mt76, q, skb);
-+ return;
-+ }
-+ fallthrough;
-+ default:
-+ dev_kfree_skb(skb);
-+ break;
-+ }
-+}
-+
- static void
- mt7915_tx_cleanup(struct mt7915_dev *dev)
- {
-@@ -79,6 +112,8 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev)
-
- int mt7915_dma_init(struct mt7915_dev *dev)
- {
-+ /* Increase buffer size to receive large VHT/HE MPDUs */
-+ int rx_buf_size = MT_RX_BUF_SIZE * 2;
- u32 hif1_ofs = 0;
- int ret;
-
-@@ -142,28 +177,28 @@ int mt7915_dma_init(struct mt7915_dev *dev)
- /* event from WM */
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
- MT7915_RXQ_MCU_WM, MT7915_RX_MCU_RING_SIZE,
-- MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
-+ rx_buf_size, MT_RX_EVENT_RING_BASE);
- if (ret)
- return ret;
-
- /* event from WA */
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
- MT7915_RXQ_MCU_WA, MT7915_RX_MCU_RING_SIZE,
-- MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
-+ rx_buf_size, MT_RX_EVENT_RING_BASE);
- if (ret)
- return ret;
-
- /* rx data queue */
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
- MT7915_RXQ_BAND0, MT7915_RX_RING_SIZE,
-- MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
-+ rx_buf_size, MT_RX_DATA_RING_BASE);
- if (ret)
- return ret;
-
- if (dev->dbdc_support) {
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT],
- MT7915_RXQ_BAND1, MT7915_RX_RING_SIZE,
-- MT_RX_BUF_SIZE,
-+ rx_buf_size,
- MT_RX_DATA_RING_BASE + hif1_ofs);
- if (ret)
- return ret;
-@@ -172,7 +207,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT_WA],
- MT7915_RXQ_MCU_WA_EXT,
- MT7915_RX_MCU_RING_SIZE,
-- MT_RX_BUF_SIZE,
-+ rx_buf_size,
- MT_RX_EVENT_RING_BASE + hif1_ofs);
- if (ret)
- return ret;
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
-index ee3d64434821..8ededf2e5279 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
-@@ -4,12 +4,22 @@
- #include "mt7915.h"
- #include "eeprom.h"
-
-+static u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset)
-+{
-+ u8 *data = dev->mt76.eeprom.data;
-+
-+ if (data[offset] == 0xff && !dev->flash_mode)
-+ mt7915_mcu_get_eeprom(dev, offset);
-+
-+ return data[offset];
-+}
-+
- static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
- {
- struct mt76_dev *mdev = &dev->mt76;
-- u8 *eeprom = mdev->eeprom.data;
-- u32 val = eeprom[MT_EE_DO_PRE_CAL];
-+ u32 val;
-
-+ val = mt7915_eeprom_read(dev, MT_EE_DO_PRE_CAL);
- if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
- return 0;
-
-@@ -33,13 +43,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
- dev->flash_mode = true;
- ret = mt7915_eeprom_load_precal(dev);
- } else {
-- u32 block_num, i;
--
-- block_num = DIV_ROUND_UP(MT7915_EEPROM_SIZE,
-- MT7915_EEPROM_BLOCK_SIZE);
-- for (i = 0; i < block_num; i++)
-- mt7915_mcu_get_eeprom(dev,
-- i * MT7915_EEPROM_BLOCK_SIZE);
-+ memset(dev->mt76.eeprom.data, -1, MT7915_EEPROM_SIZE);
- }
-
- return ret;
-@@ -48,7 +52,10 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
- static int mt7915_check_eeprom(struct mt7915_dev *dev)
- {
- u8 *eeprom = dev->mt76.eeprom.data;
-- u16 val = get_unaligned_le16(eeprom);
-+ u16 val;
-+
-+ mt7915_eeprom_read(dev, MT_EE_CHIP_ID);
-+ val = get_unaligned_le16(eeprom);
-
- switch (val) {
- case 0x7915:
-@@ -62,10 +69,9 @@ void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
- {
- struct mt7915_dev *dev = phy->dev;
- bool ext_phy = phy != &dev->phy;
-- u8 *eeprom = dev->mt76.eeprom.data;
- u32 val;
-
-- val = eeprom[MT_EE_WIFI_CONF + ext_phy];
-+ val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy);
- val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
- if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support)
- val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
-@@ -137,7 +143,6 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
- struct ieee80211_channel *chan,
- u8 chain_idx)
- {
-- u8 *eeprom = dev->mt76.eeprom.data;
- int index, target_power;
- bool tssi_on;
-
-@@ -148,18 +153,18 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
-
- if (chan->band == NL80211_BAND_2GHZ) {
- index = MT_EE_TX0_POWER_2G + chain_idx * 3;
-- target_power = eeprom[index];
-+ target_power = mt7915_eeprom_read(dev, index);
-
- if (!tssi_on)
-- target_power += eeprom[index + 1];
-+ target_power += mt7915_eeprom_read(dev, index + 1);
- } else {
- int group = mt7915_get_channel_group(chan->hw_value);
-
- index = MT_EE_TX0_POWER_5G + chain_idx * 12;
-- target_power = eeprom[index + group];
-+ target_power = mt7915_eeprom_read(dev, index + group);
-
- if (!tssi_on)
-- target_power += eeprom[index + 8];
-+ target_power += mt7915_eeprom_read(dev, index + 8);
- }
-
- return target_power;
-@@ -167,14 +172,13 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
-
- s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
- {
-- u8 *eeprom = dev->mt76.eeprom.data;
- u32 val;
- s8 delta;
-
- if (band == NL80211_BAND_2GHZ)
-- val = eeprom[MT_EE_RATE_DELTA_2G];
-+ val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_2G);
- else
-- val = eeprom[MT_EE_RATE_DELTA_5G];
-+ val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_5G);
-
- if (!(val & MT_EE_RATE_DELTA_EN))
- return 0;
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
-index 4798d6344305..feb2aa57ef22 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
-@@ -2,14 +2,39 @@
- /* Copyright (C) 2020 MediaTek Inc. */
-
- #include <linux/etherdevice.h>
--#include <linux/hwmon.h>
--#include <linux/hwmon-sysfs.h>
--#include <linux/thermal.h>
- #include "mt7915.h"
- #include "mac.h"
- #include "mcu.h"
- #include "eeprom.h"
-
-+#define CCK_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
-+ .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)), \
-+}
-+
-+#define OFDM_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+}
-+
-+static struct ieee80211_rate mt7915_rates[] = {
-+ CCK_RATE(0, 10),
-+ CCK_RATE(1, 20),
-+ CCK_RATE(2, 55),
-+ CCK_RATE(3, 110),
-+ OFDM_RATE(11, 60),
-+ OFDM_RATE(15, 90),
-+ OFDM_RATE(10, 120),
-+ OFDM_RATE(14, 180),
-+ OFDM_RATE(9, 240),
-+ OFDM_RATE(13, 360),
-+ OFDM_RATE(8, 480),
-+ OFDM_RATE(12, 540),
-+};
-+
- static const struct ieee80211_iface_limit if_limits[] = {
- {
- .max = 1,
-@@ -42,117 +67,6 @@ static const struct ieee80211_iface_combination if_comb[] = {
- }
- };
-
--static ssize_t mt7915_thermal_show_temp(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct mt7915_phy *phy = dev_get_drvdata(dev);
-- int temperature;
--
-- temperature = mt7915_mcu_get_temperature(phy);
-- if (temperature < 0)
-- return temperature;
--
-- /* display in millidegree celcius */
-- return sprintf(buf, "%u\n", temperature * 1000);
--}
--
--static SENSOR_DEVICE_ATTR(temp1_input, 0444, mt7915_thermal_show_temp,
-- NULL, 0);
--
--static struct attribute *mt7915_hwmon_attrs[] = {
-- &sensor_dev_attr_temp1_input.dev_attr.attr,
-- NULL,
--};
--ATTRIBUTE_GROUPS(mt7915_hwmon);
--
--static int
--mt7915_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
-- unsigned long *state)
--{
-- *state = MT7915_THERMAL_THROTTLE_MAX;
--
-- return 0;
--}
--
--static int
--mt7915_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
-- unsigned long *state)
--{
-- struct mt7915_phy *phy = cdev->devdata;
--
-- *state = phy->throttle_state;
--
-- return 0;
--}
--
--static int
--mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
-- unsigned long state)
--{
-- struct mt7915_phy *phy = cdev->devdata;
-- int ret;
--
-- if (state > MT7915_THERMAL_THROTTLE_MAX)
-- return -EINVAL;
--
-- if (state == phy->throttle_state)
-- return 0;
--
-- ret = mt7915_mcu_set_thermal_throttling(phy, state);
-- if (ret)
-- return ret;
--
-- phy->throttle_state = state;
--
-- return 0;
--}
--
--static const struct thermal_cooling_device_ops mt7915_thermal_ops = {
-- .get_max_state = mt7915_thermal_get_max_throttle_state,
-- .get_cur_state = mt7915_thermal_get_cur_throttle_state,
-- .set_cur_state = mt7915_thermal_set_cur_throttle_state,
--};
--
--static void mt7915_unregister_thermal(struct mt7915_phy *phy)
--{
-- struct wiphy *wiphy = phy->mt76->hw->wiphy;
--
-- if (!phy->cdev)
-- return;
--
-- sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
-- thermal_cooling_device_unregister(phy->cdev);
--}
--
--static int mt7915_thermal_init(struct mt7915_phy *phy)
--{
-- struct wiphy *wiphy = phy->mt76->hw->wiphy;
-- struct thermal_cooling_device *cdev;
-- struct device *hwmon;
--
-- cdev = thermal_cooling_device_register(wiphy_name(wiphy), phy,
-- &mt7915_thermal_ops);
-- if (!IS_ERR(cdev)) {
-- if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
-- "cooling_device") < 0)
-- thermal_cooling_device_unregister(cdev);
-- else
-- phy->cdev = cdev;
-- }
--
-- if (!IS_REACHABLE(CONFIG_HWMON))
-- return 0;
--
-- hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev,
-- wiphy_name(wiphy), phy,
-- mt7915_hwmon_groups);
-- if (IS_ERR(hwmon))
-- return PTR_ERR(hwmon);
--
-- return 0;
--}
--
- static void
- mt7915_init_txpower(struct mt7915_dev *dev,
- struct ieee80211_supported_band *sband)
-@@ -287,6 +201,7 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
- FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);
- mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);
-
-+ mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
- mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
-
- mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
-@@ -313,19 +228,20 @@ static int mt7915_txbf_init(struct mt7915_dev *dev)
- {
- int ret;
-
-+
- if (dev->dbdc_support) {
-- ret = mt7915_mcu_set_txbf(dev, MT_BF_MODULE_UPDATE);
-+ ret = mt7915_mcu_set_txbf_module(dev);
- if (ret)
- return ret;
- }
-
- /* trigger sounding packets */
-- ret = mt7915_mcu_set_txbf(dev, MT_BF_SOUNDING_ON);
-+ ret = mt7915_mcu_set_txbf_sounding(dev);
- if (ret)
- return ret;
-
- /* enable eBF */
-- return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);
-+ return mt7915_mcu_set_txbf_type(dev);
- }
-
- static int mt7915_register_ext_phy(struct mt7915_dev *dev)
-@@ -365,12 +281,8 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
- if (ret)
- goto error;
-
-- ret = mt76_register_phy(mphy, true, mt76_rates,
-- ARRAY_SIZE(mt76_rates));
-- if (ret)
-- goto error;
--
-- ret = mt7915_thermal_init(phy);
-+ ret = mt76_register_phy(mphy, true, mt7915_rates,
-+ ARRAY_SIZE(mt7915_rates));
- if (ret)
- goto error;
-
-@@ -667,6 +579,8 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
-
- switch (i) {
- case NL80211_IFTYPE_AP:
-+ he_cap_elem->mac_cap_info[0] |=
-+ IEEE80211_HE_MAC_CAP0_TWT_RES;
- he_cap_elem->mac_cap_info[2] |=
- IEEE80211_HE_MAC_CAP2_BSR;
- he_cap_elem->mac_cap_info[4] |=
-@@ -680,6 +594,8 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
- IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
- break;
- case NL80211_IFTYPE_STATION:
-+ he_cap_elem->mac_cap_info[0] |=
-+ IEEE80211_HE_MAC_CAP0_TWT_REQ;
- he_cap_elem->mac_cap_info[1] |=
- IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
-
-@@ -774,7 +690,6 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
- if (!phy)
- return;
-
-- mt7915_unregister_thermal(phy);
- mt76_unregister_phy(mphy);
- ieee80211_free_hw(mphy->hw);
- }
-@@ -816,12 +731,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
- dev->mt76.test_ops = &mt7915_testmode_ops;
- #endif
-
-- ret = mt76_register_device(&dev->mt76, true, mt76_rates,
-- ARRAY_SIZE(mt76_rates));
-- if (ret)
-- return ret;
--
-- ret = mt7915_thermal_init(&dev->phy);
-+ ret = mt76_register_device(&dev->mt76, true, mt7915_rates,
-+ ARRAY_SIZE(mt7915_rates));
- if (ret)
- return ret;
-
-@@ -837,12 +748,10 @@ int mt7915_register_device(struct mt7915_dev *dev)
- void mt7915_unregister_device(struct mt7915_dev *dev)
- {
- mt7915_unregister_ext_phy(dev);
-- mt7915_unregister_thermal(&dev->phy);
- mt76_unregister_device(&dev->mt76);
- mt7915_mcu_exit(dev);
- mt7915_tx_token_put(dev);
- mt7915_dma_cleanup(dev);
-- tasklet_disable(&dev->irq_tasklet);
-
- mt76_free_device(&dev->mt76);
- }
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
-index 2462704094b0..f4544c46c173 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
-@@ -307,8 +307,7 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb,
- }
- }
-
--static int
--mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
-+int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
- {
- struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
- struct mt76_phy *mphy = &dev->mt76.phy;
-@@ -624,10 +623,9 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
- return 0;
- }
-
--static void
--mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
--{
- #ifdef CONFIG_NL80211_TESTMODE
-+void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
-+{
- struct mt7915_phy *phy = &dev->phy;
- __le32 *rxd = (__le32 *)skb->data;
- __le32 *rxv_hdr = rxd + 2;
-@@ -665,10 +663,10 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
-
- phy->test.last_freq_offset = foe;
- phy->test.last_snr = snr;
--#endif
-
- dev_kfree_skb(skb);
- }
-+#endif
-
- static void
- mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
-@@ -900,7 +898,7 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
- }
-
- void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
-- struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
-+ struct sk_buff *skb, struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key, bool beacon)
- {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-@@ -959,12 +957,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
-
- txwi[3] = cpu_to_le32(val);
- txwi[4] = 0;
--
-- val = FIELD_PREP(MT_TXD5_PID, pid);
-- if (pid >= MT_PACKET_ID_FIRST)
-- val |= MT_TXD5_TX_STATUS_HOST;
-- txwi[5] = cpu_to_le32(val);
--
-+ txwi[5] = 0;
- txwi[6] = 0;
- txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
-
-@@ -1004,11 +997,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
- struct ieee80211_key_conf *key = info->control.hw_key;
- struct ieee80211_vif *vif = info->control.vif;
-+ struct mt76_tx_cb *cb = mt76_tx_skb_cb(tx_info->skb);
- struct mt76_txwi_cache *t;
- struct mt7915_txp *txp;
- int id, i, nbuf = tx_info->nbuf - 1;
- u8 *txwi = (u8 *)txwi_ptr;
-- int pid;
-
- if (unlikely(tx_info->skb->len <= ETH_HLEN))
- return -EINVAL;
-@@ -1016,11 +1009,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- if (!wcid)
- wcid = &dev->mt76.global_wcid;
-
-- pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
--
-- mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
-+ mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
- false);
-
-+ cb->wcid = wcid->idx;
-+
- txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
- for (i = 0; i < nbuf; i++) {
- txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
-@@ -1091,50 +1084,65 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
- }
-
- static void
--mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
-+mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb,
-+ struct ieee80211_sta *sta, u8 stat,
-+ struct list_head *free_list)
- {
-- struct mt7915_txp *txp;
-- int i;
--
-- txp = mt7915_txwi_to_txp(dev, t);
-- for (i = 0; i < txp->nbuf; i++)
-- dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
-- le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
--}
-+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+ struct ieee80211_tx_status status = {
-+ .sta = sta,
-+ .info = info,
-+ .skb = skb,
-+ .free_list = free_list,
-+ };
-+ struct ieee80211_hw *hw;
-
--static void
--mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
-- struct ieee80211_sta *sta, struct list_head *free_list)
--{
-- struct mt76_dev *mdev = &dev->mt76;
-- struct mt76_wcid *wcid;
-- __le32 *txwi;
-- u16 wcid_idx;
-+ if (sta) {
-+ struct mt7915_sta *msta;
-
-- mt7915_txp_skb_unmap(mdev, t);
-- if (!t->skb)
-- goto out;
-+ msta = (struct mt7915_sta *)sta->drv_priv;
-+ status.rate = &msta->stats.tx_rate;
-+ }
-
-- txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
-- if (sta) {
-- wcid = (struct mt76_wcid *)sta->drv_priv;
-- wcid_idx = wcid->idx;
-+#ifdef CONFIG_NL80211_TESTMODE
-+ if (mt76_is_testmode_skb(mdev, skb, &hw)) {
-+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
-+ struct ieee80211_vif *vif = phy->monitor_vif;
-+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-
-- if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
-- mt7915_tx_check_aggr(sta, txwi);
-- } else {
-- wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
-+ mt76_tx_complete_skb(mdev, mvif->sta.wcid.idx, skb);
-+ return;
- }
-+#endif
-+
-+ hw = mt76_tx_status_get_hw(mdev, skb);
-
-- __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
-+ if (info->flags & IEEE80211_TX_CTL_AMPDU)
-+ info->flags |= IEEE80211_TX_STAT_AMPDU;
-
--out:
-- t->skb = NULL;
-- mt76_put_txwi(mdev, t);
-+ if (stat)
-+ ieee80211_tx_info_clear_status(info);
-+
-+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
-+ info->flags |= IEEE80211_TX_STAT_ACK;
-+
-+ info->status.tx_time = 0;
-+ ieee80211_tx_status_ext(hw, &status);
- }
-
--static void
--mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
-+void mt7915_txp_skb_unmap(struct mt76_dev *dev,
-+ struct mt76_txwi_cache *t)
-+{
-+ struct mt7915_txp *txp;
-+ int i;
-+
-+ txp = mt7915_txwi_to_txp(dev, t);
-+ for (i = 0; i < txp->nbuf; i++)
-+ dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
-+ le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
-+}
-+
-+void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
- {
- struct mt7915_tx_free *free = (struct mt7915_tx_free *)skb->data;
- struct mt76_dev *mdev = &dev->mt76;
-@@ -1199,7 +1207,28 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
- if (!txwi)
- continue;
-
-- mt7915_txwi_free(dev, txwi, sta, &free_list);
-+ mt7915_txp_skb_unmap(mdev, txwi);
-+ if (txwi->skb) {
-+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txwi->skb);
-+ void *txwi_ptr = mt76_get_txwi_ptr(mdev, txwi);
-+
-+ if (likely(txwi->skb->protocol != cpu_to_be16(ETH_P_PAE)))
-+ mt7915_tx_check_aggr(sta, txwi_ptr);
-+
-+ if (sta && !info->tx_time_est) {
-+ struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
-+ int pending;
-+
-+ pending = atomic_dec_return(&wcid->non_aql_packets);
-+ if (pending < 0)
-+ atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
-+ }
-+
-+ mt7915_tx_complete_status(mdev, txwi->skb, sta, stat, &free_list);
-+ txwi->skb = NULL;
-+ }
-+
-+ mt76_put_txwi(mdev, txwi);
- }
-
- mt7915_mac_sta_poll(dev);
-@@ -1217,120 +1246,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
- }
- }
-
--static bool
--mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
-- __le32 *txs_data)
--{
-- struct mt76_dev *mdev = &dev->mt76;
-- struct ieee80211_tx_info *info;
-- struct sk_buff_head list;
-- struct sk_buff *skb;
--
-- mt76_tx_status_lock(mdev, &list);
-- skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
-- if (!skb)
-- goto out;
--
-- info = IEEE80211_SKB_CB(skb);
-- if (!(txs_data[0] & le32_to_cpu(MT_TXS0_ACK_ERROR_MASK)))
-- info->flags |= IEEE80211_TX_STAT_ACK;
--
-- info->status.ampdu_len = 1;
-- info->status.ampdu_ack_len = !!(info->flags &
-- IEEE80211_TX_STAT_ACK);
--
-- info->status.rates[0].idx = -1;
-- mt76_tx_status_skb_done(mdev, skb, &list);
--
--out:
-- mt76_tx_status_unlock(mdev, &list);
--
-- return !!skb;
--}
--
--static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
--{
-- struct mt7915_sta *msta = NULL;
-- struct mt76_wcid *wcid;
-- __le32 *txs_data = data;
-- u16 wcidx;
-- u32 txs;
-- u8 pid;
--
-- txs = le32_to_cpu(txs_data[0]);
-- if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1)
-- return;
--
-- txs = le32_to_cpu(txs_data[2]);
-- wcidx = FIELD_GET(MT_TXS2_WCID, txs);
--
-- txs = le32_to_cpu(txs_data[3]);
-- pid = FIELD_GET(MT_TXS3_PID, txs);
--
-- if (pid < MT_PACKET_ID_FIRST)
-- return;
--
-- if (wcidx >= MT7915_WTBL_SIZE)
-- return;
--
-- rcu_read_lock();
--
-- wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
-- if (!wcid)
-- goto out;
--
-- mt7915_mac_add_txs_skb(dev, wcid, pid, txs_data);
--
-- if (!wcid->sta)
-- goto out;
--
-- msta = container_of(wcid, struct mt7915_sta, wcid);
-- spin_lock_bh(&dev->sta_poll_lock);
-- if (list_empty(&msta->poll_list))
-- list_add_tail(&msta->poll_list, &dev->sta_poll_list);
-- spin_unlock_bh(&dev->sta_poll_lock);
--
--out:
-- rcu_read_unlock();
--}
--
--void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
-- struct sk_buff *skb)
--{
-- struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
-- __le32 *rxd = (__le32 *)skb->data;
-- __le32 *end = (__le32 *)&skb->data[skb->len];
-- enum rx_pkt_type type;
--
-- type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
--
-- switch (type) {
-- case PKT_TYPE_TXRX_NOTIFY:
-- mt7915_mac_tx_free(dev, skb);
-- break;
-- case PKT_TYPE_RX_EVENT:
-- mt7915_mcu_rx_event(dev, skb);
-- break;
-- case PKT_TYPE_TXRXV:
-- mt7915_mac_fill_rx_vector(dev, skb);
-- break;
-- case PKT_TYPE_TXS:
-- for (rxd += 2; rxd + 8 <= end; rxd += 8)
-- mt7915_mac_add_txs(dev, rxd);
-- dev_kfree_skb(skb);
-- break;
-- case PKT_TYPE_NORMAL:
-- if (!mt7915_mac_fill_rx(dev, skb)) {
-- mt76_rx(&dev->mt76, q, skb);
-- return;
-- }
-- fallthrough;
-- default:
-- dev_kfree_skb(skb);
-- break;
-- }
--}
--
- void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
- {
- struct mt7915_dev *dev;
-@@ -1352,8 +1267,15 @@ void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
- e->skb = t ? t->skb : NULL;
- }
-
-- if (e->skb)
-- mt76_tx_complete_skb(mdev, e->wcid, e->skb);
-+ if (e->skb) {
-+ struct mt76_tx_cb *cb = mt76_tx_skb_cb(e->skb);
-+ struct mt76_wcid *wcid;
-+
-+ wcid = rcu_dereference(dev->mt76.wcid[cb->wcid]);
-+
-+ mt7915_tx_complete_status(mdev, e->skb, wcid_to_sta(wcid), 0,
-+ NULL);
-+ }
- }
-
- void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy)
-@@ -1387,10 +1309,14 @@ void mt7915_mac_reset_counters(struct mt7915_phy *phy)
- memset(&dev->mt76.aggr_stats[i], 0, sizeof(dev->mt76.aggr_stats) / 2);
-
- /* reset airtime counters */
-+ mt76_rr(dev, MT_MIB_SDR9(ext_phy));
-+ mt76_rr(dev, MT_MIB_SDR36(ext_phy));
-+ mt76_rr(dev, MT_MIB_SDR37(ext_phy));
-+
-+ mt76_set(dev, MT_WF_RMAC_MIB_TIME0(ext_phy),
-+ MT_WF_RMAC_MIB_RXTIME_CLR);
- mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(ext_phy),
- MT_WF_RMAC_MIB_RXTIME_CLR);
--
-- mt7915_mcu_get_chan_mib_info(phy, true);
- }
-
- void mt7915_mac_set_timing(struct mt7915_phy *phy)
-@@ -1484,24 +1410,53 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx)
- return sum / n;
- }
-
--void mt7915_update_channel(struct mt76_phy *mphy)
-+static void
-+mt7915_phy_update_channel(struct mt76_phy *mphy, int idx)
- {
-+ struct mt7915_dev *dev = container_of(mphy->dev, struct mt7915_dev, mt76);
- struct mt7915_phy *phy = (struct mt7915_phy *)mphy->priv;
-- struct mt76_channel_state *state = mphy->chan_state;
-- bool ext_phy = phy != &phy->dev->phy;
-+ struct mt76_channel_state *state;
-+ u64 busy_time, tx_time, rx_time, obss_time;
- int nf;
-
-- mt7915_mcu_get_chan_mib_info(phy, false);
-+ busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),
-+ MT_MIB_SDR9_BUSY_MASK);
-+ tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx),
-+ MT_MIB_SDR36_TXTIME_MASK);
-+ rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx),
-+ MT_MIB_SDR37_RXTIME_MASK);
-+ obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx),
-+ MT_MIB_OBSSTIME_MASK);
-
-- nf = mt7915_phy_get_nf(phy, ext_phy);
-+ nf = mt7915_phy_get_nf(phy, idx);
- if (!phy->noise)
- phy->noise = nf << 4;
- else if (nf)
- phy->noise += nf - (phy->noise >> 4);
-
-+ state = mphy->chan_state;
-+ state->cc_busy += busy_time;
-+ state->cc_tx += tx_time;
-+ state->cc_rx += rx_time + obss_time;
-+ state->cc_bss_rx += rx_time;
- state->noise = -(phy->noise >> 4);
- }
-
-+void mt7915_update_channel(struct mt76_dev *mdev)
-+{
-+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
-+
-+ mt7915_phy_update_channel(&mdev->phy, 0);
-+ if (mdev->phy2)
-+ mt7915_phy_update_channel(mdev->phy2, 1);
-+
-+ /* reset obss airtime */
-+ mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
-+ if (mdev->phy2)
-+ mt76_set(dev, MT_WF_RMAC_MIB_TIME0(1),
-+ MT_WF_RMAC_MIB_RXTIME_CLR);
-+}
-+
- static bool
- mt7915_wait_reset_state(struct mt7915_dev *dev, u32 state)
- {
-@@ -1588,18 +1543,14 @@ mt7915_dma_reset(struct mt7915_dev *dev)
- mt76_set(dev, MT_WFDMA0_GLO_CFG,
- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
- mt76_set(dev, MT_WFDMA1_GLO_CFG,
-- MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN |
-- MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
-- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
-+ MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
- if (dev->hif2) {
- mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
- (MT_WFDMA0_GLO_CFG_TX_DMA_EN |
- MT_WFDMA0_GLO_CFG_RX_DMA_EN));
- mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
- (MT_WFDMA1_GLO_CFG_TX_DMA_EN |
-- MT_WFDMA1_GLO_CFG_RX_DMA_EN |
-- MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
-- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO));
-+ MT_WFDMA1_GLO_CFG_RX_DMA_EN));
- }
- }
-
-@@ -1610,7 +1561,14 @@ void mt7915_tx_token_put(struct mt7915_dev *dev)
-
- spin_lock_bh(&dev->mt76.token_lock);
- idr_for_each_entry(&dev->mt76.token, txwi, id) {
-- mt7915_txwi_free(dev, txwi, NULL, NULL);
-+ mt7915_txp_skb_unmap(&dev->mt76, txwi);
-+ if (txwi->skb) {
-+ struct ieee80211_hw *hw;
-+
-+ hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb);
-+ ieee80211_free_txskb(hw, txwi->skb);
-+ }
-+ mt76_put_txwi(&dev->mt76, txwi);
- dev->mt76.token_count--;
- }
- spin_unlock_bh(&dev->mt76.token_lock);
-@@ -1643,6 +1601,11 @@ void mt7915_mac_reset_work(struct work_struct *work)
- set_bit(MT76_RESET, &phy2->mt76->state);
- cancel_delayed_work_sync(&phy2->mt76->mac_work);
- }
-+ /* lock/unlock all queues to ensure that no tx is pending */
-+ mt76_txq_schedule_all(&dev->mphy);
-+ if (ext_phy)
-+ mt76_txq_schedule_all(ext_phy);
-+
- mt76_worker_disable(&dev->mt76.tx_worker);
- napi_disable(&dev->mt76.napi[0]);
- napi_disable(&dev->mt76.napi[1]);
-@@ -1668,6 +1631,10 @@ void mt7915_mac_reset_work(struct work_struct *work)
- if (phy2)
- clear_bit(MT76_RESET, &phy2->mt76->state);
-
-+ mt76_worker_enable(&dev->mt76.tx_worker);
-+ napi_enable(&dev->mt76.tx_napi);
-+ napi_schedule(&dev->mt76.tx_napi);
-+
- napi_enable(&dev->mt76.napi[0]);
- napi_schedule(&dev->mt76.napi[0]);
-
-@@ -1676,20 +1643,14 @@ void mt7915_mac_reset_work(struct work_struct *work)
-
- napi_enable(&dev->mt76.napi[2]);
- napi_schedule(&dev->mt76.napi[2]);
-- tasklet_schedule(&dev->irq_tasklet);
--
-- mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
-- mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
--
-- mt76_worker_enable(&dev->mt76.tx_worker);
--
-- napi_enable(&dev->mt76.tx_napi);
-- napi_schedule(&dev->mt76.tx_napi);
-
- ieee80211_wake_queues(mt76_hw(dev));
- if (ext_phy)
- ieee80211_wake_queues(ext_phy->hw);
-
-+ mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
-+ mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
-+
- mutex_unlock(&dev->mt76.mutex);
-
- mt7915_update_beacons(dev);
-@@ -1703,7 +1664,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
- }
-
- static void
--mt7915_mac_update_stats(struct mt7915_phy *phy)
-+mt7915_mac_update_mib_stats(struct mt7915_phy *phy)
- {
- struct mt7915_dev *dev = phy->dev;
- struct mib_stats *mib = &phy->mib;
-@@ -1785,10 +1746,8 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
-
- if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
- IEEE80211_RC_NSS_CHANGED |
-- IEEE80211_RC_BW_CHANGED)) {
-- mt7915_mcu_add_he(dev, vif, sta);
-+ IEEE80211_RC_BW_CHANGED))
- mt7915_mcu_add_rate_ctrl(dev, vif, sta);
-- }
-
- if (changed & IEEE80211_RC_SMPS_CHANGED)
- mt7915_mcu_add_smps(dev, vif, sta);
-@@ -1810,11 +1769,11 @@ void mt7915_mac_work(struct work_struct *work)
-
- mutex_lock(&mphy->dev->mutex);
-
-- mt76_update_survey(mphy);
-+ mt76_update_survey(mphy->dev);
- if (++mphy->mac_work_count == 5) {
- mphy->mac_work_count = 0;
-
-- mt7915_mac_update_stats(phy);
-+ mt7915_mac_update_mib_stats(phy);
- }
-
- if (++phy->sta_work_count == 10) {
-@@ -1824,8 +1783,6 @@ void mt7915_mac_work(struct work_struct *work)
-
- mutex_unlock(&mphy->dev->mutex);
-
-- mt76_tx_status_check(mphy->dev, NULL, false);
--
- ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
- MT7915_WATCHDOG_TIME);
- }
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
-index eb1885f4bd8e..0f929fb53027 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h
-@@ -304,62 +304,6 @@ struct mt7915_tx_free {
- /* will support this field in further revision */
- #define MT_TX_FREE_RATE GENMASK(13, 0)
-
--#define MT_TXS0_FIXED_RATE BIT(31)
--#define MT_TXS0_BW GENMASK(30, 29)
--#define MT_TXS0_TID GENMASK(28, 26)
--#define MT_TXS0_AMPDU BIT(25)
--#define MT_TXS0_TXS_FORMAT GENMASK(24, 23)
--#define MT_TXS0_BA_ERROR BIT(22)
--#define MT_TXS0_PS_FLAG BIT(21)
--#define MT_TXS0_TXOP_TIMEOUT BIT(20)
--#define MT_TXS0_BIP_ERROR BIT(19)
--
--#define MT_TXS0_QUEUE_TIMEOUT BIT(18)
--#define MT_TXS0_RTS_TIMEOUT BIT(17)
--#define MT_TXS0_ACK_TIMEOUT BIT(16)
--#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16)
--
--#define MT_TXS0_TX_STATUS_HOST BIT(15)
--#define MT_TXS0_TX_STATUS_MCU BIT(14)
--#define MT_TXS0_TX_RATE GENMASK(13, 0)
--
--#define MT_TXS1_SEQNO GENMASK(31, 20)
--#define MT_TXS1_RESP_RATE GENMASK(19, 16)
--#define MT_TXS1_RXV_SEQNO GENMASK(15, 8)
--#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0)
--
--#define MT_TXS2_BF_STATUS GENMASK(31, 30)
--#define MT_TXS2_LAST_TX_RATE GENMASK(29, 27)
--#define MT_TXS2_SHARED_ANTENNA BIT(26)
--#define MT_TXS2_WCID GENMASK(25, 16)
--#define MT_TXS2_TX_DELAY GENMASK(15, 0)
--
--#define MT_TXS3_PID GENMASK(31, 24)
--#define MT_TXS3_ANT_ID GENMASK(23, 0)
--
--#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
--
--#define MT_TXS5_F0_FINAL_MPDU BIT(31)
--#define MT_TXS5_F0_QOS BIT(30)
--#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
--#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0)
--#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24)
--#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0)
--
--#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24)
--#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16)
--#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8)
--#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0)
--#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24)
--#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0)
--
--#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24)
--#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16)
--#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8)
--#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0)
--#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24)
--#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0)
--
- struct mt7915_dfs_pulse {
- u32 max_width; /* us */
- int max_pwr; /* dbm */
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
-index c25f8da590dd..e5bd687546b6 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
-@@ -139,6 +139,12 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
- if (type != NL80211_IFTYPE_STATION)
- break;
-
-+ /* next, try to find a free repeater entry for the sta */
-+ i = get_free_idx(mask >> REPEATER_BSSID_START, 0,
-+ REPEATER_BSSID_MAX - REPEATER_BSSID_START);
-+ if (i)
-+ return i + 32 - 1;
-+
- i = get_free_idx(mask, EXT_BSSID_1, EXT_BSSID_MAX);
- if (i)
- return i - 1;
-@@ -166,22 +172,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
- return -1;
- }
-
--static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
--{
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- int i;
--
-- for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {
-- mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);
-- memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0),
-- sizeof(mvif->bitrate_mask.control[i].ht_mcs));
-- memset(mvif->bitrate_mask.control[i].vht_mcs, GENMASK(15, 0),
-- sizeof(mvif->bitrate_mask.control[i].vht_mcs));
-- memset(mvif->bitrate_mask.control[i].he_mcs, GENMASK(15, 0),
-- sizeof(mvif->bitrate_mask.control[i].he_mcs));
-- }
--}
--
- static int mt7915_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
- {
-@@ -251,8 +241,6 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
- vif->offload_flags = 0;
- vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
-
-- mt7915_init_bitrate_mask(vif);
--
- out:
- mutex_unlock(&dev->mt76.mutex);
-
-@@ -810,8 +798,7 @@ mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-
- n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx;
- /* TSF software read */
-- mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
-- MT_LPON_TCR_SW_READ);
-+ mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE);
- tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band));
- tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band));
-
-@@ -840,34 +827,7 @@ mt7915_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
- mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
- /* TSF software overwrite */
-- mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
-- MT_LPON_TCR_SW_WRITE);
--
-- mutex_unlock(&dev->mt76.mutex);
--}
--
--static void
--mt7915_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-- s64 timestamp)
--{
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- struct mt7915_dev *dev = mt7915_hw_dev(hw);
-- struct mt7915_phy *phy = mt7915_hw_phy(hw);
-- bool band = phy != &dev->phy;
-- union {
-- u64 t64;
-- u32 t32[2];
-- } tsf = { .t64 = timestamp, };
-- u16 n;
--
-- mutex_lock(&dev->mt76.mutex);
--
-- n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx;
-- mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
-- mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
-- /* TSF software adjust*/
-- mt76_rmw(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE,
-- MT_LPON_TCR_SW_ADJUST);
-+ mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_WRITE);
-
- mutex_unlock(&dev->mt76.mutex);
- }
-@@ -951,15 +911,17 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
- }
-
--static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
-+static void
-+mt7915_sta_rc_update(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta,
-+ u32 changed)
- {
-+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
- struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-- struct mt7915_dev *dev = msta->vif->phy->dev;
-- struct ieee80211_hw *hw = msta->vif->phy->mt76->hw;
-- u32 *changed = data;
-
- spin_lock_bh(&dev->sta_poll_lock);
-- msta->stats.changed |= *changed;
-+ msta->stats.changed |= changed;
- if (list_empty(&msta->rc_list))
- list_add_tail(&msta->rc_list, &dev->sta_rc_list);
- spin_unlock_bh(&dev->sta_poll_lock);
-@@ -967,39 +929,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
- ieee80211_queue_work(hw, &dev->rc_work);
- }
-
--static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
-- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta,
-- u32 changed)
--{
-- mt7915_sta_rc_work(&changed, sta);
--}
--
--static int
--mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-- const struct cfg80211_bitrate_mask *mask)
--{
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- enum nl80211_band band = mvif->phy->mt76->chandef.chan->band;
-- u32 changed;
--
-- if (mask->control[band].gi == NL80211_TXRATE_FORCE_LGI)
-- return -EINVAL;
--
-- changed = IEEE80211_RC_SUPP_RATES_CHANGED;
-- mvif->bitrate_mask = *mask;
--
-- /* Update firmware rate control to add a boundary on top of table
-- * to limit the rate selection for each peer, so when set bitrates
-- * vht-mcs-5 1:9, which actually means nss = 1 mcs = 0~9. This only
-- * applies to data frames as for the other mgmt, mcast, bcast still
-- * use legacy rates as it is.
-- */
-- ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed);
--
-- return 0;
--}
--
- static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
-@@ -1058,11 +987,9 @@ const struct ieee80211_ops mt7915_ops = {
- .get_stats = mt7915_get_stats,
- .get_tsf = mt7915_get_tsf,
- .set_tsf = mt7915_set_tsf,
-- .offset_tsf = mt7915_offset_tsf,
- .get_survey = mt76_get_survey,
- .get_antenna = mt76_get_antenna,
- .set_antenna = mt7915_set_antenna,
-- .set_bitrate_mask = mt7915_set_bitrate_mask,
- .set_coverage_class = mt7915_set_coverage_class,
- .sta_statistics = mt7915_sta_statistics,
- .sta_set_4addr = mt7915_sta_set_4addr,
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
-index 43960770a9af..106177072d18 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
-@@ -147,10 +147,10 @@ mt7915_get_he_phy_cap(struct mt7915_phy *phy, struct ieee80211_vif *vif)
- }
-
- static u8
--mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta)
-+mt7915_get_phy_mode(struct mt76_phy *mphy, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
- {
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- enum nl80211_band band = mvif->phy->mt76->chandef.chan->band;
-+ enum nl80211_band band = mphy->chandef.chan->band;
- struct ieee80211_sta_ht_cap *ht_cap;
- struct ieee80211_sta_vht_cap *vht_cap;
- const struct ieee80211_sta_he_cap *he_cap;
-@@ -163,7 +163,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta)
- } else {
- struct ieee80211_supported_band *sband;
-
-- sband = mvif->phy->mt76->hw->wiphy->bands[band];
-+ sband = mphy->hw->wiphy->bands[band];
-
- ht_cap = &sband->ht_cap;
- vht_cap = &sband->vht_cap;
-@@ -209,112 +209,6 @@ mt7915_mcu_get_sta_nss(u16 mcs_map)
- return nss - 1;
- }
-
--static void
--mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
-- const u16 *mask)
--{
-- struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-- struct cfg80211_chan_def *chandef = &msta->vif->phy->mt76->chandef;
-- int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss;
-- u16 mcs_map;
--
-- switch (chandef->width) {
-- case NL80211_CHAN_WIDTH_80P80:
-- mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80p80);
-- break;
-- case NL80211_CHAN_WIDTH_160:
-- mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_160);
-- break;
-- default:
-- mcs_map = le16_to_cpu(sta->he_cap.he_mcs_nss_supp.rx_mcs_80);
-- break;
-- }
--
-- for (nss = 0; nss < max_nss; nss++) {
-- int mcs;
--
-- switch ((mcs_map >> (2 * nss)) & 0x3) {
-- case IEEE80211_HE_MCS_SUPPORT_0_11:
-- mcs = GENMASK(11, 0);
-- break;
-- case IEEE80211_HE_MCS_SUPPORT_0_9:
-- mcs = GENMASK(9, 0);
-- break;
-- case IEEE80211_HE_MCS_SUPPORT_0_7:
-- mcs = GENMASK(7, 0);
-- break;
-- default:
-- mcs = 0;
-- }
--
-- mcs = mcs ? fls(mcs & mask[nss]) - 1 : -1;
--
-- switch (mcs) {
-- case 0 ... 7:
-- mcs = IEEE80211_HE_MCS_SUPPORT_0_7;
-- break;
-- case 8 ... 9:
-- mcs = IEEE80211_HE_MCS_SUPPORT_0_9;
-- break;
-- case 10 ... 11:
-- mcs = IEEE80211_HE_MCS_SUPPORT_0_11;
-- break;
-- default:
-- mcs = IEEE80211_HE_MCS_NOT_SUPPORTED;
-- break;
-- }
-- mcs_map &= ~(0x3 << (nss * 2));
-- mcs_map |= mcs << (nss * 2);
--
-- /* only support 2ss on 160MHz */
-- if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160))
-- break;
-- }
--
-- *he_mcs = cpu_to_le16(mcs_map);
--}
--
--static void
--mt7915_mcu_set_sta_vht_mcs(struct ieee80211_sta *sta, __le16 *vht_mcs,
-- const u16 *mask)
--{
-- u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map);
-- int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss;
-- u16 mcs;
--
-- for (nss = 0; nss < max_nss; nss++, mcs_map >>= 2) {
-- switch (mcs_map & 0x3) {
-- case IEEE80211_VHT_MCS_SUPPORT_0_9:
-- mcs = GENMASK(9, 0);
-- break;
-- case IEEE80211_VHT_MCS_SUPPORT_0_8:
-- mcs = GENMASK(8, 0);
-- break;
-- case IEEE80211_VHT_MCS_SUPPORT_0_7:
-- mcs = GENMASK(7, 0);
-- break;
-- default:
-- mcs = 0;
-- }
--
-- vht_mcs[nss] = cpu_to_le16(mcs & mask[nss]);
--
-- /* only support 2ss on 160MHz */
-- if (nss > 1 && (sta->bandwidth == IEEE80211_STA_RX_BW_160))
-- break;
-- }
--}
--
--static void
--mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,
-- const u8 *mask)
--{
-- int nss, max_nss = sta->rx_nss > 3 ? 4 : sta->rx_nss;
--
-- for (nss = 0; nss < max_nss; nss++)
-- ht_mcs[nss] = sta->ht_cap.mcs.rx_mask[nss] & mask[nss];
--}
--
- static int
- mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
- struct sk_buff *skb, int seq)
-@@ -455,24 +349,6 @@ mt7915_mcu_rx_csa_notify(struct mt7915_dev *dev, struct sk_buff *skb)
- mt7915_mcu_csa_finish, mphy->hw);
- }
-
--static void
--mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb)
--{
-- struct mt76_phy *mphy = &dev->mt76.phy;
-- struct mt7915_mcu_thermal_notify *t;
-- struct mt7915_phy *phy;
--
-- t = (struct mt7915_mcu_thermal_notify *)skb->data;
-- if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE)
-- return;
--
-- if (t->ctrl.band_idx && dev->mt76.phy2)
-- mphy = dev->mt76.phy2;
--
-- phy = (struct mt7915_phy *)mphy->priv;
-- phy->throttle_state = t->ctrl.duty.duty_cycle;
--}
--
- static void
- mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
- {
-@@ -593,7 +469,6 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb)
- u16 attempts = le16_to_cpu(ra->attempts);
- u16 curr = le16_to_cpu(ra->curr_rate);
- u16 wcidx = le16_to_cpu(ra->wlan_idx);
-- struct ieee80211_tx_status status = {};
- struct mt76_phy *mphy = &dev->mphy;
- struct mt7915_sta_stats *stats;
- struct mt7915_sta *msta;
-@@ -625,13 +500,6 @@ mt7915_mcu_tx_rate_report(struct mt7915_dev *dev, struct sk_buff *skb)
-
- stats->per = 1000 * (attempts - success) / attempts;
- }
--
-- status.sta = wcid_to_sta(wcid);
-- if (!status.sta)
-- return;
--
-- status.rate = &stats->tx_rate;
-- ieee80211_tx_status_ext(mphy->hw, &status);
- }
-
- static void
-@@ -663,9 +531,6 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
- struct mt7915_mcu_rxd *rxd = (struct mt7915_mcu_rxd *)skb->data;
-
- switch (rxd->ext_eid) {
-- case MCU_EXT_EVENT_THERMAL_PROTECT:
-- mt7915_mcu_rx_thermal_notify(dev, skb);
-- break;
- case MCU_EXT_EVENT_RDD_REPORT:
- mt7915_mcu_rx_radar_detected(dev, skb);
- break;
-@@ -868,7 +733,7 @@ mt7915_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
- memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN);
- bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
- bss->dtim_period = vif->bss_conf.dtim_period;
-- bss->phy_mode = mt7915_get_phy_mode(vif, NULL);
-+ bss->phy_mode = mt7915_get_phy_mode(phy->mt76, vif, NULL);
- } else {
- memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN);
- }
-@@ -1471,11 +1336,8 @@ mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
- static void
- mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
- {
-- struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
- struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
- struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
-- enum nl80211_band band = msta->vif->phy->mt76->chandef.chan->band;
-- const u16 *mcs_mask = msta->vif->bitrate_mask.control[band].he_mcs;
- struct sta_rec_he *he;
- struct tlv *tlv;
- u32 cap = 0;
-@@ -1566,18 +1428,15 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
- case IEEE80211_STA_RX_BW_160:
- if (elem->phy_cap_info[0] &
- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
-- mt7915_mcu_set_sta_he_mcs(sta,
-- &he->max_nss_mcs[CMD_HE_MCS_BW8080],
-- mcs_mask);
-+ he->max_nss_mcs[CMD_HE_MCS_BW8080] =
-+ he_cap->he_mcs_nss_supp.rx_mcs_80p80;
-
-- mt7915_mcu_set_sta_he_mcs(sta,
-- &he->max_nss_mcs[CMD_HE_MCS_BW160],
-- mcs_mask);
-+ he->max_nss_mcs[CMD_HE_MCS_BW160] =
-+ he_cap->he_mcs_nss_supp.rx_mcs_160;
- fallthrough;
- default:
-- mt7915_mcu_set_sta_he_mcs(sta,
-- &he->max_nss_mcs[CMD_HE_MCS_BW80],
-- mcs_mask);
-+ he->max_nss_mcs[CMD_HE_MCS_BW80] =
-+ he_cap->he_mcs_nss_supp.rx_mcs_80;
- break;
- }
-
-@@ -1685,18 +1544,27 @@ mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
- HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]);
- }
-
--static void
--mt7915_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
-+static int
-+mt7915_mcu_add_mu(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
- {
-- struct sta_rec_vht *vht;
-- struct tlv *tlv;
-+ struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-+ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-+ struct sk_buff *skb;
-+ int len = sizeof(struct sta_req_hdr) + sizeof(struct sta_rec_muru);
-+
-+ if (!sta->vht_cap.vht_supported && !sta->he_cap.has_he)
-+ return 0;
-+
-+ skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-
-- tlv = mt7915_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht));
-+ /* starec muru */
-+ mt7915_mcu_sta_muru_tlv(skb, sta);
-
-- vht = (struct sta_rec_vht *)tlv;
-- vht->vht_cap = cpu_to_le32(sta->vht_cap.cap);
-- vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map;
-- vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map;
-+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-+ MCU_EXT_CMD(STA_REC_UPDATE), true);
- }
-
- static void
-@@ -1748,6 +1616,17 @@ mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
- mt7915_mcu_sta_amsdu_tlv(skb, sta);
- }
-
-+ /* starec vht */
-+ if (sta->vht_cap.vht_supported) {
-+ struct sta_rec_vht *vht;
-+
-+ tlv = mt7915_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht));
-+ vht = (struct sta_rec_vht *)tlv;
-+ vht->vht_cap = cpu_to_le32(sta->vht_cap.cap);
-+ vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map;
-+ vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map;
-+ }
-+
- /* starec he */
- if (sta->he_cap.has_he)
- mt7915_mcu_sta_he_tlv(skb, sta);
-@@ -2137,21 +2016,26 @@ mt7915_mcu_add_txbf(struct mt7915_dev *dev, struct ieee80211_vif *vif,
- vc = mt7915_get_he_phy_cap(phy, vif);
- ve = &vc->he_cap_elem;
-
-- ebfee = !!(HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]) &&
-+ ebfee = !!((HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]) ||
-+ HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4])) &&
- HE_PHY(CAP4_SU_BEAMFORMEE, ve->phy_cap_info[4]));
-- ebf = !!(HE_PHY(CAP3_SU_BEAMFORMER, ve->phy_cap_info[3]) &&
-+ ebf = !!((HE_PHY(CAP3_SU_BEAMFORMER, ve->phy_cap_info[3]) ||
-+ HE_PHY(CAP4_MU_BEAMFORMER, ve->phy_cap_info[4])) &&
- HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]));
- } else if (sta->vht_cap.vht_supported) {
- struct ieee80211_sta_vht_cap *pc;
- struct ieee80211_sta_vht_cap *vc;
-+ u32 cr, ce;
-
- pc = &sta->vht_cap;
- vc = &phy->mt76->sband_5g.sband.vht_cap;
-+ cr = IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
-+ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
-+ ce = IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
-+ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
-
-- ebfee = !!((pc->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
-- (vc->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
-- ebf = !!((vc->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
-- (pc->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE));
-+ ebfee = !!((pc->cap & cr) && (vc->cap & ce));
-+ ebf = !!((vc->cap & cr) && (pc->cap & ce));
- }
-
- /* must keep each tag independent */
-@@ -2195,47 +2079,57 @@ static void
- mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta)
- {
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
-- struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
-- enum nl80211_band band = chandef->chan->band;
-+ struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-+ struct mt76_phy *mphy = &dev->mphy;
-+ enum nl80211_band band;
- struct sta_rec_ra *ra;
- struct tlv *tlv;
-- u32 supp_rate = sta->supp_rates[band];
-- u32 cap = sta->wme ? STA_CAP_WMM : 0;
-+ u32 supp_rate, n_rates, cap = sta->wme ? STA_CAP_WMM : 0;
-+ u8 i, nss = sta->rx_nss, mcs = 0;
-
- tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
- ra = (struct sta_rec_ra *)tlv;
-
-+ if (msta->wcid.ext_phy && dev->mt76.phy2)
-+ mphy = dev->mt76.phy2;
-+
-+ band = mphy->chandef.chan->band;
-+ supp_rate = sta->supp_rates[band];
-+ n_rates = hweight32(supp_rate);
-+
- ra->valid = true;
- ra->auto_rate = true;
-- ra->phy_mode = mt7915_get_phy_mode(vif, sta);
-- ra->channel = chandef->chan->hw_value;
-+ ra->phy_mode = mt7915_get_phy_mode(mphy, vif, sta);
-+ ra->channel = mphy->chandef.chan->hw_value;
- ra->bw = sta->bandwidth;
-+ ra->rate_len = n_rates;
- ra->phy.bw = sta->bandwidth;
-
-- if (supp_rate) {
-- supp_rate &= mask->control[band].legacy;
-- ra->rate_len = hweight32(supp_rate);
--
-+ if (n_rates) {
- if (band == NL80211_BAND_2GHZ) {
- ra->supp_mode = MODE_CCK;
- ra->supp_cck_rate = supp_rate & GENMASK(3, 0);
-+ ra->phy.type = MT_PHY_TYPE_CCK;
-
-- if (ra->rate_len > 4) {
-+ if (n_rates > 4) {
- ra->supp_mode |= MODE_OFDM;
- ra->supp_ofdm_rate = supp_rate >> 4;
-+ ra->phy.type = MT_PHY_TYPE_OFDM;
- }
- } else {
- ra->supp_mode = MODE_OFDM;
- ra->supp_ofdm_rate = supp_rate;
-+ ra->phy.type = MT_PHY_TYPE_OFDM;
- }
- }
-
- if (sta->ht_cap.ht_supported) {
-- const u8 *mcs_mask = mask->control[band].ht_mcs;
-+ for (i = 0; i < nss; i++)
-+ ra->ht_mcs[i] = sta->ht_cap.mcs.rx_mask[i];
-
-+ ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
- ra->supp_mode |= MODE_HT;
-+ mcs = hweight32(le32_to_cpu(ra->supp_ht_mcs)) - 1;
- ra->af = sta->ht_cap.ampdu_factor;
- ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
-
-@@ -2250,16 +2144,13 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
- cap |= STA_CAP_RX_STBC;
- if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)
- cap |= STA_CAP_LDPC;
--
-- mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs, mcs_mask);
-- ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
- }
-
- if (sta->vht_cap.vht_supported) {
-- const u16 *mcs_mask = mask->control[band].vht_mcs;
-- u8 af;
-+ u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map);
-+ u16 vht_mcs;
-+ u8 af, mcs_prev;
-
-- ra->supp_mode |= MODE_VHT;
- af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
- sta->vht_cap.cap);
- ra->af = max_t(u8, ra->af, af);
-@@ -2276,7 +2167,33 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
- if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)
- cap |= STA_CAP_VHT_LDPC;
-
-- mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs, mcs_mask);
-+ ra->supp_mode |= MODE_VHT;
-+ for (mcs = 0, i = 0; i < nss; i++, mcs_map >>= 2) {
-+ switch (mcs_map & 0x3) {
-+ case IEEE80211_VHT_MCS_SUPPORT_0_9:
-+ vht_mcs = GENMASK(9, 0);
-+ break;
-+ case IEEE80211_VHT_MCS_SUPPORT_0_8:
-+ vht_mcs = GENMASK(8, 0);
-+ break;
-+ case IEEE80211_VHT_MCS_SUPPORT_0_7:
-+ vht_mcs = GENMASK(7, 0);
-+ break;
-+ default:
-+ vht_mcs = 0;
-+ }
-+
-+ ra->supp_vht_mcs[i] = cpu_to_le16(vht_mcs);
-+
-+ mcs_prev = hweight16(vht_mcs) - 1;
-+ if (mcs_prev > mcs)
-+ mcs = mcs_prev;
-+
-+ /* only support 2ss on 160MHz */
-+ if (i > 1 && (ra->bw == CMD_CBW_160MHZ ||
-+ ra->bw == CMD_CBW_8080MHZ))
-+ break;
-+ }
- }
-
- if (sta->he_cap.has_he) {
-@@ -2284,7 +2201,28 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
- cap |= STA_CAP_HE;
- }
-
-- ra->sta_cap = cpu_to_le32(cap);
-+ ra->sta_status = cpu_to_le32(cap);
-+
-+ switch (BIT(fls(ra->supp_mode) - 1)) {
-+ case MODE_VHT:
-+ ra->phy.type = MT_PHY_TYPE_VHT;
-+ ra->phy.mcs = mcs;
-+ ra->phy.nss = nss;
-+ ra->phy.stbc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC);
-+ ra->phy.ldpc = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
-+ ra->phy.sgi =
-+ !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
-+ break;
-+ case MODE_HT:
-+ ra->phy.type = MT_PHY_TYPE_HT;
-+ ra->phy.mcs = mcs;
-+ ra->phy.ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING;
-+ ra->phy.stbc = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC);
-+ ra->phy.sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
-+ break;
-+ default:
-+ break;
-+ }
- }
-
- int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-@@ -2305,87 +2243,6 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
- MCU_EXT_CMD(STA_REC_UPDATE), true);
- }
-
--int mt7915_mcu_add_he(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta)
--{
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-- struct sk_buff *skb;
-- int len;
--
-- if (!sta->he_cap.has_he)
-- return 0;
--
-- len = sizeof(struct sta_req_hdr) + sizeof(struct sta_rec_he);
--
-- skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len);
-- if (IS_ERR(skb))
-- return PTR_ERR(skb);
--
-- mt7915_mcu_sta_he_tlv(skb, sta);
--
-- return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-- MCU_EXT_CMD(STA_REC_UPDATE), true);
--}
--
--static int
--mt7915_mcu_add_group(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta)
--{
--#define MT_STA_BSS_GROUP 1
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-- struct {
-- __le32 action;
-- u8 wlan_idx_lo;
-- u8 status;
-- u8 wlan_idx_hi;
-- u8 rsv0[5];
-- __le32 val;
-- u8 rsv1[8];
-- } __packed req = {
-- .action = cpu_to_le32(MT_STA_BSS_GROUP),
-- .wlan_idx_lo = to_wcid_lo(msta->wcid.idx),
-- .wlan_idx_hi = to_wcid_hi(msta->wcid.idx),
-- .val = cpu_to_le32(mvif->idx % 16),
-- };
--
-- return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SET_DRR_CTRL), &req,
-- sizeof(req), true);
--}
--
--static int
--mt7915_mcu_add_mu(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta)
--{
-- struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-- struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-- struct sk_buff *skb;
-- int ret;
--
-- if (!sta->vht_cap.vht_supported && !sta->he_cap.has_he)
-- return 0;
--
-- ret = mt7915_mcu_add_group(dev, vif, sta);
-- if (ret)
-- return ret;
--
-- skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta,
-- MT7915_STA_UPDATE_MAX_SIZE);
-- if (IS_ERR(skb))
-- return PTR_ERR(skb);
--
-- /* wait until TxBF and MU ready to update stare vht */
--
-- /* starec muru */
-- mt7915_mcu_sta_muru_tlv(skb, sta);
-- /* starec vht */
-- mt7915_mcu_sta_vht_tlv(skb, sta);
--
-- return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-- MCU_EXT_CMD(STA_REC_UPDATE), true);
--}
--
- int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, bool enable)
- {
-@@ -2396,14 +2253,17 @@ int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-
- /* must keep the order */
- ret = mt7915_mcu_add_txbf(dev, vif, sta, enable);
-- if (ret || !enable)
-+ if (ret)
- return ret;
-
- ret = mt7915_mcu_add_mu(dev, vif, sta);
- if (ret)
- return ret;
-
-- return mt7915_mcu_add_rate_ctrl(dev, vif, sta);
-+ if (enable)
-+ return mt7915_mcu_add_rate_ctrl(dev, vif, sta);
-+
-+ return 0;
- }
-
- int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-@@ -2572,7 +2432,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct sk_buff *rskb,
- cont->csa_ofs = cpu_to_le16(offs->cntdwn_counter_offs[0] - 4);
-
- buf = (u8 *)tlv + sizeof(*cont);
-- mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
-+ mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL,
- true);
- memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
- }
-@@ -3447,8 +3307,7 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)
- int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
- {
- struct mt7915_mcu_eeprom_info req = {
-- .addr = cpu_to_le32(round_down(offset,
-- MT7915_EEPROM_BLOCK_SIZE)),
-+ .addr = cpu_to_le32(round_down(offset, 16)),
- };
- struct mt7915_mcu_eeprom_info *res;
- struct sk_buff *skb;
-@@ -3462,7 +3321,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
-
- res = (struct mt7915_mcu_eeprom_info *)skb->data;
- buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
-- memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
-+ memcpy(buf, res->data, 16);
- dev_kfree_skb(skb);
-
- return 0;
-@@ -3611,128 +3470,22 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
- return 0;
- }
-
--int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch)
--{
-- /* strict order */
-- static const enum mt7915_chan_mib_offs offs[] = {
-- MIB_BUSY_TIME, MIB_TX_TIME, MIB_RX_TIME, MIB_OBSS_AIRTIME
-- };
-- struct mt76_channel_state *state = phy->mt76->chan_state;
-- struct mt76_channel_state *state_ts = &phy->state_ts;
-- struct mt7915_dev *dev = phy->dev;
-- struct mt7915_mcu_mib *res, req[4];
-- struct sk_buff *skb;
-- int i, ret;
--
-- for (i = 0; i < 4; i++) {
-- req[i].band = cpu_to_le32(phy != &dev->phy);
-- req[i].offs = cpu_to_le32(offs[i]);
-- }
--
-- ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO),
-- req, sizeof(req), true, &skb);
-- if (ret)
-- return ret;
--
-- res = (struct mt7915_mcu_mib *)(skb->data + 20);
--
-- if (chan_switch)
-- goto out;
--
--#define __res_u64(s) le64_to_cpu(res[s].data)
-- state->cc_busy += __res_u64(0) - state_ts->cc_busy;
-- state->cc_tx += __res_u64(1) - state_ts->cc_tx;
-- state->cc_bss_rx += __res_u64(2) - state_ts->cc_bss_rx;
-- state->cc_rx += __res_u64(2) + __res_u64(3) - state_ts->cc_rx;
--
--out:
-- state_ts->cc_busy = __res_u64(0);
-- state_ts->cc_tx = __res_u64(1);
-- state_ts->cc_bss_rx = __res_u64(2);
-- state_ts->cc_rx = __res_u64(2) + __res_u64(3);
--#undef __res_u64
--
-- dev_kfree_skb(skb);
--
-- return 0;
--}
--
--int mt7915_mcu_get_temperature(struct mt7915_phy *phy)
-+int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index)
- {
-- struct mt7915_dev *dev = phy->dev;
- struct {
- u8 ctrl_id;
- u8 action;
-- u8 dbdc_idx;
-+ u8 band;
- u8 rsv[5];
- } req = {
- .ctrl_id = THERMAL_SENSOR_TEMP_QUERY,
-- .dbdc_idx = phy != &dev->phy,
-+ .action = index,
- };
-
- return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req,
- sizeof(req), true);
- }
-
--int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
--{
-- struct mt7915_dev *dev = phy->dev;
-- struct {
-- struct mt7915_mcu_thermal_ctrl ctrl;
--
-- __le32 trigger_temp;
-- __le32 restore_temp;
-- __le16 sustain_time;
-- u8 rsv[2];
-- } __packed req = {
-- .ctrl = {
-- .band_idx = phy != &dev->phy,
-- },
-- };
-- int level;
--
--#define TRIGGER_TEMPERATURE 122
--#define RESTORE_TEMPERATURE 116
--#define SUSTAIN_PERIOD 10
--
-- if (!state) {
-- req.ctrl.ctrl_id = THERMAL_PROTECT_DISABLE;
-- goto out;
-- }
--
-- /* set duty cycle and level */
-- for (level = 0; level < 4; level++) {
-- int ret;
--
-- req.ctrl.ctrl_id = THERMAL_PROTECT_DUTY_CONFIG;
-- req.ctrl.duty.duty_level = level;
-- req.ctrl.duty.duty_cycle = state;
-- state = state * 4 / 5;
--
-- ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
-- &req, sizeof(req.ctrl), false);
-- if (ret)
-- return ret;
-- }
--
-- /* currently use fixed values for throttling, and would be better
-- * to implement thermal zone for dynamic trip in the long run.
-- */
--
-- /* set high-temperature trigger threshold */
-- req.ctrl.ctrl_id = THERMAL_PROTECT_ENABLE;
-- req.trigger_temp = cpu_to_le32(TRIGGER_TEMPERATURE);
-- req.restore_temp = cpu_to_le32(RESTORE_TEMPERATURE);
-- req.sustain_time = cpu_to_le16(SUSTAIN_PERIOD);
--
--out:
-- req.ctrl.type.protect_type = 1;
-- req.ctrl.type.trigger_type = 1;
--
-- return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
-- &req, sizeof(req), false);
--}
--
- int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx)
- {
- struct {
-@@ -3753,6 +3506,7 @@ int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx)
-
- int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
- {
-+#define MT7915_SKU_RATE_NUM 161
- struct mt7915_dev *dev = phy->dev;
- struct mt76_phy *mphy = phy->mt76;
- struct ieee80211_hw *hw = mphy->hw;
-@@ -3802,39 +3556,6 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
- sizeof(req), true);
- }
-
--int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
--{
--#define RATE_POWER_INFO 2
-- struct mt7915_dev *dev = phy->dev;
-- struct {
-- u8 format_id;
-- u8 category;
-- u8 band;
-- u8 _rsv;
-- } __packed req = {
-- .format_id = 7,
-- .category = RATE_POWER_INFO,
-- .band = phy != &dev->phy,
-- };
-- s8 res[MT7915_SKU_RATE_NUM][2];
-- struct sk_buff *skb;
-- int ret, i;
--
-- ret = mt76_mcu_send_and_get_msg(&dev->mt76,
-- MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),
-- &req, sizeof(req), true, &skb);
-- if (ret)
-- return ret;
--
-- memcpy(res, skb->data + 4, sizeof(res));
-- for (i = 0; i < len; i++)
-- txpower[i] = res[i][req.band];
--
-- dev_kfree_skb(skb);
--
-- return 0;
--}
--
- int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,
- u8 en)
- {
-@@ -3893,50 +3614,57 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
- &req, sizeof(req), false);
- }
-
--int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
-+int mt7915_mcu_set_txbf_module(struct mt7915_dev *dev)
- {
-+#define MT_BF_MODULE_UPDATE 25
- struct {
- u8 action;
-- union {
-- struct {
-- u8 snd_mode;
-- u8 sta_num;
-- u8 rsv;
-- u8 wlan_idx[4];
-- __le32 snd_period; /* ms */
-- } __packed snd;
-- struct {
-- bool ebf;
-- bool ibf;
-- u8 rsv;
-- } __packed type;
-- struct {
-- u8 bf_num;
-- u8 bf_bitmap;
-- u8 bf_sel[8];
-- u8 rsv[5];
-- } __packed mod;
-- };
-+ u8 bf_num;
-+ u8 bf_bitmap;
-+ u8 bf_sel[8];
-+ u8 rsv[8];
- } __packed req = {
-- .action = action,
-+ .action = MT_BF_MODULE_UPDATE,
-+ .bf_num = 2,
-+ .bf_bitmap = GENMASK(1, 0),
- };
-
--#define MT_BF_PROCESSING 4
-- switch (action) {
-- case MT_BF_SOUNDING_ON:
-- req.snd.snd_mode = MT_BF_PROCESSING;
-- break;
-- case MT_BF_TYPE_UPDATE:
-- req.type.ebf = true;
-- req.type.ibf = dev->ibf;
-- break;
-- case MT_BF_MODULE_UPDATE:
-- req.mod.bf_num = 2;
-- req.mod.bf_bitmap = GENMASK(1, 0);
-- break;
-- default:
-- return -EINVAL;
-- }
-+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
-+ sizeof(req), true);
-+}
-+
-+int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev)
-+{
-+#define MT_BF_TYPE_UPDATE 20
-+ struct {
-+ u8 action;
-+ bool ebf;
-+ bool ibf;
-+ u8 rsv;
-+ } __packed req = {
-+ .action = MT_BF_TYPE_UPDATE,
-+ .ebf = true,
-+ .ibf = dev->ibf,
-+ };
-+
-+ return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
-+ sizeof(req), true);
-+}
-+
-+int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev)
-+{
-+#define MT_BF_PROCESSING 4
-+ struct {
-+ u8 action;
-+ u8 snd_mode;
-+ u8 sta_num;
-+ u8 rsv;
-+ u8 wlan_idx[4];
-+ __le32 snd_period; /* ms */
-+ } __packed req = {
-+ .action = true,
-+ .snd_mode = MT_BF_PROCESSING,
-+ };
-
- return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TXBF_ACTION), &req,
- sizeof(req), true);
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
-index e68a562cc5b4..c0255c3ac7d0 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
-@@ -68,29 +68,6 @@ struct mt7915_mcu_rxd {
- u8 s2d_index;
- };
-
--struct mt7915_mcu_thermal_ctrl {
-- u8 ctrl_id;
-- u8 band_idx;
-- union {
-- struct {
-- u8 protect_type; /* 1: duty admit, 2: radio off */
-- u8 trigger_type; /* 0: low, 1: high */
-- } __packed type;
-- struct {
-- u8 duty_level; /* level 0~3 */
-- u8 duty_cycle;
-- } __packed duty;
-- };
--} __packed;
--
--struct mt7915_mcu_thermal_notify {
-- struct mt7915_mcu_rxd rxd;
--
-- struct mt7915_mcu_thermal_ctrl ctrl;
-- __le32 temperature;
-- u8 rsv[8];
--} __packed;
--
- struct mt7915_mcu_csa_notify {
- struct mt7915_mcu_rxd rxd;
-
-@@ -216,19 +193,6 @@ struct mt7915_mcu_phy_rx_info {
- #define MT_RA_RATE_DCM_EN BIT(4)
- #define MT_RA_RATE_BW GENMASK(14, 13)
-
--struct mt7915_mcu_mib {
-- __le32 band;
-- __le32 offs;
-- __le64 data;
--} __packed;
--
--enum mt7915_chan_mib_offs {
-- MIB_BUSY_TIME = 14,
-- MIB_TX_TIME = 81,
-- MIB_RX_TIME,
-- MIB_OBSS_AIRTIME = 86
--};
--
- struct edca {
- u8 queue;
- u8 set;
-@@ -298,7 +262,6 @@ enum {
- MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
- MCU_EXT_CMD_TXBF_ACTION = 0x1e,
- MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
-- MCU_EXT_CMD_THERMAL_PROT = 0x23,
- MCU_EXT_CMD_STA_REC_UPDATE = 0x25,
- MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26,
- MCU_EXT_CMD_EDCA_UPDATE = 0x27,
-@@ -314,7 +277,6 @@ enum {
- MCU_EXT_CMD_MUAR_UPDATE = 0x48,
- MCU_EXT_CMD_SET_RX_PATH = 0x4e,
- MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
-- MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
- MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
- MCU_EXT_CMD_SET_SER_TRIGGER = 0x81,
- MCU_EXT_CMD_SCS_CTRL = 0x82,
-@@ -957,7 +919,7 @@ struct sta_rec_ra {
- u8 op_vht_rx_nss;
- u8 op_vht_rx_nss_type;
-
-- __le32 sta_cap;
-+ __le32 sta_status;
-
- struct ra_phy phy;
- } __packed;
-@@ -1104,28 +1066,11 @@ enum {
- THERMAL_SENSOR_TASK_CTRL,
- };
-
--enum {
-- THERMAL_PROTECT_PARAMETER_CTRL,
-- THERMAL_PROTECT_BASIC_INFO,
-- THERMAL_PROTECT_ENABLE,
-- THERMAL_PROTECT_DISABLE,
-- THERMAL_PROTECT_DUTY_CONFIG,
-- THERMAL_PROTECT_MECH_INFO,
-- THERMAL_PROTECT_DUTY_INFO,
-- THERMAL_PROTECT_STATE_ACT,
--};
--
- enum {
- MT_EBF = BIT(0), /* explicit beamforming */
- MT_IBF = BIT(1) /* implicit beamforming */
- };
-
--enum {
-- MT_BF_SOUNDING_ON = 1,
-- MT_BF_TYPE_UPDATE = 20,
-- MT_BF_MODULE_UPDATE = 25
--};
--
- #define MT7915_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
- sizeof(struct wtbl_generic) + \
- sizeof(struct wtbl_rx) + \
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
-index 3f613fae6218..4ea8972d4e2f 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
-@@ -9,7 +9,7 @@
- #include "../mt76.h"
- #include "regs.h"
-
--#define MT7915_MAX_INTERFACES 19
-+#define MT7915_MAX_INTERFACES 32
- #define MT7915_MAX_WMM_SETS 4
- #define MT7915_WTBL_SIZE 288
- #define MT7915_WTBL_RESERVED (MT7915_WTBL_SIZE - 1)
-@@ -31,7 +31,6 @@
- #define MT7915_ROM_PATCH "mediatek/mt7915_rom_patch.bin"
-
- #define MT7915_EEPROM_SIZE 3584
--#define MT7915_EEPROM_BLOCK_SIZE 16
- #define MT7915_TOKEN_SIZE 8192
-
- #define MT7915_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
-@@ -39,10 +38,6 @@
- #define MT7915_5G_RATE_DEFAULT 0x4b /* OFDM 6M */
- #define MT7915_2G_RATE_DEFAULT 0x0 /* CCK 1M */
-
--#define MT7915_THERMAL_THROTTLE_MAX 100
--
--#define MT7915_SKU_RATE_NUM 161
--
- struct mt7915_vif;
- struct mt7915_sta;
- struct mt7915_dfs_pulse;
-@@ -105,7 +100,6 @@ struct mt7915_vif {
- struct mt7915_phy *phy;
-
- struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
-- struct cfg80211_bitrate_mask bitrate_mask;
- };
-
- struct mib_stats {
-@@ -132,9 +126,6 @@ struct mt7915_phy {
-
- struct ieee80211_vif *monitor_vif;
-
-- struct thermal_cooling_device *cdev;
-- u8 throttle_state;
--
- u32 rxfilter;
- u64 omac_mask;
-
-@@ -150,7 +141,6 @@ struct mt7915_phy {
- u32 ampdu_ref;
-
- struct mib_stats mib;
-- struct mt76_channel_state state_ts;
- struct list_head stats_list;
-
- u8 sta_work_count;
-@@ -179,7 +169,6 @@ struct mt7915_dev {
- struct mt7915_hif *hif2;
-
- const struct mt76_bus_ops *bus_ops;
-- struct tasklet_struct irq_tasklet;
- struct mt7915_phy phy;
-
- u16 chainmask;
-@@ -333,8 +322,6 @@ int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
- bool enable);
- int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
--int mt7915_mcu_add_he(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta);
- int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
- int mt7915_set_channel(struct mt7915_phy *phy);
-@@ -355,8 +342,9 @@ int mt7915_mcu_set_rts_thresh(struct mt7915_phy *phy, u32 val);
- int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter);
- int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
- int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
--int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len);
--int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action);
-+int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev);
-+int mt7915_mcu_set_txbf_module(struct mt7915_dev *dev);
-+int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev);
- int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val);
- int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,
- const struct mt7915_dfs_pulse *pulse);
-@@ -364,9 +352,7 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,
- const struct mt7915_dfs_pattern *pattern);
- int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev);
- int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy);
--int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch);
--int mt7915_mcu_get_temperature(struct mt7915_phy *phy);
--int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state);
-+int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index);
- int mt7915_mcu_get_tx_rate(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx);
- int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, struct rate_info *rate);
-@@ -388,11 +374,9 @@ void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, bool write_reg,
- static inline void mt7915_irq_enable(struct mt7915_dev *dev, u32 mask)
- {
- if (dev->hif2)
-- mt7915_dual_hif_set_irq_mask(dev, false, 0, mask);
-+ mt7915_dual_hif_set_irq_mask(dev, true, 0, mask);
- else
-- mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
--
-- tasklet_schedule(&dev->irq_tasklet);
-+ mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask);
- }
-
- static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask)
-@@ -408,9 +392,12 @@ void mt7915_mac_reset_counters(struct mt7915_phy *phy);
- void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
- void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);
- void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
-- struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
-+ struct sk_buff *skb, struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key, bool beacon);
- void mt7915_mac_set_timing(struct mt7915_phy *phy);
-+int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb);
-+void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb);
-+void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb);
- int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
- void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-@@ -430,11 +417,13 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- struct sk_buff *skb);
- void mt7915_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
- void mt7915_stats_work(struct work_struct *work);
-+void mt7915_txp_skb_unmap(struct mt76_dev *dev,
-+ struct mt76_txwi_cache *txwi);
- int mt76_dfs_start_rdd(struct mt7915_dev *dev, bool force);
- int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy);
- void mt7915_set_stream_he_caps(struct mt7915_phy *phy);
- void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy);
--void mt7915_update_channel(struct mt76_phy *mphy);
-+void mt7915_update_channel(struct mt76_dev *mdev);
- int mt7915_init_debugfs(struct mt7915_dev *dev);
- #ifdef CONFIG_MAC80211_DEBUGFS
- void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
-index 340b364da5f0..643f171884cf 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c
-@@ -94,15 +94,11 @@ mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
- }
-
- /* TODO: support 2/4/6/8 MSI-X vectors */
--static void mt7915_irq_tasklet(struct tasklet_struct *t)
-+static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
- {
-- struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet);
-+ struct mt7915_dev *dev = dev_instance;
- u32 intr, intr1, mask;
-
-- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-- if (dev->hif2)
-- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
--
- intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
- intr &= dev->mt76.mmio.irqmask;
- mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
-@@ -115,6 +111,9 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
- intr |= intr1;
- }
-
-+ if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
-+ return IRQ_NONE;
-+
- trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
-
- mask = intr & MT_INT_RX_DONE_ALL;
-@@ -151,20 +150,6 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
- wake_up(&dev->reset_wait);
- }
- }
--}
--
--static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
--{
-- struct mt7915_dev *dev = dev_instance;
--
-- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-- if (dev->hif2)
-- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
--
-- if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
-- return IRQ_NONE;
--
-- tasklet_schedule(&dev->irq_tasklet);
-
- return IRQ_HANDLED;
- }
-@@ -255,8 +240,6 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
- if (ret)
- return ret;
-
-- mt76_pci_disable_aspm(pdev);
--
- if (id->device == 0x7916)
- return mt7915_pci_hif2_probe(pdev);
-
-@@ -267,18 +250,10 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
-
- dev = container_of(mdev, struct mt7915_dev, mt76);
-
-- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
-- if (ret < 0)
-- goto free;
--
- ret = mt7915_mmio_init(mdev, pcim_iomap_table(pdev)[0], pdev->irq);
- if (ret)
- goto error;
-
-- tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet);
--
-- mt76_wr(dev, MT_INT_MASK_CSR, 0);
--
- /* master switch of PCIe tnterrupt enable */
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
-
-@@ -291,14 +266,10 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
-
- ret = mt7915_register_device(dev);
- if (ret)
-- goto free_irq;
-+ goto error;
-
- return 0;
--free_irq:
-- devm_free_irq(mdev->dev, pdev->irq, dev);
- error:
-- pci_free_irq_vectors(pdev);
--free:
- mt76_free_device(&dev->mt76);
-
- return ret;
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
-index a213b5cb82f8..efe0f2904c66 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
-@@ -82,6 +82,11 @@
- #define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17)
- #define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18)
-
-+#define MT_TMAC_FP0R0(_band) MT_WF_TMAC(_band, 0x020)
-+#define MT_TMAC_FP0R15(_band) MT_WF_TMAC(_band, 0x080)
-+#define MT_TMAC_FP0R18(_band) MT_WF_TMAC(_band, 0x270)
-+#define MT_TMAC_FP_MASK GENMASK(7, 0)
-+
- #define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0)
-
- #define MT_WF_DMA_BASE(_band) ((_band) ? 0xa1e00 : 0x21e00)
-@@ -99,11 +104,6 @@
- #define MT_ETBF_TX_FB_CPL GENMASK(31, 16)
- #define MT_ETBF_TX_FB_TRI GENMASK(15, 0)
-
--#define MT_ETBF_RX_FB_CONT(_band) MT_WF_ETBF(_band, 0x068)
--#define MT_ETBF_RX_FB_BW GENMASK(7, 6)
--#define MT_ETBF_RX_FB_NC GENMASK(5, 3)
--#define MT_ETBF_RX_FB_NR GENMASK(2, 0)
--
- #define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x0f0)
- #define MT_ETBF_TX_IBF_CNT GENMASK(31, 16)
- #define MT_ETBF_TX_EBF_CNT GENMASK(15, 0)
-@@ -124,8 +124,6 @@
- #define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4)
- #define MT_LPON_TCR_SW_MODE GENMASK(1, 0)
- #define MT_LPON_TCR_SW_WRITE BIT(0)
--#define MT_LPON_TCR_SW_ADJUST BIT(1)
--#define MT_LPON_TCR_SW_READ GENMASK(1, 0)
-
- /* MIB: band 0(0x24800), band 1(0xa4800) */
- #define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800)
-@@ -134,9 +132,20 @@
- #define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x014)
- #define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0)
-
-+#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c)
-+#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0)
-+
-+#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048)
-+#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0)
-+
- #define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090)
- #define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0)
-
-+#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x098)
-+#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0)
-+#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x09c)
-+#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0)
-+
- #define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0)
- #define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4)
- #define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc)
-@@ -149,6 +158,9 @@
- #define MT_MIB_BA_MISS_COUNT_MASK GENMASK(15, 0)
- #define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16)
-
-+#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4))
-+#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0)
-+
- #define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x0a8 + ((n) << 2))
- #define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x164 + ((n) << 2))
- #define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x4b8 + ((n) << 2))
-@@ -246,10 +258,14 @@
- #define MT_WF_RFCR1_DROP_CFEND BIT(7)
- #define MT_WF_RFCR1_DROP_CFACK BIT(8)
-
--#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380)
-+#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4)
- #define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31)
- #define MT_WF_RMAC_MIB_RXTIME_EN BIT(30)
-
-+#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8)
-+#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0)
-+#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380)
-+
- /* WFDMA0 */
- #define MT_WFDMA0_BASE 0xd4000
- #define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs))
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h
-index 397a6b5532bc..8f8533ef9859 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.h
-@@ -1,4 +1,4 @@
--/* SPDX-License-Identifier: ISC */
-+// SPDX-License-Identifier: ISC
- /* Copyright (C) 2020 MediaTek Inc. */
-
- #ifndef __MT7915_TESTMODE_H
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile
-index 0ebb59966a08..e531666f9fb4 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile
-@@ -1,4 +1,4 @@
--# SPDX-License-Identifier: ISC
-+#SPDX-License-Identifier: ISC
-
- obj-$(CONFIG_MT7921E) += mt7921e.o
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
-index 77468bdae460..6602903c0d02 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
-@@ -250,9 +250,6 @@ mt7921_pm_set(void *data, u64 val)
- ieee80211_iterate_active_interfaces(mphy->hw,
- IEEE80211_IFACE_ITER_RESUME_ALL,
- mt7921_pm_interface_iter, mphy->priv);
--
-- mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
--
- mt7921_mutex_release(dev);
-
- return 0;
-@@ -270,36 +267,6 @@ mt7921_pm_get(void *data, u64 *val)
-
- DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n");
-
--static int
--mt7921_deep_sleep_set(void *data, u64 val)
--{
-- struct mt7921_dev *dev = data;
-- struct mt76_connac_pm *pm = &dev->pm;
-- bool enable = !!val;
--
-- mt7921_mutex_acquire(dev);
-- if (pm->ds_enable != enable) {
-- mt76_connac_mcu_set_deep_sleep(&dev->mt76, enable);
-- pm->ds_enable = enable;
-- }
-- mt7921_mutex_release(dev);
--
-- return 0;
--}
--
--static int
--mt7921_deep_sleep_get(void *data, u64 *val)
--{
-- struct mt7921_dev *dev = data;
--
-- *val = dev->pm.ds_enable;
--
-- return 0;
--}
--
--DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get,
-- mt7921_deep_sleep_set, "%lld\n");
--
- static int
- mt7921_pm_stats(struct seq_file *s, void *data)
- {
-@@ -391,7 +358,6 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
- debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
- debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
- mt7921_pm_stats);
-- debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
-
- return 0;
- }
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
-index 7d7d43a5422f..7fca7dc466b8 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c
-@@ -74,7 +74,7 @@ static int mt7921_poll_tx(struct napi_struct *napi, int budget)
- mt7921_tx_cleanup(dev);
- if (napi_complete(napi))
- mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL);
-- mt76_connac_pm_unref(&dev->mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
-
- return 0;
- }
-@@ -92,7 +92,7 @@ static int mt7921_poll_rx(struct napi_struct *napi, int budget)
- return 0;
- }
- done = mt76_dma_rx_poll(napi, budget);
-- mt76_connac_pm_unref(&dev->mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
-
- return done;
- }
-@@ -380,7 +380,9 @@ int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev)
-
- int mt7921_dma_init(struct mt7921_dev *dev)
- {
-+ /* Increase buffer size to receive large VHT/HE MPDUs */
- struct mt76_bus_ops *bus_ops;
-+ int rx_buf_size = MT_RX_BUF_SIZE * 2;
- int ret;
-
- dev->bus_ops = dev->mt76.bus;
-@@ -428,7 +430,7 @@ int mt7921_dma_init(struct mt7921_dev *dev)
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
- MT7921_RXQ_MCU_WM,
- MT7921_RX_MCU_RING_SIZE,
-- MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
-+ rx_buf_size, MT_RX_EVENT_RING_BASE);
- if (ret)
- return ret;
-
-@@ -436,14 +438,14 @@ int mt7921_dma_init(struct mt7921_dev *dev)
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
- MT7921_RXQ_MCU_WM,
- MT7921_RX_MCU_RING_SIZE,
-- MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
-+ rx_buf_size, MT_WFDMA0(0x540));
- if (ret)
- return ret;
-
- /* rx data */
- ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
- MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE,
-- MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE);
-+ rx_buf_size, MT_RX_DATA_RING_BASE);
- if (ret)
- return ret;
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
-index a9ce10b98827..db7e436076b3 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
-@@ -7,6 +7,34 @@
- #include "mcu.h"
- #include "eeprom.h"
-
-+#define CCK_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
-+ .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)), \
-+}
-+
-+#define OFDM_RATE(_idx, _rate) { \
-+ .bitrate = _rate, \
-+ .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+ .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
-+}
-+
-+static struct ieee80211_rate mt7921_rates[] = {
-+ CCK_RATE(0, 10),
-+ CCK_RATE(1, 20),
-+ CCK_RATE(2, 55),
-+ CCK_RATE(3, 110),
-+ OFDM_RATE(11, 60),
-+ OFDM_RATE(15, 90),
-+ OFDM_RATE(10, 120),
-+ OFDM_RATE(14, 180),
-+ OFDM_RATE(9, 240),
-+ OFDM_RATE(13, 360),
-+ OFDM_RATE(8, 480),
-+ OFDM_RATE(12, 540),
-+};
-+
- static const struct ieee80211_iface_limit if_limits[] = {
- {
- .max = MT7921_MAX_INTERFACES,
-@@ -51,7 +79,6 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
- hw->queues = 4;
- hw->max_rx_aggregation_subframes = 64;
- hw->max_tx_aggregation_subframes = 128;
-- hw->netdev_features = NETIF_F_RXCSUM;
-
- hw->radiotap_timestamp.units_pos =
- IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
-@@ -62,8 +89,6 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
- hw->vif_data_size = sizeof(struct mt7921_vif);
-
- wiphy->iface_combinations = if_comb;
-- wiphy->flags &= ~WIPHY_FLAG_IBSS_RSN;
-- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
- wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
- wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
- wiphy->max_scan_ssids = 4;
-@@ -76,14 +101,12 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
- wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
- wiphy->reg_notifier = mt7921_regd_notifier;
-
-- wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
-- NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
-+ wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
-
- ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
- ieee80211_hw_set(hw, HAS_RATE_CONTROL);
- ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
-- ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
- ieee80211_hw_set(hw, WANT_MONITOR_VIF);
- ieee80211_hw_set(hw, SUPPORTS_PS);
- ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
-@@ -111,15 +134,14 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
- mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
- }
-
--int mt7921_mac_init(struct mt7921_dev *dev)
-+void mt7921_mac_init(struct mt7921_dev *dev)
- {
- int i;
-
- mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
-- /* enable hardware de-agg */
-- mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
-- /* enable hardware rx header translation */
-- mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN);
-+ /* disable hardware de-agg */
-+ mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
-+ mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN);
-
- for (i = 0; i < MT7921_WTBL_SIZE; i++)
- mt7921_mac_wtbl_update(dev, i,
-@@ -127,7 +149,7 @@ int mt7921_mac_init(struct mt7921_dev *dev)
- for (i = 0; i < 2; i++)
- mt7921_mac_init_band(dev, i);
-
-- return mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
-+ mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
- }
-
- static int mt7921_init_hardware(struct mt7921_dev *dev)
-@@ -167,7 +189,9 @@ static int mt7921_init_hardware(struct mt7921_dev *dev)
- dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;
- rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
-
-- return mt7921_mac_init(dev);
-+ mt7921_mac_init(dev);
-+
-+ return 0;
- }
-
- int mt7921_register_device(struct mt7921_dev *dev)
-@@ -186,6 +210,7 @@ int mt7921_register_device(struct mt7921_dev *dev)
- mutex_init(&dev->pm.mutex);
- init_waitqueue_head(&dev->pm.wait);
- spin_lock_init(&dev->pm.txq_lock);
-+ set_bit(MT76_STATE_PM, &dev->mphy.state);
- INIT_LIST_HEAD(&dev->phy.stats_list);
- INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work);
- INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work);
-@@ -200,8 +225,6 @@ int mt7921_register_device(struct mt7921_dev *dev)
- dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
- dev->pm.stats.last_wake_event = jiffies;
- dev->pm.stats.last_doze_event = jiffies;
-- dev->pm.enable = true;
-- dev->pm.ds_enable = true;
-
- ret = mt7921_init_hardware(dev);
- if (ret)
-@@ -216,33 +239,19 @@ int mt7921_register_device(struct mt7921_dev *dev)
- IEEE80211_HT_CAP_MAX_AMSDU;
- dev->mphy.sband_5g.sband.vht_cap.cap |=
- IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
-- IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
-- IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
-- IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
-- (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
--
-+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
- dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
- dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
-
- mt76_set_stream_caps(&dev->mphy, true);
- mt7921_set_stream_he_caps(&dev->phy);
-
-- ret = mt76_register_device(&dev->mt76, true, mt76_rates,
-- ARRAY_SIZE(mt76_rates));
-+ ret = mt76_register_device(&dev->mt76, true, mt7921_rates,
-+ ARRAY_SIZE(mt7921_rates));
- if (ret)
- return ret;
-
-- ret = mt7921_init_debugfs(dev);
-- if (ret)
-- return ret;
--
-- ret = mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable);
-- if (ret)
-- return ret;
--
-- dev->hw_init_done = true;
--
-- return 0;
-+ return mt7921_init_debugfs(dev);
- }
-
- void mt7921_unregister_device(struct mt7921_dev *dev)
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
-index 7fe2e3a50428..d7d8c909acdf 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
-@@ -308,24 +308,21 @@ mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb)
-
- int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
- {
-- u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
- struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
-- bool hdr_trans, unicast, insert_ccmp_hdr = false;
-- u8 chfreq, qos_ctl = 0, remove_pad, amsdu_info;
-- __le32 *rxv = NULL, *rxd = (__le32 *)skb->data;
- struct mt76_phy *mphy = &dev->mt76.phy;
- struct mt7921_phy *phy = &dev->phy;
- struct ieee80211_supported_band *sband;
- struct ieee80211_hdr *hdr;
-- u32 rxd0 = le32_to_cpu(rxd[0]);
-+ __le32 *rxd = (__le32 *)skb->data;
-+ __le32 *rxv = NULL;
-+ u32 mode = 0;
- u32 rxd1 = le32_to_cpu(rxd[1]);
- u32 rxd2 = le32_to_cpu(rxd[2]);
- u32 rxd3 = le32_to_cpu(rxd[3]);
-- u32 rxd4 = le32_to_cpu(rxd[4]);
-- u16 seq_ctrl = 0;
-- __le16 fc = 0;
-- u32 mode = 0;
-+ bool unicast, insert_ccmp_hdr = false;
-+ u8 remove_pad;
- int i, idx;
-+ u8 chfreq;
-
- memset(status, 0, sizeof(*status));
-
-@@ -335,13 +332,9 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
- if (!test_bit(MT76_STATE_RUNNING, &mphy->state))
- return -EINVAL;
-
-- if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
-- return -EINVAL;
--
- chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3);
- unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
- idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
-- hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
- status->wcid = mt7921_rx_get_wcid(dev, idx, unicast);
-
- if (status->wcid) {
-@@ -364,9 +357,6 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
- if (!sband->channels)
- return -EINVAL;
-
-- if ((rxd0 & csum_mask) == csum_mask)
-- skb->ip_summed = CHECKSUM_UNNECESSARY;
--
- if (rxd1 & MT_RXD1_NORMAL_FCS_ERR)
- status->flag |= RX_FLAG_FAILED_FCS_CRC;
-
-@@ -387,13 +377,6 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
-
- rxd += 6;
- if (rxd1 & MT_RXD1_NORMAL_GROUP_4) {
-- u32 v0 = le32_to_cpu(rxd[0]);
-- u32 v2 = le32_to_cpu(rxd[2]);
--
-- fc = cpu_to_le16(FIELD_GET(MT_RXD6_FRAME_CONTROL, v0));
-- seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, v2);
-- qos_ctl = FIELD_GET(MT_RXD8_QOS_CTL, v2);
--
- rxd += 4;
- if ((u8 *)rxd - skb->data >= skb->len)
- return -EINVAL;
-@@ -573,35 +556,10 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
-
- skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad);
-
-- amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4);
-- status->amsdu = !!amsdu_info;
-- if (status->amsdu) {
-- status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME;
-- status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
-- if (!hdr_trans) {
-- memmove(skb->data + 2, skb->data,
-- ieee80211_get_hdrlen_from_skb(skb));
-- skb_pull(skb, 2);
-- }
-- }
-+ if (insert_ccmp_hdr) {
-+ u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
-
-- if (!hdr_trans) {
-- if (insert_ccmp_hdr) {
-- u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);
--
-- mt76_insert_ccmp_hdr(skb, key_id);
-- }
--
-- hdr = mt76_skb_get_hdr(skb);
-- fc = hdr->frame_control;
-- if (ieee80211_is_data_qos(fc)) {
-- seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
-- qos_ctl = *ieee80211_get_qos_ctl(hdr);
-- }
-- } else {
-- status->flag &= ~(RX_FLAG_RADIOTAP_HE |
-- RX_FLAG_RADIOTAP_HE_MU);
-- status->flag |= RX_FLAG_8023;
-+ mt76_insert_ccmp_hdr(skb, key_id);
- }
-
- mt7921_mac_assoc_rssi(dev, skb);
-@@ -609,12 +567,14 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
- if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
- mt7921_mac_decode_he_radiotap(skb, status, rxv, mode);
-
-- if (!status->wcid || !ieee80211_is_data_qos(fc))
-+ hdr = mt76_skb_get_hdr(skb);
-+ if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control))
- return 0;
-
-- status->aggr = unicast && !ieee80211_is_qos_nullfunc(fc);
-- status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);
-- status->qos_ctl = qos_ctl;
-+ status->aggr = unicast &&
-+ !ieee80211_is_qos_nullfunc(hdr->frame_control);
-+ status->qos_ctl = *ieee80211_get_qos_ctl(hdr);
-+ status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
-
- return 0;
- }
-@@ -732,23 +692,6 @@ mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi,
- txwi[7] |= cpu_to_le32(val);
- }
-
--static void mt7921_update_txs(struct mt76_wcid *wcid, __le32 *txwi)
--{
-- struct mt7921_sta *msta = container_of(wcid, struct mt7921_sta, wcid);
-- u32 pid, frame_type = FIELD_GET(MT_TXD2_FRAME_TYPE, txwi[2]);
--
-- if (!(frame_type & (IEEE80211_FTYPE_DATA >> 2)))
-- return;
--
-- if (time_is_after_eq_jiffies(msta->next_txs_ts))
-- return;
--
-- msta->next_txs_ts = jiffies + msecs_to_jiffies(250);
-- pid = mt76_get_next_pkt_id(wcid);
-- txwi[5] |= cpu_to_le32(MT_TXD5_TX_STATUS_MCU |
-- FIELD_PREP(MT_TXD5_PID, pid));
--}
--
- void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
- struct sk_buff *skb, struct mt76_wcid *wcid,
- struct ieee80211_key_conf *key, bool beacon)
-@@ -825,8 +768,6 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
- txwi[6] |= cpu_to_le32(val);
- txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
- }
--
-- mt7921_update_txs(wcid, txwi);
- }
-
- static void
-@@ -1229,18 +1170,18 @@ mt7921_phy_update_channel(struct mt76_phy *mphy, int idx)
- state->noise = -(phy->noise >> 4);
- }
-
--void mt7921_update_channel(struct mt76_phy *mphy)
-+void mt7921_update_channel(struct mt76_dev *mdev)
- {
-- struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76);
-+ struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
-
-- if (mt76_connac_pm_wake(mphy, &dev->pm))
-+ if (mt76_connac_pm_wake(&dev->mphy, &dev->pm))
- return;
-
-- mt7921_phy_update_channel(mphy, 0);
-+ mt7921_phy_update_channel(&mdev->phy, 0);
- /* reset obss airtime */
- mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
-
-- mt76_connac_power_save_sched(mphy, &dev->pm);
-+ mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
- }
-
- void mt7921_tx_token_put(struct mt7921_dev *dev)
-@@ -1288,7 +1229,6 @@ mt7921_mac_reset(struct mt7921_dev *dev)
- mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
- mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
-
-- set_bit(MT76_RESET, &dev->mphy.state);
- set_bit(MT76_MCU_RESET, &dev->mphy.state);
- wake_up(&dev->mt76.mcu.wait);
- skb_queue_purge(&dev->mt76.mcu.res_q);
-@@ -1304,13 +1244,19 @@ mt7921_mac_reset(struct mt7921_dev *dev)
- mt7921_tx_token_put(dev);
- idr_init(&dev->mt76.token);
-
-- mt7921_wpdma_reset(dev, true);
-+ err = mt7921_wpdma_reset(dev, true);
-+ if (err)
-+ return err;
-
- mt76_for_each_q_rx(&dev->mt76, i) {
- napi_enable(&dev->mt76.napi[i]);
- napi_schedule(&dev->mt76.napi[i]);
- }
-
-+ napi_enable(&dev->mt76.tx_napi);
-+ napi_schedule(&dev->mt76.tx_napi);
-+ mt76_worker_enable(&dev->mt76.tx_worker);
-+
- clear_bit(MT76_MCU_RESET, &dev->mphy.state);
-
- mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA,
-@@ -1320,25 +1266,14 @@ mt7921_mac_reset(struct mt7921_dev *dev)
-
- err = mt7921_run_firmware(dev);
- if (err)
-- goto out;
-+ return err;
-
- err = mt7921_mcu_set_eeprom(dev);
- if (err)
-- goto out;
--
-- err = mt7921_mac_init(dev);
-- if (err)
-- goto out;
--
-- err = __mt7921_start(&dev->phy);
--out:
-- clear_bit(MT76_RESET, &dev->mphy.state);
--
-- napi_enable(&dev->mt76.tx_napi);
-- napi_schedule(&dev->mt76.tx_napi);
-- mt76_worker_enable(&dev->mt76.tx_worker);
-+ return err;
-
-- return err;
-+ mt7921_mac_init(dev);
-+ return __mt7921_start(&dev->phy);
- }
-
- /* system error recovery */
-@@ -1390,13 +1325,11 @@ void mt7921_reset(struct mt76_dev *mdev)
- {
- struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
-
-- if (!dev->hw_init_done)
-- return;
--
-- if (dev->hw_full_reset)
-+ if (!test_bit(MT76_STATE_RUNNING, &dev->mphy.state))
- return;
-
-- queue_work(dev->mt76.wq, &dev->reset_work);
-+ if (!dev->hw_full_reset)
-+ queue_work(dev->mt76.wq, &dev->reset_work);
- }
-
- static void
-@@ -1430,6 +1363,30 @@ mt7921_mac_update_mib_stats(struct mt7921_phy *phy)
- }
- }
-
-+static void
-+mt7921_mac_sta_stats_work(struct mt7921_phy *phy)
-+{
-+ struct mt7921_dev *dev = phy->dev;
-+ struct mt7921_sta *msta;
-+ LIST_HEAD(list);
-+
-+ spin_lock_bh(&dev->sta_poll_lock);
-+ list_splice_init(&phy->stats_list, &list);
-+
-+ while (!list_empty(&list)) {
-+ msta = list_first_entry(&list, struct mt7921_sta, stats_list);
-+ list_del_init(&msta->stats_list);
-+ spin_unlock_bh(&dev->sta_poll_lock);
-+
-+ /* query wtbl info to report tx rate for further devices */
-+ mt7921_get_wtbl_info(dev, msta->wcid.idx);
-+
-+ spin_lock_bh(&dev->sta_poll_lock);
-+ }
-+
-+ spin_unlock_bh(&dev->sta_poll_lock);
-+}
-+
- void mt7921_mac_work(struct work_struct *work)
- {
- struct mt7921_phy *phy;
-@@ -1441,12 +1398,16 @@ void mt7921_mac_work(struct work_struct *work)
-
- mt7921_mutex_acquire(phy->dev);
-
-- mt76_update_survey(mphy);
-+ mt76_update_survey(mphy->dev);
- if (++mphy->mac_work_count == 2) {
- mphy->mac_work_count = 0;
-
- mt7921_mac_update_mib_stats(phy);
- }
-+ if (++phy->sta_work_count == 4) {
-+ phy->sta_work_count = 0;
-+ mt7921_mac_sta_stats_work(phy);
-+ }
-
- mt7921_mutex_release(phy->dev);
- ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work,
-@@ -1482,15 +1443,13 @@ void mt7921_pm_power_save_work(struct work_struct *work)
- {
- struct mt7921_dev *dev;
- unsigned long delta;
-- struct mt76_phy *mphy;
-
- dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev,
- pm.ps_work.work);
-- mphy = dev->phy.mt76;
-
- delta = dev->pm.idle_timeout;
-- if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
-- test_bit(MT76_HW_SCHED_SCANNING, &mphy->state))
-+ if (test_bit(MT76_HW_SCANNING, &dev->mphy.state) ||
-+ test_bit(MT76_HW_SCHED_SCANNING, &dev->mphy.state))
- goto out;
-
- if (time_is_after_jiffies(dev->pm.last_activity + delta)) {
-@@ -1498,10 +1457,8 @@ void mt7921_pm_power_save_work(struct work_struct *work)
- goto out;
- }
-
-- if (!mt7921_mcu_fw_pmctrl(dev)) {
-- cancel_delayed_work_sync(&mphy->mac_work);
-+ if (!mt7921_mcu_fw_pmctrl(dev))
- return;
-- }
- out:
- queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);
- }
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
-index 3af67fac213d..109c8849d106 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
-@@ -88,9 +88,6 @@ enum rx_pkt_type {
-
- /* RXD DW4 */
- #define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
--#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0)
--#define MT_RXD4_MID_AMSDU_FRAME BIT(1)
--#define MT_RXD4_LAST_AMSDU_FRAME BIT(0)
- #define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
- #define MT_RXD4_NORMAL_CLS BIT(10)
- #define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
-@@ -100,17 +97,6 @@ enum rx_pkt_type {
- #define MT_RXD3_NORMAL_PF_MODE BIT(29)
- #define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
-
--/* RXD GROUP4 */
--#define MT_RXD6_FRAME_CONTROL GENMASK(15, 0)
--#define MT_RXD6_TA_LO GENMASK(31, 16)
--
--#define MT_RXD7_TA_HI GENMASK(31, 0)
--
--#define MT_RXD8_SEQ_CTRL GENMASK(15, 0)
--#define MT_RXD8_QOS_CTL GENMASK(31, 16)
--
--#define MT_RXD9_HT_CONTROL GENMASK(31, 0)
--
- /* P-RXV DW0 */
- #define MT_PRXV_TX_RATE GENMASK(6, 0)
- #define MT_PRXV_TX_DCM BIT(4)
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
-index 63ec140c9c37..992a74e122e5 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
-@@ -79,14 +79,13 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
- he_cap_elem->phy_cap_info[1] =
- IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
- he_cap_elem->phy_cap_info[2] =
-- IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
- IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
-- IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
-- IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
-- IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
-+ IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
-
- switch (i) {
- case NL80211_IFTYPE_STATION:
-+ he_cap_elem->mac_cap_info[0] |=
-+ IEEE80211_HE_MAC_CAP0_TWT_REQ;
- he_cap_elem->mac_cap_info[1] |=
- IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
-
-@@ -103,15 +102,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
- he_cap_elem->phy_cap_info[3] |=
- IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
- IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
-- he_cap_elem->phy_cap_info[4] |=
-- IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
-- IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;
-- he_cap_elem->phy_cap_info[5] |=
-- IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK |
-- IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
- he_cap_elem->phy_cap_info[6] |=
-- IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
-- IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
- IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
- IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
- IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
-@@ -325,7 +316,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
- spin_unlock_bh(&dev->sta_poll_lock);
- }
-
--static int mt7921_set_channel(struct mt7921_phy *phy)
-+int mt7921_set_channel(struct mt7921_phy *phy)
- {
- struct mt7921_dev *dev = phy->dev;
- int ret;
-@@ -389,7 +380,6 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- case WLAN_CIPHER_SUITE_WEP104:
- if (!mvif->wep_sta)
- return -EOPNOTSUPP;
-- break;
- case WLAN_CIPHER_SUITE_TKIP:
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_CCMP_256:
-@@ -442,9 +432,6 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
-
- mt7921_mutex_acquire(dev);
-
-- if (changed & IEEE80211_CONF_CHANGE_POWER)
-- mt76_connac_mcu_set_rate_txpower(phy->mt76);
--
- if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
- bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
-
-@@ -590,8 +577,7 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
- mt7921_mcu_uni_bss_ps(dev, vif);
-
- if (changed & BSS_CHANGED_ASSOC) {
-- mt7921_mcu_sta_update(dev, NULL, vif, true,
-- MT76_STA_INFO_STATE_ASSOC);
-+ mt7921_mcu_sta_add(dev, NULL, vif, true);
- mt7921_bss_bcnft_apply(dev, vif, info->assoc);
- }
-
-@@ -630,14 +616,17 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- if (ret)
- return ret;
-
-- if (vif->type == NL80211_IFTYPE_STATION)
-+ if (vif->type == NL80211_IFTYPE_STATION) {
- mvif->wep_sta = msta;
-+ if (!sta->tdls)
-+ mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
-+ &mvif->sta.wcid, true);
-+ }
-
- mt7921_mac_wtbl_update(dev, idx,
- MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
-
-- ret = mt7921_mcu_sta_update(dev, sta, vif, true,
-- MT76_STA_INFO_STATE_NONE);
-+ ret = mt7921_mcu_sta_add(dev, sta, vif, true);
- if (ret)
- return ret;
-
-@@ -646,27 +635,6 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- return 0;
- }
-
--void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta)
--{
-- struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
-- struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
-- struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
--
-- mt7921_mutex_acquire(dev);
--
-- if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
-- mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
-- true);
--
-- mt7921_mac_wtbl_update(dev, msta->wcid.idx,
-- MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
--
-- mt7921_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC);
--
-- mt7921_mutex_release(dev);
--}
--
- void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
- {
-@@ -676,7 +644,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
- mt76_connac_pm_wake(&dev->mphy, &dev->pm);
-
-- mt7921_mcu_sta_update(dev, sta, vif, false, MT76_STA_INFO_STATE_NONE);
-+ mt7921_mcu_sta_add(dev, sta, vif, false);
- mt7921_mac_wtbl_update(dev, msta->wcid.idx,
- MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
-
-@@ -711,7 +679,7 @@ void mt7921_tx_worker(struct mt76_worker *w)
- }
-
- mt76_txq_schedule_all(&dev->mphy);
-- mt76_connac_pm_unref(&dev->mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
- }
-
- static void mt7921_tx(struct ieee80211_hw *hw,
-@@ -741,7 +709,7 @@ static void mt7921_tx(struct ieee80211_hw *hw,
-
- if (mt76_connac_pm_ref(mphy, &dev->pm)) {
- mt76_tx(mphy, control->sta, wcid, skb);
-- mt76_connac_pm_unref(mphy, &dev->pm);
-+ mt76_connac_pm_unref(&dev->pm);
- return;
- }
-
-@@ -822,21 +790,20 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- return ret;
- }
-
--static int mt7921_sta_state(struct ieee80211_hw *hw,
-- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta,
-- enum ieee80211_sta_state old_state,
-- enum ieee80211_sta_state new_state)
-+static int
-+mt7921_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
- {
-- struct mt7921_dev *dev = mt7921_hw_dev(hw);
--
-- if (dev->pm.ds_enable) {
-- mt7921_mutex_acquire(dev);
-- mt76_connac_sta_state_dp(&dev->mt76, old_state, new_state);
-- mt7921_mutex_release(dev);
-- }
-+ return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST,
-+ IEEE80211_STA_NONE);
-+}
-
-- return mt76_sta_state(hw, vif, sta, old_state, new_state);
-+static int
-+mt7921_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-+ struct ieee80211_sta *sta)
-+{
-+ return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE,
-+ IEEE80211_STA_NOTEXIST);
- }
-
- static int
-@@ -1155,23 +1122,6 @@ static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- HZ / 2);
- }
-
--static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,
-- struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta,
-- bool enabled)
--{
-- struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;
-- struct mt7921_dev *dev = mt7921_hw_dev(hw);
--
-- if (enabled)
-- set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
-- else
-- clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags);
--
-- mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid,
-- MCU_UNI_CMD_STA_REC_UPDATE);
--}
--
- const struct ieee80211_ops mt7921_ops = {
- .tx = mt7921_tx,
- .start = mt7921_start,
-@@ -1182,10 +1132,10 @@ const struct ieee80211_ops mt7921_ops = {
- .conf_tx = mt7921_conf_tx,
- .configure_filter = mt7921_configure_filter,
- .bss_info_changed = mt7921_bss_info_changed,
-- .sta_state = mt7921_sta_state,
-+ .sta_add = mt7921_sta_add,
-+ .sta_remove = mt7921_sta_remove,
- .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
- .set_key = mt7921_set_key,
-- .sta_set_decap_offload = mt7921_sta_set_decap_offload,
- .ampdu_action = mt7921_ampdu_action,
- .set_rts_threshold = mt7921_set_rts_threshold,
- .wake_tx_queue = mt76_wake_tx_queue,
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
-index 9fbaacc67cfa..fc0d7dc3a5f3 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
-@@ -398,6 +398,43 @@ mt7921_mcu_tx_rate_parse(struct mt76_phy *mphy,
- }
- }
-
-+static void
-+mt7921_mcu_tx_rate_report(struct mt7921_dev *dev, struct sk_buff *skb,
-+ u16 wlan_idx)
-+{
-+ struct mt7921_mcu_wlan_info_event *wtbl_info;
-+ struct mt76_phy *mphy = &dev->mphy;
-+ struct mt7921_sta_stats *stats;
-+ struct rate_info rate = {};
-+ struct mt7921_sta *msta;
-+ struct mt76_wcid *wcid;
-+ u8 idx;
-+
-+ if (wlan_idx >= MT76_N_WCIDS)
-+ return;
-+
-+ wtbl_info = (struct mt7921_mcu_wlan_info_event *)skb->data;
-+ idx = wtbl_info->rate_info.rate_idx;
-+ if (idx >= ARRAY_SIZE(wtbl_info->rate_info.rate))
-+ return;
-+
-+ rcu_read_lock();
-+
-+ wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
-+ if (!wcid)
-+ goto out;
-+
-+ msta = container_of(wcid, struct mt7921_sta, wcid);
-+ stats = &msta->stats;
-+
-+ /* current rate */
-+ mt7921_mcu_tx_rate_parse(mphy, &wtbl_info->peer_cap, &rate,
-+ le16_to_cpu(wtbl_info->rate_info.rate[idx]));
-+ stats->tx_rate = rate;
-+out:
-+ rcu_read_unlock();
-+}
-+
- static void
- mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb)
- {
-@@ -497,49 +534,6 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb)
- trace_lp_event(dev, event->state);
- }
-
--static void
--mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb)
--{
-- struct mt7921_mcu_tx_done_event *event;
-- struct mt7921_sta *msta;
-- struct mt7921_phy *mphy = &dev->phy;
-- struct mt7921_mcu_peer_cap peer;
-- struct ieee80211_sta *sta;
-- LIST_HEAD(list);
--
-- skb_pull(skb, sizeof(struct mt7921_mcu_rxd));
-- event = (struct mt7921_mcu_tx_done_event *)skb->data;
--
-- spin_lock_bh(&dev->sta_poll_lock);
-- list_splice_init(&mphy->stats_list, &list);
--
-- while (!list_empty(&list)) {
-- msta = list_first_entry(&list, struct mt7921_sta, stats_list);
-- list_del_init(&msta->stats_list);
--
-- if (msta->wcid.idx != event->wlan_idx)
-- continue;
--
-- spin_unlock_bh(&dev->sta_poll_lock);
--
-- sta = wcid_to_sta(&msta->wcid);
--
-- /* peer config based on IEEE SPEC */
-- memset(&peer, 0x0, sizeof(peer));
-- peer.bw = event->bw;
-- peer.g2 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
-- peer.g4 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
-- peer.g8 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
-- peer.g16 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160);
-- mt7921_mcu_tx_rate_parse(mphy->mt76, &peer,
-- &msta->stats.tx_rate, event->tx_rate);
--
-- spin_lock_bh(&dev->sta_poll_lock);
-- break;
-- }
-- spin_unlock_bh(&dev->sta_poll_lock);
--}
--
- static void
- mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
- {
-@@ -566,9 +560,6 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
- case MCU_EVENT_LP_INFO:
- mt7921_mcu_low_power_event(dev, skb);
- break;
-- case MCU_EVENT_TX_DONE:
-- mt7921_mcu_tx_done_event(dev, skb);
-- break;
- default:
- break;
- }
-@@ -589,7 +580,6 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
- rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||
- rxd->eid == MCU_EVENT_BSS_ABSENCE ||
- rxd->eid == MCU_EVENT_SCAN_DONE ||
-- rxd->eid == MCU_EVENT_TX_DONE ||
- rxd->eid == MCU_EVENT_DBG_MSG ||
- rxd->eid == MCU_EVENT_COREDUMP ||
- rxd->eid == MCU_EVENT_LP_INFO ||
-@@ -956,6 +946,8 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
- dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;
- #endif /* CONFIG_PM */
-
-+ clear_bit(MT76_STATE_PM, &dev->mphy.state);
-+
- dev_err(dev->mt76.dev, "Firmware init done\n");
-
- return 0;
-@@ -989,7 +981,7 @@ int mt7921_run_firmware(struct mt7921_dev *dev)
- set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
- mt7921_mcu_fw_log_2_host(dev, 1);
-
-- return mt76_connac_mcu_get_nic_capability(&dev->mphy);
-+ return 0;
- }
-
- int mt7921_mcu_init(struct mt7921_dev *dev)
-@@ -1156,6 +1148,26 @@ int mt7921_mcu_get_eeprom(struct mt7921_dev *dev, u32 offset)
- return 0;
- }
-
-+u32 mt7921_get_wtbl_info(struct mt7921_dev *dev, u32 wlan_idx)
-+{
-+ struct mt7921_mcu_wlan_info wtbl_info = {
-+ .wlan_idx = cpu_to_le32(wlan_idx),
-+ };
-+ struct sk_buff *skb;
-+ int ret;
-+
-+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CMD_GET_WTBL,
-+ &wtbl_info, sizeof(wtbl_info), true,
-+ &skb);
-+ if (ret)
-+ return ret;
-+
-+ mt7921_mcu_tx_rate_report(dev, skb, wlan_idx);
-+ dev_kfree_skb(skb);
-+
-+ return 0;
-+}
-+
- int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif)
- {
- struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
-@@ -1268,9 +1280,8 @@ int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
- sizeof(req), false);
- }
-
--int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-- struct ieee80211_vif *vif, bool enable,
-- enum mt76_sta_info_state state)
-+int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-+ struct ieee80211_vif *vif, bool enable)
- {
- struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
- int rssi = -ewma_rssi_read(&mvif->rssi);
-@@ -1279,7 +1290,6 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
- .vif = vif,
- .enable = enable,
- .cmd = MCU_UNI_CMD_STA_REC_UPDATE,
-- .state = state,
- .offload_fw = true,
- .rcpi = to_rcpi(rssi),
- };
-@@ -1287,9 +1297,8 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-
- msta = sta ? (struct mt7921_sta *)sta->drv_priv : NULL;
- info.wcid = msta ? &msta->wcid : &mvif->sta.wcid;
-- info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true;
-
-- return mt76_connac_mcu_sta_cmd(&dev->mphy, &info);
-+ return mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info);
- }
-
- int __mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
-index de3c091f6736..adad20819341 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
-@@ -81,7 +81,6 @@ enum {
- MCU_EVENT_REG_ACCESS = 0x05,
- MCU_EVENT_LP_INFO = 0x07,
- MCU_EVENT_SCAN_DONE = 0x0d,
-- MCU_EVENT_TX_DONE = 0x0f,
- MCU_EVENT_BSS_ABSENCE = 0x11,
- MCU_EVENT_BSS_BEACON_LOSS = 0x13,
- MCU_EVENT_CH_PRIVILEGE = 0x18,
-@@ -255,6 +254,86 @@ struct mt7921_mcu_reg_event {
- __le32 val;
- } __packed;
-
-+struct mt7921_mcu_tx_config {
-+ u8 peer_addr[ETH_ALEN];
-+ u8 sw;
-+ u8 dis_rx_hdr_tran;
-+
-+ u8 aad_om;
-+ u8 pfmu_idx;
-+ __le16 partial_aid;
-+
-+ u8 ibf;
-+ u8 ebf;
-+ u8 is_ht;
-+ u8 is_vht;
-+
-+ u8 mesh;
-+ u8 baf_en;
-+ u8 cf_ack;
-+ u8 rdg_ba;
-+
-+ u8 rdg;
-+ u8 pm;
-+ u8 rts;
-+ u8 smps;
-+
-+ u8 txop_ps;
-+ u8 not_update_ipsm;
-+ u8 skip_tx;
-+ u8 ldpc;
-+
-+ u8 qos;
-+ u8 from_ds;
-+ u8 to_ds;
-+ u8 dyn_bw;
-+
-+ u8 amdsu_cross_lg;
-+ u8 check_per;
-+ u8 gid_63;
-+ u8 he;
-+
-+ u8 vht_ibf;
-+ u8 vht_ebf;
-+ u8 vht_ldpc;
-+ u8 he_ldpc;
-+} __packed;
-+
-+struct mt7921_mcu_sec_config {
-+ u8 wpi_flag;
-+ u8 rv;
-+ u8 ikv;
-+ u8 rkv;
-+
-+ u8 rcid;
-+ u8 rca1;
-+ u8 rca2;
-+ u8 even_pn;
-+
-+ u8 key_id;
-+ u8 muar_idx;
-+ u8 cipher_suit;
-+ u8 rsv[1];
-+} __packed;
-+
-+struct mt7921_mcu_key_config {
-+ u8 key[32];
-+} __packed;
-+
-+struct mt7921_mcu_rate_info {
-+ u8 mpdu_fail;
-+ u8 mpdu_tx;
-+ u8 rate_idx;
-+ u8 rsv[1];
-+ __le16 rate[8];
-+} __packed;
-+
-+struct mt7921_mcu_ba_config {
-+ u8 ba_en;
-+ u8 rsv[3];
-+ __le32 ba_winsize;
-+} __packed;
-+
- struct mt7921_mcu_ant_id_config {
- u8 ant_id[4];
- } __packed;
-@@ -278,6 +357,41 @@ struct mt7921_mcu_peer_cap {
- u8 rsv[1];
- } __packed;
-
-+struct mt7921_mcu_rx_cnt {
-+ u8 rx_rcpi[4];
-+ u8 rx_cc[4];
-+ u8 rx_cc_sel;
-+ u8 ce_rmsd;
-+ u8 rsv[2];
-+} __packed;
-+
-+struct mt7921_mcu_tx_cnt {
-+ __le16 rate1_cnt;
-+ __le16 rate1_fail_cnt;
-+ __le16 rate2_cnt;
-+ __le16 rate3_cnt;
-+ __le16 cur_bw_tx_cnt;
-+ __le16 cur_bw_tx_fail_cnt;
-+ __le16 other_bw_tx_cnt;
-+ __le16 other_bw_tx_fail_cnt;
-+} __packed;
-+
-+struct mt7921_mcu_wlan_info_event {
-+ struct mt7921_mcu_tx_config tx_config;
-+ struct mt7921_mcu_sec_config sec_config;
-+ struct mt7921_mcu_key_config key_config;
-+ struct mt7921_mcu_rate_info rate_info;
-+ struct mt7921_mcu_ba_config ba_config;
-+ struct mt7921_mcu_peer_cap peer_cap;
-+ struct mt7921_mcu_rx_cnt rx_cnt;
-+ struct mt7921_mcu_tx_cnt tx_cnt;
-+} __packed;
-+
-+struct mt7921_mcu_wlan_info {
-+ __le32 wlan_idx;
-+ struct mt7921_mcu_wlan_info_event event;
-+} __packed;
-+
- struct mt7921_txpwr_req {
- u8 ver;
- u8 action;
-@@ -293,31 +407,4 @@ struct mt7921_txpwr_event {
- struct mt7921_txpwr txpwr;
- } __packed;
-
--struct mt7921_mcu_tx_done_event {
-- u8 pid;
-- u8 status;
-- u16 seq;
--
-- u8 wlan_idx;
-- u8 tx_cnt;
-- u16 tx_rate;
--
-- u8 flag;
-- u8 tid;
-- u8 rsp_rate;
-- u8 mcs;
--
-- u8 bw;
-- u8 tx_pwr;
-- u8 reason;
-- u8 rsv0[1];
--
-- u32 delay;
-- u32 timestamp;
-- u32 applied_flag;
--
-- u8 txs[28];
--
-- u8 rsv1[32];
--} __packed;
- #endif
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
-index 2d8bd6bfc820..957084c3ca43 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
-@@ -92,8 +92,6 @@ struct mt7921_sta {
- unsigned long ampdu_state;
-
- struct mt7921_sta_key_conf bip;
--
-- unsigned long next_txs_ts;
- };
-
- DECLARE_EWMA(rssi, 10, 8);
-@@ -160,8 +158,7 @@ struct mt7921_dev {
- u16 chainmask;
-
- struct work_struct reset_work;
-- bool hw_full_reset:1;
-- bool hw_init_done:1;
-+ bool hw_full_reset;
-
- struct list_head sta_poll_list;
- spinlock_t sta_poll_lock;
-@@ -262,9 +259,9 @@ int mt7921_mcu_init(struct mt7921_dev *dev);
- int mt7921_mcu_add_key(struct mt7921_dev *dev, struct ieee80211_vif *vif,
- struct mt7921_sta *msta, struct ieee80211_key_conf *key,
- enum set_key_cmd cmd);
--int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-- struct ieee80211_vif *vif, bool enable,
-- enum mt76_sta_info_state state);
-+int mt7921_set_channel(struct mt7921_phy *phy);
-+int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta,
-+ struct ieee80211_vif *vif, bool enable);
- int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd);
- int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif);
- int mt7921_mcu_set_eeprom(struct mt7921_dev *dev);
-@@ -324,7 +321,7 @@ static inline bool mt7921_dma_need_reinit(struct mt7921_dev *dev)
- return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
- }
-
--int mt7921_mac_init(struct mt7921_dev *dev);
-+void mt7921_mac_init(struct mt7921_dev *dev);
- bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
- void mt7921_mac_reset_counters(struct mt7921_phy *phy);
- void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
-@@ -336,8 +333,6 @@ void mt7921_mac_fill_rx_vector(struct mt7921_dev *dev, struct sk_buff *skb);
- void mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb);
- int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
--void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
-- struct ieee80211_sta *sta);
- void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
- void mt7921_mac_work(struct work_struct *work);
-@@ -360,7 +355,7 @@ void mt7921_stats_work(struct work_struct *work);
- void mt7921_txp_skb_unmap(struct mt76_dev *dev,
- struct mt76_txwi_cache *txwi);
- void mt7921_set_stream_he_caps(struct mt7921_phy *phy);
--void mt7921_update_channel(struct mt76_phy *mphy);
-+void mt7921_update_channel(struct mt76_dev *mdev);
- int mt7921_init_debugfs(struct mt7921_dev *dev);
-
- int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev,
-@@ -370,6 +365,7 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
- struct ieee80211_ampdu_params *params,
- bool enable);
- void mt7921_scan_work(struct work_struct *work);
-+u32 mt7921_get_wtbl_info(struct mt7921_dev *dev, u32 wlan_idx);
- int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif);
- int mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif,
- bool enable);
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
-index c3905bcab360..13263f50dc00 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
-@@ -106,7 +106,6 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
- .rx_poll_complete = mt7921_rx_poll_complete,
- .sta_ps = mt7921_sta_ps,
- .sta_add = mt7921_mac_sta_add,
-- .sta_assoc = mt7921_mac_sta_assoc,
- .sta_remove = mt7921_mac_sta_remove,
- .update_survey = mt7921_update_channel,
- };
-@@ -208,10 +207,8 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
- goto restore_suspend;
- }
-
-- /* always enable deep sleep during suspend to reduce
-- * power consumption
-- */
-- mt76_connac_mcu_set_deep_sleep(&dev->mt76, true);
-+ if (!pm->enable)
-+ mt76_connac_mcu_set_deep_sleep(&dev->mt76, true);
-
- napi_disable(&mdev->tx_napi);
- mt76_worker_disable(&mdev->tx_worker);
-@@ -254,7 +251,7 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
- }
- napi_enable(&mdev->tx_napi);
-
-- if (!pm->ds_enable)
-+ if (!pm->enable)
- mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
-
- if (hif_suspend)
-@@ -270,10 +267,9 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
- {
- struct mt76_dev *mdev = pci_get_drvdata(pdev);
- struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
-- struct mt76_connac_pm *pm = &dev->pm;
- int i, err;
-
-- pm->suspended = false;
-+ dev->pm.suspended = false;
- err = pci_set_power_state(pdev, PCI_D0);
- if (err)
- return err;
-@@ -304,8 +300,7 @@ static int mt7921_pci_resume(struct pci_dev *pdev)
- napi_enable(&mdev->tx_napi);
- napi_schedule(&mdev->tx_napi);
-
-- /* restore previous ds setting */
-- if (!pm->ds_enable)
-+ if (!dev->pm.enable)
- mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
-
- if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state))
-diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c
-index 783a15635ec5..a18d2896ee1f 100644
---- a/drivers/net/wireless/mediatek/mt76/sdio.c
-+++ b/drivers/net/wireless/mediatek/mt76/sdio.c
-@@ -184,6 +184,9 @@ static int mt76s_process_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
- if (!q->queued)
- wake_up(&dev->tx_wait);
-
-+ if (!mcu)
-+ mt76_txq_schedule(&dev->phy, q->qid);
-+
- return nframes;
- }
-
-@@ -192,28 +195,19 @@ static void mt76s_status_worker(struct mt76_worker *w)
- struct mt76_sdio *sdio = container_of(w, struct mt76_sdio,
- status_worker);
- struct mt76_dev *dev = container_of(sdio, struct mt76_dev, sdio);
-- bool resched = false;
- int i, nframes;
-
- do {
-- int ndata_frames = 0;
--
- nframes = mt76s_process_tx_queue(dev, dev->q_mcu[MT_MCUQ_WM]);
-
- for (i = 0; i <= MT_TXQ_PSD; i++)
-- ndata_frames += mt76s_process_tx_queue(dev,
-- dev->phy.q_tx[i]);
-- nframes += ndata_frames;
-- if (ndata_frames > 0)
-- resched = true;
-+ nframes += mt76s_process_tx_queue(dev,
-+ dev->phy.q_tx[i]);
-
- if (dev->drv->tx_status_data &&
- !test_and_set_bit(MT76_READING_STATS, &dev->phy.state))
- queue_work(dev->wq, &dev->sdio.stat_work);
- } while (nframes > 0);
--
-- if (resched)
-- mt76_worker_schedule(&dev->sdio.txrx_worker);
- }
-
- static void mt76s_tx_status_data(struct work_struct *work)
-@@ -262,7 +256,6 @@ mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
-
- q->entry[q->head].skb = tx_info.skb;
- q->entry[q->head].buf_sz = len;
-- q->entry[q->head].wcid = 0xffff;
-
- smp_wmb();
-
-diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c
-index f73ffbd6e622..f614c887f323 100644
---- a/drivers/net/wireless/mediatek/mt76/testmode.c
-+++ b/drivers/net/wireless/mediatek/mt76/testmode.c
-@@ -88,8 +88,17 @@ static void
- mt76_testmode_free_skb(struct mt76_phy *phy)
- {
- struct mt76_testmode_data *td = &phy->test;
-+ struct sk_buff *skb = td->tx_skb;
-+
-+ if (!skb)
-+ return;
-
-- dev_kfree_skb(td->tx_skb);
-+ if (skb_has_frag_list(skb)) {
-+ kfree_skb_list(skb_shinfo(skb)->frag_list);
-+ skb_shinfo(skb)->frag_list = NULL;
-+ }
-+
-+ dev_kfree_skb(skb);
- td->tx_skb = NULL;
- }
-
-@@ -521,14 +530,6 @@ mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
- u64 rx_fcs_error = 0;
- int i;
-
-- if (dev->test_ops->dump_stats) {
-- int ret;
--
-- ret = dev->test_ops->dump_stats(phy, msg);
-- if (ret)
-- return ret;
-- }
--
- for (i = 0; i < ARRAY_SIZE(td->rx_stats.packets); i++) {
- rx_packets += td->rx_stats.packets[i];
- rx_fcs_error += td->rx_stats.fcs_error[i];
-@@ -543,6 +544,9 @@ mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
- MT76_TM_STATS_ATTR_PAD))
- return -EMSGSIZE;
-
-+ if (dev->test_ops->dump_stats)
-+ return dev->test_ops->dump_stats(phy, msg);
-+
- return 0;
- }
-
-diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
-index f0f7a913eaab..441d06e30b1a 100644
---- a/drivers/net/wireless/mediatek/mt76/tx.c
-+++ b/drivers/net/wireless/mediatek/mt76/tx.c
-@@ -54,23 +54,11 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
-
- spin_unlock_bh(&dev->status_list.lock);
-
-- rcu_read_lock();
- while ((skb = __skb_dequeue(list)) != NULL) {
-- struct ieee80211_tx_status status = {
-- .skb = skb,
-- .info = IEEE80211_SKB_CB(skb),
-- };
-- struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
-- struct mt76_wcid *wcid;
--
-- wcid = rcu_dereference(dev->wcid[cb->wcid]);
-- if (wcid)
-- status.sta = wcid_to_sta(wcid);
--
- hw = mt76_tx_status_get_hw(dev, skb);
-- ieee80211_tx_status_ext(hw, &status);
-+ ieee80211_tx_status(hw, skb);
- }
-- rcu_read_unlock();
-+
- }
- EXPORT_SYMBOL_GPL(mt76_tx_status_unlock);
-
-@@ -92,7 +80,7 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags,
-
- /* Tx status can be unreliable. if it fails, mark the frame as ACKed */
- if (flags & MT_TX_CB_TXS_FAILED) {
-- info->status.rates[0].count = 0;
-+ ieee80211_tx_info_clear_status(info);
- info->status.rates[0].idx = -1;
- info->flags |= IEEE80211_TX_STAT_ACK;
- }
-@@ -129,7 +117,12 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
- spin_lock_bh(&dev->status_list.lock);
-
- memset(cb, 0, sizeof(*cb));
-- pid = mt76_get_next_pkt_id(wcid);
-+ wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
-+ if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
-+ wcid->packet_id == MT_PACKET_ID_NO_SKB)
-+ wcid->packet_id = MT_PACKET_ID_FIRST;
-+
-+ pid = wcid->packet_id;
- cb->wcid = wcid->idx;
- cb->pktid = pid;
- cb->jiffies = jiffies;
-@@ -180,37 +173,36 @@ mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid, bool flush)
- EXPORT_SYMBOL_GPL(mt76_tx_status_check);
-
- static void
--mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid,
-- struct sk_buff *skb)
-+mt76_tx_check_non_aql(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb)
- {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+ struct mt76_wcid *wcid;
- int pending;
-
-- if (!wcid || info->tx_time_est)
-+ if (info->tx_time_est)
-+ return;
-+
-+ if (wcid_idx >= ARRAY_SIZE(dev->wcid))
- return;
-
-- pending = atomic_dec_return(&wcid->non_aql_packets);
-- if (pending < 0)
-- atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
-+ rcu_read_lock();
-+
-+ wcid = rcu_dereference(dev->wcid[wcid_idx]);
-+ if (wcid) {
-+ pending = atomic_dec_return(&wcid->non_aql_packets);
-+ if (pending < 0)
-+ atomic_cmpxchg(&wcid->non_aql_packets, pending, 0);
-+ }
-+
-+ rcu_read_unlock();
- }
-
--void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb,
-- struct list_head *free_list)
-+void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb)
- {
-- struct ieee80211_tx_status status = {
-- .skb = skb,
-- .free_list = free_list,
-- };
-- struct mt76_wcid *wcid = NULL;
- struct ieee80211_hw *hw;
- struct sk_buff_head list;
-
-- rcu_read_lock();
--
-- if (wcid_idx < ARRAY_SIZE(dev->wcid))
-- wcid = rcu_dereference(dev->wcid[wcid_idx]);
--
-- mt76_tx_check_non_aql(dev, wcid, skb);
-+ mt76_tx_check_non_aql(dev, wcid_idx, skb);
-
- #ifdef CONFIG_NL80211_TESTMODE
- if (mt76_is_testmode_skb(dev, skb, &hw)) {
-@@ -222,25 +214,21 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
- wake_up(&dev->tx_wait);
-
- dev_kfree_skb_any(skb);
-- goto out;
-+ return;
- }
- #endif
-
- if (!skb->prev) {
- hw = mt76_tx_status_get_hw(dev, skb);
-- status.sta = wcid_to_sta(wcid);
-- ieee80211_tx_status_ext(hw, &status);
-- goto out;
-+ ieee80211_free_txskb(hw, skb);
-+ return;
- }
-
- mt76_tx_status_lock(dev, &list);
- __mt76_tx_status_skb_done(dev, skb, MT_TX_CB_DMA_DONE, &list);
- mt76_tx_status_unlock(dev, &list);
--
--out:
-- rcu_read_unlock();
- }
--EXPORT_SYMBOL_GPL(__mt76_tx_complete_skb);
-+EXPORT_SYMBOL_GPL(mt76_tx_complete_skb);
-
- static int
- __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
-@@ -256,15 +244,11 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
-
- non_aql = !info->tx_time_est;
- idx = dev->queue_ops->tx_queue_skb(dev, q, skb, wcid, sta);
-- if (idx < 0 || !sta)
-+ if (idx < 0 || !sta || !non_aql)
- return idx;
-
- wcid = (struct mt76_wcid *)sta->drv_priv;
- q->entry[idx].wcid = wcid->idx;
--
-- if (!non_aql)
-- return idx;
--
- pending = atomic_inc_return(&wcid->non_aql_packets);
- if (stop && pending >= MT_MAX_NON_AQL_PKT)
- *stop = true;
-diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
-index 1e9f60bb811a..30bc54e98c58 100644
---- a/drivers/net/wireless/mediatek/mt76/usb.c
-+++ b/drivers/net/wireless/mediatek/mt76/usb.c
-@@ -925,7 +925,6 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
-
- q->head = (q->head + 1) % q->ndesc;
- q->entry[idx].skb = tx_info.skb;
-- q->entry[idx].wcid = 0xffff;
- q->queued++;
-
- return idx;
-diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c
-index cc772045d526..6bcc4a13ae6c 100644
---- a/drivers/net/wireless/mediatek/mt7601u/usb.c
-+++ b/drivers/net/wireless/mediatek/mt7601u/usb.c
-@@ -26,7 +26,6 @@ static const struct usb_device_id mt7601u_device_table[] = {
- { USB_DEVICE(0x2717, 0x4106) },
- { USB_DEVICE(0x2955, 0x0001) },
- { USB_DEVICE(0x2955, 0x1001) },
-- { USB_DEVICE(0x2955, 0x1003) },
- { USB_DEVICE(0x2a5f, 0x1000) },
- { USB_DEVICE(0x7392, 0x7710) },
- { 0, }
diff --git a/sys-kernel_arch-sources-g14_files-8012-mt76-mt7915-send-EAPOL-frames-at-lowest-rate.patch b/sys-kernel_arch-sources-g14_files-8012-mt76-mt7915-send-EAPOL-frames-at-lowest-rate.patch
new file mode 100644
index 000000000000..c2e18b71ae18
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8012-mt76-mt7915-send-EAPOL-frames-at-lowest-rate.patch
@@ -0,0 +1,31 @@
+From: Ryder Lee <ryder.lee@mediatek.com>
+To: Felix Fietkau <nbd@nbd.name>
+CC: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>, Shayne Chen
+ <shayne.chen@mediatek.com>, Evelyn Tsai <evelyn.tsai@mediatek.com>, Sean Wang
+ <sean.wang@mediatek.com>, <linux-wireless@vger.kernel.org>,
+ <linux-mediatek@lists.infradead.org>, Ryder Lee <ryder.lee@mediatek.com>
+Subject: [PATCH 1/2] mt76: mt7915: send EAPOL frames at lowest rate
+Date: Sat, 17 Jul 2021 13:05:48 +0800
+
+The firmware rate control may choose the high rate for EAPOL frames,
+so checking IEEE80211_TX_CTL_USE_MINRATE to use the lowest TX rate.
+
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+---
+ drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+index 2462704094b0..d47dd0f96bdb 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+@@ -869,7 +869,8 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
+ txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
+ }
+
+- if (!ieee80211_is_data(fc) || multicast)
++ if (!ieee80211_is_data(fc) || multicast ||
++ info->flags & IEEE80211_TX_CTL_USE_MINRATE)
+ val |= MT_TXD2_FIX_RATE;
+
+ txwi[2] |= cpu_to_le32(val);
diff --git a/sys-kernel_arch-sources-g14_files-8012-mt76-mt7921-continue-to-probe-driver-when-fw-already.patch b/sys-kernel_arch-sources-g14_files-8012-mt76-mt7921-continue-to-probe-driver-when-fw-already.patch
deleted file mode 100644
index 5e540d38cf47..000000000000
--- a/sys-kernel_arch-sources-g14_files-8012-mt76-mt7921-continue-to-probe-driver-when-fw-already.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 8a236b7058af9c559a5c4b8443054a6d5908afaf Mon Sep 17 00:00:00 2001
-From: Aaron Ma <aaron.ma@canonical.com>
-Date: Thu, 8 Jul 2021 21:17:10 +0800
-Subject: [PATCH 8012/8014] mt76: mt7921: continue to probe driver when fw
- already downloaded
-
-When reboot system, no power cycles, firmware is already downloaded,
-return -EIO will break driver as error:
-mt7921e: probe of 0000:03:00.0 failed with error -5
-
-Skip firmware download and continue to probe.
-
-Signed-off-by: Aaron Ma <aaron.ma@canonical.com>
----
- drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
-index 67dc4b4cc094..f7459ad2a073 100644
---- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
-+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
-@@ -910,7 +910,7 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
- ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);
- if (ret) {
- dev_dbg(dev->mt76.dev, "Firmware is already download\n");
-- return -EIO;
-+ goto fw_loaded;
- }
-
- ret = mt7921_load_patch(dev);
-@@ -928,6 +928,7 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
- return -EIO;
- }
-
-+fw_loaded:
- mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);
-
- #ifdef CONFIG_PM
---
-2.32.0
-
diff --git a/sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-robustify-hardware-initialization-flow.patch b/sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-robustify-hardware-initialization-flow.patch
new file mode 100644
index 000000000000..f475476f8832
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-robustify-hardware-initialization-flow.patch
@@ -0,0 +1,125 @@
+From: <sean.wang@mediatek.com>
+To: <nbd@nbd.name>, <lorenzo.bianconi@redhat.com>
+CC: <sean.wang@mediatek.com>, <Soul.Huang@mediatek.com>,
+ <YN.Chen@mediatek.com>, <Leon.Yen@mediatek.com>,
+ <Eric-SY.Chang@mediatek.com>, <Deren.Wu@mediatek.com>, <km.lin@mediatek.com>,
+ <robin.chiu@mediatek.com>, <ch.yeh@mediatek.com>, <posh.sun@mediatek.com>,
+ <ted.huang@mediatek.com>, <Eric.Liang@mediatek.com>,
+ <Stella.Chang@mediatek.com>, <jemele@google.com>,
+ <linux-wireless@vger.kernel.org>, <linux-mediatek@lists.infradead.org>
+Subject: [PATCH 1/2] mt76: mt7921: robustify hardware initialization flow
+Date: Tue, 14 Sep 2021 23:50:21 +0800
+
+From: Sean Wang <sean.wang@mediatek.com>
+
+Robustify hardware initialization in the current driver probing flow
+to get rid of the device is possibly lost after the machine boot due
+to possible firmware abnormal state by trying to recover the failure
+with more chances.
+
+Tested-by: Leon Yen <Leon.Yen@mediatek.com>
+Tested-by: YN Chen <YN.Chen@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+ .../net/wireless/mediatek/mt76/mt7921/init.c | 53 ++++++++++++++-----
+ .../wireless/mediatek/mt76/mt7921/mt7921.h | 1 +
+ 2 files changed, 41 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+index 1f37e64b6038..d26166a612f0 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+@@ -146,33 +146,60 @@ int mt7921_mac_init(struct mt7921_dev *dev)
+ return mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
+ }
+
+-static int mt7921_init_hardware(struct mt7921_dev *dev)
++static int __mt7921_init_hardware(struct mt7921_dev *dev)
+ {
+- int ret, idx;
+-
+- ret = mt7921_dma_init(dev);
+- if (ret)
+- return ret;
+-
+- set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
++ struct mt76_dev *mdev = &dev->mt76;
++ int ret;
+
+ /* force firmware operation mode into normal state,
+ * which should be set before firmware download stage.
+ */
+ mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
+-
+ ret = mt7921_mcu_init(dev);
+ if (ret)
+- return ret;
++ goto out;
+
+ ret = mt7921_eeprom_init(dev);
+- if (ret < 0)
+- return ret;
++ if (ret)
++ goto out;
+
+ ret = mt7921_mcu_set_eeprom(dev);
++ if (ret)
++ goto out;
++
++ ret = mt7921_mac_init(dev);
++out:
++ if (ret && mdev->eeprom.data) {
++ devm_kfree(mdev->dev, mdev->eeprom.data);
++ mdev->eeprom.data = NULL;
++ }
++
++ return ret;
++}
++
++static int mt7921_init_hardware(struct mt7921_dev *dev)
++{
++ int ret, idx, i;
++
++ ret = mt7921_dma_init(dev);
+ if (ret)
+ return ret;
+
++ set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
++
++ for (i = 0; i < MT7921_MCU_INIT_RETRY_COUNT; i++) {
++ ret = __mt7921_init_hardware(dev);
++ if (!ret)
++ break;
++
++ mt7921_wpdma_reset(dev, true);
++ }
++
++ if (i == MT7921_MCU_INIT_RETRY_COUNT) {
++ dev_err(dev->mt76.dev, "hardware init failed\n");
++ return ret;
++ }
++
+ /* Beacon and mgmt frames should occupy wcid 0 */
+ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1);
+ if (idx)
+@@ -183,7 +210,7 @@ static int mt7921_init_hardware(struct mt7921_dev *dev)
+ dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;
+ rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
+
+- return mt7921_mac_init(dev);
++ return 0;
+ }
+
+ int mt7921_register_device(struct mt7921_dev *dev)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+index 6a47ba65b96e..cee7a2507224 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+@@ -29,6 +29,7 @@
+ #define MT7921_RX_MCU_RING_SIZE 512
+
+ #define MT7921_DRV_OWN_RETRY_COUNT 10
++#define MT7921_MCU_INIT_RETRY_COUNT 10
+
+ #define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
+ #define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
diff --git a/sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-fix-retrying-release-semaphore-without-end.patch b/sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-fix-retrying-release-semaphore-without-end.patch
new file mode 100644
index 000000000000..04ef192d9482
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-fix-retrying-release-semaphore-without-end.patch
@@ -0,0 +1,38 @@
+From: <sean.wang@mediatek.com>
+To: <nbd@nbd.name>, <lorenzo.bianconi@redhat.com>
+CC: <sean.wang@mediatek.com>, <Soul.Huang@mediatek.com>,
+ <YN.Chen@mediatek.com>, <Leon.Yen@mediatek.com>,
+ <Eric-SY.Chang@mediatek.com>, <Deren.Wu@mediatek.com>, <km.lin@mediatek.com>,
+ <robin.chiu@mediatek.com>, <ch.yeh@mediatek.com>, <posh.sun@mediatek.com>,
+ <ted.huang@mediatek.com>, <Eric.Liang@mediatek.com>,
+ <Stella.Chang@mediatek.com>, <jemele@google.com>,
+ <linux-wireless@vger.kernel.org>, <linux-mediatek@lists.infradead.org>
+Subject: [PATCH 2/2] mt76: mt7921: fix retrying release semaphore without end
+Date: Tue, 14 Sep 2021 23:50:22 +0800
+
+From: Sean Wang <sean.wang@mediatek.com>
+
+We should pass the error code to the caller immediately
+to avoid the possible infinite retry to release the semaphore.
+
+Fixes: 1c099ab44727 ("mt76: mt7921: add MCU support")
+Co-developed-by: YN Chen <YN.Chen@mediatek.com>
+Signed-off-by: YN Chen <YN.Chen@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+index 9b35b5da3619..db33506567dc 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+@@ -876,7 +876,7 @@ static int mt7921_load_patch(struct mt7921_dev *dev)
+ default:
+ ret = -EAGAIN;
+ dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
+- goto out;
++ break;
+ }
+ release_firmware(fw);
+
diff --git a/sys-kernel_arch-sources-g14_files-8015-mt76-mt7921-send-EAPOL-frames-at-lowest-rate.patch b/sys-kernel_arch-sources-g14_files-8015-mt76-mt7921-send-EAPOL-frames-at-lowest-rate.patch
new file mode 100644
index 000000000000..0812eb4e785c
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8015-mt76-mt7921-send-EAPOL-frames-at-lowest-rate.patch
@@ -0,0 +1,31 @@
+From: Ryder Lee <ryder.lee@mediatek.com>
+To: Felix Fietkau <nbd@nbd.name>
+CC: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>, Shayne Chen
+ <shayne.chen@mediatek.com>, Evelyn Tsai <evelyn.tsai@mediatek.com>, Sean Wang
+ <sean.wang@mediatek.com>, <linux-wireless@vger.kernel.org>,
+ <linux-mediatek@lists.infradead.org>, Ryder Lee <ryder.lee@mediatek.com>
+Subject: [PATCH 2/2] mt76: mt7921: send EAPOL frames at lowest rate
+Date: Sat, 17 Jul 2021 13:05:49 +0800
+
+The firmware rate control may choose the high rate for EAPOL frames,
+so checking IEEE80211_TX_CTL_USE_MINRATE to use the lowest TX rate.
+
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+index 7fe2e3a50428..eb0d98c8d5d8 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+@@ -702,7 +702,8 @@ mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi,
+ txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
+ }
+
+- if (!ieee80211_is_data(fc) || multicast)
++ if (!ieee80211_is_data(fc) || multicast ||
++ info->flags & IEEE80211_TX_CTL_USE_MINRATE)
+ val |= MT_TXD2_FIX_RATE;
+
+ txwi[2] |= cpu_to_le32(val);
diff --git a/sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-Add-mt7922-support.patch b/sys-kernel_arch-sources-g14_files-8016-mt76-mt7921-Add-mt7922-support.patch
index d11143822c5f..d11143822c5f 100644
--- a/sys-kernel_arch-sources-g14_files-8014-mt76-mt7921-Add-mt7922-support.patch
+++ b/sys-kernel_arch-sources-g14_files-8016-mt76-mt7921-Add-mt7922-support.patch
diff --git a/sys-kernel_arch-sources-g14_files-8017-mt76-mt7921-enable-VO-tx-aggregation.patch b/sys-kernel_arch-sources-g14_files-8017-mt76-mt7921-enable-VO-tx-aggregation.patch
new file mode 100644
index 000000000000..b94147a0fbbe
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8017-mt76-mt7921-enable-VO-tx-aggregation.patch
@@ -0,0 +1,40 @@
+From: Deren Wu <Deren.Wu@mediatek.com>
+To: Felix Fietkau <nbd@nbd.name>, Lorenzo Bianconi
+ <lorenzo.bianconi@redhat.com>
+CC: Sean Wang <sean.wang@mediatek.com>, Soul Huang <Soul.Huang@mediatek.com>,
+ YN Chen <YN.Chen@mediatek.com>, Leon Yen <Leon.Yen@mediatek.com>, "Eric-SY
+ Chang" <Eric-SY.Chang@mediatek.com>, Deren Wu <Deren.Wu@mediatek.com>,
+ KM Lin <km.lin@mediatek.com>, Robin Chiu <robin.chiu@mediatek.com>, CH Yeh
+ <ch.yeh@mediatek.com>, Posh Sun <posh.sun@mediatek.com>, Eric Liang
+ <Eric.Liang@mediatek.com>, Stella Chang <Stella.Chang@mediatek.com>,
+ <jemele@google.com>, <yenlinlai@google.com>, linux-wireless
+ <linux-wireless@vger.kernel.org>, linux-mediatek
+ <linux-mediatek@lists.infradead.org>, Deren Wu <deren.wu@mediatek.com>
+Subject: [PATCH] mt76: mt7921: enable VO tx aggregation
+Date: Wed, 4 Aug 2021 18:11:53 +0800
+
+From: Deren Wu <deren.wu@mediatek.com>
+
+From: YN Chen <YN.Chen@mediatek.com>
+
+Avoid throughput drop in VO streaming, enable TX BA by default.
+
+Signed-off-by: Deren Wu <deren.wu@mediatek.com>
+Signed-off-by: YN Chen <YN.Chen@mediatek.com>
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+index 296e0f7a1d14..1be1e07ae786 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+@@ -913,8 +913,6 @@ mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
+ return;
+
+ tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1]));
+- 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/sys-kernel_arch-sources-g14_files-8018-mt76-mt7921-fix-dma-hang-in-rmmod.patch b/sys-kernel_arch-sources-g14_files-8018-mt76-mt7921-fix-dma-hang-in-rmmod.patch
new file mode 100644
index 000000000000..7b353ab3e5eb
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8018-mt76-mt7921-fix-dma-hang-in-rmmod.patch
@@ -0,0 +1,55 @@
+From: Deren Wu <Deren.Wu@mediatek.com>
+To: Felix Fietkau <nbd@nbd.name>, Lorenzo Bianconi
+ <lorenzo.bianconi@redhat.com>
+CC: Sean Wang <sean.wang@mediatek.com>, Soul Huang <Soul.Huang@mediatek.com>,
+ YN Chen <YN.Chen@mediatek.com>, Leon Yen <Leon.Yen@mediatek.com>, "Eric-SY
+ Chang" <Eric-SY.Chang@mediatek.com>, Deren Wu <Deren.Wu@mediatek.com>,
+ KM Lin <km.lin@mediatek.com>, Robin Chiu <robin.chiu@mediatek.com>, CH Yeh
+ <ch.yeh@mediatek.com>, Posh Sun <posh.sun@mediatek.com>, Eric Liang
+ <Eric.Liang@mediatek.com>, Stella Chang <Stella.Chang@mediatek.com>, Jimmy Hu
+ <Jimmy.Hu@mediatek.com>, <jemele@google.com>, <yenlinlai@google.com>,
+ linux-wireless <linux-wireless@vger.kernel.org>, linux-mediatek
+ <linux-mediatek@lists.infradead.org>, Deren Wu <deren.wu@mediatek.com>
+Subject: [PATCH] mt76: mt7921: fix dma hang in rmmod
+Date: Tue, 27 Jul 2021 17:47:09 +0800
+
+From: Deren Wu <deren.wu@mediatek.com>
+
+The dma would be broken after rmmod flow. There are two different
+cases causing this issue.
+1. dma access without privilege.
+2. hw access sequence borken by another context.
+
+This patch handle both cases to avoid hw crash.
+
+Fixes: 2b9ea5a8cf1bd ("mt76: mt7921: add mt7921_dma_cleanup in mt7921_unregister_device")
+Signed-off-by: Deren Wu <deren.wu@mediatek.com>
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/init.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+index 49725caca7ed..1f37e64b6038 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+@@ -266,10 +266,20 @@ int mt7921_register_device(struct mt7921_dev *dev)
+
+ void mt7921_unregister_device(struct mt7921_dev *dev)
+ {
++ int i;
++ struct mt76_connac_pm *pm = &dev->pm;
++
+ mt76_unregister_device(&dev->mt76);
++ mt76_for_each_q_rx(&dev->mt76, i)
++ napi_disable(&dev->mt76.napi[i]);
++ cancel_delayed_work_sync(&pm->ps_work);
++ cancel_work_sync(&pm->wake_work);
++
+ mt7921_tx_token_put(dev);
++ mt7921_mcu_drv_pmctrl(dev);
+ mt7921_dma_cleanup(dev);
+ mt7921_mcu_exit(dev);
++ mt7921_mcu_fw_pmctrl(dev);
+
+ tasklet_disable(&dev->irq_tasklet);
+ mt76_free_device(&dev->mt76);
diff --git a/sys-kernel_arch-sources-g14_files-8019-mt76-mt7921-fix-firmware-usage-of-RA-info-using-legacy-rates.patch b/sys-kernel_arch-sources-g14_files-8019-mt76-mt7921-fix-firmware-usage-of-RA-info-using-legacy-rates.patch
new file mode 100644
index 000000000000..870e24a3a1ff
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8019-mt76-mt7921-fix-firmware-usage-of-RA-info-using-legacy-rates.patch
@@ -0,0 +1,72 @@
+From: <sean.wang@mediatek.com>
+To: <nbd@nbd.name>, <lorenzo.bianconi@redhat.com>
+CC: <sean.wang@mediatek.com>, <Soul.Huang@mediatek.com>,
+ <YN.Chen@mediatek.com>, <Leon.Yen@mediatek.com>,
+ <Eric-SY.Chang@mediatek.com>, <Deren.Wu@mediatek.com>, <km.lin@mediatek.com>,
+ <robin.chiu@mediatek.com>, <ch.yeh@mediatek.com>, <posh.sun@mediatek.com>,
+ <Eric.Liang@mediatek.com>, <Stella.Chang@mediatek.com>, <jemele@google.com>,
+ <yenlinlai@google.com>, <linux-wireless@vger.kernel.org>,
+ <linux-mediatek@lists.infradead.org>
+Subject: [PATCH] mt76: mt7921: fix firmware usage of RA info using legacy
+ rates
+Date: Wed, 11 Aug 2021 13:58:24 +0800
+
+From: Sean Wang <sean.wang@mediatek.com>
+
+According to the firmware usage, OFDM rates should fill out bit 6 - 13
+while CCK rates should fill out bit 0 - 3 in legacy field of RA info to
+make the rate adaption runs propertly. Otherwise, a unicast frame might be
+picking up the unsupported rate to send out.
+
+Fixes: 1c099ab44727 ("mt76: mt7921: add MCU support")
+Reported-by: Joshua Emele <jemele@chromium.org>
+Co-developed-by: YN Chen <YN.Chen@mediatek.com>
+Signed-off-by: YN Chen <YN.Chen@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+ drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 11 ++++++++++-
+ drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 2 ++
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+index a2555dc0f003..27e45f4fc05f 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+@@ -719,6 +719,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
+ struct sta_rec_state *state;
+ struct sta_rec_phy *phy;
+ struct tlv *tlv;
++ u16 supp_rates;
+
+ /* starec ht */
+ if (sta->ht_cap.ht_supported) {
+@@ -767,7 +768,15 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
+
+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info));
+ ra_info = (struct sta_rec_ra_info *)tlv;
+- ra_info->legacy = cpu_to_le16((u16)sta->supp_rates[band]);
++
++ supp_rates = sta->supp_rates[band];
++ if (band == NL80211_BAND_2GHZ)
++ supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates >> 4) |
++ FIELD_PREP(RA_LEGACY_CCK, supp_rates & 0xf);
++ else
++ supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates);
++
++ ra_info->legacy = cpu_to_le16(supp_rates);
+
+ if (sta->ht_cap.ht_supported)
+ memcpy(ra_info->rx_mcs_bitmask, sta->ht_cap.mcs.rx_mask,
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+index ab77289c0541..9dfdf7625844 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+@@ -124,6 +124,8 @@ struct sta_rec_state {
+ u8 rsv[1];
+ } __packed;
+
++#define RA_LEGACY_OFDM GENMASK(13, 6)
++#define RA_LEGACY_CCK GENMASK(3, 0)
+ #define HT_MCS_MASK_NUM 10
+ struct sta_rec_ra_info {
+ __le16 tag;
diff --git a/sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch b/sys-kernel_arch-sources-g14_files-8020-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch
index e3c25ccae6f9..e3c25ccae6f9 100644
--- a/sys-kernel_arch-sources-g14_files-8013-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch
+++ b/sys-kernel_arch-sources-g14_files-8020-mt76-mt7921-Fix-out-of-order-process-by-invalid-even.patch
diff --git a/sys-kernel_arch-sources-g14_files-8021-mt76-mt7921-fix-the-inconsistent-state-between-bind-and-unbind.patch b/sys-kernel_arch-sources-g14_files-8021-mt76-mt7921-fix-the-inconsistent-state-between-bind-and-unbind.patch
new file mode 100644
index 000000000000..c1a9eabc6f02
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8021-mt76-mt7921-fix-the-inconsistent-state-between-bind-and-unbind.patch
@@ -0,0 +1,46 @@
+From: <sean.wang@mediatek.com>
+To: <nbd@nbd.name>, <lorenzo.bianconi@redhat.com>
+CC: <sean.wang@mediatek.com>, <Soul.Huang@mediatek.com>,
+ <YN.Chen@mediatek.com>, <Leon.Yen@mediatek.com>,
+ <Eric-SY.Chang@mediatek.com>, <Deren.Wu@mediatek.com>, <km.lin@mediatek.com>,
+ <robin.chiu@mediatek.com>, <ch.yeh@mediatek.com>, <posh.sun@mediatek.com>,
+ <Eric.Liang@mediatek.com>, <Stella.Chang@mediatek.com>, <jemele@google.com>,
+ <linux-wireless@vger.kernel.org>, <linux-mediatek@lists.infradead.org>
+Subject: [PATCH] mt76: mt7921: fix the inconsistent state between bind and
+ unbind
+Date: Mon, 23 Aug 2021 10:26:51 +0800
+
+From: Sean Wang <sean.wang@mediatek.com>
+
+We shouldn't put back the device into fw own state after wifi reset at
+driver unbind stage to fix the following error because that is not the
+consistent state the current driver bind stage expects.
+
+localhost ~ # echo 0000:01:00.0 > /sys/bus/pci/drivers/mt7921e/unbind
+localhost ~ # echo 0000:01:00.0 > /sys/bus/pci/drivers/mt7921e/bind
+...
+[ 481.172969] mt7921e 0000:01:00.0: ASIC revision: feed0000
+[ 482.133547] mt7921e: probe of 0000:01:00.0 failed with error -110
+-bash: echo: write error: No such device
+
+Fixes: c1af184ba830 ("mt76: mt7921: fix dma hang in rmmod")
+Co-developed-by: YN Chen <YN.Chen@mediatek.com>
+Signed-off-by: YN Chen <YN.Chen@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/init.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+index 1f37e64b6038..3e84ef8f5358 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+@@ -279,7 +279,6 @@ void mt7921_unregister_device(struct mt7921_dev *dev)
+ mt7921_mcu_drv_pmctrl(dev);
+ mt7921_dma_cleanup(dev);
+ mt7921_mcu_exit(dev);
+- mt7921_mcu_fw_pmctrl(dev);
+
+ tasklet_disable(&dev->irq_tasklet);
+ mt76_free_device(&dev->mt76);
diff --git a/sys-kernel_arch-sources-g14_files-8022-mt76-mt7921-report-HE-MU-radiotap.patch b/sys-kernel_arch-sources-g14_files-8022-mt76-mt7921-report-HE-MU-radiotap.patch
new file mode 100644
index 000000000000..ebb44077b5f8
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8022-mt76-mt7921-report-HE-MU-radiotap.patch
@@ -0,0 +1,187 @@
+From: <sean.wang@mediatek.com>
+To: <nbd@nbd.name>, <lorenzo.bianconi@redhat.com>
+CC: <sean.wang@mediatek.com>, <Soul.Huang@mediatek.com>,
+ <YN.Chen@mediatek.com>, <Leon.Yen@mediatek.com>,
+ <Eric-SY.Chang@mediatek.com>, <Deren.Wu@mediatek.com>, <km.lin@mediatek.com>,
+ <robin.chiu@mediatek.com>, <ch.yeh@mediatek.com>, <posh.sun@mediatek.com>,
+ <Eric.Liang@mediatek.com>, <Stella.Chang@mediatek.com>, <jemele@google.com>,
+ <yenlinlai@google.com>, <linux-wireless@vger.kernel.org>,
+ <linux-mediatek@lists.infradead.org>, Ryder Lee <ryder.lee@mediatek.com>
+Subject: [PATCH] mt76: mt7921: report HE MU radiotap
+Date: Fri, 13 Aug 2021 06:48:24 +0800
+
+From: Sean Wang <sean.wang@mediatek.com>
+
+Report HE MU/BF radiotap.
+
+That fixed HE MU packets dropped by mac80211 because they are missing the
+ieee80211_radiotap_he_mu header.
+
+Fixes: 163f4d22c118d ("mt76: mt7921: add MAC support")
+Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+Co-developed-by: Eric-SY Chang <Eric-SY.Chang@mediatek.com>
+Signed-off-by: Eric-SY Chang <Eric-SY.Chang@mediatek.com>
+Tested-by: Eric-SY Chang <Eric-SY.Chang@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+ .../net/wireless/mediatek/mt76/mt7921/mac.c | 65 ++++++++++++++++---
+ .../net/wireless/mediatek/mt76/mt7921/mac.h | 8 +++
+ 2 files changed, 65 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+index 296e0f7a1d14..7ee9ef2fb9f0 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+@@ -180,12 +180,56 @@ mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
+ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
+ }
+
++static void
++mt7921_mac_decode_he_mu_radiotap(struct sk_buff *skb,
++ struct mt76_rx_status *status,
++ __le32 *rxv)
++{
++ static const struct ieee80211_radiotap_he_mu mu_known = {
++ .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
++ HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
++ HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
++ HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN) |
++ HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN),
++ .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN) |
++ HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN),
++ };
++ struct ieee80211_radiotap_he_mu *he_mu = NULL;
++
++ he_mu = skb_push(skb, sizeof(mu_known));
++ memcpy(he_mu, &mu_known, sizeof(mu_known));
++
++#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
++
++ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
++ if (status->he_dcm)
++ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
++
++ he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
++ MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
++ le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
++
++ he_mu->ru_ch1[0] = FIELD_GET(MT_CRXV_HE_RU0, cpu_to_le32(rxv[3]));
++
++ if (status->bw >= RATE_INFO_BW_40) {
++ he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
++ he_mu->ru_ch2[0] =
++ FIELD_GET(MT_CRXV_HE_RU1, cpu_to_le32(rxv[3]));
++ }
++
++ if (status->bw >= RATE_INFO_BW_80) {
++ he_mu->ru_ch1[1] =
++ FIELD_GET(MT_CRXV_HE_RU2, cpu_to_le32(rxv[3]));
++ he_mu->ru_ch2[1] =
++ FIELD_GET(MT_CRXV_HE_RU3, cpu_to_le32(rxv[3]));
++ }
++}
++
+ static void
+ mt7921_mac_decode_he_radiotap(struct sk_buff *skb,
+ struct mt76_rx_status *status,
+ __le32 *rxv, u32 phy)
+ {
+- /* TODO: struct ieee80211_radiotap_he_mu */
+ static const struct ieee80211_radiotap_he known = {
+ .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
+ HE_BITS(DATA1_DATA_DCM_KNOWN) |
+@@ -193,6 +237,7 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb,
+ HE_BITS(DATA1_CODING_KNOWN) |
+ HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
+ HE_BITS(DATA1_DOPPLER_KNOWN) |
++ HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
+ HE_BITS(DATA1_BSS_COLOR_KNOWN),
+ .data2 = HE_BITS(DATA2_GI_KNOWN) |
+ HE_BITS(DATA2_TXBF_KNOWN) |
+@@ -207,9 +252,12 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb,
+
+ he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) |
+ HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]);
++ he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
+ he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
+ le16_encode_bits(ltf_size,
+ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
++ if (cpu_to_le32(rxv[0]) & MT_PRXV_TXBF)
++ he->data5 |= HE_BITS(DATA5_TXBF);
+ he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
+ HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
+
+@@ -217,8 +265,7 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb,
+ case MT_PHY_TYPE_HE_SU:
+ he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
+ HE_BITS(DATA1_UL_DL_KNOWN) |
+- HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
+- HE_BITS(DATA1_SPTL_REUSE_KNOWN);
++ HE_BITS(DATA1_BEAM_CHANGE_KNOWN);
+
+ he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
+ HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
+@@ -232,17 +279,15 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb,
+ break;
+ case MT_PHY_TYPE_HE_MU:
+ he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
+- HE_BITS(DATA1_UL_DL_KNOWN) |
+- HE_BITS(DATA1_SPTL_REUSE_KNOWN);
++ HE_BITS(DATA1_UL_DL_KNOWN);
+
+ he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
+- he->data4 |= HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
++ he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
+
+ mt7921_mac_decode_he_radiotap_ru(status, he, rxv);
+ break;
+ case MT_PHY_TYPE_HE_TB:
+ he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
+- HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
+ HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
+ HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
+ HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
+@@ -606,9 +651,13 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
+
+ mt7921_mac_assoc_rssi(dev, skb);
+
+- if (rxv && status->flag & RX_FLAG_RADIOTAP_HE)
++ if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) {
+ mt7921_mac_decode_he_radiotap(skb, status, rxv, mode);
+
++ if (status->flag & RX_FLAG_RADIOTAP_HE_MU)
++ mt7921_mac_decode_he_mu_radiotap(skb, status, rxv);
++ }
++
+ if (!status->wcid || !ieee80211_is_data_qos(fc))
+ return 0;
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
+index 3af67fac213d..f0194c878037 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h
+@@ -116,6 +116,7 @@ enum rx_pkt_type {
+ #define MT_PRXV_TX_DCM BIT(4)
+ #define MT_PRXV_TX_ER_SU_106T BIT(5)
+ #define MT_PRXV_NSTS GENMASK(9, 7)
++#define MT_PRXV_TXBF BIT(10)
+ #define MT_PRXV_HT_AD_CODE BIT(11)
+ #define MT_PRXV_FRAME_MODE GENMASK(14, 12)
+ #define MT_PRXV_SGI GENMASK(16, 15)
+@@ -138,8 +139,15 @@ enum rx_pkt_type {
+ #define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
+ #define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
+ #define MT_CRXV_HE_PE_DISAMBIG BIT(23)
++#define MT_CRXV_HE_NUM_USER GENMASK(30, 24)
+ #define MT_CRXV_HE_UPLINK BIT(31)
+
++#define MT_CRXV_HE_RU0 GENMASK(7, 0)
++#define MT_CRXV_HE_RU1 GENMASK(15, 8)
++#define MT_CRXV_HE_RU2 GENMASK(23, 16)
++#define MT_CRXV_HE_RU3 GENMASK(31, 24)
++#define MT_CRXV_HE_MU_AID GENMASK(30, 20)
++
+ #define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
+ #define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
+ #define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
diff --git a/sys-kernel_arch-sources-g14_files-8023-v2-mt76-mt7921-fix-kernel-warning-from-cfg80211_calculate_bitrate.patch b/sys-kernel_arch-sources-g14_files-8023-v2-mt76-mt7921-fix-kernel-warning-from-cfg80211_calculate_bitrate.patch
new file mode 100644
index 000000000000..b71d4dc6db89
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-8023-v2-mt76-mt7921-fix-kernel-warning-from-cfg80211_calculate_bitrate.patch
@@ -0,0 +1,99 @@
+From: <sean.wang@mediatek.com>
+To: <nbd@nbd.name>, <lorenzo.bianconi@redhat.com>
+CC: <sean.wang@mediatek.com>, <Soul.Huang@mediatek.com>,
+ <YN.Chen@mediatek.com>, <Leon.Yen@mediatek.com>,
+ <Eric-SY.Chang@mediatek.com>, <Deren.Wu@mediatek.com>, <km.lin@mediatek.com>,
+ <robin.chiu@mediatek.com>, <ch.yeh@mediatek.com>, <posh.sun@mediatek.com>,
+ <Eric.Liang@mediatek.com>, <Stella.Chang@mediatek.com>, <jemele@google.com>,
+ <yenlinlai@google.com>, <linux-wireless@vger.kernel.org>,
+ <linux-mediatek@lists.infradead.org>
+Subject: [PATCH v2] mt76: mt7921: fix kernel warning from
+ cfg80211_calculate_bitrate
+Date: Sat, 14 Aug 2021 02:09:18 +0800
+
+From: Sean Wang <sean.wang@mediatek.com>
+
+Fix the kernel warning from cfg80211_calculate_bitrate
+due to the legacy rate is not parsed well in the current driver.
+
+Also, zeros struct rate_info before we fill it out to avoid the old value
+is kept such as rate->legacy.
+
+[ 790.921560] WARNING: CPU: 7 PID: 970 at net/wireless/util.c:1298 cfg80211_calculate_bitrate+0x354/0x35c [cfg80211]
+[ 790.987738] Hardware name: MediaTek Asurada rev1 board (DT)
+[ 790.993298] pstate: a0400009 (NzCv daif +PAN -UAO)
+[ 790.998104] pc : cfg80211_calculate_bitrate+0x354/0x35c [cfg80211]
+[ 791.004295] lr : cfg80211_calculate_bitrate+0x180/0x35c [cfg80211]
+[ 791.010462] sp : ffffffc0129c3880
+[ 791.013765] x29: ffffffc0129c3880 x28: ffffffd38305bea8
+[ 791.019065] x27: ffffffc0129c3970 x26: 0000000000000013
+[ 791.024364] x25: 00000000000003ca x24: 000000000000002f
+[ 791.029664] x23: 00000000000000d0 x22: ffffff8d108bc000
+[ 791.034964] x21: ffffff8d108bc0d0 x20: ffffffc0129c39a8
+[ 791.040264] x19: ffffffc0129c39a8 x18: 00000000ffff0a10
+[ 791.045563] x17: 0000000000000050 x16: 00000000000000ec
+[ 791.050910] x15: ffffffd3f9ebed9c x14: 0000000000000006
+[ 791.056211] x13: 00000000000b2eea x12: 0000000000000000
+[ 791.061511] x11: 00000000ffffffff x10: 0000000000000000
+[ 791.066811] x9 : 0000000000000000 x8 : 0000000000000000
+[ 791.072110] x7 : 0000000000000000 x6 : ffffffd3fafa5a7b
+[ 791.077409] x5 : 0000000000000000 x4 : 0000000000000000
+[ 791.082708] x3 : 0000000000000000 x2 : 0000000000000000
+[ 791.088008] x1 : ffffff8d3f79c918 x0 : 0000000000000000
+[ 791.093308] Call trace:
+[ 791.095770] cfg80211_calculate_bitrate+0x354/0x35c [cfg80211]
+[ 791.101615] nl80211_put_sta_rate+0x6c/0x2c0 [cfg80211]
+[ 791.106853] nl80211_send_station+0x980/0xaa4 [cfg80211]
+[ 791.112178] nl80211_get_station+0xb4/0x134 [cfg80211]
+[ 791.117308] genl_rcv_msg+0x3a0/0x440
+[ 791.120960] netlink_rcv_skb+0xcc/0x118
+[ 791.124785] genl_rcv+0x34/0x48
+[ 791.127916] netlink_unicast+0x144/0x1dc
+
+Fixes: 1c099ab44727 ("mt76: mt7921: add MCU support")
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+v2: don't do unnecessary line removal
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+index cadb633639d3..9b35b5da3619 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+@@ -328,11 +328,13 @@ mt7921_mcu_tx_rate_parse(struct mt76_phy *mphy,
+ struct rate_info *rate, u16 r)
+ {
+ struct ieee80211_supported_band *sband;
+- u16 flags = 0;
++ u16 flags = 0, rate_idx;
+ u8 txmode = FIELD_GET(MT_WTBL_RATE_TX_MODE, r);
+ u8 gi = 0;
+ u8 bw = 0;
++ bool cck = false;
+
++ memset(rate, 0, sizeof(*rate));
+ rate->mcs = FIELD_GET(MT_WTBL_RATE_MCS, r);
+ rate->nss = FIELD_GET(MT_WTBL_RATE_NSS, r) + 1;
+
+@@ -357,13 +359,18 @@ mt7921_mcu_tx_rate_parse(struct mt76_phy *mphy,
+
+ switch (txmode) {
+ case MT_PHY_TYPE_CCK:
++ cck = true;
++ fallthrough;
+ case MT_PHY_TYPE_OFDM:
+ if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
+ sband = &mphy->sband_5g.sband;
+ else
+ sband = &mphy->sband_2g.sband;
+
+- rate->legacy = sband->bitrates[rate->mcs].bitrate;
++ rate_idx = FIELD_GET(MT_TX_RATE_IDX, r);
++ rate_idx = mt76_get_rate(mphy->dev, sband, rate_idx,
++ cck);
++ rate->legacy = sband->bitrates[rate_idx].bitrate;
+ break;
+ case MT_PHY_TYPE_HT:
+ case MT_PHY_TYPE_HT_GF:
diff --git a/sys-kernel_arch-sources-g14_files-9001-v5.13.13-s0ix-patch-2021-08-28.patch b/sys-kernel_arch-sources-g14_files-9001-v5.13.13-s0ix-patch-2021-08-28.patch
deleted file mode 100644
index 6c44b9da37a4..000000000000
--- a/sys-kernel_arch-sources-g14_files-9001-v5.13.13-s0ix-patch-2021-08-28.patch
+++ /dev/null
@@ -1,1081 +0,0 @@
-From e0bda89bd4057c851932c59ddb5bd3890005214f Mon Sep 17 00:00:00 2001
-From: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Tue, 24 Aug 2021 21:21:09 -0700
-Subject: [PATCH] v5.13.13-s0ix patch 2021-08-24
-
-Squashed commit of the following:
-
-commit 3ba8d2ed7f58ddf970dfe2bc1bfb93b9b3d66190
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Mon Aug 9 20:40:04 2021 -0500
-
- ACPI: PM: s2idle: Invert Microsoft UUID entry and exit
-
- It was reported by a user with a Dell m15 R5 (5800H) that
- the keyboard backlight was turning on when entering suspend
- and turning off when exiting (the opposite of how it should be).
-
- The user bisected it back to commit 5dbf50997578 ("ACPI: PM:
- s2idle: Add support for new Microsoft UUID"). Previous to that
- commit the LEDs didn't turn off at all. Confirming in the spec,
- these were reversed when introduced.
-
- Fix them to match the spec.
-
- BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1230#note_1021836
- Fixes: 5dbf50997578 ("ACPI: PM: s2idle: Add support for new Microsoft UUID")
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-
-commit 606229f0125a3af622a407797ca94fade1ea1993
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jul 7 09:16:47 2021 -0500
-
- platform/x86: amd-pmc: Use return code on suspend
-
- Right now the driver will still return success even if the OS_HINT
- command failed to send to the SMU. In the rare event of a failure,
- the suspend should really be aborted here so that relevant logs
- can may be captured.
-
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-
-commit a1c785973ae351de6448f88b7c19dd26b8f70540
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 30 14:46:06 2021 -0500
-
- ACPI: PM: Only mark EC GPE for wakeup on Intel systems
-
- When using s2idle on a variety of AMD notebook systems, they are
- experiencing spurious events that the EC or SMU are in the wrong
- state leading to a hard time waking up or higher than expected
- power consumption.
-
- These events only occur when the EC GPE is inadvertently set as a wakeup
- source. Originally the EC GPE was only set as a wakeup source when using
- the intel-vbtn or intel-hid drivers in commit 10a08fd65ec1 ("ACPI: PM:
- Set up EC GPE for system wakeup from drivers that need it") but during
- testing a reporter discovered that this was not enough for their ASUS
- Zenbook UX430UNR/i7-8550U to wakeup by lid event or keypress.
- Marking the EC GPE for wakeup universally resolved this for that
- reporter in commit b90ff3554aa3 ("ACPI: PM: s2idle: Always set up EC GPE
- for system wakeup").
-
- However this behavior has lead to a number of problems:
-
- * On both Lenovo T14 and P14s the keyboard wakeup doesn't work, and
- sometimes the power button event doesn't work.
- * On HP 635 G7 detaching or attaching AC during suspend will cause
- the system not to wakeup
- * On Asus vivobook to prevent detaching AC causing resume problems
- * On Lenovo 14ARE05 to prevent detaching AC causing resume problems
- * On HP ENVY x360 to prevent detaching AC causing resume problems
-
- As there may be other Intel systems besides ASUS Zenbook UX430UNR/i7-8550U
- that don't use intel-vbtn or intel-hid avoid these problems by only
- universally marking the EC GPE wakesource on non-AMD systems.
-
- Link: https://patchwork.kernel.org/project/linux-pm/cover/5997740.FPbUVk04hV@kreacher/#22825489
- Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1230
- Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1629
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Acked-by: Alex Deucher <alexander.deucher@amd.com>
-
-commit 0f7dadec802150229cc8e6c74e0e7b3b2e53a9fd
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:03 2021 +0530
-
- platform/x86: amd-pmc: Add new acpi id for future PMC controllers
-
- The upcoming PMC controller would have a newer acpi id, add that to
- the supported acpid device list.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit e787353c8c9ff51b8cf23cb68f31aa44fea6a4b8
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:02 2021 +0530
-
- platform/x86: amd-pmc: Add support for ACPI ID AMDI0006
-
- Some newer BIOSes have added another ACPI ID for the uPEP device.
- SMU statistics behave identically on this device.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit 7e46535ba2b3eb3a91ada3241208429f01b5811c
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:01 2021 +0530
-
- amd-pmc: Add support for logging s0ix counters
-
- Even the FCH SSC registers provides certain level of information
- about the s0ix entry and exit times which comes handy when the SMU
- fails to report the statistics via the mailbox communication.
-
- This information is captured via a new debugfs file "s0ix_stats".
- A non-zero entry in this counters would mean that the system entered
- the s0ix state.
-
- If s0ix entry time and exit time don't change during suspend to idle,
- the silicon has not entered the deepest state.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit d9ddd835b8c990895bad75cdc46bf376b0e5a96d
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:00 2021 +0530
-
- platform/x86: amd-pmc: Add support for logging SMU metrics
-
- SMU provides a way to dump the s0ix debug statistics in the form of a
- metrics table via a of set special mailbox commands.
-
- Add support to the driver which can send these commands to SMU and expose
- the information received via debugfs. The information contains the s0ix
- entry/exit, active time of each IP block etc.
-
- As a side note, SMU subsystem logging is not supported on Picasso based
- SoC's.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit b5849744bf0f7fba2b498511681447b9a0eb1d1b
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:17:59 2021 +0530
-
- platform/x86: amd-pmc: call dump registers only once
-
- Currently amd_pmc_dump_registers() routine is being called at
- multiple places. The best to call it is after command submission
- to SMU.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-
-commit 58fdac16c271d4695a627751a4dbea899101d0ea
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Thu Jun 17 11:42:12 2021 -0500
-
- ACPI: PM: Adjust behavior for field problems on AMD systems
-
- Some AMD Systems with uPEP _HID AMD004/AMDI005 have an off by one bug
- in their function mask return. This means that they will call entrance
- but not exit for matching functions.
-
- Other AMD systems with this HID should use the Microsoft generic UUID.
-
- AMD systems with uPEP HID AMDI006 should be using the Microsoft method.
-
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-
-commit 36b57e1cf35997a22cb01f1832729a8f833ad6c8
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:11 2021 -0500
-
- ACPI: PM: s2idle: Add support for new Microsoft UUID
-
- This adds supports for _DSM notifications to the Microsoft UUID
- described by Microsoft documentation for s2idle.
-
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby-firmware-notifications
- Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit c4d632cf2df5bc7e2d8dccd8de8d3984e59f8e40
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:10 2021 -0500
-
- ACPI: PM: s2idle: Add support for multiple func mask
-
- Required for follow-up patch adding new UUID
- needing new function mask.
-
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit 8ab790396d0bd01b73755cedb3873ea60f7327dd
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:09 2021 -0500
-
- ACPI: PM: s2idle: Refactor common code
-
- Refactor common code to prepare for upcoming changes.
- * Remove unused struct.
- * Print error before returning.
- * Frees ACPI obj if _DSM type is not as expected.
- * Treat lps0_dsm_func_mask as an integer rather than character
- * Remove extra out_obj
- * Move rev_id
-
- Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit 18da9bb5a1742a867963541c171e55d290c86868
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:08 2021 -0500
-
- ACPI: PM: s2idle: Use correct revision id
-
- AMD spec mentions only revision 0. With this change,
- device constraint list is populated properly.
-
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit 4e4c8f117e567a8c97d4d94c7f813285beb38d53
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 9 13:40:18 2021 -0500
-
- ACPI: Add quirks for AMD Renoir/Lucienne CPUs to force the D3 hint
-
- AMD systems from Renoir and Lucienne require that the NVME controller
- is put into D3 over a Modern Standby / suspend-to-idle
- cycle. This is "typically" accomplished using the `StorageD3Enable`
- property in the _DSD, but this property was introduced after many
- of these systems launched and most OEM systems don't have it in
- their BIOS.
-
- On AMD Renoir without these drives going into D3 over suspend-to-idle
- the resume will fail with the NVME controller being reset and a trace
- like this in the kernel logs:
- ```
- [ 83.556118] nvme nvme0: I/O 161 QID 2 timeout, aborting
- [ 83.556178] nvme nvme0: I/O 162 QID 2 timeout, aborting
- [ 83.556187] nvme nvme0: I/O 163 QID 2 timeout, aborting
- [ 83.556196] nvme nvme0: I/O 164 QID 2 timeout, aborting
- [ 95.332114] nvme nvme0: I/O 25 QID 0 timeout, reset controller
- [ 95.332843] nvme nvme0: Abort status: 0x371
- [ 95.332852] nvme nvme0: Abort status: 0x371
- [ 95.332856] nvme nvme0: Abort status: 0x371
- [ 95.332859] nvme nvme0: Abort status: 0x371
- [ 95.332909] PM: dpm_run_callback(): pci_pm_resume+0x0/0xe0 returns -16
- [ 95.332936] nvme 0000:03:00.0: PM: failed to resume async: error -16
- ```
-
- The Microsoft documentation for StorageD3Enable mentioned that Windows has
- a hardcoded allowlist for D3 support, which was used for these platforms.
- Introduce quirks to hardcode them for Linux as well.
-
- As this property is now "standardized", OEM systems using AMD Cezanne and
- newer APU's have adopted this property, and quirks like this should not be
- necessary.
-
- CC: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
- CC: Alexander Deucher <Alexander.Deucher@amd.com>
- CC: Prike Liang <prike.liang@amd.com>
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
- Tested-by: Julian Sikorski <belegdol@gmail.com>
- Signed-off-by: Christoph Hellwig <hch@lst.de>
-
-commit b8914e70b7a47a61430a6372f41912991f71e2eb
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 9 13:40:17 2021 -0500
-
- ACPI: Check StorageD3Enable _DSD property in ACPI code
-
- Although first implemented for NVME, this check may be usable by
- other drivers as well. Microsoft's specification explicitly mentions
- that is may be usable by SATA and AHCI devices. Google also indicates
- that they have used this with SDHCI in a downstream kernel tree that
- a user can plug a storage device into.
-
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
- Suggested-by: Keith Busch <kbusch@kernel.org>
- CC: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
- CC: Alexander Deucher <Alexander.Deucher@amd.com>
- CC: Rafael J. Wysocki <rjw@rjwysocki.net>
- CC: Prike Liang <prike.liang@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
- Signed-off-by: Christoph Hellwig <hch@lst.de>
----
- drivers/acpi/device_pm.c | 32 ++++++
- drivers/acpi/internal.h | 9 ++
- drivers/acpi/x86/s2idle.c | 157 +++++++++++++++++--------
- drivers/acpi/x86/utils.c | 25 ++++
- drivers/nvme/host/pci.c | 28 +----
- drivers/platform/x86/amd-pmc.c | 204 ++++++++++++++++++++++++++++++---
- include/linux/acpi.h | 5 +
- 7 files changed, 369 insertions(+), 91 deletions(-)
-
-diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
-index 9d2d3b9bb8b5..0cfdef2fc3ad 100644
---- a/drivers/acpi/device_pm.c
-+++ b/drivers/acpi/device_pm.c
-@@ -1338,4 +1338,36 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
- return 1;
- }
- EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
-+
-+/**
-+ * acpi_storage_d3 - Check if D3 should be used in the suspend path
-+ * @dev: Device to check
-+ *
-+ * Return %true if the platform firmware wants @dev to be programmed
-+ * into D3hot or D3cold (if supported) in the suspend path, or %false
-+ * when there is no specific preference. On some platforms, if this
-+ * hint is ignored, @dev may remain unresponsive after suspending the
-+ * platform as a whole.
-+ *
-+ * Although the property has storage in the name it actually is
-+ * applied to the PCIe slot and plugging in a non-storage device the
-+ * same platform restrictions will likely apply.
-+ */
-+bool acpi_storage_d3(struct device *dev)
-+{
-+ struct acpi_device *adev = ACPI_COMPANION(dev);
-+ u8 val;
-+
-+ if (force_storage_d3())
-+ return true;
-+
-+ if (!adev)
-+ return false;
-+ if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
-+ &val))
-+ return false;
-+ return val == 1;
-+}
-+EXPORT_SYMBOL_GPL(acpi_storage_d3);
-+
- #endif /* CONFIG_PM */
-diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
-index e21611c9a170..7ac01b03ba67 100644
---- a/drivers/acpi/internal.h
-+++ b/drivers/acpi/internal.h
-@@ -236,6 +236,15 @@ static inline int suspend_nvs_save(void) { return 0; }
- static inline void suspend_nvs_restore(void) {}
- #endif
-
-+#ifdef CONFIG_X86
-+bool force_storage_d3(void);
-+#else
-+static inline bool force_storage_d3(void)
-+{
-+ return false;
-+}
-+#endif
-+
- /*--------------------------------------------------------------------------
- Device properties
- -------------------------------------------------------------------------- */
-diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
-index 2d7ddb8a8cb6..b16c245bbe5b 100644
---- a/drivers/acpi/x86/s2idle.c
-+++ b/drivers/acpi/x86/s2idle.c
-@@ -32,6 +32,9 @@ static const struct acpi_device_id lps0_device_ids[] = {
- {"", },
- };
-
-+/* Microsoft platform agnostic UUID */
-+#define ACPI_LPS0_DSM_UUID_MICROSOFT "11e00d56-ce64-47ce-837b-1f898f9aa461"
-+
- #define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
-
- #define ACPI_LPS0_GET_DEVICE_CONSTRAINTS 1
-@@ -39,6 +42,8 @@ static const struct acpi_device_id lps0_device_ids[] = {
- #define ACPI_LPS0_SCREEN_ON 4
- #define ACPI_LPS0_ENTRY 5
- #define ACPI_LPS0_EXIT 6
-+#define ACPI_LPS0_MS_ENTRY 7
-+#define ACPI_LPS0_MS_EXIT 8
-
- /* AMD */
- #define ACPI_LPS0_DSM_UUID_AMD "e3f32452-febc-43ce-9039-932122d37721"
-@@ -49,7 +54,10 @@ static const struct acpi_device_id lps0_device_ids[] = {
-
- static acpi_handle lps0_device_handle;
- static guid_t lps0_dsm_guid;
--static char lps0_dsm_func_mask;
-+static int lps0_dsm_func_mask;
-+
-+static guid_t lps0_dsm_guid_microsoft;
-+static int lps0_dsm_func_mask_microsoft;
-
- /* Device constraint entry structure */
- struct lpi_device_info {
-@@ -70,15 +78,7 @@ struct lpi_constraints {
- int min_dstate;
- };
-
--/* AMD */
--/* Device constraint entry structure */
--struct lpi_device_info_amd {
-- int revision;
-- int count;
-- union acpi_object *package;
--};
--
--/* Constraint package structure */
-+/* AMD Constraint package structure */
- struct lpi_device_constraint_amd {
- char *name;
- int enabled;
-@@ -96,15 +96,15 @@ static void lpi_device_get_constraints_amd(void)
- int i, j, k;
-
- out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
-- 1, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
-+ rev_id, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
- NULL, ACPI_TYPE_PACKAGE);
-
-- if (!out_obj)
-- return;
--
- acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
- out_obj ? "successful" : "failed");
-
-+ if (!out_obj)
-+ return;
-+
- for (i = 0; i < out_obj->package.count; i++) {
- union acpi_object *package = &out_obj->package.elements[i];
-
-@@ -317,14 +317,15 @@ static void lpi_check_constraints(void)
- }
- }
-
--static void acpi_sleep_run_lps0_dsm(unsigned int func)
-+static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, guid_t dsm_guid)
- {
- union acpi_object *out_obj;
-
-- if (!(lps0_dsm_func_mask & (1 << func)))
-+ if (!(func_mask & (1 << func)))
- return;
-
-- out_obj = acpi_evaluate_dsm(lps0_device_handle, &lps0_dsm_guid, rev_id, func, NULL);
-+ out_obj = acpi_evaluate_dsm(lps0_device_handle, &dsm_guid,
-+ rev_id, func, NULL);
- ACPI_FREE(out_obj);
-
- acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n",
-@@ -336,11 +337,33 @@ static bool acpi_s2idle_vendor_amd(void)
- return boot_cpu_data.x86_vendor == X86_VENDOR_AMD;
- }
-
-+static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *dsm_guid)
-+{
-+ union acpi_object *obj;
-+ int ret = -EINVAL;
-+
-+ guid_parse(uuid, dsm_guid);
-+ obj = acpi_evaluate_dsm(handle, dsm_guid, rev, 0, NULL);
-+
-+ /* Check if the _DSM is present and as expected. */
-+ if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length == 0 ||
-+ obj->buffer.length > sizeof(u32)) {
-+ acpi_handle_debug(handle,
-+ "_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev);
-+ goto out;
-+ }
-+
-+ ret = *(int *)obj->buffer.pointer;
-+ acpi_handle_debug(handle, "_DSM UUID %s rev %d function mask: 0x%x\n", uuid, rev, ret);
-+
-+out:
-+ ACPI_FREE(obj);
-+ return ret;
-+}
-+
- static int lps0_device_attach(struct acpi_device *adev,
- const struct acpi_device_id *not_used)
- {
-- union acpi_object *out_obj;
--
- if (lps0_device_handle)
- return 0;
-
-@@ -348,28 +371,36 @@ static int lps0_device_attach(struct acpi_device *adev,
- return 0;
-
- if (acpi_s2idle_vendor_amd()) {
-- guid_parse(ACPI_LPS0_DSM_UUID_AMD, &lps0_dsm_guid);
-- out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 0, 0, NULL);
-+ /* AMD0004, AMDI0005:
-+ * - Should use rev_id 0x0
-+ * - function mask > 0x3: Should use AMD method, but has off by one bug
-+ * - function mask = 0x3: Should use Microsoft method
-+ * AMDI0006:
-+ * - should use rev_id 0x0
-+ * - function mask = 0x3: Should use Microsoft method
-+ */
-+ const char *hid = acpi_device_hid(adev);
- rev_id = 0;
-+ lps0_dsm_func_mask = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid);
-+ lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID_MICROSOFT, rev_id,
-+ &lps0_dsm_guid_microsoft);
-+ if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") ||
-+ !strcmp(hid, "AMDI0005"))) {
-+ lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
-+ acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
-+ ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
-+ }
- } else {
-- guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid);
-- out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL);
- rev_id = 1;
-+ lps0_dsm_func_mask = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid);
-+ lps0_dsm_func_mask_microsoft = -EINVAL;
- }
-
-- /* Check if the _DSM is present and as expected. */
-- if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) {
-- acpi_handle_debug(adev->handle,
-- "_DSM function 0 evaluation failed\n");
-- return 0;
-- }
--
-- lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer;
--
-- ACPI_FREE(out_obj);
--
-- acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
-- lps0_dsm_func_mask);
-+ if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0)
-+ return 0; //function evaluation failed
-
- lps0_device_handle = adev->handle;
-
-@@ -386,11 +417,15 @@ static int lps0_device_attach(struct acpi_device *adev,
- mem_sleep_current = PM_SUSPEND_TO_IDLE;
-
- /*
-- * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
-- * EC GPE to be enabled while suspended for certain wakeup devices to
-- * work, so mark it as wakeup-capable.
-+ * Some Intel based LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U don't
-+ * use intel-hid or intel-vbtn but require the EC GPE to be enabled while
-+ * suspended for certain wakeup devices to work, so mark it as wakeup-capable.
-+ *
-+ * Only enable on !AMD as enabling this universally causes problems for a number
-+ * of AMD based systems.
- */
-- acpi_ec_mark_gpe_for_wake();
-+ if (!acpi_s2idle_vendor_amd())
-+ acpi_ec_mark_gpe_for_wake();
-
- return 0;
- }
-@@ -408,12 +443,23 @@ int acpi_s2idle_prepare_late(void)
- if (pm_debug_messages_on)
- lpi_check_constraints();
-
-- if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD);
-+ if (lps0_dsm_func_mask_microsoft > 0) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ } else if (acpi_s2idle_vendor_amd()) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- }
-
- return 0;
-@@ -424,12 +470,23 @@ void acpi_s2idle_restore_early(void)
- if (!lps0_device_handle || sleep_no_lps0)
- return;
-
-- if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT_AMD);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD);
-+ if (lps0_dsm_func_mask_microsoft > 0) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ } else if (acpi_s2idle_vendor_amd()) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT_AMD,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- }
- }
-
-diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
-index bdc1ba00aee9..f22f23933063 100644
---- a/drivers/acpi/x86/utils.c
-+++ b/drivers/acpi/x86/utils.c
-@@ -135,3 +135,28 @@ bool acpi_device_always_present(struct acpi_device *adev)
-
- return ret;
- }
-+
-+/*
-+ * AMD systems from Renoir and Lucienne *require* that the NVME controller
-+ * is put into D3 over a Modern Standby / suspend-to-idle cycle.
-+ *
-+ * This is "typically" accomplished using the `StorageD3Enable`
-+ * property in the _DSD that is checked via the `acpi_storage_d3` function
-+ * but this property was introduced after many of these systems launched
-+ * and most OEM systems don't have it in their BIOS.
-+ *
-+ * The Microsoft documentation for StorageD3Enable mentioned that Windows has
-+ * a hardcoded allowlist for D3 support, which was used for these platforms.
-+ *
-+ * This allows quirking on Linux in a similar fashion.
-+ */
-+static const struct x86_cpu_id storage_d3_cpu_ids[] = {
-+ X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 96, NULL), /* Renoir */
-+ X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 104, NULL), /* Lucienne */
-+ {}
-+};
-+
-+bool force_storage_d3(void)
-+{
-+ return x86_match_cpu(storage_d3_cpu_ids);
-+}
-diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
-index d963f25fc7ae..66455e2261d0 100644
---- a/drivers/nvme/host/pci.c
-+++ b/drivers/nvme/host/pci.c
-@@ -2880,32 +2880,6 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
- return 0;
- }
-
--#ifdef CONFIG_ACPI
--static bool nvme_acpi_storage_d3(struct pci_dev *dev)
--{
-- struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
-- u8 val;
--
-- /*
-- * Look for _DSD property specifying that the storage device on the port
-- * must use D3 to support deep platform power savings during
-- * suspend-to-idle.
-- */
--
-- if (!adev)
-- return false;
-- if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
-- &val))
-- return false;
-- return val == 1;
--}
--#else
--static inline bool nvme_acpi_storage_d3(struct pci_dev *dev)
--{
-- return false;
--}
--#endif /* CONFIG_ACPI */
--
- static void nvme_async_probe(void *data, async_cookie_t cookie)
- {
- struct nvme_dev *dev = data;
-@@ -2955,7 +2929,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-
- quirks |= check_vendor_combination_bug(pdev);
-
-- if (!noacpi && nvme_acpi_storage_d3(pdev)) {
-+ if (!noacpi && acpi_storage_d3(&pdev->dev)) {
- /*
- * Some systems use a bios work around to ask for D3 on
- * platforms that support kernel managed suspend.
-diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
-index ca95c2a52e26..663a4ca0580d 100644
---- a/drivers/platform/x86/amd-pmc.c
-+++ b/drivers/platform/x86/amd-pmc.c
-@@ -46,26 +46,70 @@
- #define AMD_PMC_RESULT_CMD_UNKNOWN 0xFE
- #define AMD_PMC_RESULT_FAILED 0xFF
-
-+/* FCH SSC Registers */
-+#define FCH_S0I3_ENTRY_TIME_L_OFFSET 0x30
-+#define FCH_S0I3_ENTRY_TIME_H_OFFSET 0x34
-+#define FCH_S0I3_EXIT_TIME_L_OFFSET 0x38
-+#define FCH_S0I3_EXIT_TIME_H_OFFSET 0x3C
-+#define FCH_SSC_MAPPING_SIZE 0x800
-+#define FCH_BASE_PHY_ADDR_LOW 0xFED81100
-+#define FCH_BASE_PHY_ADDR_HIGH 0x00000000
-+
-+/* SMU Message Definations */
-+#define SMU_MSG_GETSMUVERSION 0x02
-+#define SMU_MSG_LOG_GETDRAM_ADDR_HI 0x04
-+#define SMU_MSG_LOG_GETDRAM_ADDR_LO 0x05
-+#define SMU_MSG_LOG_START 0x06
-+#define SMU_MSG_LOG_RESET 0x07
-+#define SMU_MSG_LOG_DUMP_DATA 0x08
-+#define SMU_MSG_GET_SUP_CONSTRAINTS 0x09
- /* List of supported CPU ids */
- #define AMD_CPU_ID_RV 0x15D0
- #define AMD_CPU_ID_RN 0x1630
- #define AMD_CPU_ID_PCO AMD_CPU_ID_RV
- #define AMD_CPU_ID_CZN AMD_CPU_ID_RN
-+#define AMD_CPU_ID_YC 0x14B5
-
- #define PMC_MSG_DELAY_MIN_US 100
- #define RESPONSE_REGISTER_LOOP_MAX 200
-
-+#define SOC_SUBSYSTEM_IP_MAX 12
-+#define DELAY_MIN_US 2000
-+#define DELAY_MAX_US 3000
- enum amd_pmc_def {
- MSG_TEST = 0x01,
- MSG_OS_HINT_PCO,
- MSG_OS_HINT_RN,
- };
-
-+struct amd_pmc_bit_map {
-+ const char *name;
-+ u32 bit_mask;
-+};
-+
-+static const struct amd_pmc_bit_map soc15_ip_blk[] = {
-+ {"DISPLAY", BIT(0)},
-+ {"CPU", BIT(1)},
-+ {"GFX", BIT(2)},
-+ {"VDD", BIT(3)},
-+ {"ACP", BIT(4)},
-+ {"VCN", BIT(5)},
-+ {"ISP", BIT(6)},
-+ {"NBIO", BIT(7)},
-+ {"DF", BIT(8)},
-+ {"USB0", BIT(9)},
-+ {"USB1", BIT(10)},
-+ {"LAPIC", BIT(11)},
-+ {}
-+};
-+
- struct amd_pmc_dev {
- void __iomem *regbase;
-- void __iomem *smu_base;
-+ void __iomem *smu_virt_addr;
-+ void __iomem *fch_virt_addr;
- u32 base_addr;
- u32 cpu_id;
-+ u32 active_ips;
- struct device *dev;
- struct mutex lock; /* generic mutex lock */
- #if IS_ENABLED(CONFIG_DEBUG_FS)
-@@ -74,6 +118,7 @@ struct amd_pmc_dev {
- };
-
- static struct amd_pmc_dev pmc;
-+static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg, bool ret);
-
- static inline u32 amd_pmc_reg_read(struct amd_pmc_dev *dev, int reg_offset)
- {
-@@ -85,13 +130,76 @@ static inline void amd_pmc_reg_write(struct amd_pmc_dev *dev, int reg_offset, u3
- iowrite32(val, dev->regbase + reg_offset);
- }
-
-+struct smu_metrics {
-+ u32 table_version;
-+ u32 hint_count;
-+ u32 s0i3_cyclecount;
-+ u32 timein_s0i2;
-+ u64 timeentering_s0i3_lastcapture;
-+ u64 timeentering_s0i3_totaltime;
-+ u64 timeto_resume_to_os_lastcapture;
-+ u64 timeto_resume_to_os_totaltime;
-+ u64 timein_s0i3_lastcapture;
-+ u64 timein_s0i3_totaltime;
-+ u64 timein_swdrips_lastcapture;
-+ u64 timein_swdrips_totaltime;
-+ u64 timecondition_notmet_lastcapture[SOC_SUBSYSTEM_IP_MAX];
-+ u64 timecondition_notmet_totaltime[SOC_SUBSYSTEM_IP_MAX];
-+} __packed;
-+
- #ifdef CONFIG_DEBUG_FS
- static int smu_fw_info_show(struct seq_file *s, void *unused)
- {
-+ struct amd_pmc_dev *dev = s->private;
-+ struct smu_metrics table;
-+ int idx;
-+
-+ if (dev->cpu_id == AMD_CPU_ID_PCO)
-+ return -EINVAL;
-+
-+ memcpy_fromio(&table, dev->smu_virt_addr, sizeof(struct smu_metrics));
-+
-+ seq_puts(s, "\n=== SMU Statistics ===\n");
-+ seq_printf(s, "Table Version: %d\n", table.table_version);
-+ seq_printf(s, "Hint Count: %d\n", table.hint_count);
-+ seq_printf(s, "S0i3 Cycle Count: %d\n", table.s0i3_cyclecount);
-+ seq_printf(s, "Time (in us) to S0i3: %lld\n", table.timeentering_s0i3_lastcapture);
-+ seq_printf(s, "Time (in us) in S0i3: %lld\n", table.timein_s0i3_lastcapture);
-+
-+ seq_puts(s, "\n=== Active time (in us) ===\n");
-+ for (idx = 0 ; idx < SOC_SUBSYSTEM_IP_MAX ; idx++) {
-+ if (soc15_ip_blk[idx].bit_mask & dev->active_ips)
-+ seq_printf(s, "%-8s : %lld\n", soc15_ip_blk[idx].name,
-+ table.timecondition_notmet_lastcapture[idx]);
-+ }
-+
- return 0;
- }
- DEFINE_SHOW_ATTRIBUTE(smu_fw_info);
-
-+static int s0ix_stats_show(struct seq_file *s, void *unused)
-+{
-+ struct amd_pmc_dev *dev = s->private;
-+ u64 entry_time, exit_time, residency;
-+
-+ entry_time = ioread32(dev->fch_virt_addr + FCH_S0I3_ENTRY_TIME_H_OFFSET);
-+ entry_time = entry_time << 32 | ioread32(dev->fch_virt_addr + FCH_S0I3_ENTRY_TIME_L_OFFSET);
-+
-+ exit_time = ioread32(dev->fch_virt_addr + FCH_S0I3_EXIT_TIME_H_OFFSET);
-+ exit_time = exit_time << 32 | ioread32(dev->fch_virt_addr + FCH_S0I3_EXIT_TIME_L_OFFSET);
-+
-+ /* It's in 48MHz. We need to convert it */
-+ residency = (exit_time - entry_time) / 48;
-+
-+ seq_puts(s, "=== S0ix statistics ===\n");
-+ seq_printf(s, "S0ix Entry Time: %lld\n", entry_time);
-+ seq_printf(s, "S0ix Exit Time: %lld\n", exit_time);
-+ seq_printf(s, "Residency Time: %lld\n", residency);
-+
-+ return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(s0ix_stats);
-+
- static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
- {
- debugfs_remove_recursive(dev->dbgfs_dir);
-@@ -102,6 +210,8 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
- dev->dbgfs_dir = debugfs_create_dir("amd_pmc", NULL);
- debugfs_create_file("smu_fw_info", 0644, dev->dbgfs_dir, dev,
- &smu_fw_info_fops);
-+ debugfs_create_file("s0ix_stats", 0644, dev->dbgfs_dir, dev,
-+ &s0ix_stats_fops);
- }
- #else
- static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
-@@ -113,6 +223,32 @@ static inline void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
- }
- #endif /* CONFIG_DEBUG_FS */
-
-+static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
-+{
-+ u32 phys_addr_low, phys_addr_hi;
-+ u64 smu_phys_addr;
-+
-+ if (dev->cpu_id == AMD_CPU_ID_PCO)
-+ return -EINVAL;
-+
-+ /* Get Active devices list from SMU */
-+ amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, 1);
-+
-+ /* Get dram address */
-+ amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, 1);
-+ amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, 1);
-+ smu_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
-+
-+ dev->smu_virt_addr = devm_ioremap(dev->dev, smu_phys_addr, sizeof(struct smu_metrics));
-+ if (!dev->smu_virt_addr)
-+ return -ENOMEM;
-+
-+ /* Start the logging */
-+ amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, 0);
-+
-+ return 0;
-+}
-+
- static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
- {
- u32 value;
-@@ -127,10 +263,9 @@ static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
- dev_dbg(dev->dev, "AMD_PMC_REGISTER_MESSAGE:%x\n", value);
- }
-
--static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
-+static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg, bool ret)
- {
- int rc;
-- u8 msg;
- u32 val;
-
- mutex_lock(&dev->lock);
-@@ -150,8 +285,8 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_ARGUMENT, set);
-
- /* Write message ID to message ID register */
-- msg = (dev->cpu_id == AMD_CPU_ID_RN) ? MSG_OS_HINT_RN : MSG_OS_HINT_PCO;
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_MESSAGE, msg);
-+
- /* Wait until we get a valid response */
- rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
- val, val != 0, PMC_MSG_DELAY_MIN_US,
-@@ -163,6 +298,11 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
-
- switch (val) {
- case AMD_PMC_RESULT_OK:
-+ if (ret) {
-+ /* PMFW may take longer time to return back the data */
-+ usleep_range(DELAY_MIN_US, 10 * DELAY_MAX_US);
-+ *data = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_ARGUMENT);
-+ }
- break;
- case AMD_PMC_RESULT_CMD_REJECT_BUSY:
- dev_err(dev->dev, "SMU not ready. err: 0x%x\n", val);
-@@ -182,32 +322,54 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
-
- out_unlock:
- mutex_unlock(&dev->lock);
-+ amd_pmc_dump_registers(dev);
- return rc;
- }
-
-+static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev)
-+{
-+ switch (dev->cpu_id) {
-+ case AMD_CPU_ID_PCO:
-+ return MSG_OS_HINT_PCO;
-+ case AMD_CPU_ID_RN:
-+ case AMD_CPU_ID_YC:
-+ return MSG_OS_HINT_RN;
-+ }
-+ return -EINVAL;
-+}
-+
- static int __maybe_unused amd_pmc_suspend(struct device *dev)
- {
- struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
- int rc;
-+ u8 msg;
-
-- rc = amd_pmc_send_cmd(pdev, 1);
-+ /* Reset and Start SMU logging - to monitor the s0i3 stats */
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_RESET, 0);
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_START, 0);
-+
-+ msg = amd_pmc_get_os_hint(pdev);
-+ rc = amd_pmc_send_cmd(pdev, 1, NULL, msg, 0);
- if (rc)
- dev_err(pdev->dev, "suspend failed\n");
-
-- amd_pmc_dump_registers(pdev);
-- return 0;
-+ return rc;
- }
-
- static int __maybe_unused amd_pmc_resume(struct device *dev)
- {
- struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
- int rc;
-+ u8 msg;
-
-- rc = amd_pmc_send_cmd(pdev, 0);
-+ /* Let SMU know that we are looking for stats */
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0);
-+
-+ msg = amd_pmc_get_os_hint(pdev);
-+ rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, 0);
- if (rc)
- dev_err(pdev->dev, "resume failed\n");
-
-- amd_pmc_dump_registers(pdev);
- return 0;
- }
-
-@@ -216,6 +378,7 @@ static const struct dev_pm_ops amd_pmc_pm_ops = {
- };
-
- static const struct pci_device_id pmc_pci_ids[] = {
-+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_YC) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_CZN) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RN) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) },
-@@ -227,9 +390,8 @@ static int amd_pmc_probe(struct platform_device *pdev)
- {
- struct amd_pmc_dev *dev = &pmc;
- struct pci_dev *rdev;
-- u32 base_addr_lo;
-- u32 base_addr_hi;
-- u64 base_addr;
-+ u32 base_addr_lo, base_addr_hi;
-+ u64 base_addr, fch_phys_addr;
- int err;
- u32 val;
-
-@@ -279,9 +441,21 @@ static int amd_pmc_probe(struct platform_device *pdev)
- if (!dev->regbase)
- return -ENOMEM;
-
-- amd_pmc_dump_registers(dev);
--
- mutex_init(&dev->lock);
-+
-+ /* Use FCH registers to get the S0ix stats */
-+ base_addr_lo = FCH_BASE_PHY_ADDR_LOW;
-+ base_addr_hi = FCH_BASE_PHY_ADDR_HIGH;
-+ fch_phys_addr = ((u64)base_addr_hi << 32 | base_addr_lo);
-+ dev->fch_virt_addr = devm_ioremap(dev->dev, fch_phys_addr, FCH_SSC_MAPPING_SIZE);
-+ if (!dev->fch_virt_addr)
-+ return -ENOMEM;
-+
-+ /* Use SMU to get the s0i3 debug stats */
-+ err = amd_pmc_setup_smu_logging(dev);
-+ if (err)
-+ dev_err(dev->dev, "SMU debugging info not supported on this platform\n");
-+
- platform_set_drvdata(pdev, dev);
- amd_pmc_dbgfs_register(dev);
- return 0;
-@@ -298,6 +472,8 @@ static int amd_pmc_remove(struct platform_device *pdev)
-
- static const struct acpi_device_id amd_pmc_acpi_ids[] = {
- {"AMDI0005", 0},
-+ {"AMDI0006", 0},
-+ {"AMDI0007", 0},
- {"AMD0004", 0},
- { }
- };
-diff --git a/include/linux/acpi.h b/include/linux/acpi.h
-index c60745f657e9..dd0dafd21e33 100644
---- a/include/linux/acpi.h
-+++ b/include/linux/acpi.h
-@@ -1004,6 +1004,7 @@ int acpi_dev_resume(struct device *dev);
- int acpi_subsys_runtime_suspend(struct device *dev);
- int acpi_subsys_runtime_resume(struct device *dev);
- int acpi_dev_pm_attach(struct device *dev, bool power_on);
-+bool acpi_storage_d3(struct device *dev);
- #else
- static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
- static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
-@@ -1011,6 +1012,10 @@ static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
- {
- return 0;
- }
-+static inline bool acpi_storage_d3(struct device *dev)
-+{
-+ return false;
-+}
- #endif
-
- #if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP)
---
-2.33.0
-
diff --git a/sys-kernel_arch-sources-g14_files-9001-v5.13.14-s0ix-patch-2021-09-03.patch b/sys-kernel_arch-sources-g14_files-9001-v5.13.14-s0ix-patch-2021-09-03.patch
deleted file mode 100644
index f4a636338294..000000000000
--- a/sys-kernel_arch-sources-g14_files-9001-v5.13.14-s0ix-patch-2021-09-03.patch
+++ /dev/null
@@ -1,1293 +0,0 @@
-From 36f737e3129d1058f2717dafa8e21c30a825f79f Mon Sep 17 00:00:00 2001
-From: Scott B <arglebargle@arglebargle.dev>
-Date: Fri, 3 Sep 2021 03:07:06 -0700
-Subject: [PATCH] v5.13.14 s0ix patch 2021-09-03
-
-Squashed commit of the following:
-
-commit d41335d4b59b3af5b5b0004da80a16067acd8303
-Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-Date: Tue Aug 31 17:36:12 2021 +0530
-
- pinctrl: amd: Add irq field data
-
- pinctrl_amd use gpiochip_get_data() to get their local state containers
- back from the gpiochip passed as amd_gpio chip data.
-
- Hence added irq field data to get directly using amd_gpio chip data.
-
- Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-
-commit 5ae23ad72e5302c875a1218886350368de215b42
-Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-Date: Tue Aug 31 17:36:13 2021 +0530
-
- pinctrl: amd: Handle wake-up interrupt
-
- Enable/disable power management wakeup mode, which is disabled by
- default. enable_irq_wake enables wakes the system from sleep.
-
- Hence added enable/disable irq_wake to handle wake-up interrupt.
-
- Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-
-commit df56b40e5e30d43eef647a54e6f2b57988a99e36
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Mon Aug 9 15:15:13 2021 -0500
-
- pinctrl: amd: Fix an issue with shutdown when system set to s0ix
-
- IRQs are getting armed on shutdown causing the system to immediately
- wake back up.
-
- Link: https://lkml.org/lkml/2021/8/2/1114
- Reported-by: nix.or.die@googlemail.com
- Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Tested-by: Gabriel Craciunescu <nix.or.die@gmail.com>
- CC: Raul E Rangel <rrangel@chromium.org>
- Fixes: d62bd5ce12d7 ("pinctrl: amd: Implement irq_set_wake")
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Link: https://lore.kernel.org/r/20210809201513.12367-1-mario.limonciello@amd.com
- Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-
-commit 38c5d80d5a7e15529e7c9f4136273f46938bec9f
-Author: Raul E Rangel <rrangel@chromium.org>
-Date: Thu Apr 29 16:34:24 2021 -0600
-
- pinctrl: amd: Implement irq_set_wake
-
- This allows the OS to control which devices produce wake events.
-
- $ grep enabled /sys/kernel/irq/*/wakeup
- /sys/kernel/irq/24/wakeup:enabled
-
- Signed-off-by: Raul E Rangel <rrangel@chromium.org>
- Link: https://lore.kernel.org/r/20210429163341.1.I7631534622233689dd81410525e0dd617b9b2012@changeid
- Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-
-commit e3629e35a34298d38875fcc8a8d9d2b5352a4f32
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Tue Aug 31 11:36:19 2021 -0500
-
- ACPI: PM: s2idle: Run both AMD and Microsoft methods if both are supported
-
- It was reported that on "HP ENVY x360" that power LED does not come back
- on, certain keys like brightness controls do not work, and the fan never
- spins up, even under load.
-
- In analysis of the SSDT it's clear that the Microsoft UUID doesn't provide
- functional support, but rather the AMD UUID should be supporting this
- system.
-
- Because this is a gap in the expected logic, confirmation with internal
- team is that AMD uPEP *does* run even when Microsoft UUID present, but
- most OEM systems have adopted value of "0x3" for supported functions and
- hence nothing runs.
-
- Henceforth add support for running both Microsoft and AMD methods. This
- approach will also allow the same logic on Intel systems if desired at a
- future time as well by pulling the evaluation of
- `lps0_dsm_func_mask_microsoft` out of the if block for
- `acpi_s2idle_vendor_amd`.
-
- BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1691
- Reported-by: Maxwell Beck <max@ryt.one>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-
-commit 80ced3f9f485dd07ac5a5180bf2cc88f2179e2e3
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Mon Aug 9 20:40:04 2021 -0500
-
- ACPI: PM: s2idle: Invert Microsoft UUID entry and exit
-
- It was reported by a user with a Dell m15 R5 (5800H) that
- the keyboard backlight was turning on when entering suspend
- and turning off when exiting (the opposite of how it should be).
-
- The user bisected it back to commit 5dbf50997578 ("ACPI: PM:
- s2idle: Add support for new Microsoft UUID"). Previous to that
- commit the LEDs didn't turn off at all. Confirming in the spec,
- these were reversed when introduced.
-
- Fix them to match the spec.
-
- BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1230#note_1021836
- Fixes: 5dbf50997578 ("ACPI: PM: s2idle: Add support for new Microsoft UUID")
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-
-commit 6d363060e6590441f4755cdd96ced1f5e5ffb1e0
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jul 7 09:16:47 2021 -0500
-
- platform/x86: amd-pmc: Use return code on suspend
-
- Right now the driver will still return success even if the OS_HINT
- command failed to send to the SMU. In the rare event of a failure,
- the suspend should really be aborted here so that relevant logs
- can may be captured.
-
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-
-commit 311131001c64e1fb04d73c45a8e4ba7a6835a079
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 30 14:46:06 2021 -0500
-
- ACPI: PM: Only mark EC GPE for wakeup on Intel systems
-
- When using s2idle on a variety of AMD notebook systems, they are
- experiencing spurious events that the EC or SMU are in the wrong
- state leading to a hard time waking up or higher than expected
- power consumption.
-
- These events only occur when the EC GPE is inadvertently set as a wakeup
- source. Originally the EC GPE was only set as a wakeup source when using
- the intel-vbtn or intel-hid drivers in commit 10a08fd65ec1 ("ACPI: PM:
- Set up EC GPE for system wakeup from drivers that need it") but during
- testing a reporter discovered that this was not enough for their ASUS
- Zenbook UX430UNR/i7-8550U to wakeup by lid event or keypress.
- Marking the EC GPE for wakeup universally resolved this for that
- reporter in commit b90ff3554aa3 ("ACPI: PM: s2idle: Always set up EC GPE
- for system wakeup").
-
- However this behavior has lead to a number of problems:
-
- * On both Lenovo T14 and P14s the keyboard wakeup doesn't work, and
- sometimes the power button event doesn't work.
- * On HP 635 G7 detaching or attaching AC during suspend will cause
- the system not to wakeup
- * On Asus vivobook to prevent detaching AC causing resume problems
- * On Lenovo 14ARE05 to prevent detaching AC causing resume problems
- * On HP ENVY x360 to prevent detaching AC causing resume problems
-
- As there may be other Intel systems besides ASUS Zenbook UX430UNR/i7-8550U
- that don't use intel-vbtn or intel-hid avoid these problems by only
- universally marking the EC GPE wakesource on non-AMD systems.
-
- Link: https://patchwork.kernel.org/project/linux-pm/cover/5997740.FPbUVk04hV@kreacher/#22825489
- Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1230
- Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1629
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Acked-by: Alex Deucher <alexander.deucher@amd.com>
-
-commit 0a7afaec19f871bc83950919530fe84e93e90dd5
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:03 2021 +0530
-
- platform/x86: amd-pmc: Add new acpi id for future PMC controllers
-
- The upcoming PMC controller would have a newer acpi id, add that to
- the supported acpid device list.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit ab0fbff1630447b320a00a56d2d03abcb956e8d3
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:02 2021 +0530
-
- platform/x86: amd-pmc: Add support for ACPI ID AMDI0006
-
- Some newer BIOSes have added another ACPI ID for the uPEP device.
- SMU statistics behave identically on this device.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit 27a6b6eb5de59f8be31d5276044eda4fda974450
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:01 2021 +0530
-
- amd-pmc: Add support for logging s0ix counters
-
- Even the FCH SSC registers provides certain level of information
- about the s0ix entry and exit times which comes handy when the SMU
- fails to report the statistics via the mailbox communication.
-
- This information is captured via a new debugfs file "s0ix_stats".
- A non-zero entry in this counters would mean that the system entered
- the s0ix state.
-
- If s0ix entry time and exit time don't change during suspend to idle,
- the silicon has not entered the deepest state.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit 44c1c5f0d6d12a7c368b28e549315dd0f9475649
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:18:00 2021 +0530
-
- platform/x86: amd-pmc: Add support for logging SMU metrics
-
- SMU provides a way to dump the s0ix debug statistics in the form of a
- metrics table via a of set special mailbox commands.
-
- Add support to the driver which can send these commands to SMU and expose
- the information received via debugfs. The information contains the s0ix
- entry/exit, active time of each IP block etc.
-
- As a side note, SMU subsystem logging is not supported on Picasso based
- SoC's.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-
-commit 2fc643aca016fa2290274cc0211865c9faced3c8
-Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-Date: Tue Jun 29 14:17:59 2021 +0530
-
- platform/x86: amd-pmc: call dump registers only once
-
- Currently amd_pmc_dump_registers() routine is being called at
- multiple places. The best to call it is after command submission
- to SMU.
-
- Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
-
-commit cf41f866c72024d26d540503f29f4fd40ff99e47
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Thu Jun 17 11:42:12 2021 -0500
-
- ACPI: PM: Adjust behavior for field problems on AMD systems
-
- Some AMD Systems with uPEP _HID AMD004/AMDI005 have an off by one bug
- in their function mask return. This means that they will call entrance
- but not exit for matching functions.
-
- Other AMD systems with this HID should use the Microsoft generic UUID.
-
- AMD systems with uPEP HID AMDI006 should be using the Microsoft method.
-
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-
-commit eee65e7c8960f636fc10c94b00c183a7a844b971
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:11 2021 -0500
-
- ACPI: PM: s2idle: Add support for new Microsoft UUID
-
- This adds supports for _DSM notifications to the Microsoft UUID
- described by Microsoft documentation for s2idle.
-
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby-firmware-notifications
- Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit aebc1c48faed67b707ca79a7c66029684cb8eeab
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:10 2021 -0500
-
- ACPI: PM: s2idle: Add support for multiple func mask
-
- Required for follow-up patch adding new UUID
- needing new function mask.
-
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit 4d027ca3853f82e0f678b1ca2c2247140762fb3e
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:09 2021 -0500
-
- ACPI: PM: s2idle: Refactor common code
-
- Refactor common code to prepare for upcoming changes.
- * Remove unused struct.
- * Print error before returning.
- * Frees ACPI obj if _DSM type is not as expected.
- * Treat lps0_dsm_func_mask as an integer rather than character
- * Remove extra out_obj
- * Move rev_id
-
- Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit c2a6a33c8255b8c38ad935c623848ecbc6964811
-Author: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-Date: Thu Jun 17 11:42:08 2021 -0500
-
- ACPI: PM: s2idle: Use correct revision id
-
- AMD spec mentions only revision 0. With this change,
- device constraint list is populated properly.
-
- Signed-off-by: Pratik Vishwakarma <Pratik.Vishwakarma@amd.com>
-
-commit a799a0e4fd4dfab53e85e0cc687f64a9c22a41a2
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 9 13:40:18 2021 -0500
-
- ACPI: Add quirks for AMD Renoir/Lucienne CPUs to force the D3 hint
-
- AMD systems from Renoir and Lucienne require that the NVME controller
- is put into D3 over a Modern Standby / suspend-to-idle
- cycle. This is "typically" accomplished using the `StorageD3Enable`
- property in the _DSD, but this property was introduced after many
- of these systems launched and most OEM systems don't have it in
- their BIOS.
-
- On AMD Renoir without these drives going into D3 over suspend-to-idle
- the resume will fail with the NVME controller being reset and a trace
- like this in the kernel logs:
- ```
- [ 83.556118] nvme nvme0: I/O 161 QID 2 timeout, aborting
- [ 83.556178] nvme nvme0: I/O 162 QID 2 timeout, aborting
- [ 83.556187] nvme nvme0: I/O 163 QID 2 timeout, aborting
- [ 83.556196] nvme nvme0: I/O 164 QID 2 timeout, aborting
- [ 95.332114] nvme nvme0: I/O 25 QID 0 timeout, reset controller
- [ 95.332843] nvme nvme0: Abort status: 0x371
- [ 95.332852] nvme nvme0: Abort status: 0x371
- [ 95.332856] nvme nvme0: Abort status: 0x371
- [ 95.332859] nvme nvme0: Abort status: 0x371
- [ 95.332909] PM: dpm_run_callback(): pci_pm_resume+0x0/0xe0 returns -16
- [ 95.332936] nvme 0000:03:00.0: PM: failed to resume async: error -16
- ```
-
- The Microsoft documentation for StorageD3Enable mentioned that Windows has
- a hardcoded allowlist for D3 support, which was used for these platforms.
- Introduce quirks to hardcode them for Linux as well.
-
- As this property is now "standardized", OEM systems using AMD Cezanne and
- newer APU's have adopted this property, and quirks like this should not be
- necessary.
-
- CC: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
- CC: Alexander Deucher <Alexander.Deucher@amd.com>
- CC: Prike Liang <prike.liang@amd.com>
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
- Tested-by: Julian Sikorski <belegdol@gmail.com>
- Signed-off-by: Christoph Hellwig <hch@lst.de>
-
-commit b626c7c5162646c04f1b208951421d70996cda0e
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Wed Jun 9 13:40:17 2021 -0500
-
- ACPI: Check StorageD3Enable _DSD property in ACPI code
-
- Although first implemented for NVME, this check may be usable by
- other drivers as well. Microsoft's specification explicitly mentions
- that is may be usable by SATA and AHCI devices. Google also indicates
- that they have used this with SDHCI in a downstream kernel tree that
- a user can plug a storage device into.
-
- Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
- Suggested-by: Keith Busch <kbusch@kernel.org>
- CC: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
- CC: Alexander Deucher <Alexander.Deucher@amd.com>
- CC: Rafael J. Wysocki <rjw@rjwysocki.net>
- CC: Prike Liang <prike.liang@amd.com>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
- Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
- Signed-off-by: Christoph Hellwig <hch@lst.de>
----
- drivers/acpi/device_pm.c | 32 ++++++
- drivers/acpi/internal.h | 9 ++
- drivers/acpi/x86/s2idle.c | 176 +++++++++++++++++++---------
- drivers/acpi/x86/utils.c | 25 ++++
- drivers/nvme/host/pci.c | 28 +----
- drivers/pinctrl/pinctrl-amd.c | 50 +++++++-
- drivers/pinctrl/pinctrl-amd.h | 1 +
- drivers/platform/x86/amd-pmc.c | 204 ++++++++++++++++++++++++++++++---
- include/linux/acpi.h | 5 +
- 9 files changed, 429 insertions(+), 101 deletions(-)
-
-diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
-index 9d2d3b9bb8b5..0cfdef2fc3ad 100644
---- a/drivers/acpi/device_pm.c
-+++ b/drivers/acpi/device_pm.c
-@@ -1338,4 +1338,36 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
- return 1;
- }
- EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
-+
-+/**
-+ * acpi_storage_d3 - Check if D3 should be used in the suspend path
-+ * @dev: Device to check
-+ *
-+ * Return %true if the platform firmware wants @dev to be programmed
-+ * into D3hot or D3cold (if supported) in the suspend path, or %false
-+ * when there is no specific preference. On some platforms, if this
-+ * hint is ignored, @dev may remain unresponsive after suspending the
-+ * platform as a whole.
-+ *
-+ * Although the property has storage in the name it actually is
-+ * applied to the PCIe slot and plugging in a non-storage device the
-+ * same platform restrictions will likely apply.
-+ */
-+bool acpi_storage_d3(struct device *dev)
-+{
-+ struct acpi_device *adev = ACPI_COMPANION(dev);
-+ u8 val;
-+
-+ if (force_storage_d3())
-+ return true;
-+
-+ if (!adev)
-+ return false;
-+ if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
-+ &val))
-+ return false;
-+ return val == 1;
-+}
-+EXPORT_SYMBOL_GPL(acpi_storage_d3);
-+
- #endif /* CONFIG_PM */
-diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
-index e21611c9a170..7ac01b03ba67 100644
---- a/drivers/acpi/internal.h
-+++ b/drivers/acpi/internal.h
-@@ -236,6 +236,15 @@ static inline int suspend_nvs_save(void) { return 0; }
- static inline void suspend_nvs_restore(void) {}
- #endif
-
-+#ifdef CONFIG_X86
-+bool force_storage_d3(void);
-+#else
-+static inline bool force_storage_d3(void)
-+{
-+ return false;
-+}
-+#endif
-+
- /*--------------------------------------------------------------------------
- Device properties
- -------------------------------------------------------------------------- */
-diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
-index 2d7ddb8a8cb6..bd35009bb005 100644
---- a/drivers/acpi/x86/s2idle.c
-+++ b/drivers/acpi/x86/s2idle.c
-@@ -32,6 +32,9 @@ static const struct acpi_device_id lps0_device_ids[] = {
- {"", },
- };
-
-+/* Microsoft platform agnostic UUID */
-+#define ACPI_LPS0_DSM_UUID_MICROSOFT "11e00d56-ce64-47ce-837b-1f898f9aa461"
-+
- #define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
-
- #define ACPI_LPS0_GET_DEVICE_CONSTRAINTS 1
-@@ -39,6 +42,8 @@ static const struct acpi_device_id lps0_device_ids[] = {
- #define ACPI_LPS0_SCREEN_ON 4
- #define ACPI_LPS0_ENTRY 5
- #define ACPI_LPS0_EXIT 6
-+#define ACPI_LPS0_MS_ENTRY 7
-+#define ACPI_LPS0_MS_EXIT 8
-
- /* AMD */
- #define ACPI_LPS0_DSM_UUID_AMD "e3f32452-febc-43ce-9039-932122d37721"
-@@ -49,7 +54,10 @@ static const struct acpi_device_id lps0_device_ids[] = {
-
- static acpi_handle lps0_device_handle;
- static guid_t lps0_dsm_guid;
--static char lps0_dsm_func_mask;
-+static int lps0_dsm_func_mask;
-+
-+static guid_t lps0_dsm_guid_microsoft;
-+static int lps0_dsm_func_mask_microsoft;
-
- /* Device constraint entry structure */
- struct lpi_device_info {
-@@ -70,15 +78,7 @@ struct lpi_constraints {
- int min_dstate;
- };
-
--/* AMD */
--/* Device constraint entry structure */
--struct lpi_device_info_amd {
-- int revision;
-- int count;
-- union acpi_object *package;
--};
--
--/* Constraint package structure */
-+/* AMD Constraint package structure */
- struct lpi_device_constraint_amd {
- char *name;
- int enabled;
-@@ -96,15 +96,15 @@ static void lpi_device_get_constraints_amd(void)
- int i, j, k;
-
- out_obj = acpi_evaluate_dsm_typed(lps0_device_handle, &lps0_dsm_guid,
-- 1, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
-+ rev_id, ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
- NULL, ACPI_TYPE_PACKAGE);
-
-- if (!out_obj)
-- return;
--
- acpi_handle_debug(lps0_device_handle, "_DSM function 1 eval %s\n",
- out_obj ? "successful" : "failed");
-
-+ if (!out_obj)
-+ return;
-+
- for (i = 0; i < out_obj->package.count; i++) {
- union acpi_object *package = &out_obj->package.elements[i];
-
-@@ -317,14 +317,15 @@ static void lpi_check_constraints(void)
- }
- }
-
--static void acpi_sleep_run_lps0_dsm(unsigned int func)
-+static void acpi_sleep_run_lps0_dsm(unsigned int func, unsigned int func_mask, guid_t dsm_guid)
- {
- union acpi_object *out_obj;
-
-- if (!(lps0_dsm_func_mask & (1 << func)))
-+ if (!(func_mask & (1 << func)))
- return;
-
-- out_obj = acpi_evaluate_dsm(lps0_device_handle, &lps0_dsm_guid, rev_id, func, NULL);
-+ out_obj = acpi_evaluate_dsm(lps0_device_handle, &dsm_guid,
-+ rev_id, func, NULL);
- ACPI_FREE(out_obj);
-
- acpi_handle_debug(lps0_device_handle, "_DSM function %u evaluation %s\n",
-@@ -336,11 +337,33 @@ static bool acpi_s2idle_vendor_amd(void)
- return boot_cpu_data.x86_vendor == X86_VENDOR_AMD;
- }
-
-+static int validate_dsm(acpi_handle handle, const char *uuid, int rev, guid_t *dsm_guid)
-+{
-+ union acpi_object *obj;
-+ int ret = -EINVAL;
-+
-+ guid_parse(uuid, dsm_guid);
-+ obj = acpi_evaluate_dsm(handle, dsm_guid, rev, 0, NULL);
-+
-+ /* Check if the _DSM is present and as expected. */
-+ if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length == 0 ||
-+ obj->buffer.length > sizeof(u32)) {
-+ acpi_handle_debug(handle,
-+ "_DSM UUID %s rev %d function 0 evaluation failed\n", uuid, rev);
-+ goto out;
-+ }
-+
-+ ret = *(int *)obj->buffer.pointer;
-+ acpi_handle_debug(handle, "_DSM UUID %s rev %d function mask: 0x%x\n", uuid, rev, ret);
-+
-+out:
-+ ACPI_FREE(obj);
-+ return ret;
-+}
-+
- static int lps0_device_attach(struct acpi_device *adev,
- const struct acpi_device_id *not_used)
- {
-- union acpi_object *out_obj;
--
- if (lps0_device_handle)
- return 0;
-
-@@ -348,28 +371,36 @@ static int lps0_device_attach(struct acpi_device *adev,
- return 0;
-
- if (acpi_s2idle_vendor_amd()) {
-- guid_parse(ACPI_LPS0_DSM_UUID_AMD, &lps0_dsm_guid);
-- out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 0, 0, NULL);
-+ /* AMD0004, AMDI0005:
-+ * - Should use rev_id 0x0
-+ * - function mask > 0x3: Should use AMD method, but has off by one bug
-+ * - function mask = 0x3: Should use Microsoft method
-+ * AMDI0006:
-+ * - should use rev_id 0x0
-+ * - function mask = 0x3: Should use Microsoft method
-+ */
-+ const char *hid = acpi_device_hid(adev);
- rev_id = 0;
-+ lps0_dsm_func_mask = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID_AMD, rev_id, &lps0_dsm_guid);
-+ lps0_dsm_func_mask_microsoft = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID_MICROSOFT, rev_id,
-+ &lps0_dsm_guid_microsoft);
-+ if (lps0_dsm_func_mask > 0x3 && (!strcmp(hid, "AMD0004") ||
-+ !strcmp(hid, "AMDI0005"))) {
-+ lps0_dsm_func_mask = (lps0_dsm_func_mask << 1) | 0x1;
-+ acpi_handle_debug(adev->handle, "_DSM UUID %s: Adjusted function mask: 0x%x\n",
-+ ACPI_LPS0_DSM_UUID_AMD, lps0_dsm_func_mask);
-+ }
- } else {
-- guid_parse(ACPI_LPS0_DSM_UUID, &lps0_dsm_guid);
-- out_obj = acpi_evaluate_dsm(adev->handle, &lps0_dsm_guid, 1, 0, NULL);
- rev_id = 1;
-+ lps0_dsm_func_mask = validate_dsm(adev->handle,
-+ ACPI_LPS0_DSM_UUID, rev_id, &lps0_dsm_guid);
-+ lps0_dsm_func_mask_microsoft = -EINVAL;
- }
-
-- /* Check if the _DSM is present and as expected. */
-- if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER) {
-- acpi_handle_debug(adev->handle,
-- "_DSM function 0 evaluation failed\n");
-- return 0;
-- }
--
-- lps0_dsm_func_mask = *(char *)out_obj->buffer.pointer;
--
-- ACPI_FREE(out_obj);
--
-- acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
-- lps0_dsm_func_mask);
-+ if (lps0_dsm_func_mask < 0 && lps0_dsm_func_mask_microsoft < 0)
-+ return 0; //function evaluation failed
-
- lps0_device_handle = adev->handle;
-
-@@ -386,11 +417,15 @@ static int lps0_device_attach(struct acpi_device *adev,
- mem_sleep_current = PM_SUSPEND_TO_IDLE;
-
- /*
-- * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the
-- * EC GPE to be enabled while suspended for certain wakeup devices to
-- * work, so mark it as wakeup-capable.
-+ * Some Intel based LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U don't
-+ * use intel-hid or intel-vbtn but require the EC GPE to be enabled while
-+ * suspended for certain wakeup devices to work, so mark it as wakeup-capable.
-+ *
-+ * Only enable on !AMD as enabling this universally causes problems for a number
-+ * of AMD based systems.
- */
-- acpi_ec_mark_gpe_for_wake();
-+ if (!acpi_s2idle_vendor_amd())
-+ acpi_ec_mark_gpe_for_wake();
-
- return 0;
- }
-@@ -408,14 +443,30 @@ int acpi_s2idle_prepare_late(void)
- if (pm_debug_messages_on)
- lpi_check_constraints();
-
-- if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD);
-- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
-- }
-+ /* screen off */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_SCREEN_OFF_AMD :
-+ ACPI_LPS0_SCREEN_OFF,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-
-+ if (lps0_dsm_func_mask_microsoft > 0)
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+
-+ /* lps0 entry */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_ENTRY_AMD :
-+ ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ if (lps0_dsm_func_mask_microsoft > 0) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ /* modern standby entry */
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ }
- return 0;
- }
-
-@@ -424,13 +475,30 @@ void acpi_s2idle_restore_early(void)
- if (!lps0_device_handle || sleep_no_lps0)
- return;
-
-- if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT_AMD);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD);
-- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
-- }
-+ /* mdoern standby exit */
-+ if (lps0_dsm_func_mask_microsoft > 0)
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+
-+ /* lps0 exit */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_EXIT_AMD :
-+ ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ if (lps0_dsm_func_mask_microsoft > 0)
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+
-+ /* screen on */
-+ if (lps0_dsm_func_mask_microsoft > 0)
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_SCREEN_ON_AMD :
-+ ACPI_LPS0_SCREEN_ON,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- }
-
- static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
-diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
-index bdc1ba00aee9..f22f23933063 100644
---- a/drivers/acpi/x86/utils.c
-+++ b/drivers/acpi/x86/utils.c
-@@ -135,3 +135,28 @@ bool acpi_device_always_present(struct acpi_device *adev)
-
- return ret;
- }
-+
-+/*
-+ * AMD systems from Renoir and Lucienne *require* that the NVME controller
-+ * is put into D3 over a Modern Standby / suspend-to-idle cycle.
-+ *
-+ * This is "typically" accomplished using the `StorageD3Enable`
-+ * property in the _DSD that is checked via the `acpi_storage_d3` function
-+ * but this property was introduced after many of these systems launched
-+ * and most OEM systems don't have it in their BIOS.
-+ *
-+ * The Microsoft documentation for StorageD3Enable mentioned that Windows has
-+ * a hardcoded allowlist for D3 support, which was used for these platforms.
-+ *
-+ * This allows quirking on Linux in a similar fashion.
-+ */
-+static const struct x86_cpu_id storage_d3_cpu_ids[] = {
-+ X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 96, NULL), /* Renoir */
-+ X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 104, NULL), /* Lucienne */
-+ {}
-+};
-+
-+bool force_storage_d3(void)
-+{
-+ return x86_match_cpu(storage_d3_cpu_ids);
-+}
-diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
-index d963f25fc7ae..66455e2261d0 100644
---- a/drivers/nvme/host/pci.c
-+++ b/drivers/nvme/host/pci.c
-@@ -2880,32 +2880,6 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
- return 0;
- }
-
--#ifdef CONFIG_ACPI
--static bool nvme_acpi_storage_d3(struct pci_dev *dev)
--{
-- struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
-- u8 val;
--
-- /*
-- * Look for _DSD property specifying that the storage device on the port
-- * must use D3 to support deep platform power savings during
-- * suspend-to-idle.
-- */
--
-- if (!adev)
-- return false;
-- if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
-- &val))
-- return false;
-- return val == 1;
--}
--#else
--static inline bool nvme_acpi_storage_d3(struct pci_dev *dev)
--{
-- return false;
--}
--#endif /* CONFIG_ACPI */
--
- static void nvme_async_probe(void *data, async_cookie_t cookie)
- {
- struct nvme_dev *dev = data;
-@@ -2955,7 +2929,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-
- quirks |= check_vendor_combination_bug(pdev);
-
-- if (!noacpi && nvme_acpi_storage_d3(pdev)) {
-+ if (!noacpi && acpi_storage_d3(&pdev->dev)) {
- /*
- * Some systems use a bios work around to ask for D3 on
- * platforms that support kernel managed suspend.
-diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
-index c5950a3b4e4c..d19974aceb2e 100644
---- a/drivers/pinctrl/pinctrl-amd.c
-+++ b/drivers/pinctrl/pinctrl-amd.c
-@@ -438,6 +438,38 @@ static void amd_gpio_irq_unmask(struct irq_data *d)
- raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
- }
-
-+static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-+{
-+ u32 pin_reg;
-+ unsigned long flags;
-+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-+ struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
-+ u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3);
-+ int err;
-+
-+ raw_spin_lock_irqsave(&gpio_dev->lock, flags);
-+ pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
-+
-+ if (on)
-+ pin_reg |= wake_mask;
-+ else
-+ pin_reg &= ~wake_mask;
-+
-+ writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
-+ raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
-+
-+ if (on)
-+ err = enable_irq_wake(gpio_dev->irq);
-+ else
-+ err = disable_irq_wake(gpio_dev->irq);
-+
-+ if (err)
-+ dev_err(&gpio_dev->pdev->dev, "failed to %s wake-up interrupt\n",
-+ on ? "enable" : "disable");
-+
-+ return 0;
-+}
-+
- static void amd_gpio_irq_eoi(struct irq_data *d)
- {
- u32 reg;
-@@ -552,9 +584,16 @@ static struct irq_chip amd_gpio_irqchip = {
- .irq_disable = amd_gpio_irq_disable,
- .irq_mask = amd_gpio_irq_mask,
- .irq_unmask = amd_gpio_irq_unmask,
-+ .irq_set_wake = amd_gpio_irq_set_wake,
- .irq_eoi = amd_gpio_irq_eoi,
- .irq_set_type = amd_gpio_irq_set_type,
-- .flags = IRQCHIP_SKIP_SET_WAKE,
-+ /*
-+ * We need to set IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND so that a wake event
-+ * also generates an IRQ. We need the IRQ so the irq_handler can clear
-+ * the wake event. Otherwise the wake event will never clear and
-+ * prevent the system from suspending.
-+ */
-+ .flags = IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,
- };
-
- #define PIN_IRQ_PENDING (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF))
-@@ -875,7 +914,6 @@ static struct pinctrl_desc amd_pinctrl_desc = {
- static int amd_gpio_probe(struct platform_device *pdev)
- {
- int ret = 0;
-- int irq_base;
- struct resource *res;
- struct amd_gpio *gpio_dev;
- struct gpio_irq_chip *girq;
-@@ -898,9 +936,9 @@ static int amd_gpio_probe(struct platform_device *pdev)
- if (!gpio_dev->base)
- return -ENOMEM;
-
-- irq_base = platform_get_irq(pdev, 0);
-- if (irq_base < 0)
-- return irq_base;
-+ gpio_dev->irq = platform_get_irq(pdev, 0);
-+ if (gpio_dev->irq < 0)
-+ return gpio_dev->irq;
-
- #ifdef CONFIG_PM_SLEEP
- gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins,
-@@ -960,7 +998,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
- goto out2;
- }
-
-- ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler,
-+ ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler,
- IRQF_SHARED, KBUILD_MODNAME, gpio_dev);
- if (ret)
- goto out2;
-diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
-index 95e763424042..1d4317073654 100644
---- a/drivers/pinctrl/pinctrl-amd.h
-+++ b/drivers/pinctrl/pinctrl-amd.h
-@@ -98,6 +98,7 @@ struct amd_gpio {
- struct resource *res;
- struct platform_device *pdev;
- u32 *saved_regs;
-+ int irq;
- };
-
- /* KERNCZ configuration*/
-diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
-index ca95c2a52e26..663a4ca0580d 100644
---- a/drivers/platform/x86/amd-pmc.c
-+++ b/drivers/platform/x86/amd-pmc.c
-@@ -46,26 +46,70 @@
- #define AMD_PMC_RESULT_CMD_UNKNOWN 0xFE
- #define AMD_PMC_RESULT_FAILED 0xFF
-
-+/* FCH SSC Registers */
-+#define FCH_S0I3_ENTRY_TIME_L_OFFSET 0x30
-+#define FCH_S0I3_ENTRY_TIME_H_OFFSET 0x34
-+#define FCH_S0I3_EXIT_TIME_L_OFFSET 0x38
-+#define FCH_S0I3_EXIT_TIME_H_OFFSET 0x3C
-+#define FCH_SSC_MAPPING_SIZE 0x800
-+#define FCH_BASE_PHY_ADDR_LOW 0xFED81100
-+#define FCH_BASE_PHY_ADDR_HIGH 0x00000000
-+
-+/* SMU Message Definations */
-+#define SMU_MSG_GETSMUVERSION 0x02
-+#define SMU_MSG_LOG_GETDRAM_ADDR_HI 0x04
-+#define SMU_MSG_LOG_GETDRAM_ADDR_LO 0x05
-+#define SMU_MSG_LOG_START 0x06
-+#define SMU_MSG_LOG_RESET 0x07
-+#define SMU_MSG_LOG_DUMP_DATA 0x08
-+#define SMU_MSG_GET_SUP_CONSTRAINTS 0x09
- /* List of supported CPU ids */
- #define AMD_CPU_ID_RV 0x15D0
- #define AMD_CPU_ID_RN 0x1630
- #define AMD_CPU_ID_PCO AMD_CPU_ID_RV
- #define AMD_CPU_ID_CZN AMD_CPU_ID_RN
-+#define AMD_CPU_ID_YC 0x14B5
-
- #define PMC_MSG_DELAY_MIN_US 100
- #define RESPONSE_REGISTER_LOOP_MAX 200
-
-+#define SOC_SUBSYSTEM_IP_MAX 12
-+#define DELAY_MIN_US 2000
-+#define DELAY_MAX_US 3000
- enum amd_pmc_def {
- MSG_TEST = 0x01,
- MSG_OS_HINT_PCO,
- MSG_OS_HINT_RN,
- };
-
-+struct amd_pmc_bit_map {
-+ const char *name;
-+ u32 bit_mask;
-+};
-+
-+static const struct amd_pmc_bit_map soc15_ip_blk[] = {
-+ {"DISPLAY", BIT(0)},
-+ {"CPU", BIT(1)},
-+ {"GFX", BIT(2)},
-+ {"VDD", BIT(3)},
-+ {"ACP", BIT(4)},
-+ {"VCN", BIT(5)},
-+ {"ISP", BIT(6)},
-+ {"NBIO", BIT(7)},
-+ {"DF", BIT(8)},
-+ {"USB0", BIT(9)},
-+ {"USB1", BIT(10)},
-+ {"LAPIC", BIT(11)},
-+ {}
-+};
-+
- struct amd_pmc_dev {
- void __iomem *regbase;
-- void __iomem *smu_base;
-+ void __iomem *smu_virt_addr;
-+ void __iomem *fch_virt_addr;
- u32 base_addr;
- u32 cpu_id;
-+ u32 active_ips;
- struct device *dev;
- struct mutex lock; /* generic mutex lock */
- #if IS_ENABLED(CONFIG_DEBUG_FS)
-@@ -74,6 +118,7 @@ struct amd_pmc_dev {
- };
-
- static struct amd_pmc_dev pmc;
-+static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg, bool ret);
-
- static inline u32 amd_pmc_reg_read(struct amd_pmc_dev *dev, int reg_offset)
- {
-@@ -85,13 +130,76 @@ static inline void amd_pmc_reg_write(struct amd_pmc_dev *dev, int reg_offset, u3
- iowrite32(val, dev->regbase + reg_offset);
- }
-
-+struct smu_metrics {
-+ u32 table_version;
-+ u32 hint_count;
-+ u32 s0i3_cyclecount;
-+ u32 timein_s0i2;
-+ u64 timeentering_s0i3_lastcapture;
-+ u64 timeentering_s0i3_totaltime;
-+ u64 timeto_resume_to_os_lastcapture;
-+ u64 timeto_resume_to_os_totaltime;
-+ u64 timein_s0i3_lastcapture;
-+ u64 timein_s0i3_totaltime;
-+ u64 timein_swdrips_lastcapture;
-+ u64 timein_swdrips_totaltime;
-+ u64 timecondition_notmet_lastcapture[SOC_SUBSYSTEM_IP_MAX];
-+ u64 timecondition_notmet_totaltime[SOC_SUBSYSTEM_IP_MAX];
-+} __packed;
-+
- #ifdef CONFIG_DEBUG_FS
- static int smu_fw_info_show(struct seq_file *s, void *unused)
- {
-+ struct amd_pmc_dev *dev = s->private;
-+ struct smu_metrics table;
-+ int idx;
-+
-+ if (dev->cpu_id == AMD_CPU_ID_PCO)
-+ return -EINVAL;
-+
-+ memcpy_fromio(&table, dev->smu_virt_addr, sizeof(struct smu_metrics));
-+
-+ seq_puts(s, "\n=== SMU Statistics ===\n");
-+ seq_printf(s, "Table Version: %d\n", table.table_version);
-+ seq_printf(s, "Hint Count: %d\n", table.hint_count);
-+ seq_printf(s, "S0i3 Cycle Count: %d\n", table.s0i3_cyclecount);
-+ seq_printf(s, "Time (in us) to S0i3: %lld\n", table.timeentering_s0i3_lastcapture);
-+ seq_printf(s, "Time (in us) in S0i3: %lld\n", table.timein_s0i3_lastcapture);
-+
-+ seq_puts(s, "\n=== Active time (in us) ===\n");
-+ for (idx = 0 ; idx < SOC_SUBSYSTEM_IP_MAX ; idx++) {
-+ if (soc15_ip_blk[idx].bit_mask & dev->active_ips)
-+ seq_printf(s, "%-8s : %lld\n", soc15_ip_blk[idx].name,
-+ table.timecondition_notmet_lastcapture[idx]);
-+ }
-+
- return 0;
- }
- DEFINE_SHOW_ATTRIBUTE(smu_fw_info);
-
-+static int s0ix_stats_show(struct seq_file *s, void *unused)
-+{
-+ struct amd_pmc_dev *dev = s->private;
-+ u64 entry_time, exit_time, residency;
-+
-+ entry_time = ioread32(dev->fch_virt_addr + FCH_S0I3_ENTRY_TIME_H_OFFSET);
-+ entry_time = entry_time << 32 | ioread32(dev->fch_virt_addr + FCH_S0I3_ENTRY_TIME_L_OFFSET);
-+
-+ exit_time = ioread32(dev->fch_virt_addr + FCH_S0I3_EXIT_TIME_H_OFFSET);
-+ exit_time = exit_time << 32 | ioread32(dev->fch_virt_addr + FCH_S0I3_EXIT_TIME_L_OFFSET);
-+
-+ /* It's in 48MHz. We need to convert it */
-+ residency = (exit_time - entry_time) / 48;
-+
-+ seq_puts(s, "=== S0ix statistics ===\n");
-+ seq_printf(s, "S0ix Entry Time: %lld\n", entry_time);
-+ seq_printf(s, "S0ix Exit Time: %lld\n", exit_time);
-+ seq_printf(s, "Residency Time: %lld\n", residency);
-+
-+ return 0;
-+}
-+DEFINE_SHOW_ATTRIBUTE(s0ix_stats);
-+
- static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
- {
- debugfs_remove_recursive(dev->dbgfs_dir);
-@@ -102,6 +210,8 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
- dev->dbgfs_dir = debugfs_create_dir("amd_pmc", NULL);
- debugfs_create_file("smu_fw_info", 0644, dev->dbgfs_dir, dev,
- &smu_fw_info_fops);
-+ debugfs_create_file("s0ix_stats", 0644, dev->dbgfs_dir, dev,
-+ &s0ix_stats_fops);
- }
- #else
- static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
-@@ -113,6 +223,32 @@ static inline void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
- }
- #endif /* CONFIG_DEBUG_FS */
-
-+static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
-+{
-+ u32 phys_addr_low, phys_addr_hi;
-+ u64 smu_phys_addr;
-+
-+ if (dev->cpu_id == AMD_CPU_ID_PCO)
-+ return -EINVAL;
-+
-+ /* Get Active devices list from SMU */
-+ amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, 1);
-+
-+ /* Get dram address */
-+ amd_pmc_send_cmd(dev, 0, &phys_addr_low, SMU_MSG_LOG_GETDRAM_ADDR_LO, 1);
-+ amd_pmc_send_cmd(dev, 0, &phys_addr_hi, SMU_MSG_LOG_GETDRAM_ADDR_HI, 1);
-+ smu_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
-+
-+ dev->smu_virt_addr = devm_ioremap(dev->dev, smu_phys_addr, sizeof(struct smu_metrics));
-+ if (!dev->smu_virt_addr)
-+ return -ENOMEM;
-+
-+ /* Start the logging */
-+ amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, 0);
-+
-+ return 0;
-+}
-+
- static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
- {
- u32 value;
-@@ -127,10 +263,9 @@ static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
- dev_dbg(dev->dev, "AMD_PMC_REGISTER_MESSAGE:%x\n", value);
- }
-
--static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
-+static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg, bool ret)
- {
- int rc;
-- u8 msg;
- u32 val;
-
- mutex_lock(&dev->lock);
-@@ -150,8 +285,8 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_ARGUMENT, set);
-
- /* Write message ID to message ID register */
-- msg = (dev->cpu_id == AMD_CPU_ID_RN) ? MSG_OS_HINT_RN : MSG_OS_HINT_PCO;
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_MESSAGE, msg);
-+
- /* Wait until we get a valid response */
- rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
- val, val != 0, PMC_MSG_DELAY_MIN_US,
-@@ -163,6 +298,11 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
-
- switch (val) {
- case AMD_PMC_RESULT_OK:
-+ if (ret) {
-+ /* PMFW may take longer time to return back the data */
-+ usleep_range(DELAY_MIN_US, 10 * DELAY_MAX_US);
-+ *data = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_ARGUMENT);
-+ }
- break;
- case AMD_PMC_RESULT_CMD_REJECT_BUSY:
- dev_err(dev->dev, "SMU not ready. err: 0x%x\n", val);
-@@ -182,32 +322,54 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set)
-
- out_unlock:
- mutex_unlock(&dev->lock);
-+ amd_pmc_dump_registers(dev);
- return rc;
- }
-
-+static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev)
-+{
-+ switch (dev->cpu_id) {
-+ case AMD_CPU_ID_PCO:
-+ return MSG_OS_HINT_PCO;
-+ case AMD_CPU_ID_RN:
-+ case AMD_CPU_ID_YC:
-+ return MSG_OS_HINT_RN;
-+ }
-+ return -EINVAL;
-+}
-+
- static int __maybe_unused amd_pmc_suspend(struct device *dev)
- {
- struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
- int rc;
-+ u8 msg;
-
-- rc = amd_pmc_send_cmd(pdev, 1);
-+ /* Reset and Start SMU logging - to monitor the s0i3 stats */
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_RESET, 0);
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_START, 0);
-+
-+ msg = amd_pmc_get_os_hint(pdev);
-+ rc = amd_pmc_send_cmd(pdev, 1, NULL, msg, 0);
- if (rc)
- dev_err(pdev->dev, "suspend failed\n");
-
-- amd_pmc_dump_registers(pdev);
-- return 0;
-+ return rc;
- }
-
- static int __maybe_unused amd_pmc_resume(struct device *dev)
- {
- struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
- int rc;
-+ u8 msg;
-
-- rc = amd_pmc_send_cmd(pdev, 0);
-+ /* Let SMU know that we are looking for stats */
-+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0);
-+
-+ msg = amd_pmc_get_os_hint(pdev);
-+ rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, 0);
- if (rc)
- dev_err(pdev->dev, "resume failed\n");
-
-- amd_pmc_dump_registers(pdev);
- return 0;
- }
-
-@@ -216,6 +378,7 @@ static const struct dev_pm_ops amd_pmc_pm_ops = {
- };
-
- static const struct pci_device_id pmc_pci_ids[] = {
-+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_YC) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_CZN) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RN) },
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) },
-@@ -227,9 +390,8 @@ static int amd_pmc_probe(struct platform_device *pdev)
- {
- struct amd_pmc_dev *dev = &pmc;
- struct pci_dev *rdev;
-- u32 base_addr_lo;
-- u32 base_addr_hi;
-- u64 base_addr;
-+ u32 base_addr_lo, base_addr_hi;
-+ u64 base_addr, fch_phys_addr;
- int err;
- u32 val;
-
-@@ -279,9 +441,21 @@ static int amd_pmc_probe(struct platform_device *pdev)
- if (!dev->regbase)
- return -ENOMEM;
-
-- amd_pmc_dump_registers(dev);
--
- mutex_init(&dev->lock);
-+
-+ /* Use FCH registers to get the S0ix stats */
-+ base_addr_lo = FCH_BASE_PHY_ADDR_LOW;
-+ base_addr_hi = FCH_BASE_PHY_ADDR_HIGH;
-+ fch_phys_addr = ((u64)base_addr_hi << 32 | base_addr_lo);
-+ dev->fch_virt_addr = devm_ioremap(dev->dev, fch_phys_addr, FCH_SSC_MAPPING_SIZE);
-+ if (!dev->fch_virt_addr)
-+ return -ENOMEM;
-+
-+ /* Use SMU to get the s0i3 debug stats */
-+ err = amd_pmc_setup_smu_logging(dev);
-+ if (err)
-+ dev_err(dev->dev, "SMU debugging info not supported on this platform\n");
-+
- platform_set_drvdata(pdev, dev);
- amd_pmc_dbgfs_register(dev);
- return 0;
-@@ -298,6 +472,8 @@ static int amd_pmc_remove(struct platform_device *pdev)
-
- static const struct acpi_device_id amd_pmc_acpi_ids[] = {
- {"AMDI0005", 0},
-+ {"AMDI0006", 0},
-+ {"AMDI0007", 0},
- {"AMD0004", 0},
- { }
- };
-diff --git a/include/linux/acpi.h b/include/linux/acpi.h
-index c60745f657e9..dd0dafd21e33 100644
---- a/include/linux/acpi.h
-+++ b/include/linux/acpi.h
-@@ -1004,6 +1004,7 @@ int acpi_dev_resume(struct device *dev);
- int acpi_subsys_runtime_suspend(struct device *dev);
- int acpi_subsys_runtime_resume(struct device *dev);
- int acpi_dev_pm_attach(struct device *dev, bool power_on);
-+bool acpi_storage_d3(struct device *dev);
- #else
- static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
- static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
-@@ -1011,6 +1012,10 @@ static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
- {
- return 0;
- }
-+static inline bool acpi_storage_d3(struct device *dev)
-+{
-+ return false;
-+}
- #endif
-
- #if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP)
---
-2.33.0
-
diff --git a/sys-kernel_arch-sources-g14_files-9001-v5.14.1-s0ix-patch-2021-09-03.patch b/sys-kernel_arch-sources-g14_files-9001-v5.14.1-s0ix-patch-2021-09-03.patch
deleted file mode 100644
index 21d22c496a3a..000000000000
--- a/sys-kernel_arch-sources-g14_files-9001-v5.14.1-s0ix-patch-2021-09-03.patch
+++ /dev/null
@@ -1,766 +0,0 @@
-From 20d622ad8d682cdfa8d2db3aac2e2940fb6b7f37 Mon Sep 17 00:00:00 2001
-From: Scott B <arglebargle@arglebargle.dev>
-Date: Fri, 3 Sep 2021 06:18:48 -0700
-Subject: [PATCH] v5.14.1 s0ix patch 2021-09-03
-
-Squashed commit of the following:
-
-commit 59a128d473a903fc256ca20b05a83aedae570fef
-Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-Date: Tue Aug 31 17:36:12 2021 +0530
-
- pinctrl: amd: Add irq field data
-
- pinctrl_amd use gpiochip_get_data() to get their local state containers
- back from the gpiochip passed as amd_gpio chip data.
-
- Hence added irq field data to get directly using amd_gpio chip data.
-
- Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-
-commit d48c21c63803949bb4655e93b0fb064d56db5682
-Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-Date: Tue Aug 31 17:36:13 2021 +0530
-
- pinctrl: amd: Handle wake-up interrupt
-
- Enable/disable power management wakeup mode, which is disabled by
- default. enable_irq_wake enables wakes the system from sleep.
-
- Hence added enable/disable irq_wake to handle wake-up interrupt.
-
- Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
-
-commit 2219e4d484f61a7234a1744fe7f44255850264fb
-Author: Mario Limonciello <mario.limonciello@amd.com>
-Date: Tue Aug 31 11:36:19 2021 -0500
-
- ACPI: PM: s2idle: Run both AMD and Microsoft methods if both are supported
-
- It was reported that on "HP ENVY x360" that power LED does not come back
- on, certain keys like brightness controls do not work, and the fan never
- spins up, even under load.
-
- In analysis of the SSDT it's clear that the Microsoft UUID doesn't provide
- functional support, but rather the AMD UUID should be supporting this
- system.
-
- Because this is a gap in the expected logic, confirmation with internal
- team is that AMD uPEP *does* run even when Microsoft UUID present, but
- most OEM systems have adopted value of "0x3" for supported functions and
- hence nothing runs.
-
- Henceforth add support for running both Microsoft and AMD methods. This
- approach will also allow the same logic on Intel systems if desired at a
- future time as well by pulling the evaluation of
- `lps0_dsm_func_mask_microsoft` out of the if block for
- `acpi_s2idle_vendor_amd`.
-
- BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1691
- Reported-by: Maxwell Beck <max@ryt.one>
- Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
-
-commit 290e605b95a082a6cef455fcb89e263271db9ee5
-Author: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Wed Jul 21 18:10:28 2021 -0700
-
- amd-pmc smu register dump for diagnostics
-
- patch this per Mario's request:
- https://gitlab.freedesktop.org/drm/amd/-/issues/1629#note_1000332
-
-commit 69a3e85d633dbdac57017feb9a059b97c8937034
-Author: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Tue Jul 20 23:33:01 2021 -0700
-
- drm/amd/pm: Add information about SMU12 firmware version
-
- hacky manual import of: https://lists.freedesktop.org/archives/amd-gfx/2021-July/066835.html
-
- This information is useful for root causing issues with S0ix.
-
- Signed-off-by: Mario Limonciello <mario.limonciello at amd.com>
-
-commit 24c0c263a463b39c74216a640873fd2060d82156
-Author: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Tue Jul 20 23:31:31 2021 -0700
-
- drm/amd/pm: Add information about SMU11 firmware version
-
- hacky manual import of: https://lists.freedesktop.org/archives/amd-gfx/2021-July/066834.html
-
- This information is useful for root causing issues with S0ix.
-
- Signed-off-by: Mario Limonciello <mario.limonciello at amd.com>
-
-commit 1406ea8541b9148c692abd0b97de373df3db413f
-Author: Guchun Chen <guchun.chen@amd.com>
-Date: Thu Jul 22 17:20:21 2021 +0800
-
- drm/amdgpu: fix build error
-
- drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu_cmn.c: In function 'smu_cmn_send_msg_without_waiting':
- drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu_cmn.c:259:15: error: 'struct amdgpu_device' has no member named 'in_pci_err_recovery'
- if (smu->adev->in_pci_err_recovery)
- ^~
- CC [M] drivers/staging/rtl8192u/ieee80211/ieee80211_tx.o
- scripts/Makefile.build:272: recipe for target 'drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu_cmn.o' failed
- make[7]: *** [drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu_cmn.o] Error 1
- scripts/Makefile.build:515: recipe for target 'drivers/gpu/drm/amd/amdgpu' failed
- make[6]: *** [drivers/gpu/drm/amd/amdgpu] Error 2
- make[6]: *** Waiting for unfinished jobs....
-
- Fixes: e070ba49f3a7 drm/amd/pm: Fix a bug communicating with the SMU (v5)
- Signed-off-by: Guchun Chen <guchun.chen@amd.com>
- Reviewed-by: Luben Tuikov <luben.tuikov@amd.com>
-
-commit ec7f3b175ad85caf3289506ae95b27ddb106416e
-Author: Luben Tuikov <luben.tuikov@amd.com>
-Date: Fri Jul 9 23:33:11 2021 -0400
-
- drm/amd/pm: Fix a bug communicating with the SMU (v5)
-
- This fixes a bug which if we probe a non-existing
- I2C device, and the SMU returns 0xFF, from then on
- we can never communicate with the SMU, because the
- code before this patch reads and interprets 0xFF
- as a terminal error, and thus we never write 0
- into register 90 to clear the status (and
- subsequently send a new command to the SMU.)
-
- It is not an error that the SMU returns status
- 0xFF. This means that the SMU executed the last
- command successfully (execution status), but the
- command result is an error of some sort (execution
- result), depending on what the command was.
-
- When doing a status check of the SMU, before we
- send a new command, the only status which
- precludes us from sending a new command is 0--the
- SMU hasn't finished executing a previous command,
- and 0xFC--the SMU is busy.
-
- This bug was seen as the following line in the
- kernel log,
-
- amdgpu: Msg issuing pre-check failed(0xff) and SMU may be not in the right state!
-
- when subsequent SMU commands, not necessarily
- related to I2C, were sent to the SMU.
-
- This patch fixes this bug.
-
- v2: Add a comment to the description of
- __smu_cmn_poll_stat() to explain why we're NOT
- defining the SMU FW return codes as macros, but
- are instead hard-coding them. Such a change, can
- be followed up by a subsequent patch.
-
- v3: The changes are,
- a) Add comments to break labels in
- __smu_cmn_reg2errno().
-
- b) When an unknown/unspecified/undefined result is
- returned back from the SMU, map that to
- -EREMOTEIO, to distinguish failure at the SMU
- FW.
-
- c) Add kernel-doc to
- smu_cmn_send_msg_without_waiting(),
- smu_cmn_wait_for_response(),
- smu_cmn_send_smc_msg_with_param().
-
- d) In smu_cmn_send_smc_msg_with_param(), since we
- wait for completion of the command, if the
- result of the completion is
- undefined/unknown/unspecified, we print that to
- the kernel log.
-
- v4: a) Add macros as requested, though redundant, to
- be removed when SMU consolidates for all
- ASICs--see comment in code.
- b) Get out if the SMU code is unknown.
-
- v5: Rename the macro names.
-
- Cc: Alex Deucher <Alexander.Deucher@amd.com>
- Cc: Evan Quan <evan.quan@amd.com>
- Cc: Lijo Lazar <Lijo.Lazar@amd.com>
- Fixes: fcb1fe9c9e0031 ("drm/amd/powerplay: pre-check the SMU state before issuing message")
- Signed-off-by: Luben Tuikov <luben.tuikov@amd.com>
- Reviewed-by: Alex Deucher <Alexander.Deucher@amd.com>
----
- drivers/acpi/x86/s2idle.c | 67 ++--
- .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 3 +
- .../gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c | 3 +
- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 290 +++++++++++++++---
- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 3 +-
- drivers/pinctrl/pinctrl-amd.c | 19 +-
- drivers/pinctrl/pinctrl-amd.h | 1 +
- drivers/platform/x86/amd-pmc.c | 1 +
- 8 files changed, 306 insertions(+), 81 deletions(-)
-
-diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
-index 3a308461246a..7d1976e5dd8b 100644
---- a/drivers/acpi/x86/s2idle.c
-+++ b/drivers/acpi/x86/s2idle.c
-@@ -449,25 +449,30 @@ int acpi_s2idle_prepare_late(void)
- if (pm_debug_messages_on)
- lpi_check_constraints();
-
-- if (lps0_dsm_func_mask_microsoft > 0) {
-+ /* screen off */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_SCREEN_OFF_AMD :
-+ ACPI_LPS0_SCREEN_OFF,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+
-+ if (lps0_dsm_func_mask_microsoft > 0)
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+
-+ /* lps0 entry */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_ENTRY_AMD :
-+ ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ if (lps0_dsm_func_mask_microsoft > 0) {
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ /* modern standby entry */
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- } else if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-- lps0_dsm_func_mask, lps0_dsm_guid);
- }
--
- return 0;
- }
-
-@@ -476,24 +481,30 @@ void acpi_s2idle_restore_early(void)
- if (!lps0_device_handle || sleep_no_lps0)
- return;
-
-- if (lps0_dsm_func_mask_microsoft > 0) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ /* mdoern standby exit */
-+ if (lps0_dsm_func_mask_microsoft > 0)
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+
-+ /* lps0 exit */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_EXIT_AMD :
-+ ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ if (lps0_dsm_func_mask_microsoft > 0)
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+
-+ /* screen on */
-+ if (lps0_dsm_func_mask_microsoft > 0)
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- } else if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT_AMD,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- }
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_SCREEN_ON_AMD :
-+ ACPI_LPS0_SCREEN_ON,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- }
-
- static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
-diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
-index 0a5d46ac9ccd..626d7c2bdf66 100644
---- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
-+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
-@@ -272,6 +272,9 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
- break;
- }
-
-+ dev_info(smu->adev->dev, "smu fw reported version = 0x%08x (%d.%d.%d)\n",
-+ smu_version, smu_major, smu_minor, smu_debug);
-+
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
-diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
-index d60b8c5e8715..00ebc381a605 100644
---- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
-+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
-@@ -88,6 +88,9 @@ int smu_v12_0_check_fw_version(struct smu_context *smu)
- if (smu->is_apu)
- adev->pm.fw_version = smu_version;
-
-+ dev_info(smu->adev->dev, "smu fw reported version = 0x%08x (%d.%d.%d)\n",
-+ smu_version, smu_major, smu_minor, smu_debug);
-+
- /*
- * 1. if_version mismatch is not critical as our fw is designed
- * to be backward compatible.
-diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
-index e802f9a95f08..a0e2111eb783 100644
---- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
-+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
-@@ -55,7 +55,7 @@
-
- #undef __SMU_DUMMY_MAP
- #define __SMU_DUMMY_MAP(type) #type
--static const char* __smu_message_names[] = {
-+static const char * const __smu_message_names[] = {
- SMU_MESSAGE_TYPES
- };
-
-@@ -76,55 +76,258 @@ static void smu_cmn_read_arg(struct smu_context *smu,
- *arg = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
- }
-
--int smu_cmn_wait_for_response(struct smu_context *smu)
-+/* Redefine the SMU error codes here.
-+ *
-+ * Note that these definitions are redundant and should be removed
-+ * when the SMU has exported a unified header file containing these
-+ * macros, which header file we can just include and use the SMU's
-+ * macros. At the moment, these error codes are defined by the SMU
-+ * per-ASIC unfortunately, yet we're a one driver for all ASICs.
-+ */
-+#define SMU_RESP_NONE 0
-+#define SMU_RESP_OK 1
-+#define SMU_RESP_CMD_FAIL 0xFF
-+#define SMU_RESP_CMD_UNKNOWN 0xFE
-+#define SMU_RESP_CMD_BAD_PREREQ 0xFD
-+#define SMU_RESP_BUSY_OTHER 0xFC
-+#define SMU_RESP_DEBUG_END 0xFB
-+
-+/**
-+ * __smu_cmn_poll_stat -- poll for a status from the SMU
-+ * smu: a pointer to SMU context
-+ *
-+ * Returns the status of the SMU, which could be,
-+ * 0, the SMU is busy with your previous command;
-+ * 1, execution status: success, execution result: success;
-+ * 0xFF, execution status: success, execution result: failure;
-+ * 0xFE, unknown command;
-+ * 0xFD, valid command, but bad (command) prerequisites;
-+ * 0xFC, the command was rejected as the SMU is busy;
-+ * 0xFB, "SMC_Result_DebugDataDumpEnd".
-+ *
-+ * The values here are not defined by macros, because I'd rather we
-+ * include a single header file which defines them, which is
-+ * maintained by the SMU FW team, so that we're impervious to firmware
-+ * changes. At the moment those values are defined in various header
-+ * files, one for each ASIC, yet here we're a single ASIC-agnostic
-+ * interface. Such a change can be followed-up by a subsequent patch.
-+ */
-+static u32 __smu_cmn_poll_stat(struct smu_context *smu)
- {
- struct amdgpu_device *adev = smu->adev;
-- uint32_t cur_value, i, timeout = adev->usec_timeout * 20;
-+ int timeout = adev->usec_timeout * 20;
-+ u32 reg;
-
-- for (i = 0; i < timeout; i++) {
-- cur_value = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
-- if ((cur_value & MP1_C2PMSG_90__CONTENT_MASK) != 0)
-- return cur_value;
-+ for ( ; timeout > 0; timeout--) {
-+ reg = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
-+ if ((reg & MP1_C2PMSG_90__CONTENT_MASK) != 0)
-+ break;
-
- udelay(1);
- }
-
-- /* timeout means wrong logic */
-- if (i == timeout)
-- return -ETIME;
--
-- return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
-+ return reg;
- }
-
--int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
-- uint16_t msg, uint32_t param)
-+static void __smu_cmn_reg_print_error(struct smu_context *smu,
-+ u32 reg_c2pmsg_90,
-+ int msg_index,
-+ u32 param,
-+ enum smu_message_type msg)
- {
- struct amdgpu_device *adev = smu->adev;
-- int ret;
-+ const char *message = smu_get_message_name(smu, msg);
-
-- ret = smu_cmn_wait_for_response(smu);
-- if (ret != 0x1) {
-- dev_err(adev->dev, "Msg issuing pre-check failed(0x%x) and "
-- "SMU may be not in the right state!\n", ret);
-- if (ret != -ETIME)
-- ret = -EIO;
-- return ret;
-+ switch (reg_c2pmsg_90) {
-+ case SMU_RESP_NONE:
-+ dev_err_ratelimited(adev->dev,
-+ "SMU: I'm not done with your previous command!");
-+ break;
-+ case SMU_RESP_OK:
-+ /* The SMU executed the command. It completed with a
-+ * successful result.
-+ */
-+ break;
-+ case SMU_RESP_CMD_FAIL:
-+ /* The SMU executed the command. It completed with an
-+ * unsuccessful result.
-+ */
-+ break;
-+ case SMU_RESP_CMD_UNKNOWN:
-+ dev_err_ratelimited(adev->dev,
-+ "SMU: unknown command: index:%d param:0x%08X message:%s",
-+ msg_index, param, message);
-+ break;
-+ case SMU_RESP_CMD_BAD_PREREQ:
-+ dev_err_ratelimited(adev->dev,
-+ "SMU: valid command, bad prerequisites: index:%d param:0x%08X message:%s",
-+ msg_index, param, message);
-+ break;
-+ case SMU_RESP_BUSY_OTHER:
-+ dev_err_ratelimited(adev->dev,
-+ "SMU: I'm very busy for your command: index:%d param:0x%08X message:%s",
-+ msg_index, param, message);
-+ break;
-+ case SMU_RESP_DEBUG_END:
-+ dev_err_ratelimited(adev->dev,
-+ "SMU: I'm debugging!");
-+ break;
-+ default:
-+ dev_err_ratelimited(adev->dev,
-+ "SMU: response:0x%08X for index:%d param:0x%08X message:%s?",
-+ reg_c2pmsg_90, msg_index, param, message);
-+ break;
- }
-+}
-+
-+static int __smu_cmn_reg2errno(struct smu_context *smu, u32 reg_c2pmsg_90)
-+{
-+ int res;
-+
-+ switch (reg_c2pmsg_90) {
-+ case SMU_RESP_NONE:
-+ /* The SMU is busy--still executing your command.
-+ */
-+ res = -ETIME;
-+ break;
-+ case SMU_RESP_OK:
-+ res = 0;
-+ break;
-+ case SMU_RESP_CMD_FAIL:
-+ /* Command completed successfully, but the command
-+ * status was failure.
-+ */
-+ res = -EIO;
-+ break;
-+ case SMU_RESP_CMD_UNKNOWN:
-+ /* Unknown command--ignored by the SMU.
-+ */
-+ res = -EOPNOTSUPP;
-+ break;
-+ case SMU_RESP_CMD_BAD_PREREQ:
-+ /* Valid command--bad prerequisites.
-+ */
-+ res = -EINVAL;
-+ break;
-+ case SMU_RESP_BUSY_OTHER:
-+ /* The SMU is busy with other commands. The client
-+ * should retry in 10 us.
-+ */
-+ res = -EBUSY;
-+ break;
-+ default:
-+ /* Unknown or debug response from the SMU.
-+ */
-+ res = -EREMOTEIO;
-+ break;
-+ }
-+
-+ return res;
-+}
-+
-+static void __smu_cmn_send_msg(struct smu_context *smu,
-+ u16 msg,
-+ u32 param)
-+{
-+ struct amdgpu_device *adev = smu->adev;
-
- WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
- WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, param);
- WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
--
-- return 0;
- }
-
-+/**
-+ * smu_cmn_send_msg_without_waiting -- send the message; don't wait for status
-+ * @smu: pointer to an SMU context
-+ * @msg_index: message index
-+ * @param: message parameter to send to the SMU
-+ *
-+ * Send a message to the SMU with the parameter passed. Do not wait
-+ * for status/result of the message, thus the "without_waiting".
-+ *
-+ * Return 0 on success, -errno on error if we weren't able to _send_
-+ * the message for some reason. See __smu_cmn_reg2errno() for details
-+ * of the -errno.
-+ */
-+int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
-+ uint16_t msg_index,
-+ uint32_t param)
-+{
-+ u32 reg;
-+ int res;
-+
-+ if (smu->adev->no_hw_access)
-+ return 0;
-+
-+ mutex_lock(&smu->message_lock);
-+ reg = __smu_cmn_poll_stat(smu);
-+ res = __smu_cmn_reg2errno(smu, reg);
-+ if (reg == SMU_RESP_NONE ||
-+ reg == SMU_RESP_BUSY_OTHER ||
-+ res == -EREMOTEIO)
-+ goto Out;
-+ __smu_cmn_send_msg(smu, msg_index, param);
-+ res = 0;
-+Out:
-+ mutex_unlock(&smu->message_lock);
-+ return res;
-+}
-+
-+/**
-+ * smu_cmn_wait_for_response -- wait for response from the SMU
-+ * @smu: pointer to an SMU context
-+ *
-+ * Wait for status from the SMU.
-+ *
-+ * Return 0 on success, -errno on error, indicating the execution
-+ * status and result of the message being waited for. See
-+ * __smu_cmn_reg2errno() for details of the -errno.
-+ */
-+int smu_cmn_wait_for_response(struct smu_context *smu)
-+{
-+ u32 reg;
-+
-+ reg = __smu_cmn_poll_stat(smu);
-+ return __smu_cmn_reg2errno(smu, reg);
-+}
-+
-+/**
-+ * smu_cmn_send_smc_msg_with_param -- send a message with parameter
-+ * @smu: pointer to an SMU context
-+ * @msg: message to send
-+ * @param: parameter to send to the SMU
-+ * @read_arg: pointer to u32 to return a value from the SMU back
-+ * to the caller
-+ *
-+ * Send the message @msg with parameter @param to the SMU, wait for
-+ * completion of the command, and return back a value from the SMU in
-+ * @read_arg pointer.
-+ *
-+ * Return 0 on success, -errno on error, if we weren't able to send
-+ * the message or if the message completed with some kind of
-+ * error. See __smu_cmn_reg2errno() for details of the -errno.
-+ *
-+ * If we weren't able to send the message to the SMU, we also print
-+ * the error to the standard log.
-+ *
-+ * Command completion status is printed only if the -errno is
-+ * -EREMOTEIO, indicating that the SMU returned back an
-+ * undefined/unknown/unspecified result. All other cases are
-+ * well-defined, not printed, but instead given back to the client to
-+ * decide what further to do.
-+ *
-+ * The return value, @read_arg is read back regardless, to give back
-+ * more information to the client, which on error would most likely be
-+ * @param, but we can't assume that. This also eliminates more
-+ * conditionals.
-+ */
- int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
- enum smu_message_type msg,
- uint32_t param,
- uint32_t *read_arg)
- {
-- struct amdgpu_device *adev = smu->adev;
-- int ret = 0, index = 0;
-+ int res, index;
-+ u32 reg;
-
- if (smu->adev->no_hw_access)
- return 0;
-@@ -136,31 +339,24 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
- return index == -EACCES ? 0 : index;
-
- mutex_lock(&smu->message_lock);
-- ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index, param);
-- if (ret)
-- goto out;
--
-- ret = smu_cmn_wait_for_response(smu);
-- if (ret != 0x1) {
-- if (ret == -ETIME) {
-- dev_err(adev->dev, "message: %15s (%d) \tparam: 0x%08x is timeout (no response)\n",
-- smu_get_message_name(smu, msg), index, param);
-- } else {
-- dev_err(adev->dev, "failed send message: %15s (%d) \tparam: 0x%08x response %#x\n",
-- smu_get_message_name(smu, msg), index, param,
-- ret);
-- ret = -EIO;
-- }
-- goto out;
-+ reg = __smu_cmn_poll_stat(smu);
-+ res = __smu_cmn_reg2errno(smu, reg);
-+ if (reg == SMU_RESP_NONE ||
-+ reg == SMU_RESP_BUSY_OTHER ||
-+ res == -EREMOTEIO) {
-+ __smu_cmn_reg_print_error(smu, reg, index, param, msg);
-+ goto Out;
- }
--
-+ __smu_cmn_send_msg(smu, (uint16_t) index, param);
-+ reg = __smu_cmn_poll_stat(smu);
-+ res = __smu_cmn_reg2errno(smu, reg);
-+ if (res == -EREMOTEIO)
-+ __smu_cmn_reg_print_error(smu, reg, index, param, msg);
- if (read_arg)
- smu_cmn_read_arg(smu, read_arg);
--
-- ret = 0; /* 0 as driver return value */
--out:
-+Out:
- mutex_unlock(&smu->message_lock);
-- return ret;
-+ return res;
- }
-
- int smu_cmn_send_smc_msg(struct smu_context *smu,
-diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
-index 9add5f16ff56..16993daa2ae0 100644
---- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
-+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
-@@ -27,7 +27,8 @@
-
- #if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || defined(SWSMU_CODE_LAYER_L4)
- int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
-- uint16_t msg, uint32_t param);
-+ uint16_t msg_index,
-+ uint32_t param);
- int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
- enum smu_message_type msg,
- uint32_t param,
-diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
-index 5b764740b829..d19974aceb2e 100644
---- a/drivers/pinctrl/pinctrl-amd.c
-+++ b/drivers/pinctrl/pinctrl-amd.c
-@@ -445,6 +445,7 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
- u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3);
-+ int err;
-
- raw_spin_lock_irqsave(&gpio_dev->lock, flags);
- pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
-@@ -457,6 +458,15 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
- writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
- raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
-
-+ if (on)
-+ err = enable_irq_wake(gpio_dev->irq);
-+ else
-+ err = disable_irq_wake(gpio_dev->irq);
-+
-+ if (err)
-+ dev_err(&gpio_dev->pdev->dev, "failed to %s wake-up interrupt\n",
-+ on ? "enable" : "disable");
-+
- return 0;
- }
-
-@@ -904,7 +914,6 @@ static struct pinctrl_desc amd_pinctrl_desc = {
- static int amd_gpio_probe(struct platform_device *pdev)
- {
- int ret = 0;
-- int irq_base;
- struct resource *res;
- struct amd_gpio *gpio_dev;
- struct gpio_irq_chip *girq;
-@@ -927,9 +936,9 @@ static int amd_gpio_probe(struct platform_device *pdev)
- if (!gpio_dev->base)
- return -ENOMEM;
-
-- irq_base = platform_get_irq(pdev, 0);
-- if (irq_base < 0)
-- return irq_base;
-+ gpio_dev->irq = platform_get_irq(pdev, 0);
-+ if (gpio_dev->irq < 0)
-+ return gpio_dev->irq;
-
- #ifdef CONFIG_PM_SLEEP
- gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins,
-@@ -989,7 +998,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
- goto out2;
- }
-
-- ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler,
-+ ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler,
- IRQF_SHARED, KBUILD_MODNAME, gpio_dev);
- if (ret)
- goto out2;
-diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
-index 95e763424042..1d4317073654 100644
---- a/drivers/pinctrl/pinctrl-amd.h
-+++ b/drivers/pinctrl/pinctrl-amd.h
-@@ -98,6 +98,7 @@ struct amd_gpio {
- struct resource *res;
- struct platform_device *pdev;
- u32 *saved_regs;
-+ int irq;
- };
-
- /* KERNCZ configuration*/
-diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
-index 3481479a2942..52a88c9bc0ab 100644
---- a/drivers/platform/x86/amd-pmc.c
-+++ b/drivers/platform/x86/amd-pmc.c
-@@ -270,6 +270,7 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg
- u32 val;
-
- mutex_lock(&dev->lock);
-+ amd_pmc_dump_registers(dev);
- /* Wait until we get a valid response */
- rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
- val, val != 0, PMC_MSG_DELAY_MIN_US,
---
-2.33.0
-
diff --git a/sys-kernel_arch-sources-g14_files-9001-v5.14.4-s0ix-patch-2021-09-15.patch b/sys-kernel_arch-sources-g14_files-9001-v5.14.4-s0ix-patch-2021-09-15.patch
new file mode 100644
index 000000000000..25f571901530
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-9001-v5.14.4-s0ix-patch-2021-09-15.patch
@@ -0,0 +1,342 @@
+From a7056f48cf6be7f02cad9fa8406cd92dd8e23b10 Mon Sep 17 00:00:00 2001
+From: Scott B <arglebargle@arglebargle.dev>
+Date: Wed, 15 Sep 2021 03:19:12 -0700
+Subject: [PATCH] v5.14.4 s0ix patch 2021-09-15
+
+Squashed commit of the following:
+
+commit 172a95ed32721a87abb5b865608ca52cf469da6c
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Thu Sep 9 11:19:43 2021 -0500
+
+ platform/x86: amd-pmc: Increase the response register timeout
+
+ There have been reports of approximately a 9% failure rate in SMU
+ communication timeouts with s0i3 entry on some OEM designs. Currently
+ the design in amd-pmc is to try every 100us for up to 20ms.
+
+ However the GPU driver which also communicates with the SMU using a
+ mailbox register which the driver polls every 1us for up to 2000ms.
+ In the GPU driver this was increased by commit 055162645a40 ("drm/amd/pm:
+ increase time out value when sending msg to SMU")
+
+ Increase the maximum timeout used by amd-pmc to 2000ms to match this
+ behavior.
+
+ Cc: stable@kernel.org
+ Reported-by: Julian Sikorski <belegdol@gmail.com>
+ BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1629
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit b53b1045fd67d18ed948ff9d54517e9bfe01ce83
+Author: Scott B <28817345+foundObjects@users.noreply.github.com>
+Date: Wed Jul 21 18:10:28 2021 -0700
+
+ DEBUG: amd-pmc smu register dump for diagnostics
+
+ patch this per Mario's request:
+ https://gitlab.freedesktop.org/drm/amd/-/issues/1629#note_1000332
+
+commit ef5537a8e3ad810798d4296f687445d4e538e5e4
+Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+Date: Tue Aug 31 17:36:12 2021 +0530
+
+ pinctrl: amd: Add irq field data
+
+ pinctrl_amd use gpiochip_get_data() to get their local state containers
+ back from the gpiochip passed as amd_gpio chip data.
+
+ Hence added irq field data to get directly using amd_gpio chip data.
+
+ Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+
+commit 2ed2ba9e98dd6438596792b2204ffb79f850d898
+Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+Date: Tue Aug 31 17:36:13 2021 +0530
+
+ pinctrl: amd: Handle wake-up interrupt
+
+ Enable/disable power management wakeup mode, which is disabled by
+ default. enable_irq_wake enables wakes the system from sleep.
+
+ Hence added enable/disable irq_wake to handle wake-up interrupt.
+
+ Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+
+commit fa619f720d9b7ecf7c9914f9164a2d33e7c4dbad
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Tue Aug 31 11:36:19 2021 -0500
+
+ ACPI: PM: s2idle: Run both AMD and Microsoft methods if both are supported
+
+ It was reported that on "HP ENVY x360" that power LED does not come back
+ on, certain keys like brightness controls do not work, and the fan never
+ spins up, even under load.
+
+ In analysis of the SSDT it's clear that the Microsoft UUID doesn't provide
+ functional support, but rather the AMD UUID should be supporting this
+ system.
+
+ Because this is a gap in the expected logic, confirmation with internal
+ team is that AMD uPEP *does* run even when Microsoft UUID present, but
+ most OEM systems have adopted value of "0x3" for supported functions and
+ hence nothing runs.
+
+ Henceforth add support for running both Microsoft and AMD methods. This
+ approach will also allow the same logic on Intel systems if desired at a
+ future time as well by pulling the evaluation of
+ `lps0_dsm_func_mask_microsoft` out of the if block for
+ `acpi_s2idle_vendor_amd`.
+
+ BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1691
+ Reported-by: Maxwell Beck <max@ryt.one>
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit a8126200ab377bbb8025ba3a60b935a485ca7602
+Author: Scott B <28817345+foundObjects@users.noreply.github.com>
+Date: Tue Jul 20 23:33:01 2021 -0700
+
+ drm/amd/pm: Add information about SMU12 firmware version
+
+ hacky manual import of: https://lists.freedesktop.org/archives/amd-gfx/2021-July/066835.html
+
+ This information is useful for root causing issues with S0ix.
+
+ Signed-off-by: Mario Limonciello <mario.limonciello at amd.com>
+
+commit aaaa4dc0eedb97a20688dbe7936bb1701118648a
+Author: Scott B <28817345+foundObjects@users.noreply.github.com>
+Date: Tue Jul 20 23:31:31 2021 -0700
+
+ drm/amd/pm: Add information about SMU11 firmware version
+
+ hacky manual import of: https://lists.freedesktop.org/archives/amd-gfx/2021-July/066834.html
+
+ This information is useful for root causing issues with S0ix.
+
+ Signed-off-by: Mario Limonciello <mario.limonciello at amd.com>
+---
+ drivers/acpi/x86/s2idle.c | 67 +++++++++++--------
+ .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 3 +
+ .../gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c | 3 +
+ drivers/pinctrl/pinctrl-amd.c | 19 ++++--
+ drivers/pinctrl/pinctrl-amd.h | 1 +
+ drivers/platform/x86/amd-pmc.c | 3 +-
+ 6 files changed, 62 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
+index 3a308461246a..7d1976e5dd8b 100644
+--- a/drivers/acpi/x86/s2idle.c
++++ b/drivers/acpi/x86/s2idle.c
+@@ -449,25 +449,30 @@ int acpi_s2idle_prepare_late(void)
+ if (pm_debug_messages_on)
+ lpi_check_constraints();
+
+- if (lps0_dsm_func_mask_microsoft > 0) {
++ /* screen off */
++ if (lps0_dsm_func_mask > 0)
++ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
++ ACPI_LPS0_SCREEN_OFF_AMD :
++ ACPI_LPS0_SCREEN_OFF,
++ lps0_dsm_func_mask, lps0_dsm_guid);
++
++ if (lps0_dsm_func_mask_microsoft > 0)
+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
++
++ /* lps0 entry */
++ if (lps0_dsm_func_mask > 0)
++ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
++ ACPI_LPS0_ENTRY_AMD :
++ ACPI_LPS0_ENTRY,
++ lps0_dsm_func_mask, lps0_dsm_guid);
++ if (lps0_dsm_func_mask_microsoft > 0) {
++ acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
++ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
++ /* modern standby entry */
+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
+- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+- } else if (acpi_s2idle_vendor_amd()) {
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD,
+- lps0_dsm_func_mask, lps0_dsm_guid);
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD,
+- lps0_dsm_func_mask, lps0_dsm_guid);
+- } else {
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
+- lps0_dsm_func_mask, lps0_dsm_guid);
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
+- lps0_dsm_func_mask, lps0_dsm_guid);
+ }
+-
+ return 0;
+ }
+
+@@ -476,24 +481,30 @@ void acpi_s2idle_restore_early(void)
+ if (!lps0_device_handle || sleep_no_lps0)
+ return;
+
+- if (lps0_dsm_func_mask_microsoft > 0) {
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
+- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
++ /* mdoern standby exit */
++ if (lps0_dsm_func_mask_microsoft > 0)
+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
++
++ /* lps0 exit */
++ if (lps0_dsm_func_mask > 0)
++ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
++ ACPI_LPS0_EXIT_AMD :
++ ACPI_LPS0_EXIT,
++ lps0_dsm_func_mask, lps0_dsm_guid);
++ if (lps0_dsm_func_mask_microsoft > 0)
++ acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
++ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
++
++ /* screen on */
++ if (lps0_dsm_func_mask_microsoft > 0)
+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+- } else if (acpi_s2idle_vendor_amd()) {
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT_AMD,
+- lps0_dsm_func_mask, lps0_dsm_guid);
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD,
+- lps0_dsm_func_mask, lps0_dsm_guid);
+- } else {
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
+- lps0_dsm_func_mask, lps0_dsm_guid);
+- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
+- lps0_dsm_func_mask, lps0_dsm_guid);
+- }
++ if (lps0_dsm_func_mask > 0)
++ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
++ ACPI_LPS0_SCREEN_ON_AMD :
++ ACPI_LPS0_SCREEN_ON,
++ lps0_dsm_func_mask, lps0_dsm_guid);
+ }
+
+ static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+index 0a5d46ac9ccd..626d7c2bdf66 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+@@ -272,6 +272,9 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
+ break;
+ }
+
++ dev_info(smu->adev->dev, "smu fw reported version = 0x%08x (%d.%d.%d)\n",
++ smu_version, smu_major, smu_minor, smu_debug);
++
+ /*
+ * 1. if_version mismatch is not critical as our fw is designed
+ * to be backward compatible.
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
+index d60b8c5e8715..00ebc381a605 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
+@@ -88,6 +88,9 @@ int smu_v12_0_check_fw_version(struct smu_context *smu)
+ if (smu->is_apu)
+ adev->pm.fw_version = smu_version;
+
++ dev_info(smu->adev->dev, "smu fw reported version = 0x%08x (%d.%d.%d)\n",
++ smu_version, smu_major, smu_minor, smu_debug);
++
+ /*
+ * 1. if_version mismatch is not critical as our fw is designed
+ * to be backward compatible.
+diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
+index 5b764740b829..d19974aceb2e 100644
+--- a/drivers/pinctrl/pinctrl-amd.c
++++ b/drivers/pinctrl/pinctrl-amd.c
+@@ -445,6 +445,7 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
+ u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3);
++ int err;
+
+ raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+ pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
+@@ -457,6 +458,15 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+ writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
+ raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
++ if (on)
++ err = enable_irq_wake(gpio_dev->irq);
++ else
++ err = disable_irq_wake(gpio_dev->irq);
++
++ if (err)
++ dev_err(&gpio_dev->pdev->dev, "failed to %s wake-up interrupt\n",
++ on ? "enable" : "disable");
++
+ return 0;
+ }
+
+@@ -904,7 +914,6 @@ static struct pinctrl_desc amd_pinctrl_desc = {
+ static int amd_gpio_probe(struct platform_device *pdev)
+ {
+ int ret = 0;
+- int irq_base;
+ struct resource *res;
+ struct amd_gpio *gpio_dev;
+ struct gpio_irq_chip *girq;
+@@ -927,9 +936,9 @@ static int amd_gpio_probe(struct platform_device *pdev)
+ if (!gpio_dev->base)
+ return -ENOMEM;
+
+- irq_base = platform_get_irq(pdev, 0);
+- if (irq_base < 0)
+- return irq_base;
++ gpio_dev->irq = platform_get_irq(pdev, 0);
++ if (gpio_dev->irq < 0)
++ return gpio_dev->irq;
+
+ #ifdef CONFIG_PM_SLEEP
+ gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins,
+@@ -989,7 +998,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
+ goto out2;
+ }
+
+- ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler,
++ ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler,
+ IRQF_SHARED, KBUILD_MODNAME, gpio_dev);
+ if (ret)
+ goto out2;
+diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h
+index 95e763424042..1d4317073654 100644
+--- a/drivers/pinctrl/pinctrl-amd.h
++++ b/drivers/pinctrl/pinctrl-amd.h
+@@ -98,6 +98,7 @@ struct amd_gpio {
+ struct resource *res;
+ struct platform_device *pdev;
+ u32 *saved_regs;
++ int irq;
+ };
+
+ /* KERNCZ configuration*/
+diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
+index 3481479a2942..6d2d3650f8b9 100644
+--- a/drivers/platform/x86/amd-pmc.c
++++ b/drivers/platform/x86/amd-pmc.c
+@@ -71,7 +71,7 @@
+ #define AMD_CPU_ID_YC 0x14B5
+
+ #define PMC_MSG_DELAY_MIN_US 100
+-#define RESPONSE_REGISTER_LOOP_MAX 200
++#define RESPONSE_REGISTER_LOOP_MAX 20000
+
+ #define SOC_SUBSYSTEM_IP_MAX 12
+ #define DELAY_MIN_US 2000
+@@ -270,6 +270,7 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg
+ u32 val;
+
+ mutex_lock(&dev->lock);
++ amd_pmc_dump_registers(dev);
+ /* Wait until we get a valid response */
+ rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
+ val, val != 0, PMC_MSG_DELAY_MIN_US,
+--
+2.33.0
+
diff --git a/sys-kernel_arch-sources-g14_files-9002-amd-pmc-delay-test.patch b/sys-kernel_arch-sources-g14_files-9002-amd-pmc-delay-test.patch
deleted file mode 100644
index 5c1d59cc0ddf..000000000000
--- a/sys-kernel_arch-sources-g14_files-9002-amd-pmc-delay-test.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 47e5da763d58a3b6657e2a716130a470e1deee2f Mon Sep 17 00:00:00 2001
-From: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Wed, 25 Aug 2021 07:35:52 -0700
-Subject: [PATCH] amd-pmc delay test
-
----
- drivers/platform/x86/amd-pmc.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
-index 52a88c9bc0ab..336303e963c5 100644
---- a/drivers/platform/x86/amd-pmc.c
-+++ b/drivers/platform/x86/amd-pmc.c
-@@ -71,7 +71,7 @@
- #define AMD_CPU_ID_YC 0x14B5
-
- #define PMC_MSG_DELAY_MIN_US 100
--#define RESPONSE_REGISTER_LOOP_MAX 200
-+#define RESPONSE_REGISTER_LOOP_MAX 2000
-
- #define SOC_SUBSYSTEM_IP_MAX 12
- #define DELAY_MIN_US 2000
-@@ -283,12 +283,18 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg
- /* Write zero to response register */
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_RESPONSE, 0);
-
-+ udelay(500);
-+
- /* Write argument into response register */
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_ARGUMENT, set);
-
-+ udelay(500);
-+
- /* Write message ID to message ID register */
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_MESSAGE, msg);
-
-+ udelay(500);
-+
- /* Wait until we get a valid response */
- rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
- val, val != 0, PMC_MSG_DELAY_MIN_US,
---
-2.33.0
-
diff --git a/sys-kernel_arch-sources-g14_files-9002-amd-pmc-smu-register-dump-for-diagnostics.patch b/sys-kernel_arch-sources-g14_files-9002-amd-pmc-smu-register-dump-for-diagnostics.patch
deleted file mode 100644
index b10c91036482..000000000000
--- a/sys-kernel_arch-sources-g14_files-9002-amd-pmc-smu-register-dump-for-diagnostics.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 5a236062383273593ffef3a4d79c9c7892eab5ca Mon Sep 17 00:00:00 2001
-From: Scott B <28817345+foundObjects@users.noreply.github.com>
-Date: Wed, 21 Jul 2021 18:10:28 -0700
-Subject: [PATCH] amd-pmc smu register dump for diagnostics
-
-patch this per Mario's request:
-https://gitlab.freedesktop.org/drm/amd/-/issues/1629#note_1000332
----
- drivers/platform/x86/amd-pmc.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
-index 663a4ca0580d..dd67b6585095 100644
---- a/drivers/platform/x86/amd-pmc.c
-+++ b/drivers/platform/x86/amd-pmc.c
-@@ -269,6 +269,7 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg
- u32 val;
-
- mutex_lock(&dev->lock);
-+ amd_pmc_dump_registers(dev);
- /* Wait until we get a valid response */
- rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
- val, val != 0, PMC_MSG_DELAY_MIN_US,
---
-2.32.0
-
diff --git a/sys-kernel_arch-sources-g14_files-9003-ACPI-PM-s2idle-Invert-Microsoft-UUID-entry-and-exit.patch b/sys-kernel_arch-sources-g14_files-9003-ACPI-PM-s2idle-Invert-Microsoft-UUID-entry-and-exit.patch
deleted file mode 100644
index 10d96825accd..000000000000
--- a/sys-kernel_arch-sources-g14_files-9003-ACPI-PM-s2idle-Invert-Microsoft-UUID-entry-and-exit.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From ee3b91570a02d421d73f235edfe21ea62c628100 Mon Sep 17 00:00:00 2001
-From: Mario Limonciello <mario.limonciello@amd.com>
-Date: Mon, 9 Aug 2021 20:40:04 -0500
-Subject: [PATCH] ACPI: PM: s2idle: Invert Microsoft UUID entry and exit
-
-It was reported by a user with a Dell m15 R5 (5800H) that
-the keyboard backlight was turning on when entering suspend
-and turning off when exiting (the opposite of how it should be).
-
-The user bisected it back to commit 5dbf50997578 ("ACPI: PM:
-s2idle: Add support for new Microsoft UUID"). Previous to that
-commit the LEDs didn't turn off at all. Confirming in the spec,
-these were reversed when introduced.
-
-Fix them to match the spec.
-
-BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1230#note_1021836
-Fixes: 5dbf50997578 ("ACPI: PM: s2idle: Add support for new Microsoft UUID")
-Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
----
- drivers/acpi/x86/s2idle.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
-index fbdbef0ab552..3a308461246a 100644
---- a/drivers/acpi/x86/s2idle.c
-+++ b/drivers/acpi/x86/s2idle.c
-@@ -452,7 +452,7 @@ int acpi_s2idle_prepare_late(void)
- if (lps0_dsm_func_mask_microsoft > 0) {
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-@@ -479,7 +479,7 @@ void acpi_s2idle_restore_early(void)
- if (lps0_dsm_func_mask_microsoft > 0) {
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
---
-2.32.0
-
diff --git a/sys-kernel_arch-sources-g14_files-9007-s2idle-call-multiple-methods-test.patch b/sys-kernel_arch-sources-g14_files-9007-s2idle-call-multiple-methods-test.patch
deleted file mode 100644
index 6e0bb2b3c4d2..000000000000
--- a/sys-kernel_arch-sources-g14_files-9007-s2idle-call-multiple-methods-test.patch
+++ /dev/null
@@ -1,128 +0,0 @@
-From 00e5506bbaa3259a5e9ac98106dcfc60b1adecab Mon Sep 17 00:00:00 2001
-From: Mario Limonciello <mario.limonciello@amd.com>
-Date: Tue, 31 Aug 2021 11:36:19 -0500
-Subject: [PATCH] ACPI: PM: s2idle: Run both AMD and Microsoft methods if both
- are supported
-
-It was reported that on "HP ENVY x360" that power LED does not come back
-on, certain keys like brightness controls do not work, and the fan never
-spins up, even under load.
-
-In analysis of the SSDT it's clear that the Microsoft UUID doesn't provide
-functional support, but rather the AMD UUID should be supporting this
-system.
-
-Because this is a gap in the expected logic, confirmation with internal
-team is that AMD uPEP *does* run even when Microsoft UUID present, but
-most OEM systems have adopted value of "0x3" for supported functions and
-hence nothing runs.
-
-Henceforth add support for running both Microsoft and AMD methods. This
-approach will also allow the same logic on Intel systems if desired at a
-future time as well by pulling the evaluation of
-`lps0_dsm_func_mask_microsoft` out of the if block for
-`acpi_s2idle_vendor_amd`.
-
-BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1691
-Reported-by: Maxwell Beck <max@ryt.one>
-Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
----
- drivers/acpi/x86/s2idle.c | 67 +++++++++++++++++++++++----------------
- 1 file changed, 39 insertions(+), 28 deletions(-)
-
-diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
-index 3a308461246a..7d1976e5dd8b 100644
---- a/drivers/acpi/x86/s2idle.c
-+++ b/drivers/acpi/x86/s2idle.c
-@@ -449,25 +449,30 @@ int acpi_s2idle_prepare_late(void)
- if (pm_debug_messages_on)
- lpi_check_constraints();
-
-- if (lps0_dsm_func_mask_microsoft > 0) {
-+ /* screen off */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_SCREEN_OFF_AMD :
-+ ACPI_LPS0_SCREEN_OFF,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+
-+ if (lps0_dsm_func_mask_microsoft > 0)
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
-- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+
-+ /* lps0 entry */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_ENTRY_AMD :
-+ ACPI_LPS0_ENTRY,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ if (lps0_dsm_func_mask_microsoft > 0) {
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- } else if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF_AMD,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- } else {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-+ /* modern standby entry */
-+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
- }
--
- return 0;
- }
-
-@@ -476,24 +481,30 @@ void acpi_s2idle_restore_early(void)
- if (!lps0_device_handle || sleep_no_lps0)
- return;
-
-- if (lps0_dsm_func_mask_microsoft > 0) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ /* mdoern standby exit */
-+ if (lps0_dsm_func_mask_microsoft > 0)
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
-- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-- } else if (acpi_s2idle_vendor_amd()) {
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT_AMD,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON_AMD,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- } else {
-+
-+ /* lps0 exit */
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_EXIT_AMD :
-+ ACPI_LPS0_EXIT,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
-+ if (lps0_dsm_func_mask_microsoft > 0)
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+
-+ /* screen on */
-+ if (lps0_dsm_func_mask_microsoft > 0)
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
-- lps0_dsm_func_mask, lps0_dsm_guid);
-- }
-+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-+ if (lps0_dsm_func_mask > 0)
-+ acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-+ ACPI_LPS0_SCREEN_ON_AMD :
-+ ACPI_LPS0_SCREEN_ON,
-+ lps0_dsm_func_mask, lps0_dsm_guid);
- }
-
- static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
---
-GitLab
diff --git a/sys-kernel_arch-sources-g14_files-9009-amd-pstate-sqashed.patch b/sys-kernel_arch-sources-g14_files-9009-amd-pstate-sqashed.patch
index d313ef86c88f..09471946e6f9 100644
--- a/sys-kernel_arch-sources-g14_files-9009-amd-pstate-sqashed.patch
+++ b/sys-kernel_arch-sources-g14_files-9009-amd-pstate-sqashed.patch
@@ -1,16 +1,744 @@
-From 674082f34ac8bfab164a630a275eac291e1bd7be Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 28 Jan 2021 10:50:26 +0800
-Subject: [PATCH 01/19] x86/cpufreatures: add AMD CPPC extension feature flag
+From 1cf7e7f39c0c1a259ffd8c58b69edfc933936913 Mon Sep 17 00:00:00 2001
+From: Scott B <arglebargle@arglebargle.dev>
+Date: Thu, 9 Sep 2021 18:02:09 -0700
+Subject: [PATCH] amd-pstate v1
-Add Collaborative Processor Performance Control Extension feature flag
-for AMD processors.
+Squashed commit of the following:
-Signed-off-by: Huang Rui <ray.huang@amd.com>
+commit aee7d6c2aa9fde5120b03083676ad86bf293aeaa
+Author: Huang Rui <ray.huang@amd.com>
+Date: Thu Jun 10 23:40:18 2021 +0800
+
+ Documentation: amd-pstate: add amd-pstate driver introduction
+
+ Introduce the amd-pstate driver design and implementation.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit d5130811e36f5557e2678de2f612c2db00a5c719
+Author: Huang Rui <ray.huang@amd.com>
+Date: Thu Jun 10 23:48:03 2021 +0800
+
+ cpupower: print amd-pstate information on cpupower
+
+ amd-pstate kernel module is using the fine grain frequency instead of
+ acpi hardware pstate. So the performance and frequency values should be
+ printed in frequency-info.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 8c239cb8a6e3704a75ab4139fd275a7e17b336c6
+Author: Huang Rui <ray.huang@amd.com>
+Date: Sun Jun 20 18:25:55 2021 +0800
+
+ cpupower: add amd-pstate get data function to query the info
+
+ Frequency-info needs an interface to query the current amd-pstate data.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit ce0b684f184fee1fba6b6e0ef4ae4506a0d275c1
+Author: Huang Rui <ray.huang@amd.com>
+Date: Sun Jun 20 17:35:45 2021 +0800
+
+ cpupower: enable boost state support for amd-pstate module
+
+ The AMD P-state boost API is different from ACPI hardware P-states, so
+ implement the support for amd-pstate kernel module.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 97f78342eb9bcecfe44ef5307941dea1051e3a75
+Author: Huang Rui <ray.huang@amd.com>
+Date: Sun Jun 20 17:07:25 2021 +0800
+
+ cpupower: add amd-pstate sysfs entries into libcpufreq
+
+ These amd-pstate sysfs entries will be used on cpupower for amd-pstate
+ kernel module.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit d99ecc31f798a4025baaea72607246dadedefca0
+Author: Huang Rui <ray.huang@amd.com>
+Date: Sun Jun 27 22:40:14 2021 +0800
+
+ cpupower: initial AMD P-state capability
+
+ If kernel enables AMD P-state, cpupower won't need to respond ACPI
+ hardware P-states function anymore.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit f766224ca2c54192b9e9abaa50ce58ef5e72670d
+Author: Huang Rui <ray.huang@amd.com>
+Date: Sun Jun 27 22:25:39 2021 +0800
+
+ cpupower: add the function to check amd-pstate enabled
+
+ Introduce the cpupower_amd_pstate_enabled() to check whether the kernel
+ mode enables amd-pstate.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 0eca00885d7ce1cf7c03b8999fce887c9bafc411
+Author: Huang Rui <ray.huang@amd.com>
+Date: Mon Jun 14 22:52:01 2021 +0800
+
+ cpupower: add AMD P-state capability flag
+
+ Add AMD P-state capability flag in cpupower to indicate AMD new P-state
+ kernel module support on Ryzen processors.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 9a70d7b125cad2356910cbf04e476d53b458c786
+Author: Huang Rui <ray.huang@amd.com>
+Date: Sun Jun 20 15:01:08 2021 +0800
+
+ cpufreq: amd: add amd-pstate performance attributes
+
+ Introduce sysfs attributes to get the different level amd-pstate
+ performances.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 48c5ae9172d62b6a6a8220f27afeaf47408ebb66
+Author: Huang Rui <ray.huang@amd.com>
+Date: Sun Jun 20 13:26:01 2021 +0800
+
+ cpufreq: amd: add amd-pstate frequencies attributes
+
+ Introduce sysfs attributes to get the different level processor
+ frequencies.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 4d003338827eca88097f35fae6e3ec75566bc788
+Author: Huang Rui <ray.huang@amd.com>
+Date: Sat Jun 19 23:41:30 2021 +0800
+
+ cpufreq: amd: add amd-pstate checking support check attribute
+
+ The amd-pstate hardware support check will be needed by cpupower to know
+ whether amd-pstate is enabled and supported.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit e8aa42d8143a5c8b65a63de34cd38bdc6d70fd82
+Author: Huang Rui <ray.huang@amd.com>
+Date: Thu Jun 10 23:13:00 2021 +0800
+
+ cpufreq: amd: add boost mode support for amd-pstate
+
+ If the sbios supports the boost mode of amd-pstate, let's switch to
+ boost enabled by default.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 1cb45daf02f2cad44457ccc237c9d74f60eec621
+Author: Huang Rui <ray.huang@amd.com>
+Date: Thu Jun 10 20:24:00 2021 +0800
+
+ cpufreq: amd: add trace for amd-pstate module
+
+ Add trace event to monitor the performance value changes which is
+ controlled by cpu governors.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 152251e4cc636f4748d308ac31089ae7fd4e09c9
+Author: Huang Rui <ray.huang@amd.com>
+Date: Mon Aug 9 19:06:51 2021 +0800
+
+ cpufreq: amd: add acpi cppc function as the backend for legacy processors
+
+ In some old Zen based processors, they are using the shared memory that
+ exposed from ACPI SBIOS.
+
+ Signed-off-by: Jinzhou Su <Jinzhou.Su@amd.com>
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit a2a9f14e19c4b34986e6410dd4f430449a32d2a3
+Author: Huang Rui <ray.huang@amd.com>
+Date: Fri Aug 13 18:43:47 2021 +0800
+
+ cpufreq: amd: add fast switch function for amd-pstate module
+
+ Introduce the fast switch function for amd-pstate module on the AMD
+ processors which support the full MSR register control. It's able to
+ decrease the lattency on interrupt context.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit ffb5347387a6a070554d2e6f6af918ffbf1965c4
+Author: Huang Rui <ray.huang@amd.com>
+Date: Thu Jun 10 18:04:45 2021 +0800
+
+ cpufreq: amd: introduce a new amd pstate driver to support future processors
+
+ amd-pstate is the AMD CPU performance scaling driver that introduces a
+ new CPU frequency control mechanism on AMD Zen based CPU series in Linux
+ kernel. The new mechanism is based on Collaborative processor
+ performance control (CPPC) which is finer grain frequency management
+ than legacy ACPI hardware P-States. Current AMD CPU platforms are using
+ the ACPI P-states driver to manage CPU frequency and clocks with
+ switching only in 3 P-states. AMD P-States is to replace the ACPI
+ P-states controls, allows a flexible, low-latency interface for the
+ Linux kernel to directly communicate the performance hints to hardware.
+
+ "amd-pstate" leverages the Linux kernel governors such as *schedutil*,
+ *ondemand*, etc. to manage the performance hints which are provided by CPPC
+ hardware functionality. The first version for amd-pstate is to support one
+ of the Zen3 processors, and we will support more in future after we verify
+ the hardware and SBIOS functionalities.
+
+ There are two types of hardware implementations for amd-pstate: one is full
+ MSR support and another is shared memory support. It can use
+ X86_FEATURE_AMD_CPPC_EXT feature flag to distinguish the different types.
+
+ Using the new AMD P-States method + kernel governors (*schedutil*,
+ *ondemand*, ...) to manage the frequency update is the most appropriate
+ bridge between AMD Zen based hardware processor and Linux kernel, the
+ processor is able to ajust to the most efficiency frequency according to
+ the kernel scheduler loading.
+
+ Performance Per Watt (PPW) Caculation:
+
+ The PPW caculation is referred by below paper:
+ https://software.intel.com/content/dam/develop/external/us/en/documents/performance-per-what-paper.pdf
+
+ Below formula is referred from below spec to measure the PPW:
+
+ (F / t) / P = F * t / (t * E) = F / E,
+
+ "F" is the number of frames per second.
+ "P" is power measurd in watts.
+ "E" is energy measured in joules.
+
+ We use the RAPL interface with "perf" tool to get the energy data of the
+ package power.
+
+ The data comparsions between amd-pstate and acpi-freq module are tested on
+ AMD Cezanne processor:
+
+ 1) TBench CPU benchmark:
+
+ +---------------------------------------------------------------------+
+ | |
+ | TBench (Performance Per Watt) |
+ | Higher is better |
+ +-------------------+------------------------+------------------------+
+ | | Performance Per Watt | Performance Per Watt |
+ | Kernel Module | (Schedutil) | (Ondemand) |
+ | | Unit: MB / (s * J) | Unit: MB / (s * J) |
+ +-------------------+------------------------+------------------------+
+ | | | |
+ | acpi-cpufreq | 3.022 | 2.969 |
+ | | | |
+ +-------------------+------------------------+------------------------+
+ | | | |
+ | amd-pstate | 3.131 | 3.284 |
+ | | | |
+ +-------------------+------------------------+------------------------+
+
+ 2) Gitsource CPU benchmark:
+
+ +---------------------------------------------------------------------+
+ | |
+ | Gitsource (Performance Per Watt) |
+ | Higher is better |
+ +-------------------+------------------------+------------------------+
+ | | Performance Per Watt | Performance Per Watt |
+ | Kernel Module | (Schedutil) | (Ondemand) |
+ | | Unit: 1 / (s * J) | Unit: 1 / (s * J) |
+ +-------------------+------------------------+------------------------+
+ | | | |
+ | acpi-cpufreq | 3.42172E-07 | 2.74508E-07 |
+ | | | |
+ +-------------------+------------------------+------------------------+
+ | | | |
+ | amd-pstate | 4.09141E-07 | 3.47610E-07 |
+ | | | |
+ +-------------------+------------------------+------------------------+
+
+ 3) Speedometer 2.0 CPU benchmark:
+
+ +---------------------------------------------------------------------+
+ | |
+ | Speedometer 2.0 (Performance Per Watt) |
+ | Higher is better |
+ +-------------------+------------------------+------------------------+
+ | | Performance Per Watt | Performance Per Watt |
+ | Kernel Module | (Schedutil) | (Ondemand) |
+ | | Unit: 1 / (s * J) | Unit: 1 / (s * J) |
+ +-------------------+------------------------+------------------------+
+ | | | |
+ | acpi-cpufreq | 0.116111767 | 0.110321664 |
+ | | | |
+ +-------------------+------------------------+------------------------+
+ | | | |
+ | amd-pstate | 0.115825281 | 0.122024299 |
+ | | | |
+ +-------------------+------------------------+------------------------+
+
+ According to above average data, we can see this solution has shown better
+ performance per watt scaling on mobile CPU benchmarks in most of cases.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 5648469cb7cd30bc5bbd460b362c09223bdec3e5
+Author: Jinzhou Su <Jinzhou.Su@amd.com>
+Date: Mon Aug 9 19:04:17 2021 +0800
+
+ ACPI: CPPC: add cppc enable register function
+
+ Export the cppc enable register function for future use.
+
+ Signed-off-by: Jinzhou Su <Jinzhou.Su@amd.com>
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit a0f215fdf3e24f2a74aa767cb5faef008ca3881e
+Author: Huang Rui <ray.huang@amd.com>
+Date: Mon Jan 25 15:50:24 2021 +0800
+
+ x86/msr: add AMD CPPC MSR definitions
+
+ AMD CPPC (Collaborative Processor Performance Control) function uses MSR
+ registers to manage the performance hints. So add the MSR register macro
+ here.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
+
+commit 1bff64e92f53c19784369a0cc1b7a05c918ed941
+Author: Huang Rui <ray.huang@amd.com>
+Date: Thu Jan 28 10:50:26 2021 +0800
+
+ x86/cpufreatures: add AMD CPPC extension feature flag
+
+ Add Collaborative Processor Performance Control Extension feature flag
+ for AMD processors.
+
+ Signed-off-by: Huang Rui <ray.huang@amd.com>
---
- arch/x86/include/asm/cpufeatures.h | 1 +
- 1 file changed, 1 insertion(+)
+ Documentation/admin-guide/pm/amd_pstate.rst | 377 ++++++++
+ .../admin-guide/pm/working-state.rst | 1 +
+ arch/x86/include/asm/cpufeatures.h | 1 +
+ arch/x86/include/asm/msr-index.h | 17 +
+ drivers/acpi/cppc_acpi.c | 42 +
+ drivers/cpufreq/Kconfig.x86 | 13 +
+ drivers/cpufreq/Makefile | 5 +
+ drivers/cpufreq/amd-pstate-trace.c | 2 +
+ drivers/cpufreq/amd-pstate-trace.h | 96 +++
+ drivers/cpufreq/amd-pstate.c | 812 ++++++++++++++++++
+ include/acpi/cppc_acpi.h | 5 +
+ tools/power/cpupower/lib/cpufreq.c | 44 +-
+ tools/power/cpupower/lib/cpufreq.h | 16 +
+ tools/power/cpupower/utils/cpufreq-info.c | 27 +-
+ tools/power/cpupower/utils/helpers/cpuid.c | 13 +
+ tools/power/cpupower/utils/helpers/helpers.h | 6 +
+ tools/power/cpupower/utils/helpers/misc.c | 27 +
+ 17 files changed, 1500 insertions(+), 4 deletions(-)
+ create mode 100644 Documentation/admin-guide/pm/amd_pstate.rst
+ create mode 100644 drivers/cpufreq/amd-pstate-trace.c
+ create mode 100644 drivers/cpufreq/amd-pstate-trace.h
+ create mode 100644 drivers/cpufreq/amd-pstate.c
+diff --git a/Documentation/admin-guide/pm/amd_pstate.rst b/Documentation/admin-guide/pm/amd_pstate.rst
+new file mode 100644
+index 000000000000..c3659dde0cee
+--- /dev/null
++++ b/Documentation/admin-guide/pm/amd_pstate.rst
+@@ -0,0 +1,377 @@
++.. SPDX-License-Identifier: GPL-2.0
++.. include:: <isonum.txt>
++
++===============================================
++``amd-pstate`` CPU Performance Scaling Driver
++===============================================
++
++:Copyright: |copy| 2021 Advanced Micro Devices, Inc.
++
++:Author: Huang Rui <ray.huang@amd.com>
++
++
++Introduction
++===================
++
++``amd-pstate`` is the AMD CPU performance scaling driver that introduces a
++new CPU frequency control mechanism on modern AMD APU and CPU series in
++Linux kernel. The new mechanism is based on Collaborative Processor
++Performance Control (CPPC) which provides finer grain frequency management
++than legacy ACPI hardware P-States. Current AMD CPU/APU platforms are using
++the ACPI P-states driver to manage CPU frequency and clocks with switching
++only in 3 P-states. CPPC replaces the ACPI P-states controls, allows a
++flexible, low-latency interface for the Linux kernel to directly
++communicate the performance hints to hardware.
++
++``amd-pstate`` leverages the Linux kernel governors such as ``schedutil``,
++``ondemand``, etc. to manage the performance hints which are provided by
++CPPC hardware functionality that internally follows the hardware
++specification (for details refer to AMD64 Architecture Programmer's Manual
++Volume 2: System Programming [1]_). Currently ``amd-pstate`` supports basic
++frequency control function according to kernel governors on some of the
++Zen2 and Zen3 processors, and we will implement more AMD specific functions
++in future after we verify them on the hardware and SBIOS.
++
++
++AMD CPPC Overview
++=======================
++
++Collaborative Processor Performance Control (CPPC) interface enumerates a
++continuous, abstract, and unit-less performance value in a scale that is
++not tied to a specific performance state / frequency. This is an ACPI
++standard [2]_ which software can specify application performance goals and
++hints as a relative target to the infrastructure limits. AMD processors
++provides the low latency register model (MSR) instead of AML code
++interpreter for performance adjustments. ``amd-pstate`` will initialize a
++``struct cpufreq_driver`` instance ``amd_pstate_driver`` with the callbacks
++to manage each performance update behavior. ::
++
++ Highest Perf ------>+-----------------------+ +-----------------------+
++ | | | |
++ | | | |
++ | | Max Perf ---->| |
++ | | | |
++ | | | |
++ Nominal Perf ------>+-----------------------+ +-----------------------+
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ | | Desired Perf ---->| |
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ | | | |
++ Lowest non- | | | |
++ linear perf ------>+-----------------------+ +-----------------------+
++ | | | |
++ | | Lowest perf ---->| |
++ | | | |
++ Lowest perf ------>+-----------------------+ +-----------------------+
++ | | | |
++ | | | |
++ | | | |
++ 0 ------>+-----------------------+ +-----------------------+
++
++ AMD P-States Performance Scale
++
++
++.. _perf_cap:
++
++AMD CPPC Performance Capability
++--------------------------------
++
++Highest Performance (RO)
++.........................
++
++It is the absolute maximum performance an individual processor may reach,
++assuming ideal conditions. This performance level may not be sustainable
++for long durations and may only be achievable if other platform components
++are in a specific state; for example, it may require other processors be in
++an idle state. This would be equivalent to the highest frequencies
++supported by the processor.
++
++Nominal (Guaranteed) Performance (RO)
++......................................
++
++It is the maximum sustained performance level of the processor, assuming
++ideal operating conditions. In absence of an external constraint (power,
++thermal, etc.) this is the performance level the processor is expected to
++be able to maintain continuously. All cores/processors are expected to be
++able to sustain their nominal performance state simultaneously.
++
++Lowest non-linear Performance (RO)
++...................................
++
++It is the lowest performance level at which nonlinear power savings are
++achieved, for example, due to the combined effects of voltage and frequency
++scaling. Above this threshold, lower performance levels should be generally
++more energy efficient than higher performance levels. This register
++effectively conveys the most efficient performance level to ``amd-pstate``.
++
++Lowest Performance (RO)
++........................
++
++It is the absolute lowest performance level of the processor. Selecting a
++performance level lower than the lowest nonlinear performance level may
++cause an efficiency penalty but should reduce the instantaneous power
++consumption of the processor.
++
++AMD CPPC Performance Control
++------------------------------
++
++``amd-pstate`` passes performance goals through these registers. The
++register drives the behavior of the desired performance target.
++
++Minimum requested performance (RW)
++...................................
++
++``amd-pstate`` specifies the minimum allowed performance level.
++
++Maximum requested performance (RW)
++...................................
++
++``amd-pstate`` specifies a limit the maximum performance that is expected
++to be supplied by the hardware.
++
++Desired performance target (RW)
++...................................
++
++``amd-pstate`` specifies a desired target in the CPPC performance scale as
++a relative number. This can be expressed as percentage of nominal
++performance (infrastructure max). Below the nominal sustained performance
++level, desired performance expresses the average performance level of the
++processor subject to hardware. Above the nominal performance level,
++processor must provide at least nominal performance requested and go higher
++if current operating conditions allow.
++
++Energy Performance Preference (EPP) (RW)
++.........................................
++
++Provides a hint to the hardware if software wants to bias toward performance
++(0x0) or energy efficiency (0xff).
++
++
++Key Governors Support
++=======================
++
++``amd-pstate`` can be used with all the (generic) scaling governors listed
++by the ``scaling_available_governors`` policy attribute in ``sysfs``. Then,
++it is responsible for the configuration of policy objects corresponding to
++CPUs and provides the ``CPUFreq`` core (and the scaling governors attached
++to the policy objects) with accurate information on the maximum and minimum
++operating frequencies supported by the hardware. Users can check the
++``scaling_cur_freq`` information comes from the ``CPUFreq`` core.
++
++``amd-pstate`` mainly supports ``schedutil`` and ``ondemand`` for dynamic
++frequency control. It is to fine tune the processor configuration on
++``amd-pstate`` to the ``schedutil`` with CPU CFS scheduler. ``amd-pstate``
++registers adjust_perf callback to implement the CPPC similar performance
++update behavior. It is initialized by ``sugov_start`` and then populate the
++CPU's update_util_data pointer to assign ``sugov_update_single_perf`` as
++the utilization update callback function in CPU scheduler. CPU scheduler
++will call ``cpufreq_update_util`` and assign the target performance
++according to the ``struct sugov_cpu`` that utilization update belongs to.
++Then ``amd-pstate`` updates the desired performance according to the CPU
++scheduler assigned.
++
++
++Processor Support
++=======================
++
++The ``amd-pstate`` initialization will fail if the _CPC in ACPI SBIOS is
++not existed at the detected processor, and it uses ``acpi_cpc_valid`` to
++check the _CPC existence. All Zen based processors support legacy ACPI
++hardware P-States function, so while the ``amd-pstate`` fails to be
++initialized, the kernel will fall back to initialize ``acpi-cpufreq``
++driver.
++
++There are two types of hardware implementations for ``amd-pstate``: one is
++`Full MSR Support <perf_cap_>`_ and another is `Shared Memory Support
++<perf_cap_>`_. It can use :c:macro:`X86_FEATURE_AMD_CPPC_EXT` feature flag
++(for details refer to Processor Programming Reference (PPR) for AMD Family
++19h Model 21h, Revision B0 Processors [3]_) to indicate the different
++types. ``amd-pstate`` is to register different ``amd_pstate_perf_funcs``
++instances for different hardware implementations.
++
++Currently, some of Zen2 and Zen3 processors support ``amd-pstate``. In the
++future, it will be supported on more and more AMD processors.
++
++Full MSR Support
++-----------------
++
++Some new Zen3 processors such as Cezanne provide the MSR registers directly
++while the :c:macro:`X86_FEATURE_AMD_CPPC_EXT` CPU feature flag is set.
++``amd-pstate`` can handle the MSR register to implement the fast switch
++function in ``CPUFreq`` that can shrink latency of frequency control on the
++interrupt context.
++
++Shared Memory Support
++----------------------
++
++If :c:macro:`X86_FEATURE_AMD_CPPC_EXT` CPU feature flag is not set, that
++means the processor supports shared memory solution. In this case,
++``amd-pstate`` uses the ``cppc_acpi`` helper methods to implement the
++callback functions of ``amd_pstate_perf_funcs``.
++
++
++AMD P-States and ACPI hardware P-States always can be supported in one
++processor. But AMD P-States has the higher priority and if it is enabled
++with :c:macro:`MSR_AMD_CPPC_ENABLE` or ``cppc_set_enable``, it will respond
++to the request from AMD P-States.
++
++
++User Space Interface in ``sysfs``
++==================================
++
++``amd-pstate`` exposes several global attributes (files) in ``sysfs`` to
++control its functionality at the system level. They located in the
++``/sys/devices/system/cpu/cpufreq/policyX/`` directory and affect all CPUs. ::
++
++ root@hr-test1:/home/ray# ls /sys/devices/system/cpu/cpufreq/policy0/*amd*
++ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_highest_perf
++ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_lowest_nonlinear_freq
++ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_lowest_nonlinear_perf
++ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_lowest_perf
++ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_max_freq
++ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_min_freq
++ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_nominal_freq
++ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_nominal_perf
++ /sys/devices/system/cpu/cpufreq/policy0/is_amd_pstate_enabled
++
++
++``is_amd_pstate_enabled``
++
++Query whether current kernel loads ``amd-pstate`` to enable the AMD
++P-States functionality.
++This attribute is read-only.
++
++``amd_pstate_highest_perf / amd_pstate_max_freq``
++
++Maximum CPPC performance and CPU frequency that the driver is allowed to
++set in percent of the maximum supported CPPC performance level (the highest
++performance supported in `AMD CPPC Performance Capability <perf_cap_>`_).
++This attribute is read-only.
++
++``amd_pstate_nominal_perf / amd_pstate_nominal_freq``
++
++Nominal CPPC performance and CPU frequency that the driver is allowed to
++set in percent of the maximum supported CPPC performance level (Please see
++nominal performance in `AMD CPPC Performance Capability <perf_cap_>`_).
++This attribute is read-only.
++
++``amd_pstate_lowest_nonlinear_perf / amd_pstate_lowest_nonlinear_freq``
++
++The lowest non-linear CPPC performance and CPU frequency that the driver is
++allowed to set in percent of the maximum supported CPPC performance level
++(Please see the lowest non-linear performance in `AMD CPPC Performance
++Capability <perf_cap_>`_).
++This attribute is read-only.
++
++``amd_pstate_lowest_perf / amd_pstate_min_freq``
++
++The lowest physical CPPC performance and CPU frequency.
++This attribute is read-only.
++
++
++``amd-pstate`` vs ``acpi-cpufreq``
++======================================
++
++On majority of AMD platforms supported by ``acpi-cpufreq``, the ACPI tables
++provided by the platform firmware used for CPU performance scaling, but
++only provides 3 P-states on AMD processors.
++However, on modern AMD APU and CPU series, it provides the collaborative
++processor performance control according to ACPI protocol and customize this
++for AMD platforms. That is fine-grain and continuous frequency range
++instead of the legacy hardware P-states. ``amd-pstate`` is the kernel
++module which supports the new AMD P-States mechanism on most of future AMD
++platforms. The AMD P-States mechanism will be the more performance and energy
++efficiency frequency management method on AMD processors.
++
++``cpupower`` tool support for ``amd-pstate``
++===============================================
++
++``amd-pstate`` is supported on ``cpupower`` tool that can be used to dump the frequency
++information. And it is in progress to support more and more operations for new
++``amd-pstate`` module with this tool. ::
++
++ root@hr-test1:/home/ray# cpupower frequency-info
++ analyzing CPU 0:
++ driver: amd-pstate
++ CPUs which run at the same hardware frequency: 0
++ CPUs which need to have their frequency coordinated by software: 0
++ maximum transition latency: 131 us
++ hardware limits: 400 MHz - 4.68 GHz
++ available cpufreq governors: ondemand conservative powersave userspace performance schedutil
++ current policy: frequency should be within 400 MHz and 4.68 GHz.
++ The governor "schedutil" may decide which speed to use
++ within this range.
++ current CPU frequency: Unable to call hardware
++ current CPU frequency: 4.02 GHz (asserted by call to kernel)
++ boost state support:
++ Supported: yes
++ Active: yes
++ AMD PSTATE Highest Performance: 166. Maximum Frequency: 4.68 GHz.
++ AMD PSTATE Nominal Performance: 117. Nominal Frequency: 3.30 GHz.
++ AMD PSTATE Lowest Non-linear Performance: 39. Lowest Non-linear Frequency: 1.10 GHz.
++ AMD PSTATE Lowest Performance: 15. Lowest Frequency: 400 MHz.
++
++
++Diagnostics and Tuning
++=======================
++
++Trace Events
++--------------
++
++There are two static trace events that can be used for ``amd-pstate``
++diagnostics. One of them is the cpu_frequency trace event generally used
++by ``CPUFreq``, and the other one is the ``amd_pstate_perf`` trace event
++specific to ``amd-pstate``. The following sequence of shell commands can
++be used to enable them and see their output (if the kernel is generally
++configured to support event tracing). ::
++
++ root@hr-test1:/home/ray# cd /sys/kernel/tracing/
++ root@hr-test1:/sys/kernel/tracing# echo 1 > events/amd_cpu/enable
++ root@hr-test1:/sys/kernel/tracing# cat trace
++ # tracer: nop
++ #
++ # entries-in-buffer/entries-written: 47827/42233061 #P:2
++ #
++ # _-----=> irqs-off
++ # / _----=> need-resched
++ # | / _---=> hardirq/softirq
++ # || / _--=> preempt-depth
++ # ||| / delay
++ # TASK-PID CPU# |||| TIMESTAMP FUNCTION
++ # | | | |||| | |
++ <idle>-0 [000] d.s. 244057.464842: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
++ <idle>-0 [000] d.h. 244057.475436: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
++ <idle>-0 [000] d.h. 244057.476629: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
++ <idle>-0 [000] d.s. 244057.484847: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
++ <idle>-0 [000] d.h. 244057.499821: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
++ avahi-daemon-528 [000] d... 244057.513568: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
++
++The cpu_frequency trace event will be triggered either by the ``schedutil`` scaling
++governor (for the policies it is attached to), or by the ``CPUFreq`` core (for the
++policies with other scaling governors).
++
++
++Reference
++===========
++
++.. [1] AMD64 Architecture Programmer's Manual Volume 2: System Programming,
++ https://www.amd.com/system/files/TechDocs/24593.pdf
++
++.. [2] Advanced Configuration and Power Interface Specification,
++ https://uefi.org/sites/default/files/resources/ACPI_Spec_6_4_Jan22.pdf
++
++.. [3] Processor Programming Reference (PPR) for AMD Family 19h Model 21h, Revision B0 Processors
++ https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
++
+diff --git a/Documentation/admin-guide/pm/working-state.rst b/Documentation/admin-guide/pm/working-state.rst
+index f40994c422dc..28db6156b55d 100644
+--- a/Documentation/admin-guide/pm/working-state.rst
++++ b/Documentation/admin-guide/pm/working-state.rst
+@@ -11,6 +11,7 @@ Working-State Power Management
+ intel_idle
+ cpufreq
+ intel_pstate
++ amd_pstate
+ cpufreq_drivers
+ intel_epb
+ intel-speed-select
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index d0ce5cfd3ac1..f7aea50e3371 100644
--- a/arch/x86/include/asm/cpufeatures.h
@@ -23,23 +751,6 @@ index d0ce5cfd3ac1..f7aea50e3371 100644
/* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */
#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */
---
-2.33.0
-
-From 8180f01cf18d8ba79dac94a817294e85a8d84dc4 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Mon, 25 Jan 2021 15:50:24 +0800
-Subject: [PATCH 02/19] x86/msr: add AMD CPPC MSR definitions
-
-AMD CPPC (Collaborative Processor Performance Control) function uses MSR
-registers to manage the performance hints. So add the MSR register macro
-here.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- arch/x86/include/asm/msr-index.h | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
-
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index a7c413432b33..ce42e15cf303 100644
--- a/arch/x86/include/asm/msr-index.h
@@ -68,23 +779,6 @@ index a7c413432b33..ce42e15cf303 100644
/* Fam 17h MSRs */
#define MSR_F17H_IRPERF 0xc00000e9
---
-2.33.0
-
-From 8dc33d1590f80a60f12325e7c646a8551a41adf1 Mon Sep 17 00:00:00 2001
-From: Jinzhou Su <Jinzhou.Su@amd.com>
-Date: Mon, 9 Aug 2021 19:04:17 +0800
-Subject: [PATCH 03/19] ACPI: CPPC: add cppc enable register function
-
-Export the cppc enable register function for future use.
-
-Signed-off-by: Jinzhou Su <Jinzhou.Su@amd.com>
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/acpi/cppc_acpi.c | 42 ++++++++++++++++++++++++++++++++++++++++
- include/acpi/cppc_acpi.h | 5 +++++
- 2 files changed, 47 insertions(+)
-
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index a4d4eebba1da..de4b30545215 100644
--- a/drivers/acpi/cppc_acpi.c
@@ -138,154 +832,6 @@ index a4d4eebba1da..de4b30545215 100644
/**
* cppc_set_perf - Set a CPU's performance controls.
* @cpu: CPU for which to set performance controls.
-diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
-index 9f4985b4d64d..3fdae40a75fc 100644
---- a/include/acpi/cppc_acpi.h
-+++ b/include/acpi/cppc_acpi.h
-@@ -137,6 +137,7 @@ struct cppc_cpudata {
- extern int cppc_get_desired_perf(int cpunum, u64 *desired_perf);
- extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs);
- extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls);
-+extern int cppc_set_enable(int cpu, u32 enable);
- extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
- extern bool acpi_cpc_valid(void);
- extern int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data);
-@@ -157,6 +158,10 @@ static inline int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
- {
- return -ENOTSUPP;
- }
-+static inline int cppc_set_enable(int cpu, u32 enable)
-+{
-+ return -ENOTSUPP;
-+}
- static inline int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps)
- {
- return -ENOTSUPP;
---
-2.33.0
-
-From df9ad0b99a9f0e3371aa94e49fe92a2c2a9fa95d Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 18:04:45 +0800
-Subject: [PATCH 04/19] cpufreq: amd: introduce a new amd pstate driver to
- support future processors
-
-amd-pstate is the AMD CPU performance scaling driver that introduces a
-new CPU frequency control mechanism on AMD Zen based CPU series in Linux
-kernel. The new mechanism is based on Collaborative processor
-performance control (CPPC) which is finer grain frequency management
-than legacy ACPI hardware P-States. Current AMD CPU platforms are using
-the ACPI P-states driver to manage CPU frequency and clocks with
-switching only in 3 P-states. AMD P-States is to replace the ACPI
-P-states controls, allows a flexible, low-latency interface for the
-Linux kernel to directly communicate the performance hints to hardware.
-
-"amd-pstate" leverages the Linux kernel governors such as *schedutil*,
-*ondemand*, etc. to manage the performance hints which are provided by CPPC
-hardware functionality. The first version for amd-pstate is to support one
-of the Zen3 processors, and we will support more in future after we verify
-the hardware and SBIOS functionalities.
-
-There are two types of hardware implementations for amd-pstate: one is full
-MSR support and another is shared memory support. It can use
-X86_FEATURE_AMD_CPPC_EXT feature flag to distinguish the different types.
-
-Using the new AMD P-States method + kernel governors (*schedutil*,
-*ondemand*, ...) to manage the frequency update is the most appropriate
-bridge between AMD Zen based hardware processor and Linux kernel, the
-processor is able to ajust to the most efficiency frequency according to
-the kernel scheduler loading.
-
-Performance Per Watt (PPW) Caculation:
-
-The PPW caculation is referred by below paper:
-https://software.intel.com/content/dam/develop/external/us/en/documents/performance-per-what-paper.pdf
-
-Below formula is referred from below spec to measure the PPW:
-
-(F / t) / P = F * t / (t * E) = F / E,
-
-"F" is the number of frames per second.
-"P" is power measurd in watts.
-"E" is energy measured in joules.
-
-We use the RAPL interface with "perf" tool to get the energy data of the
-package power.
-
-The data comparsions between amd-pstate and acpi-freq module are tested on
-AMD Cezanne processor:
-
-1) TBench CPU benchmark:
-
-+---------------------------------------------------------------------+
-| |
-| TBench (Performance Per Watt) |
-| Higher is better |
-+-------------------+------------------------+------------------------+
-| | Performance Per Watt | Performance Per Watt |
-| Kernel Module | (Schedutil) | (Ondemand) |
-| | Unit: MB / (s * J) | Unit: MB / (s * J) |
-+-------------------+------------------------+------------------------+
-| | | |
-| acpi-cpufreq | 3.022 | 2.969 |
-| | | |
-+-------------------+------------------------+------------------------+
-| | | |
-| amd-pstate | 3.131 | 3.284 |
-| | | |
-+-------------------+------------------------+------------------------+
-
-2) Gitsource CPU benchmark:
-
-+---------------------------------------------------------------------+
-| |
-| Gitsource (Performance Per Watt) |
-| Higher is better |
-+-------------------+------------------------+------------------------+
-| | Performance Per Watt | Performance Per Watt |
-| Kernel Module | (Schedutil) | (Ondemand) |
-| | Unit: 1 / (s * J) | Unit: 1 / (s * J) |
-+-------------------+------------------------+------------------------+
-| | | |
-| acpi-cpufreq | 3.42172E-07 | 2.74508E-07 |
-| | | |
-+-------------------+------------------------+------------------------+
-| | | |
-| amd-pstate | 4.09141E-07 | 3.47610E-07 |
-| | | |
-+-------------------+------------------------+------------------------+
-
-3) Speedometer 2.0 CPU benchmark:
-
-+---------------------------------------------------------------------+
-| |
-| Speedometer 2.0 (Performance Per Watt) |
-| Higher is better |
-+-------------------+------------------------+------------------------+
-| | Performance Per Watt | Performance Per Watt |
-| Kernel Module | (Schedutil) | (Ondemand) |
-| | Unit: 1 / (s * J) | Unit: 1 / (s * J) |
-+-------------------+------------------------+------------------------+
-| | | |
-| acpi-cpufreq | 0.116111767 | 0.110321664 |
-| | | |
-+-------------------+------------------------+------------------------+
-| | | |
-| amd-pstate | 0.115825281 | 0.122024299 |
-| | | |
-+-------------------+------------------------+------------------------+
-
-According to above average data, we can see this solution has shown better
-performance per watt scaling on mobile CPU benchmarks in most of cases.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/Kconfig.x86 | 13 +
- drivers/cpufreq/Makefile | 1 +
- drivers/cpufreq/amd-pstate.c | 478 +++++++++++++++++++++++++++++++++++
- 3 files changed, 492 insertions(+)
- create mode 100644 drivers/cpufreq/amd-pstate.c
-
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index 92701a18bdd9..9cd7e338bdcd 100644
--- a/drivers/cpufreq/Kconfig.x86
@@ -311,23 +857,144 @@ index 92701a18bdd9..9cd7e338bdcd 100644
tristate "ACPI Processor P-States driver"
depends on ACPI_PROCESSOR
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
-index 27d3bd7ea9d4..3d4bd7141cf8 100644
+index 27d3bd7ea9d4..c1909475eaf9 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
-@@ -24,6 +24,7 @@ obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
+@@ -17,6 +17,10 @@ obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o
+ obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o
+ obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
+
++# Traces
++CFLAGS_amd-pstate-trace.o := -I$(src)
++amd_pstate-y := amd-pstate.o amd-pstate-trace.o
++
+ ##################################################################################
+ # x86 drivers.
+ # Link order matters. K8 is preferred to ACPI because of firmware bugs in early
+@@ -24,6 +28,7 @@ obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
# powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers.
# speedstep-* is preferred over p4-clockmod.
-+obj-$(CONFIG_X86_AMD_PSTATE) += amd-pstate.o
++obj-$(CONFIG_X86_AMD_PSTATE) += amd_pstate.o
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
+diff --git a/drivers/cpufreq/amd-pstate-trace.c b/drivers/cpufreq/amd-pstate-trace.c
+new file mode 100644
+index 000000000000..891b696dcd69
+--- /dev/null
++++ b/drivers/cpufreq/amd-pstate-trace.c
+@@ -0,0 +1,2 @@
++#define CREATE_TRACE_POINTS
++#include "amd-pstate-trace.h"
+diff --git a/drivers/cpufreq/amd-pstate-trace.h b/drivers/cpufreq/amd-pstate-trace.h
+new file mode 100644
+index 000000000000..50c85e150f30
+--- /dev/null
++++ b/drivers/cpufreq/amd-pstate-trace.h
+@@ -0,0 +1,96 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * amd-pstate-trace.h - AMD Processor P-state Frequency Driver Tracer
++ *
++ * Copyright (C) 2021 Advanced Micro Devices, Inc. All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * Author: Huang Rui <ray.huang@amd.com>
++ */
++
++#if !defined(_AMD_PSTATE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
++#define _AMD_PSTATE_TRACE_H
++
++#include <linux/cpufreq.h>
++#include <linux/tracepoint.h>
++#include <linux/trace_events.h>
++
++#undef TRACE_SYSTEM
++#define TRACE_SYSTEM amd_cpu
++
++#undef TRACE_INCLUDE_FILE
++#define TRACE_INCLUDE_FILE amd-pstate-trace
++
++#define TPS(x) tracepoint_string(x)
++
++TRACE_EVENT(amd_pstate_perf,
++
++ TP_PROTO(unsigned long min_perf,
++ unsigned long target_perf,
++ unsigned long capacity,
++ unsigned int cpu_id,
++ u64 prev,
++ u64 value,
++ int type
++ ),
++
++ TP_ARGS(min_perf,
++ target_perf,
++ capacity,
++ cpu_id,
++ prev,
++ value,
++ type
++ ),
++
++ TP_STRUCT__entry(
++ __field(unsigned long, min_perf)
++ __field(unsigned long, target_perf)
++ __field(unsigned long, capacity)
++ __field(unsigned int, cpu_id)
++ __field(u64, prev)
++ __field(u64, value)
++ __field(int, type)
++ ),
++
++ TP_fast_assign(
++ __entry->min_perf = min_perf;
++ __entry->target_perf = target_perf;
++ __entry->capacity = capacity;
++ __entry->cpu_id = cpu_id;
++ __entry->prev = prev;
++ __entry->value = value;
++ __entry->type = type;
++ ),
++
++ TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu cpu_id=%u prev=0x%llx value=0x%llx type=0x%d",
++ (unsigned long)__entry->min_perf,
++ (unsigned long)__entry->target_perf,
++ (unsigned long)__entry->capacity,
++ (unsigned int)__entry->cpu_id,
++ (u64)__entry->prev,
++ (u64)__entry->value,
++ (int)__entry->type
++ )
++);
++
++#endif /* _AMD_PSTATE_TRACE_H */
++
++/* This part must be outside protection */
++#undef TRACE_INCLUDE_PATH
++#define TRACE_INCLUDE_PATH .
++
++#include <trace/define_trace.h>
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
new file mode 100644
-index 000000000000..4c9c9bf1d72b
+index 000000000000..9c60388d45ed
--- /dev/null
+++ b/drivers/cpufreq/amd-pstate.c
-@@ -0,0 +1,478 @@
+@@ -0,0 +1,812 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * amd-pstate.c - AMD Processor P-state Frequency Driver
@@ -374,10 +1041,18 @@ index 000000000000..4c9c9bf1d72b
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
+#include <asm/cpu_device_id.h>
++#include "amd-pstate-trace.h"
+
+#define AMD_PSTATE_TRANSITION_LATENCY 0x20000
+#define AMD_PSTATE_TRANSITION_DELAY 500
+
++enum switch_type
++{
++ AMD_TARGET = 0,
++ AMD_ADJUST_PERF,
++ AMD_FAST_SWITCH,
++};
++
+static struct cpufreq_driver amd_pstate_driver;
+
+struct amd_cpudata {
@@ -397,6 +1072,8 @@ index 000000000000..4c9c9bf1d72b
+ u32 min_freq;
+ u32 nominal_freq;
+ u32 lowest_nonlinear_freq;
++
++ bool boost_supported;
+};
+
+struct amd_pstate_perf_funcs {
@@ -412,6 +1089,19 @@ index 000000000000..4c9c9bf1d72b
+ return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable ? 1 : 0);
+}
+
++static int cppc_enable(bool enable)
++{
++ int cpu, ret = 0;
++
++ for_each_online_cpu(cpu) {
++ ret = cppc_set_enable(cpu, enable ? 1 : 0);
++ if (ret)
++ return ret;
++ }
++
++ return ret;
++}
++
+static int
+amd_pstate_enable(struct amd_pstate_perf_funcs *funcs, bool enable)
+{
@@ -443,6 +1133,24 @@ index 000000000000..4c9c9bf1d72b
+ return 0;
+}
+
++static int cppc_init_perf(struct amd_cpudata *cpudata)
++{
++ struct cppc_perf_caps cppc_perf;
++
++ int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
++ if (ret)
++ return ret;
++
++ WRITE_ONCE(cpudata->highest_perf, amd_get_highest_perf());
++
++ WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
++ WRITE_ONCE(cpudata->lowest_nonlinear_perf,
++ cppc_perf.lowest_nonlinear_perf);
++ WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
++
++ return 0;
++}
++
+static int amd_pstate_init_perf(struct amd_cpudata *cpudata)
+{
+ struct amd_pstate_perf_funcs *funcs = cpufreq_get_driver_data();
@@ -464,6 +1172,19 @@ index 000000000000..4c9c9bf1d72b
+ READ_ONCE(cpudata->cppc_req_cached));
+}
+
++static void cppc_update_perf(struct amd_cpudata *cpudata,
++ u32 min_perf, u32 des_perf,
++ u32 max_perf, bool fast_switch)
++{
++ struct cppc_perf_ctrls perf_ctrls;
++
++ perf_ctrls.max_perf = max_perf;
++ perf_ctrls.min_perf = min_perf;
++ perf_ctrls.desired_perf = des_perf;
++
++ cppc_set_perf(cpudata->cpu, &perf_ctrls);
++}
++
+static int
+amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
+ u32 des_perf, u32 max_perf, bool fast_switch)
@@ -481,7 +1202,8 @@ index 000000000000..4c9c9bf1d72b
+
+static int
+amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
-+ u32 des_perf, u32 max_perf, bool fast_switch)
++ u32 des_perf, u32 max_perf, bool fast_switch,
++ enum switch_type type)
+{
+ u64 prev = READ_ONCE(cpudata->cppc_req_cached);
+ u64 value = prev;
@@ -495,6 +1217,8 @@ index 000000000000..4c9c9bf1d72b
+ value &= ~REQ_MAX_PERF(~0L);
+ value |= REQ_MAX_PERF(max_perf);
+
++ trace_amd_pstate_perf(min_perf, des_perf, max_perf,
++ cpudata->cpu, prev, value, type);
+ if (value == prev)
+ return 0;
+
@@ -504,6 +1228,19 @@ index 000000000000..4c9c9bf1d72b
+ max_perf, fast_switch);
+}
+
++static bool amd_pstate_boost_supported(struct amd_cpudata *cpudata)
++{
++ u32 highest_perf, nominal_perf;
++
++ highest_perf = READ_ONCE(cpudata->highest_perf);
++ nominal_perf = READ_ONCE(cpudata->nominal_perf);
++
++ if (highest_perf > nominal_perf)
++ return true;
++
++ return false;
++}
++
+static int amd_pstate_verify(struct cpufreq_policy_data *policy)
+{
+ cpufreq_verify_within_cpu_limits(policy);
@@ -536,12 +1273,72 @@ index 000000000000..4c9c9bf1d72b
+
+ cpufreq_freq_transition_begin(policy, &freqs);
+ ret = amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-+ amd_max_perf, false);
++ amd_max_perf, false, AMD_TARGET);
+ cpufreq_freq_transition_end(policy, &freqs, false);
+
+ return ret;
+}
+
++static void amd_pstate_adjust_perf(unsigned int cpu,
++ unsigned long min_perf,
++ unsigned long target_perf,
++ unsigned long capacity)
++{
++ unsigned long amd_max_perf, amd_min_perf, amd_des_perf,
++ amd_cap_perf, lowest_nonlinear_perf;
++ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
++ struct amd_cpudata *cpudata = policy->driver_data;
++
++ amd_cap_perf = READ_ONCE(cpudata->highest_perf);
++ lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
++
++ if (target_perf < capacity)
++ amd_des_perf = DIV_ROUND_UP(amd_cap_perf * target_perf,
++ capacity);
++
++ amd_min_perf = READ_ONCE(cpudata->highest_perf);
++ if (min_perf < capacity)
++ amd_min_perf = DIV_ROUND_UP(amd_cap_perf * min_perf, capacity);
++
++ if (amd_min_perf < lowest_nonlinear_perf)
++ amd_min_perf = lowest_nonlinear_perf;
++
++ amd_max_perf = amd_cap_perf;
++ if (amd_max_perf < amd_min_perf)
++ amd_max_perf = amd_min_perf;
++
++ amd_des_perf = clamp_t(unsigned long, amd_des_perf,
++ amd_min_perf, amd_max_perf);
++
++ amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
++ amd_max_perf, true, AMD_ADJUST_PERF);
++}
++
++static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
++ unsigned int target_freq)
++{
++ u64 ratio;
++ struct amd_cpudata *cpudata = policy->driver_data;
++ unsigned long amd_max_perf, amd_min_perf, amd_des_perf, nominal_perf;
++
++ if (!cpudata->max_freq)
++ return -ENODEV;
++
++ amd_max_perf = READ_ONCE(cpudata->highest_perf);
++ amd_min_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
++
++ amd_des_perf = DIV_ROUND_UP(target_freq * amd_max_perf,
++ cpudata->max_freq);
++
++ amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
++ amd_max_perf, true, AMD_FAST_SWITCH);
++
++ nominal_perf = READ_ONCE(cpudata->nominal_perf);
++ ratio = div_u64(amd_des_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
++
++ return cpudata->nominal_freq * ratio >> SCHED_CAPACITY_SHIFT;
++}
++
+static int amd_get_min_freq(struct amd_cpudata *cpudata)
+{
+ struct cppc_perf_caps cppc_perf;
@@ -617,6 +1414,37 @@ index 000000000000..4c9c9bf1d72b
+ return lowest_nonlinear_freq * 1000;
+}
+
++static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
++{
++ struct amd_cpudata *cpudata = policy->driver_data;
++ int ret;
++
++ if (!cpudata->boost_supported) {
++ pr_err("Boost mode is not supported by this processor or SBIOS\n");
++ return -EINVAL;
++ }
++
++ if (state)
++ policy->cpuinfo.max_freq = cpudata->max_freq;
++ else
++ policy->cpuinfo.max_freq = cpudata->nominal_freq;
++
++ policy->max = policy->cpuinfo.max_freq;
++
++ ret = freq_qos_update_request(&cpudata->req[1],
++ policy->cpuinfo.max_freq);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
++static void amd_pstate_boost_init(struct amd_cpudata *cpudata)
++{
++ cpudata->boost_supported = true;
++ amd_pstate_driver.boost_enabled = true;
++}
++
+static int amd_pstate_init_freqs_in_cpudata(struct amd_cpudata *cpudata,
+ u32 max_freq, u32 min_freq,
+ u32 nominal_freq,
@@ -640,6 +1468,12 @@ index 000000000000..4c9c9bf1d72b
+ .update_perf = pstate_update_perf,
+};
+
++static struct amd_pstate_perf_funcs cppc_funcs = {
++ .enable = cppc_enable,
++ .init_perf = cppc_init_perf,
++ .update_perf = cppc_update_perf,
++};
++
+static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+{
+ int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
@@ -686,6 +1520,9 @@ index 000000000000..4c9c9bf1d72b
+ /* It will be updated by governor */
+ policy->cur = policy->cpuinfo.min_freq;
+
++ if (boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT))
++ policy->fast_switch_possible = true;
++
+ ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
+ FREQ_QOS_MIN, policy->cpuinfo.min_freq);
+ if (ret < 0) {
@@ -710,6 +1547,9 @@ index 000000000000..4c9c9bf1d72b
+
+ policy->driver_data = cpudata;
+
++ if (amd_pstate_boost_supported(cpudata))
++ amd_pstate_boost_init(cpudata);
++
+ return 0;
+
+free_cpudata3:
@@ -734,730 +1574,10 @@ index 000000000000..4c9c9bf1d72b
+ return 0;
+}
+
-+static struct cpufreq_driver amd_pstate_driver = {
-+ .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
-+ .verify = amd_pstate_verify,
-+ .target = amd_pstate_target,
-+ .init = amd_pstate_cpu_init,
-+ .exit = amd_pstate_cpu_exit,
-+ .name = "amd-pstate",
-+};
-+
-+static int __init amd_pstate_init(void)
-+{
-+ int ret;
-+ struct amd_pstate_perf_funcs *funcs;
-+
-+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
-+ return -ENODEV;
-+
-+ if (!acpi_cpc_valid()) {
-+ pr_debug("%s, the _CPC object is not present in SBIOS\n",
-+ __func__);
-+ return -ENODEV;
-+ }
-+
-+ /* don't keep reloading if cpufreq_driver exists */
-+ if (cpufreq_get_current_driver())
-+ return -EEXIST;
-+
-+ /* capability check */
-+ if (!boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT)) {
-+ pr_debug("%s, AMD CPPC extension functionality is supported\n",
-+ __func__);
-+ return -ENODEV;
-+ }
-+
-+ funcs = &pstate_funcs;
-+
-+ /* enable amd pstate feature */
-+ ret = amd_pstate_enable(funcs, true);
-+ if (ret) {
-+ pr_err("%s, failed to enable amd-pstate with return %d\n",
-+ __func__, ret);
-+ return ret;
-+ }
-+
-+ amd_pstate_driver.driver_data = funcs;
-+
-+ ret = cpufreq_register_driver(&amd_pstate_driver);
-+ if (ret) {
-+ pr_err("%s, return %d\n", __func__, ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static void __exit amd_pstate_exit(void)
-+{
-+ struct amd_pstate_perf_funcs *funcs;
-+
-+ funcs = cpufreq_get_driver_data();
-+
-+ cpufreq_unregister_driver(&amd_pstate_driver);
-+
-+ amd_pstate_enable(funcs, false);
-+}
-+
-+module_init(amd_pstate_init);
-+module_exit(amd_pstate_exit);
-+
-+MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>");
-+MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver");
-+MODULE_LICENSE("GPL");
---
-2.33.0
-
-From 54beca4738acc38c08710cfcb1c3312755000cf6 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Fri, 13 Aug 2021 18:43:47 +0800
-Subject: [PATCH 05/19] cpufreq: amd: add fast switch function for amd-pstate
- module
-
-Introduce the fast switch function for amd-pstate module on the AMD
-processors which support the full MSR register control. It's able to
-decrease the lattency on interrupt context.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/amd-pstate.c | 64 ++++++++++++++++++++++++++++++++++++
- 1 file changed, 64 insertions(+)
-
-diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 4c9c9bf1d72b..32b4f6d79783 100644
---- a/drivers/cpufreq/amd-pstate.c
-+++ b/drivers/cpufreq/amd-pstate.c
-@@ -212,6 +212,66 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
- return ret;
- }
-
-+static void amd_pstate_adjust_perf(unsigned int cpu,
-+ unsigned long min_perf,
-+ unsigned long target_perf,
-+ unsigned long capacity)
-+{
-+ unsigned long amd_max_perf, amd_min_perf, amd_des_perf,
-+ amd_cap_perf, lowest_nonlinear_perf;
-+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+
-+ amd_cap_perf = READ_ONCE(cpudata->highest_perf);
-+ lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
-+
-+ if (target_perf < capacity)
-+ amd_des_perf = DIV_ROUND_UP(amd_cap_perf * target_perf,
-+ capacity);
-+
-+ amd_min_perf = READ_ONCE(cpudata->highest_perf);
-+ if (min_perf < capacity)
-+ amd_min_perf = DIV_ROUND_UP(amd_cap_perf * min_perf, capacity);
-+
-+ if (amd_min_perf < lowest_nonlinear_perf)
-+ amd_min_perf = lowest_nonlinear_perf;
-+
-+ amd_max_perf = amd_cap_perf;
-+ if (amd_max_perf < amd_min_perf)
-+ amd_max_perf = amd_min_perf;
-+
-+ amd_des_perf = clamp_t(unsigned long, amd_des_perf,
-+ amd_min_perf, amd_max_perf);
-+
-+ amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-+ amd_max_perf, true);
-+}
-+
-+static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
-+ unsigned int target_freq)
-+{
-+ u64 ratio;
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+ unsigned long amd_max_perf, amd_min_perf, amd_des_perf, nominal_perf;
-+
-+ if (!cpudata->max_freq)
-+ return -ENODEV;
-+
-+ amd_max_perf = READ_ONCE(cpudata->highest_perf);
-+ amd_min_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
-+
-+ amd_des_perf = DIV_ROUND_UP(target_freq * amd_max_perf,
-+ cpudata->max_freq);
-+
-+ amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-+ amd_max_perf, true);
-+
-+ nominal_perf = READ_ONCE(cpudata->nominal_perf);
-+ ratio = div_u64(amd_des_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
-+
-+ return cpudata->nominal_freq * ratio >> SCHED_CAPACITY_SHIFT;
-+}
-+
- static int amd_get_min_freq(struct amd_cpudata *cpudata)
- {
- struct cppc_perf_caps cppc_perf;
-@@ -356,6 +416,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
- /* It will be updated by governor */
- policy->cur = policy->cpuinfo.min_freq;
-
-+ policy->fast_switch_possible = true;
-+
- ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
- FREQ_QOS_MIN, policy->cpuinfo.min_freq);
- if (ret < 0) {
-@@ -408,6 +470,8 @@ static struct cpufreq_driver amd_pstate_driver = {
- .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
- .verify = amd_pstate_verify,
- .target = amd_pstate_target,
-+ .fast_switch = amd_pstate_fast_switch,
-+ .adjust_perf = amd_pstate_adjust_perf,
- .init = amd_pstate_cpu_init,
- .exit = amd_pstate_cpu_exit,
- .name = "amd-pstate",
---
-2.33.0
-
-From ad7cc7a238ee889b9001d95fef83172763b95939 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Mon, 9 Aug 2021 19:06:51 +0800
-Subject: [PATCH 06/19] cpufreq: amd: add acpi cppc function as the backend for
- legacy processors
-
-In some old Zen based processors, they are using the shared memory that
-exposed from ACPI SBIOS.
-
-Signed-off-by: Jinzhou Su <Jinzhou.Su@amd.com>
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/amd-pstate.c | 63 ++++++++++++++++++++++++++++++++----
- 1 file changed, 57 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 32b4f6d79783..a46cd5dd9f7c 100644
---- a/drivers/cpufreq/amd-pstate.c
-+++ b/drivers/cpufreq/amd-pstate.c
-@@ -82,6 +82,19 @@ static inline int pstate_enable(bool enable)
- return wrmsrl_safe(MSR_AMD_CPPC_ENABLE, enable ? 1 : 0);
- }
-
-+static int cppc_enable(bool enable)
-+{
-+ int cpu, ret = 0;
-+
-+ for_each_online_cpu(cpu) {
-+ ret = cppc_set_enable(cpu, enable ? 1 : 0);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ return ret;
-+}
-+
- static int
- amd_pstate_enable(struct amd_pstate_perf_funcs *funcs, bool enable)
- {
-@@ -113,6 +126,24 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
- return 0;
- }
-
-+static int cppc_init_perf(struct amd_cpudata *cpudata)
-+{
-+ struct cppc_perf_caps cppc_perf;
-+
-+ int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
-+ if (ret)
-+ return ret;
-+
-+ WRITE_ONCE(cpudata->highest_perf, amd_get_highest_perf());
-+
-+ WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
-+ WRITE_ONCE(cpudata->lowest_nonlinear_perf,
-+ cppc_perf.lowest_nonlinear_perf);
-+ WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
-+
-+ return 0;
-+}
-+
- static int amd_pstate_init_perf(struct amd_cpudata *cpudata)
- {
- struct amd_pstate_perf_funcs *funcs = cpufreq_get_driver_data();
-@@ -134,6 +165,19 @@ static void pstate_update_perf(struct amd_cpudata *cpudata,
- READ_ONCE(cpudata->cppc_req_cached));
- }
-
-+static void cppc_update_perf(struct amd_cpudata *cpudata,
-+ u32 min_perf, u32 des_perf,
-+ u32 max_perf, bool fast_switch)
-+{
-+ struct cppc_perf_ctrls perf_ctrls;
-+
-+ perf_ctrls.max_perf = max_perf;
-+ perf_ctrls.min_perf = min_perf;
-+ perf_ctrls.desired_perf = des_perf;
-+
-+ cppc_set_perf(cpudata->cpu, &perf_ctrls);
-+}
-+
- static int
- amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
- u32 des_perf, u32 max_perf, bool fast_switch)
-@@ -370,6 +414,12 @@ static struct amd_pstate_perf_funcs pstate_funcs = {
- .update_perf = pstate_update_perf,
- };
-
-+static struct amd_pstate_perf_funcs cppc_funcs = {
-+ .enable = cppc_enable,
-+ .init_perf = cppc_init_perf,
-+ .update_perf = cppc_update_perf,
-+};
-+
- static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
- {
- int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
-@@ -416,7 +466,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
- /* It will be updated by governor */
- policy->cur = policy->cpuinfo.min_freq;
-
-- policy->fast_switch_possible = true;
-+ if (boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT))
-+ policy->fast_switch_possible = true;
-
- ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
- FREQ_QOS_MIN, policy->cpuinfo.min_freq);
-@@ -471,7 +522,6 @@ static struct cpufreq_driver amd_pstate_driver = {
- .verify = amd_pstate_verify,
- .target = amd_pstate_target,
- .fast_switch = amd_pstate_fast_switch,
-- .adjust_perf = amd_pstate_adjust_perf,
- .init = amd_pstate_cpu_init,
- .exit = amd_pstate_cpu_exit,
- .name = "amd-pstate",
-@@ -496,14 +546,15 @@ static int __init amd_pstate_init(void)
- return -EEXIST;
-
- /* capability check */
-- if (!boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT)) {
-+ if (boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT)) {
- pr_debug("%s, AMD CPPC extension functionality is supported\n",
- __func__);
-- return -ENODEV;
-+ funcs = &pstate_funcs;
-+ amd_pstate_driver.adjust_perf = amd_pstate_adjust_perf;
-+ } else {
-+ funcs = &cppc_funcs;
- }
-
-- funcs = &pstate_funcs;
--
- /* enable amd pstate feature */
- ret = amd_pstate_enable(funcs, true);
- if (ret) {
---
-2.33.0
-
-From e007c18166d11d78757454ebfac967ae460ebf08 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 20:24:00 +0800
-Subject: [PATCH 07/19] cpufreq: amd: add trace for amd-pstate module
-
-Add trace event to monitor the performance value changes which is
-controlled by cpu governors.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/Makefile | 6 +-
- drivers/cpufreq/amd-pstate-trace.c | 2 +
- drivers/cpufreq/amd-pstate-trace.h | 96 ++++++++++++++++++++++++++++++
- drivers/cpufreq/amd-pstate.c | 19 ++++--
- 4 files changed, 118 insertions(+), 5 deletions(-)
- create mode 100644 drivers/cpufreq/amd-pstate-trace.c
- create mode 100644 drivers/cpufreq/amd-pstate-trace.h
-
-diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
-index 3d4bd7141cf8..c1909475eaf9 100644
---- a/drivers/cpufreq/Makefile
-+++ b/drivers/cpufreq/Makefile
-@@ -17,6 +17,10 @@ obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o
- obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o
- obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
-
-+# Traces
-+CFLAGS_amd-pstate-trace.o := -I$(src)
-+amd_pstate-y := amd-pstate.o amd-pstate-trace.o
-+
- ##################################################################################
- # x86 drivers.
- # Link order matters. K8 is preferred to ACPI because of firmware bugs in early
-@@ -24,7 +28,7 @@ obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o
- # powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers.
- # speedstep-* is preferred over p4-clockmod.
-
--obj-$(CONFIG_X86_AMD_PSTATE) += amd-pstate.o
-+obj-$(CONFIG_X86_AMD_PSTATE) += amd_pstate.o
- obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
- obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
- obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
-diff --git a/drivers/cpufreq/amd-pstate-trace.c b/drivers/cpufreq/amd-pstate-trace.c
-new file mode 100644
-index 000000000000..891b696dcd69
---- /dev/null
-+++ b/drivers/cpufreq/amd-pstate-trace.c
-@@ -0,0 +1,2 @@
-+#define CREATE_TRACE_POINTS
-+#include "amd-pstate-trace.h"
-diff --git a/drivers/cpufreq/amd-pstate-trace.h b/drivers/cpufreq/amd-pstate-trace.h
-new file mode 100644
-index 000000000000..50c85e150f30
---- /dev/null
-+++ b/drivers/cpufreq/amd-pstate-trace.h
-@@ -0,0 +1,96 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * amd-pstate-trace.h - AMD Processor P-state Frequency Driver Tracer
-+ *
-+ * Copyright (C) 2021 Advanced Micro Devices, Inc. All Rights Reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version 2
-+ * of the License, or (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-+ *
-+ * Author: Huang Rui <ray.huang@amd.com>
-+ */
-+
-+#if !defined(_AMD_PSTATE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
-+#define _AMD_PSTATE_TRACE_H
-+
-+#include <linux/cpufreq.h>
-+#include <linux/tracepoint.h>
-+#include <linux/trace_events.h>
-+
-+#undef TRACE_SYSTEM
-+#define TRACE_SYSTEM amd_cpu
-+
-+#undef TRACE_INCLUDE_FILE
-+#define TRACE_INCLUDE_FILE amd-pstate-trace
-+
-+#define TPS(x) tracepoint_string(x)
-+
-+TRACE_EVENT(amd_pstate_perf,
-+
-+ TP_PROTO(unsigned long min_perf,
-+ unsigned long target_perf,
-+ unsigned long capacity,
-+ unsigned int cpu_id,
-+ u64 prev,
-+ u64 value,
-+ int type
-+ ),
-+
-+ TP_ARGS(min_perf,
-+ target_perf,
-+ capacity,
-+ cpu_id,
-+ prev,
-+ value,
-+ type
-+ ),
-+
-+ TP_STRUCT__entry(
-+ __field(unsigned long, min_perf)
-+ __field(unsigned long, target_perf)
-+ __field(unsigned long, capacity)
-+ __field(unsigned int, cpu_id)
-+ __field(u64, prev)
-+ __field(u64, value)
-+ __field(int, type)
-+ ),
-+
-+ TP_fast_assign(
-+ __entry->min_perf = min_perf;
-+ __entry->target_perf = target_perf;
-+ __entry->capacity = capacity;
-+ __entry->cpu_id = cpu_id;
-+ __entry->prev = prev;
-+ __entry->value = value;
-+ __entry->type = type;
-+ ),
-+
-+ TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu cpu_id=%u prev=0x%llx value=0x%llx type=0x%d",
-+ (unsigned long)__entry->min_perf,
-+ (unsigned long)__entry->target_perf,
-+ (unsigned long)__entry->capacity,
-+ (unsigned int)__entry->cpu_id,
-+ (u64)__entry->prev,
-+ (u64)__entry->value,
-+ (int)__entry->type
-+ )
-+);
-+
-+#endif /* _AMD_PSTATE_TRACE_H */
-+
-+/* This part must be outside protection */
-+#undef TRACE_INCLUDE_PATH
-+#define TRACE_INCLUDE_PATH .
-+
-+#include <trace/define_trace.h>
-diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index a46cd5dd9f7c..ea965a122431 100644
---- a/drivers/cpufreq/amd-pstate.c
-+++ b/drivers/cpufreq/amd-pstate.c
-@@ -44,10 +44,18 @@
- #include <asm/processor.h>
- #include <asm/cpufeature.h>
- #include <asm/cpu_device_id.h>
-+#include "amd-pstate-trace.h"
-
- #define AMD_PSTATE_TRANSITION_LATENCY 0x20000
- #define AMD_PSTATE_TRANSITION_DELAY 500
-
-+enum switch_type
-+{
-+ AMD_TARGET = 0,
-+ AMD_ADJUST_PERF,
-+ AMD_FAST_SWITCH,
-+};
-+
- static struct cpufreq_driver amd_pstate_driver;
-
- struct amd_cpudata {
-@@ -195,7 +203,8 @@ amd_pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
-
- static int
- amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
-- u32 des_perf, u32 max_perf, bool fast_switch)
-+ u32 des_perf, u32 max_perf, bool fast_switch,
-+ enum switch_type type)
- {
- u64 prev = READ_ONCE(cpudata->cppc_req_cached);
- u64 value = prev;
-@@ -209,6 +218,8 @@ amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
- value &= ~REQ_MAX_PERF(~0L);
- value |= REQ_MAX_PERF(max_perf);
-
-+ trace_amd_pstate_perf(min_perf, des_perf, max_perf,
-+ cpudata->cpu, prev, value, type);
- if (value == prev)
- return 0;
-
-@@ -250,7 +261,7 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
-
- cpufreq_freq_transition_begin(policy, &freqs);
- ret = amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-- amd_max_perf, false);
-+ amd_max_perf, false, AMD_TARGET);
- cpufreq_freq_transition_end(policy, &freqs, false);
-
- return ret;
-@@ -288,7 +299,7 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
- amd_min_perf, amd_max_perf);
-
- amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-- amd_max_perf, true);
-+ amd_max_perf, true, AMD_ADJUST_PERF);
- }
-
- static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
-@@ -308,7 +319,7 @@ static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
- cpudata->max_freq);
-
- amd_pstate_update(cpudata, amd_min_perf, amd_des_perf,
-- amd_max_perf, true);
-+ amd_max_perf, true, AMD_FAST_SWITCH);
-
- nominal_perf = READ_ONCE(cpudata->nominal_perf);
- ratio = div_u64(amd_des_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
---
-2.33.0
-
-From 24ab2966561da669b9879a6167e2cc7e5929735c Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 23:13:00 +0800
-Subject: [PATCH 08/19] cpufreq: amd: add boost mode support for amd-pstate
-
-If the sbios supports the boost mode of amd-pstate, let's switch to
-boost enabled by default.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/amd-pstate.c | 50 ++++++++++++++++++++++++++++++++++++
- 1 file changed, 50 insertions(+)
-
-diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index ea965a122431..67a9a117f524 100644
---- a/drivers/cpufreq/amd-pstate.c
-+++ b/drivers/cpufreq/amd-pstate.c
-@@ -75,6 +75,8 @@ struct amd_cpudata {
- u32 min_freq;
- u32 nominal_freq;
- u32 lowest_nonlinear_freq;
-+
-+ bool boost_supported;
- };
-
- struct amd_pstate_perf_funcs {
-@@ -229,6 +231,19 @@ amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
- max_perf, fast_switch);
- }
-
-+static bool amd_pstate_boost_supported(struct amd_cpudata *cpudata)
-+{
-+ u32 highest_perf, nominal_perf;
-+
-+ highest_perf = READ_ONCE(cpudata->highest_perf);
-+ nominal_perf = READ_ONCE(cpudata->nominal_perf);
-+
-+ if (highest_perf > nominal_perf)
-+ return true;
-+
-+ return false;
-+}
-+
- static int amd_pstate_verify(struct cpufreq_policy_data *policy)
- {
- cpufreq_verify_within_cpu_limits(policy);
-@@ -402,6 +417,37 @@ static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata)
- return lowest_nonlinear_freq * 1000;
- }
-
-+static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
-+{
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+ int ret;
-+
-+ if (!cpudata->boost_supported) {
-+ pr_err("Boost mode is not supported by this processor or SBIOS\n");
-+ return -EINVAL;
-+ }
-+
-+ if (state)
-+ policy->cpuinfo.max_freq = cpudata->max_freq;
-+ else
-+ policy->cpuinfo.max_freq = cpudata->nominal_freq;
-+
-+ policy->max = policy->cpuinfo.max_freq;
-+
-+ ret = freq_qos_update_request(&cpudata->req[1],
-+ policy->cpuinfo.max_freq);
-+ if (ret < 0)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+static void amd_pstate_boost_init(struct amd_cpudata *cpudata)
-+{
-+ cpudata->boost_supported = true;
-+ amd_pstate_driver.boost_enabled = true;
-+}
-+
- static int amd_pstate_init_freqs_in_cpudata(struct amd_cpudata *cpudata,
- u32 max_freq, u32 min_freq,
- u32 nominal_freq,
-@@ -504,6 +550,9 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
-
- policy->driver_data = cpudata;
-
-+ if (amd_pstate_boost_supported(cpudata))
-+ amd_pstate_boost_init(cpudata);
-+
- return 0;
-
- free_cpudata3:
-@@ -535,6 +584,7 @@ static struct cpufreq_driver amd_pstate_driver = {
- .fast_switch = amd_pstate_fast_switch,
- .init = amd_pstate_cpu_init,
- .exit = amd_pstate_cpu_exit,
-+ .set_boost = amd_pstate_set_boost,
- .name = "amd-pstate",
- };
-
---
-2.33.0
-
-From fdbec5a44fab1213e459312b542e27dc0181d7e4 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sat, 19 Jun 2021 23:41:30 +0800
-Subject: [PATCH 09/19] cpufreq: amd: add amd-pstate checking support check
- attribute
-
-The amd-pstate hardware support check will be needed by cpupower to know
-whether amd-pstate is enabled and supported.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/amd-pstate.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 67a9a117f524..48dedd5af101 100644
---- a/drivers/cpufreq/amd-pstate.c
-+++ b/drivers/cpufreq/amd-pstate.c
-@@ -577,6 +577,19 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
- return 0;
- }
-
-+static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
-+ char *buf)
-+{
-+ return sprintf(&buf[0], "%d\n", acpi_cpc_valid() ? 1 : 0);
-+}
-+
-+cpufreq_freq_attr_ro(is_amd_pstate_enabled);
-+
-+static struct freq_attr *amd_pstate_attr[] = {
-+ &is_amd_pstate_enabled,
-+ NULL,
-+};
-+
- static struct cpufreq_driver amd_pstate_driver = {
- .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
- .verify = amd_pstate_verify,
-@@ -586,6 +599,7 @@ static struct cpufreq_driver amd_pstate_driver = {
- .exit = amd_pstate_cpu_exit,
- .set_boost = amd_pstate_set_boost,
- .name = "amd-pstate",
-+ .attr = amd_pstate_attr,
- };
-
- static int __init amd_pstate_init(void)
---
-2.33.0
-
-From 4043d05067a68c58255a6759c528bb78db656327 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 13:26:01 +0800
-Subject: [PATCH 10/19] cpufreq: amd: add amd-pstate frequencies attributes
-
-Introduce sysfs attributes to get the different level processor
-frequencies.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/amd-pstate.c | 80 +++++++++++++++++++++++++++++++++++-
- 1 file changed, 79 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 48dedd5af101..3c727a22cb69 100644
---- a/drivers/cpufreq/amd-pstate.c
-+++ b/drivers/cpufreq/amd-pstate.c
-@@ -577,16 +577,94 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
- return 0;
- }
-
--static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
+/* Sysfs attributes */
+
+static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy,
- char *buf)
++ char *buf)
+{
+ int ret = 0, max_freq;
+ struct amd_cpudata *cpudata;
@@ -1524,51 +1644,6 @@ index 48dedd5af101..3c727a22cb69 100644
+ return ret;
+}
+
-+static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
-+ char *buf)
- {
- return sprintf(&buf[0], "%d\n", acpi_cpc_valid() ? 1 : 0);
- }
-
- cpufreq_freq_attr_ro(is_amd_pstate_enabled);
-+cpufreq_freq_attr_ro(amd_pstate_max_freq);
-+cpufreq_freq_attr_ro(amd_pstate_nominal_freq);
-+cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
-+cpufreq_freq_attr_ro(amd_pstate_min_freq);
-
- static struct freq_attr *amd_pstate_attr[] = {
- &is_amd_pstate_enabled,
-+ &amd_pstate_max_freq,
-+ &amd_pstate_nominal_freq,
-+ &amd_pstate_lowest_nonlinear_freq,
-+ &amd_pstate_min_freq,
- NULL,
- };
-
---
-2.33.0
-
-From 4b56a82d37ecb8e9f9df2d0b055939577ff147cf Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 15:01:08 +0800
-Subject: [PATCH 11/19] cpufreq: amd: add amd-pstate performance attributes
-
-Introduce sysfs attributes to get the different level amd-pstate
-performances.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- drivers/cpufreq/amd-pstate.c | 66 ++++++++++++++++++++++++++++++++++++
- 1 file changed, 66 insertions(+)
-
-diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 3c727a22cb69..9c60388d45ed 100644
---- a/drivers/cpufreq/amd-pstate.c
-+++ b/drivers/cpufreq/amd-pstate.c
-@@ -647,6 +647,62 @@ static ssize_t show_amd_pstate_min_freq(struct cpufreq_policy *policy, char *buf
- return ret;
- }
-
+static ssize_t
+show_amd_pstate_highest_perf(struct cpufreq_policy *policy, char *buf)
+{
@@ -1625,187 +1700,138 @@ index 3c727a22cb69..9c60388d45ed 100644
+ return ret;
+}
+
- static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
- char *buf)
- {
-@@ -654,17 +710,27 @@ static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
- }
-
- cpufreq_freq_attr_ro(is_amd_pstate_enabled);
++static ssize_t show_is_amd_pstate_enabled(struct cpufreq_policy *policy,
++ char *buf)
++{
++ return sprintf(&buf[0], "%d\n", acpi_cpc_valid() ? 1 : 0);
++}
++
++cpufreq_freq_attr_ro(is_amd_pstate_enabled);
++
++cpufreq_freq_attr_ro(amd_pstate_max_freq);
++cpufreq_freq_attr_ro(amd_pstate_nominal_freq);
++cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
++cpufreq_freq_attr_ro(amd_pstate_min_freq);
+
- cpufreq_freq_attr_ro(amd_pstate_max_freq);
- cpufreq_freq_attr_ro(amd_pstate_nominal_freq);
- cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
- cpufreq_freq_attr_ro(amd_pstate_min_freq);
-
+cpufreq_freq_attr_ro(amd_pstate_highest_perf);
+cpufreq_freq_attr_ro(amd_pstate_nominal_perf);
+cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_perf);
+cpufreq_freq_attr_ro(amd_pstate_lowest_perf);
+
- static struct freq_attr *amd_pstate_attr[] = {
- &is_amd_pstate_enabled,
- &amd_pstate_max_freq,
- &amd_pstate_nominal_freq,
- &amd_pstate_lowest_nonlinear_freq,
- &amd_pstate_min_freq,
++static struct freq_attr *amd_pstate_attr[] = {
++ &is_amd_pstate_enabled,
++ &amd_pstate_max_freq,
++ &amd_pstate_nominal_freq,
++ &amd_pstate_lowest_nonlinear_freq,
++ &amd_pstate_min_freq,
+ &amd_pstate_highest_perf,
+ &amd_pstate_nominal_perf,
+ &amd_pstate_lowest_nonlinear_perf,
+ &amd_pstate_lowest_perf,
- NULL,
- };
-
---
-2.33.0
-
-From 5b16452c4363a46a28bd65a00a4a3282bdb7ec69 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Mon, 14 Jun 2021 22:52:01 +0800
-Subject: [PATCH 12/19] cpupower: add AMD P-state capability flag
-
-Add AMD P-state capability flag in cpupower to indicate AMD new P-state
-kernel module support on Ryzen processors.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- tools/power/cpupower/utils/helpers/helpers.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
-index 33ffacee7fcb..b4813efdfb00 100644
---- a/tools/power/cpupower/utils/helpers/helpers.h
-+++ b/tools/power/cpupower/utils/helpers/helpers.h
-@@ -73,6 +73,7 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
- #define CPUPOWER_CAP_AMD_HW_PSTATE 0x00000100
- #define CPUPOWER_CAP_AMD_PSTATEDEF 0x00000200
- #define CPUPOWER_CAP_AMD_CPB_MSR 0x00000400
-+#define CPUPOWER_CAP_AMD_PSTATE 0x00000800
-
- #define CPUPOWER_AMD_CPBDIS 0x02000000
-
---
-2.33.0
-
-From 456b88736d16414c3cce9dd5101b05dfe38baa18 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 27 Jun 2021 22:25:39 +0800
-Subject: [PATCH 13/19] cpupower: add the function to check amd-pstate enabled
-
-Introduce the cpupower_amd_pstate_enabled() to check whether the kernel
-mode enables amd-pstate.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- tools/power/cpupower/utils/helpers/helpers.h | 5 +++++
- tools/power/cpupower/utils/helpers/misc.c | 20 ++++++++++++++++++++
- 2 files changed, 25 insertions(+)
-
-diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
-index b4813efdfb00..eb43c14d1728 100644
---- a/tools/power/cpupower/utils/helpers/helpers.h
-+++ b/tools/power/cpupower/utils/helpers/helpers.h
-@@ -136,6 +136,11 @@ extern int decode_pstates(unsigned int cpu, int boost_states,
-
- extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
- int *active, int * states);
-+
-+/* AMD PSTATE enabling **************************/
++ NULL,
++};
+
-+extern unsigned long cpupower_amd_pstate_enabled(unsigned int cpu);
++static struct cpufreq_driver amd_pstate_driver = {
++ .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
++ .verify = amd_pstate_verify,
++ .target = amd_pstate_target,
++ .fast_switch = amd_pstate_fast_switch,
++ .init = amd_pstate_cpu_init,
++ .exit = amd_pstate_cpu_exit,
++ .set_boost = amd_pstate_set_boost,
++ .name = "amd-pstate",
++ .attr = amd_pstate_attr,
++};
+
- /*
- * CPUID functions returning a single datum
- */
-diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
-index fc6e34511721..07d80775fb68 100644
---- a/tools/power/cpupower/utils/helpers/misc.c
-+++ b/tools/power/cpupower/utils/helpers/misc.c
-@@ -83,6 +83,26 @@ int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
- return 0;
- }
-
-+unsigned long cpupower_amd_pstate_enabled(unsigned int cpu)
++static int __init amd_pstate_init(void)
+{
-+ char linebuf[MAX_LINE_LEN];
-+ char path[SYSFS_PATH_MAX];
-+ unsigned long val;
-+ char *endp;
++ int ret;
++ struct amd_pstate_perf_funcs *funcs;
+
-+ snprintf(path, sizeof(path),
-+ PATH_TO_CPU "cpu%u/cpufreq/is_amd_pstate_enabled", cpu);
++ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
++ return -ENODEV;
+
-+ if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0)
-+ return 0;
++ if (!acpi_cpc_valid()) {
++ pr_debug("%s, the _CPC object is not present in SBIOS\n",
++ __func__);
++ return -ENODEV;
++ }
+
-+ val = strtoul(linebuf, &endp, 0);
-+ if (endp == linebuf || errno == ERANGE)
-+ return 0;
++ /* don't keep reloading if cpufreq_driver exists */
++ if (cpufreq_get_current_driver())
++ return -EEXIST;
+
-+ return val;
++ /* capability check */
++ if (boot_cpu_has(X86_FEATURE_AMD_CPPC_EXT)) {
++ pr_debug("%s, AMD CPPC extension functionality is supported\n",
++ __func__);
++ funcs = &pstate_funcs;
++ amd_pstate_driver.adjust_perf = amd_pstate_adjust_perf;
++ } else {
++ funcs = &cppc_funcs;
++ }
++
++ /* enable amd pstate feature */
++ ret = amd_pstate_enable(funcs, true);
++ if (ret) {
++ pr_err("%s, failed to enable amd-pstate with return %d\n",
++ __func__, ret);
++ return ret;
++ }
++
++ amd_pstate_driver.driver_data = funcs;
++
++ ret = cpufreq_register_driver(&amd_pstate_driver);
++ if (ret) {
++ pr_err("%s, return %d\n", __func__, ret);
++ return ret;
++ }
++
++ return 0;
+}
+
- #endif /* #if defined(__i386__) || defined(__x86_64__) */
-
- /* get_cpustate
---
-2.33.0
-
-From 9537cd2a2aa718faba5d61c1196d7b05c52a89f4 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 27 Jun 2021 22:40:14 +0800
-Subject: [PATCH 14/19] cpupower: initial AMD P-state capability
-
-If kernel enables AMD P-state, cpupower won't need to respond ACPI
-hardware P-states function anymore.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- tools/power/cpupower/utils/helpers/cpuid.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
-diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
-index 72eb43593180..78218c54acca 100644
---- a/tools/power/cpupower/utils/helpers/cpuid.c
-+++ b/tools/power/cpupower/utils/helpers/cpuid.c
-@@ -149,6 +149,19 @@ int get_cpu_info(struct cpupower_cpu_info *cpu_info)
- if (ext_cpuid_level >= 0x80000008 &&
- cpuid_ebx(0x80000008) & (1 << 4))
- cpu_info->caps |= CPUPOWER_CAP_AMD_RDPRU;
++static void __exit amd_pstate_exit(void)
++{
++ struct amd_pstate_perf_funcs *funcs;
+
-+ if (cpupower_amd_pstate_enabled(0)) {
-+ cpu_info->caps |= CPUPOWER_CAP_AMD_PSTATE;
++ funcs = cpufreq_get_driver_data();
+
-+ /*
-+ * If AMD P-state is enabled, the firmware will treat
-+ * AMD P-state function as high priority.
-+ */
-+ cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB;
-+ cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB_MSR;
-+ cpu_info->caps &= ~CPUPOWER_CAP_AMD_HW_PSTATE;
-+ cpu_info->caps &= ~CPUPOWER_CAP_AMD_PSTATEDEF;
-+ }
- }
-
- if (cpu_info->vendor == X86_VENDOR_INTEL) {
---
-2.33.0
-
-From d3f392c951479c73e5a4b0c8d94901aafd5b9da7 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 17:07:25 +0800
-Subject: [PATCH 15/19] cpupower: add amd-pstate sysfs entries into libcpufreq
-
-These amd-pstate sysfs entries will be used on cpupower for amd-pstate
-kernel module.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- tools/power/cpupower/lib/cpufreq.c | 18 +++++++++++++++++-
- 1 file changed, 17 insertions(+), 1 deletion(-)
-
++ cpufreq_unregister_driver(&amd_pstate_driver);
++
++ amd_pstate_enable(funcs, false);
++}
++
++module_init(amd_pstate_init);
++module_exit(amd_pstate_exit);
++
++MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>");
++MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver");
++MODULE_LICENSE("GPL");
+diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
+index 9f4985b4d64d..3fdae40a75fc 100644
+--- a/include/acpi/cppc_acpi.h
++++ b/include/acpi/cppc_acpi.h
+@@ -137,6 +137,7 @@ struct cppc_cpudata {
+ extern int cppc_get_desired_perf(int cpunum, u64 *desired_perf);
+ extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs);
+ extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls);
++extern int cppc_set_enable(int cpu, u32 enable);
+ extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
+ extern bool acpi_cpc_valid(void);
+ extern int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data);
+@@ -157,6 +158,10 @@ static inline int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
+ {
+ return -ENOTSUPP;
+ }
++static inline int cppc_set_enable(int cpu, u32 enable)
++{
++ return -ENOTSUPP;
++}
+ static inline int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps)
+ {
+ return -ENOTSUPP;
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
-index c3b56db8b921..3f92ddadaad2 100644
+index c3b56db8b921..1443080868da 100644
--- a/tools/power/cpupower/lib/cpufreq.c
+++ b/tools/power/cpupower/lib/cpufreq.c
@@ -69,6 +69,14 @@ enum cpufreq_value {
@@ -1840,30 +1866,7 @@ index c3b56db8b921..3f92ddadaad2 100644
};
---
-2.33.0
-
-From c7249e524ce793bfe0575f45a0f8245f51b02af7 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 17:35:45 +0800
-Subject: [PATCH 16/19] cpupower: enable boost state support for amd-pstate
- module
-
-The AMD P-state boost API is different from ACPI hardware P-states, so
-implement the support for amd-pstate kernel module.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- tools/power/cpupower/lib/cpufreq.c | 20 ++++++++++++++++++++
- tools/power/cpupower/lib/cpufreq.h | 3 +++
- tools/power/cpupower/utils/helpers/misc.c | 7 +++++++
- 3 files changed, 30 insertions(+)
-
-diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
-index 3f92ddadaad2..37da87bdcfb1 100644
---- a/tools/power/cpupower/lib/cpufreq.c
-+++ b/tools/power/cpupower/lib/cpufreq.c
-@@ -790,3 +790,23 @@ unsigned long cpufreq_get_transitions(unsigned int cpu)
+@@ -774,3 +790,29 @@ unsigned long cpufreq_get_transitions(unsigned int cpu)
{
return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
}
@@ -1887,70 +1890,6 @@ index 3f92ddadaad2..37da87bdcfb1 100644
+
+ return cpuinfo_max == amd_pstate_max ? 1 : 0;
+}
-diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
-index 95f4fd9e2656..d54d02a7a4f4 100644
---- a/tools/power/cpupower/lib/cpufreq.h
-+++ b/tools/power/cpupower/lib/cpufreq.h
-@@ -203,6 +203,9 @@ int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
- int cpufreq_set_frequency(unsigned int cpu,
- unsigned long target_frequency);
-
-+int amd_pstate_boost_support(unsigned int cpu);
-+int amd_pstate_boost_enabled(unsigned int cpu);
-+
- #ifdef __cplusplus
- }
- #endif
-diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
-index 07d80775fb68..aba979320760 100644
---- a/tools/power/cpupower/utils/helpers/misc.c
-+++ b/tools/power/cpupower/utils/helpers/misc.c
-@@ -10,6 +10,7 @@
- #if defined(__i386__) || defined(__x86_64__)
-
- #include "cpupower_intern.h"
-+#include "cpufreq.h"
-
- #define MSR_AMD_HWCR 0xc0010015
-
-@@ -39,6 +40,12 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
- if (ret)
- return ret;
- }
-+ } if ((cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) &&
-+ amd_pstate_boost_support(cpu)) {
-+ *support = 1;
-+
-+ if (amd_pstate_boost_enabled(cpu))
-+ *active = 1;
- } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
- *support = *active = 1;
- return 0;
---
-2.33.0
-
-From cf79733de00a260c6d3e5038f00cdb91a71df9af Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Sun, 20 Jun 2021 18:25:55 +0800
-Subject: [PATCH 17/19] cpupower: add amd-pstate get data function to query the
- info
-
-Frequency-info needs an interface to query the current amd-pstate data.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- tools/power/cpupower/lib/cpufreq.c | 6 ++++++
- tools/power/cpupower/lib/cpufreq.h | 13 +++++++++++++
- 2 files changed, 19 insertions(+)
-
-diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
-index 37da87bdcfb1..1443080868da 100644
---- a/tools/power/cpupower/lib/cpufreq.c
-+++ b/tools/power/cpupower/lib/cpufreq.c
-@@ -810,3 +810,9 @@ int amd_pstate_boost_enabled(unsigned int cpu)
-
- return cpuinfo_max == amd_pstate_max ? 1 : 0;
- }
+
+unsigned amd_pstate_get_data(unsigned int cpu, enum amd_pstate_param param)
+{
@@ -1958,13 +1897,16 @@ index 37da87bdcfb1..1443080868da 100644
+ param + AMD_PSTATE_HIGHEST_PERF);
+}
diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
-index d54d02a7a4f4..954e72704fc0 100644
+index 95f4fd9e2656..954e72704fc0 100644
--- a/tools/power/cpupower/lib/cpufreq.h
+++ b/tools/power/cpupower/lib/cpufreq.h
-@@ -206,6 +206,19 @@ int cpufreq_set_frequency(unsigned int cpu,
- int amd_pstate_boost_support(unsigned int cpu);
- int amd_pstate_boost_enabled(unsigned int cpu);
+@@ -203,6 +203,22 @@ int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
+ int cpufreq_set_frequency(unsigned int cpu,
+ unsigned long target_frequency);
++int amd_pstate_boost_support(unsigned int cpu);
++int amd_pstate_boost_enabled(unsigned int cpu);
++
+enum amd_pstate_param {
+ HIGHEST_PERF,
+ NOMINAL_PERF,
@@ -1981,23 +1923,6 @@ index d54d02a7a4f4..954e72704fc0 100644
#ifdef __cplusplus
}
#endif
---
-2.33.0
-
-From 573a0ff1add6bb6df585d6535abaaa0e1afc61c9 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 23:48:03 +0800
-Subject: [PATCH 18/19] cpupower: print amd-pstate information on cpupower
-
-amd-pstate kernel module is using the fine grain frequency instead of
-acpi hardware pstate. So the performance and frequency values should be
-printed in frequency-info.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- tools/power/cpupower/utils/cpufreq-info.c | 27 ++++++++++++++++++++---
- 1 file changed, 24 insertions(+), 3 deletions(-)
-
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index f9895e31ff5a..9eabed209adc 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
@@ -2036,419 +1961,106 @@ index f9895e31ff5a..9eabed209adc 100644
ret = decode_pstates(cpu, b_states, pstates, &pstate_no);
if (ret)
return ret;
---
-2.33.0
-
-From abfcbc164c1aa0c63d5e256854bad977a9645586 Mon Sep 17 00:00:00 2001
-From: Huang Rui <ray.huang@amd.com>
-Date: Thu, 10 Jun 2021 23:40:18 +0800
-Subject: [PATCH 19/19] Documentation: amd-pstate: add amd-pstate driver
- introduction
-
-Introduce the amd-pstate driver design and implementation.
-
-Signed-off-by: Huang Rui <ray.huang@amd.com>
----
- Documentation/admin-guide/pm/amd_pstate.rst | 377 ++++++++++++++++++
- .../admin-guide/pm/working-state.rst | 1 +
- 2 files changed, 378 insertions(+)
- create mode 100644 Documentation/admin-guide/pm/amd_pstate.rst
-
-diff --git a/Documentation/admin-guide/pm/amd_pstate.rst b/Documentation/admin-guide/pm/amd_pstate.rst
-new file mode 100644
-index 000000000000..c3659dde0cee
---- /dev/null
-+++ b/Documentation/admin-guide/pm/amd_pstate.rst
-@@ -0,0 +1,377 @@
-+.. SPDX-License-Identifier: GPL-2.0
-+.. include:: <isonum.txt>
-+
-+===============================================
-+``amd-pstate`` CPU Performance Scaling Driver
-+===============================================
-+
-+:Copyright: |copy| 2021 Advanced Micro Devices, Inc.
-+
-+:Author: Huang Rui <ray.huang@amd.com>
-+
-+
-+Introduction
-+===================
-+
-+``amd-pstate`` is the AMD CPU performance scaling driver that introduces a
-+new CPU frequency control mechanism on modern AMD APU and CPU series in
-+Linux kernel. The new mechanism is based on Collaborative Processor
-+Performance Control (CPPC) which provides finer grain frequency management
-+than legacy ACPI hardware P-States. Current AMD CPU/APU platforms are using
-+the ACPI P-states driver to manage CPU frequency and clocks with switching
-+only in 3 P-states. CPPC replaces the ACPI P-states controls, allows a
-+flexible, low-latency interface for the Linux kernel to directly
-+communicate the performance hints to hardware.
-+
-+``amd-pstate`` leverages the Linux kernel governors such as ``schedutil``,
-+``ondemand``, etc. to manage the performance hints which are provided by
-+CPPC hardware functionality that internally follows the hardware
-+specification (for details refer to AMD64 Architecture Programmer's Manual
-+Volume 2: System Programming [1]_). Currently ``amd-pstate`` supports basic
-+frequency control function according to kernel governors on some of the
-+Zen2 and Zen3 processors, and we will implement more AMD specific functions
-+in future after we verify them on the hardware and SBIOS.
-+
-+
-+AMD CPPC Overview
-+=======================
-+
-+Collaborative Processor Performance Control (CPPC) interface enumerates a
-+continuous, abstract, and unit-less performance value in a scale that is
-+not tied to a specific performance state / frequency. This is an ACPI
-+standard [2]_ which software can specify application performance goals and
-+hints as a relative target to the infrastructure limits. AMD processors
-+provides the low latency register model (MSR) instead of AML code
-+interpreter for performance adjustments. ``amd-pstate`` will initialize a
-+``struct cpufreq_driver`` instance ``amd_pstate_driver`` with the callbacks
-+to manage each performance update behavior. ::
-+
-+ Highest Perf ------>+-----------------------+ +-----------------------+
-+ | | | |
-+ | | | |
-+ | | Max Perf ---->| |
-+ | | | |
-+ | | | |
-+ Nominal Perf ------>+-----------------------+ +-----------------------+
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | Desired Perf ---->| |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ | | | |
-+ Lowest non- | | | |
-+ linear perf ------>+-----------------------+ +-----------------------+
-+ | | | |
-+ | | Lowest perf ---->| |
-+ | | | |
-+ Lowest perf ------>+-----------------------+ +-----------------------+
-+ | | | |
-+ | | | |
-+ | | | |
-+ 0 ------>+-----------------------+ +-----------------------+
-+
-+ AMD P-States Performance Scale
-+
-+
-+.. _perf_cap:
-+
-+AMD CPPC Performance Capability
-+--------------------------------
-+
-+Highest Performance (RO)
-+.........................
-+
-+It is the absolute maximum performance an individual processor may reach,
-+assuming ideal conditions. This performance level may not be sustainable
-+for long durations and may only be achievable if other platform components
-+are in a specific state; for example, it may require other processors be in
-+an idle state. This would be equivalent to the highest frequencies
-+supported by the processor.
-+
-+Nominal (Guaranteed) Performance (RO)
-+......................................
-+
-+It is the maximum sustained performance level of the processor, assuming
-+ideal operating conditions. In absence of an external constraint (power,
-+thermal, etc.) this is the performance level the processor is expected to
-+be able to maintain continuously. All cores/processors are expected to be
-+able to sustain their nominal performance state simultaneously.
-+
-+Lowest non-linear Performance (RO)
-+...................................
-+
-+It is the lowest performance level at which nonlinear power savings are
-+achieved, for example, due to the combined effects of voltage and frequency
-+scaling. Above this threshold, lower performance levels should be generally
-+more energy efficient than higher performance levels. This register
-+effectively conveys the most efficient performance level to ``amd-pstate``.
-+
-+Lowest Performance (RO)
-+........................
-+
-+It is the absolute lowest performance level of the processor. Selecting a
-+performance level lower than the lowest nonlinear performance level may
-+cause an efficiency penalty but should reduce the instantaneous power
-+consumption of the processor.
-+
-+AMD CPPC Performance Control
-+------------------------------
-+
-+``amd-pstate`` passes performance goals through these registers. The
-+register drives the behavior of the desired performance target.
-+
-+Minimum requested performance (RW)
-+...................................
-+
-+``amd-pstate`` specifies the minimum allowed performance level.
-+
-+Maximum requested performance (RW)
-+...................................
-+
-+``amd-pstate`` specifies a limit the maximum performance that is expected
-+to be supplied by the hardware.
-+
-+Desired performance target (RW)
-+...................................
-+
-+``amd-pstate`` specifies a desired target in the CPPC performance scale as
-+a relative number. This can be expressed as percentage of nominal
-+performance (infrastructure max). Below the nominal sustained performance
-+level, desired performance expresses the average performance level of the
-+processor subject to hardware. Above the nominal performance level,
-+processor must provide at least nominal performance requested and go higher
-+if current operating conditions allow.
-+
-+Energy Performance Preference (EPP) (RW)
-+.........................................
-+
-+Provides a hint to the hardware if software wants to bias toward performance
-+(0x0) or energy efficiency (0xff).
-+
-+
-+Key Governors Support
-+=======================
-+
-+``amd-pstate`` can be used with all the (generic) scaling governors listed
-+by the ``scaling_available_governors`` policy attribute in ``sysfs``. Then,
-+it is responsible for the configuration of policy objects corresponding to
-+CPUs and provides the ``CPUFreq`` core (and the scaling governors attached
-+to the policy objects) with accurate information on the maximum and minimum
-+operating frequencies supported by the hardware. Users can check the
-+``scaling_cur_freq`` information comes from the ``CPUFreq`` core.
-+
-+``amd-pstate`` mainly supports ``schedutil`` and ``ondemand`` for dynamic
-+frequency control. It is to fine tune the processor configuration on
-+``amd-pstate`` to the ``schedutil`` with CPU CFS scheduler. ``amd-pstate``
-+registers adjust_perf callback to implement the CPPC similar performance
-+update behavior. It is initialized by ``sugov_start`` and then populate the
-+CPU's update_util_data pointer to assign ``sugov_update_single_perf`` as
-+the utilization update callback function in CPU scheduler. CPU scheduler
-+will call ``cpufreq_update_util`` and assign the target performance
-+according to the ``struct sugov_cpu`` that utilization update belongs to.
-+Then ``amd-pstate`` updates the desired performance according to the CPU
-+scheduler assigned.
-+
-+
-+Processor Support
-+=======================
-+
-+The ``amd-pstate`` initialization will fail if the _CPC in ACPI SBIOS is
-+not existed at the detected processor, and it uses ``acpi_cpc_valid`` to
-+check the _CPC existence. All Zen based processors support legacy ACPI
-+hardware P-States function, so while the ``amd-pstate`` fails to be
-+initialized, the kernel will fall back to initialize ``acpi-cpufreq``
-+driver.
-+
-+There are two types of hardware implementations for ``amd-pstate``: one is
-+`Full MSR Support <perf_cap_>`_ and another is `Shared Memory Support
-+<perf_cap_>`_. It can use :c:macro:`X86_FEATURE_AMD_CPPC_EXT` feature flag
-+(for details refer to Processor Programming Reference (PPR) for AMD Family
-+19h Model 21h, Revision B0 Processors [3]_) to indicate the different
-+types. ``amd-pstate`` is to register different ``amd_pstate_perf_funcs``
-+instances for different hardware implementations.
-+
-+Currently, some of Zen2 and Zen3 processors support ``amd-pstate``. In the
-+future, it will be supported on more and more AMD processors.
-+
-+Full MSR Support
-+-----------------
-+
-+Some new Zen3 processors such as Cezanne provide the MSR registers directly
-+while the :c:macro:`X86_FEATURE_AMD_CPPC_EXT` CPU feature flag is set.
-+``amd-pstate`` can handle the MSR register to implement the fast switch
-+function in ``CPUFreq`` that can shrink latency of frequency control on the
-+interrupt context.
-+
-+Shared Memory Support
-+----------------------
-+
-+If :c:macro:`X86_FEATURE_AMD_CPPC_EXT` CPU feature flag is not set, that
-+means the processor supports shared memory solution. In this case,
-+``amd-pstate`` uses the ``cppc_acpi`` helper methods to implement the
-+callback functions of ``amd_pstate_perf_funcs``.
-+
-+
-+AMD P-States and ACPI hardware P-States always can be supported in one
-+processor. But AMD P-States has the higher priority and if it is enabled
-+with :c:macro:`MSR_AMD_CPPC_ENABLE` or ``cppc_set_enable``, it will respond
-+to the request from AMD P-States.
-+
-+
-+User Space Interface in ``sysfs``
-+==================================
-+
-+``amd-pstate`` exposes several global attributes (files) in ``sysfs`` to
-+control its functionality at the system level. They located in the
-+``/sys/devices/system/cpu/cpufreq/policyX/`` directory and affect all CPUs. ::
-+
-+ root@hr-test1:/home/ray# ls /sys/devices/system/cpu/cpufreq/policy0/*amd*
-+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_highest_perf
-+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_lowest_nonlinear_freq
-+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_lowest_nonlinear_perf
-+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_lowest_perf
-+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_max_freq
-+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_min_freq
-+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_nominal_freq
-+ /sys/devices/system/cpu/cpufreq/policy0/amd_pstate_nominal_perf
-+ /sys/devices/system/cpu/cpufreq/policy0/is_amd_pstate_enabled
-+
-+
-+``is_amd_pstate_enabled``
-+
-+Query whether current kernel loads ``amd-pstate`` to enable the AMD
-+P-States functionality.
-+This attribute is read-only.
-+
-+``amd_pstate_highest_perf / amd_pstate_max_freq``
-+
-+Maximum CPPC performance and CPU frequency that the driver is allowed to
-+set in percent of the maximum supported CPPC performance level (the highest
-+performance supported in `AMD CPPC Performance Capability <perf_cap_>`_).
-+This attribute is read-only.
-+
-+``amd_pstate_nominal_perf / amd_pstate_nominal_freq``
-+
-+Nominal CPPC performance and CPU frequency that the driver is allowed to
-+set in percent of the maximum supported CPPC performance level (Please see
-+nominal performance in `AMD CPPC Performance Capability <perf_cap_>`_).
-+This attribute is read-only.
-+
-+``amd_pstate_lowest_nonlinear_perf / amd_pstate_lowest_nonlinear_freq``
-+
-+The lowest non-linear CPPC performance and CPU frequency that the driver is
-+allowed to set in percent of the maximum supported CPPC performance level
-+(Please see the lowest non-linear performance in `AMD CPPC Performance
-+Capability <perf_cap_>`_).
-+This attribute is read-only.
-+
-+``amd_pstate_lowest_perf / amd_pstate_min_freq``
-+
-+The lowest physical CPPC performance and CPU frequency.
-+This attribute is read-only.
-+
-+
-+``amd-pstate`` vs ``acpi-cpufreq``
-+======================================
-+
-+On majority of AMD platforms supported by ``acpi-cpufreq``, the ACPI tables
-+provided by the platform firmware used for CPU performance scaling, but
-+only provides 3 P-states on AMD processors.
-+However, on modern AMD APU and CPU series, it provides the collaborative
-+processor performance control according to ACPI protocol and customize this
-+for AMD platforms. That is fine-grain and continuous frequency range
-+instead of the legacy hardware P-states. ``amd-pstate`` is the kernel
-+module which supports the new AMD P-States mechanism on most of future AMD
-+platforms. The AMD P-States mechanism will be the more performance and energy
-+efficiency frequency management method on AMD processors.
-+
-+``cpupower`` tool support for ``amd-pstate``
-+===============================================
-+
-+``amd-pstate`` is supported on ``cpupower`` tool that can be used to dump the frequency
-+information. And it is in progress to support more and more operations for new
-+``amd-pstate`` module with this tool. ::
-+
-+ root@hr-test1:/home/ray# cpupower frequency-info
-+ analyzing CPU 0:
-+ driver: amd-pstate
-+ CPUs which run at the same hardware frequency: 0
-+ CPUs which need to have their frequency coordinated by software: 0
-+ maximum transition latency: 131 us
-+ hardware limits: 400 MHz - 4.68 GHz
-+ available cpufreq governors: ondemand conservative powersave userspace performance schedutil
-+ current policy: frequency should be within 400 MHz and 4.68 GHz.
-+ The governor "schedutil" may decide which speed to use
-+ within this range.
-+ current CPU frequency: Unable to call hardware
-+ current CPU frequency: 4.02 GHz (asserted by call to kernel)
-+ boost state support:
-+ Supported: yes
-+ Active: yes
-+ AMD PSTATE Highest Performance: 166. Maximum Frequency: 4.68 GHz.
-+ AMD PSTATE Nominal Performance: 117. Nominal Frequency: 3.30 GHz.
-+ AMD PSTATE Lowest Non-linear Performance: 39. Lowest Non-linear Frequency: 1.10 GHz.
-+ AMD PSTATE Lowest Performance: 15. Lowest Frequency: 400 MHz.
-+
+diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
+index 72eb43593180..78218c54acca 100644
+--- a/tools/power/cpupower/utils/helpers/cpuid.c
++++ b/tools/power/cpupower/utils/helpers/cpuid.c
+@@ -149,6 +149,19 @@ int get_cpu_info(struct cpupower_cpu_info *cpu_info)
+ if (ext_cpuid_level >= 0x80000008 &&
+ cpuid_ebx(0x80000008) & (1 << 4))
+ cpu_info->caps |= CPUPOWER_CAP_AMD_RDPRU;
+
-+Diagnostics and Tuning
-+=======================
++ if (cpupower_amd_pstate_enabled(0)) {
++ cpu_info->caps |= CPUPOWER_CAP_AMD_PSTATE;
+
-+Trace Events
-+--------------
++ /*
++ * If AMD P-state is enabled, the firmware will treat
++ * AMD P-state function as high priority.
++ */
++ cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB;
++ cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB_MSR;
++ cpu_info->caps &= ~CPUPOWER_CAP_AMD_HW_PSTATE;
++ cpu_info->caps &= ~CPUPOWER_CAP_AMD_PSTATEDEF;
++ }
+ }
+
+ if (cpu_info->vendor == X86_VENDOR_INTEL) {
+diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
+index 33ffacee7fcb..eb43c14d1728 100644
+--- a/tools/power/cpupower/utils/helpers/helpers.h
++++ b/tools/power/cpupower/utils/helpers/helpers.h
+@@ -73,6 +73,7 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
+ #define CPUPOWER_CAP_AMD_HW_PSTATE 0x00000100
+ #define CPUPOWER_CAP_AMD_PSTATEDEF 0x00000200
+ #define CPUPOWER_CAP_AMD_CPB_MSR 0x00000400
++#define CPUPOWER_CAP_AMD_PSTATE 0x00000800
+
+ #define CPUPOWER_AMD_CPBDIS 0x02000000
+
+@@ -135,6 +136,11 @@ extern int decode_pstates(unsigned int cpu, int boost_states,
+
+ extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
+ int *active, int * states);
+
-+There are two static trace events that can be used for ``amd-pstate``
-+diagnostics. One of them is the cpu_frequency trace event generally used
-+by ``CPUFreq``, and the other one is the ``amd_pstate_perf`` trace event
-+specific to ``amd-pstate``. The following sequence of shell commands can
-+be used to enable them and see their output (if the kernel is generally
-+configured to support event tracing). ::
++/* AMD PSTATE enabling **************************/
+
-+ root@hr-test1:/home/ray# cd /sys/kernel/tracing/
-+ root@hr-test1:/sys/kernel/tracing# echo 1 > events/amd_cpu/enable
-+ root@hr-test1:/sys/kernel/tracing# cat trace
-+ # tracer: nop
-+ #
-+ # entries-in-buffer/entries-written: 47827/42233061 #P:2
-+ #
-+ # _-----=> irqs-off
-+ # / _----=> need-resched
-+ # | / _---=> hardirq/softirq
-+ # || / _--=> preempt-depth
-+ # ||| / delay
-+ # TASK-PID CPU# |||| TIMESTAMP FUNCTION
-+ # | | | |||| | |
-+ <idle>-0 [000] d.s. 244057.464842: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ <idle>-0 [000] d.h. 244057.475436: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ <idle>-0 [000] d.h. 244057.476629: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ <idle>-0 [000] d.s. 244057.484847: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ <idle>-0 [000] d.h. 244057.499821: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
-+ avahi-daemon-528 [000] d... 244057.513568: amd_pstate_perf: amd_min_perf=39 amd_des_perf=39 amd_max_perf=166 cpu_id=0 prev=0x2727a6 value=0x2727a6
++extern unsigned long cpupower_amd_pstate_enabled(unsigned int cpu);
+
-+The cpu_frequency trace event will be triggered either by the ``schedutil`` scaling
-+governor (for the policies it is attached to), or by the ``CPUFreq`` core (for the
-+policies with other scaling governors).
+ /*
+ * CPUID functions returning a single datum
+ */
+diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
+index fc6e34511721..aba979320760 100644
+--- a/tools/power/cpupower/utils/helpers/misc.c
++++ b/tools/power/cpupower/utils/helpers/misc.c
+@@ -10,6 +10,7 @@
+ #if defined(__i386__) || defined(__x86_64__)
+
+ #include "cpupower_intern.h"
++#include "cpufreq.h"
+
+ #define MSR_AMD_HWCR 0xc0010015
+
+@@ -39,6 +40,12 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
+ if (ret)
+ return ret;
+ }
++ } if ((cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) &&
++ amd_pstate_boost_support(cpu)) {
++ *support = 1;
+
++ if (amd_pstate_boost_enabled(cpu))
++ *active = 1;
+ } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
+ *support = *active = 1;
+ return 0;
+@@ -83,6 +90,26 @@ int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
+ return 0;
+ }
+
++unsigned long cpupower_amd_pstate_enabled(unsigned int cpu)
++{
++ char linebuf[MAX_LINE_LEN];
++ char path[SYSFS_PATH_MAX];
++ unsigned long val;
++ char *endp;
+
-+Reference
-+===========
++ snprintf(path, sizeof(path),
++ PATH_TO_CPU "cpu%u/cpufreq/is_amd_pstate_enabled", cpu);
+
-+.. [1] AMD64 Architecture Programmer's Manual Volume 2: System Programming,
-+ https://www.amd.com/system/files/TechDocs/24593.pdf
++ if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0)
++ return 0;
+
-+.. [2] Advanced Configuration and Power Interface Specification,
-+ https://uefi.org/sites/default/files/resources/ACPI_Spec_6_4_Jan22.pdf
++ val = strtoul(linebuf, &endp, 0);
++ if (endp == linebuf || errno == ERANGE)
++ return 0;
+
-+.. [3] Processor Programming Reference (PPR) for AMD Family 19h Model 21h, Revision B0 Processors
-+ https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
++ return val;
++}
+
-diff --git a/Documentation/admin-guide/pm/working-state.rst b/Documentation/admin-guide/pm/working-state.rst
-index f40994c422dc..28db6156b55d 100644
---- a/Documentation/admin-guide/pm/working-state.rst
-+++ b/Documentation/admin-guide/pm/working-state.rst
-@@ -11,6 +11,7 @@ Working-State Power Management
- intel_idle
- cpufreq
- intel_pstate
-+ amd_pstate
- cpufreq_drivers
- intel_epb
- intel-speed-select
+ #endif /* #if defined(__i386__) || defined(__x86_64__) */
+
+ /* get_cpustate
--
2.33.0
diff --git a/sys-kernel_arch-sources-g14_files-9010-amd-apci-allow-c3.patch b/sys-kernel_arch-sources-g14_files-9010-amd-apci-allow-c3.patch
new file mode 100644
index 000000000000..64bca0b29482
--- /dev/null
+++ b/sys-kernel_arch-sources-g14_files-9010-amd-apci-allow-c3.patch
@@ -0,0 +1,34 @@
+From 52841ba456b08f0f76b2bf26fa7caba18166cdd9 Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Wed, 15 Sep 2021 16:52:16 -0500
+Subject: [PATCH] ACPI: processor idle: Allow playing dead in C3
+
+commit 1a022e3f1be1 ("idle, x86: Allow off-lined CPU to enter
+deeper C states") originally allowed offlined CPUs to play dead
+up to ACPI C2. Although this improves power consumption of offlined
+CPUs, it does not allow the CPUs to get into the deepest state
+on AMD platforms blocking s0i3 entry.
+
+BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1708
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+---
+ drivers/acpi/processor_idle.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index 095c8aca141e..1b6529396371 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -789,7 +789,8 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
+ state->enter = acpi_idle_enter;
+
+ state->flags = 0;
+- if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2) {
++ if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2
++ || cx->type == ACPI_STATE_C3) {
+ state->enter_dead = acpi_idle_play_dead;
+ drv->safe_state_index = count;
+ }
+--
+2.25.1
+