diff options
author | dragonn | 2021-09-18 10:01:44 +0200 |
---|---|---|
committer | dragonn | 2021-09-18 10:01:44 +0200 |
commit | 825d71ed713c470164cb24131dd6af6fcb19664e (patch) | |
tree | 2422ae50eb0bf5fec3e80d533425293bf1a57730 | |
parent | 8f5e12722e0aa4ead0854037a38ff6dbb1981a6b (diff) | |
download | aur-825d71ed713c470164cb24131dd6af6fcb19664e.tar.gz |
5.14.5
41 files changed, 2959 insertions, 14375 deletions
@@ -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 @@ -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 @@ -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 + |