]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Sep 2024 14:29:20 +0000 (16:29 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Sep 2024 14:29:20 +0000 (16:29 +0200)
added patches:
acpi-cppc-add-helper-to-get-the-highest-performance-value.patch
cpufreq-amd-pstate-enable-amd-pstate-preferred-core-support.patch
cpufreq-amd-pstate-fix-the-highest-frequency-issue-which-limits-performance.patch

queue-6.6/acpi-cppc-add-helper-to-get-the-highest-performance-value.patch [new file with mode: 0644]
queue-6.6/cpufreq-amd-pstate-enable-amd-pstate-preferred-core-support.patch [new file with mode: 0644]
queue-6.6/cpufreq-amd-pstate-fix-the-highest-frequency-issue-which-limits-performance.patch [new file with mode: 0644]
queue-6.6/series

diff --git a/queue-6.6/acpi-cppc-add-helper-to-get-the-highest-performance-value.patch b/queue-6.6/acpi-cppc-add-helper-to-get-the-highest-performance-value.patch
new file mode 100644 (file)
index 0000000..92379ad
--- /dev/null
@@ -0,0 +1,75 @@
+From 12753d71e8c5c3e716cedba23ddeed508da0bdc4 Mon Sep 17 00:00:00 2001
+From: Meng Li <li.meng@amd.com>
+Date: Fri, 19 Jan 2024 17:04:57 +0800
+Subject: ACPI: CPPC: Add helper to get the highest performance value
+
+From: Meng Li <li.meng@amd.com>
+
+commit 12753d71e8c5c3e716cedba23ddeed508da0bdc4 upstream.
+
+Add support for getting the highest performance to the
+generic CPPC driver. This enables downstream drivers
+such as amd-pstate to discover and use these values.
+
+Refer to Chapter 8.4.6.1.1.1. Highest Performance of ACPI
+Specification 6.5 for details on continuous performance control
+of CPPC (linked below).
+
+Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Wyes Karny <wyes.karny@amd.com>
+Reviewed-by: Perry Yuan <perry.yuan@amd.com>
+Acked-by: Huang Rui <ray.huang@amd.com>
+Signed-off-by: Meng Li <li.meng@amd.com>
+Link: https://uefi.org/specs/ACPI/6.5/08_Processor_Configuration_and_Control.html?highlight=cppc#highest-performance
+[ rjw: Subject and changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/cppc_acpi.c |   13 +++++++++++++
+ include/acpi/cppc_acpi.h |    5 +++++
+ 2 files changed, 18 insertions(+)
+
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -1197,6 +1197,19 @@ int cppc_get_nominal_perf(int cpunum, u6
+ }
+ /**
++ * cppc_get_highest_perf - Get the highest performance register value.
++ * @cpunum: CPU from which to get highest performance.
++ * @highest_perf: Return address.
++ *
++ * Return: 0 for success, -EIO otherwise.
++ */
++int cppc_get_highest_perf(int cpunum, u64 *highest_perf)
++{
++      return cppc_get_perf(cpunum, HIGHEST_PERF, highest_perf);
++}
++EXPORT_SYMBOL_GPL(cppc_get_highest_perf);
++
++/**
+  * cppc_get_epp_perf - Get the epp register value.
+  * @cpunum: CPU from which to get epp preference value.
+  * @epp_perf: Return address.
+--- a/include/acpi/cppc_acpi.h
++++ b/include/acpi/cppc_acpi.h
+@@ -139,6 +139,7 @@ struct cppc_cpudata {
+ #ifdef CONFIG_ACPI_CPPC_LIB
+ extern int cppc_get_desired_perf(int cpunum, u64 *desired_perf);
+ extern int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf);
++extern int cppc_get_highest_perf(int cpunum, u64 *highest_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, bool enable);
+@@ -165,6 +166,10 @@ static inline int cppc_get_nominal_perf(
+ {
+       return -ENOTSUPP;
+ }
++static inline int cppc_get_highest_perf(int cpunum, u64 *highest_perf)
++{
++      return -ENOTSUPP;
++}
+ static inline int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
+ {
+       return -ENOTSUPP;
diff --git a/queue-6.6/cpufreq-amd-pstate-enable-amd-pstate-preferred-core-support.patch b/queue-6.6/cpufreq-amd-pstate-enable-amd-pstate-preferred-core-support.patch
new file mode 100644 (file)
index 0000000..64fa5ab
--- /dev/null
@@ -0,0 +1,304 @@
+From f3a052391822b772b4e27f2594526cf1eb103cab Mon Sep 17 00:00:00 2001
+From: Meng Li <li.meng@amd.com>
+Date: Fri, 19 Jan 2024 17:04:58 +0800
+Subject: cpufreq: amd-pstate: Enable amd-pstate preferred core support
+
+From: Meng Li <li.meng@amd.com>
+
+commit f3a052391822b772b4e27f2594526cf1eb103cab upstream.
+
+amd-pstate driver utilizes the functions and data structures
+provided by the ITMT architecture to enable the scheduler to
+favor scheduling on cores which can be get a higher frequency
+with lower voltage. We call it amd-pstate preferrred core.
+
+Here sched_set_itmt_core_prio() is called to set priorities and
+sched_set_itmt_support() is called to enable ITMT feature.
+amd-pstate driver uses the highest performance value to indicate
+the priority of CPU. The higher value has a higher priority.
+
+The initial core rankings are set up by amd-pstate when the
+system boots.
+
+Add a variable hw_prefcore in cpudata structure. It will check
+if the processor and power firmware support preferred core
+feature.
+
+Add one new early parameter `disable` to allow user to disable
+the preferred core.
+
+Only when hardware supports preferred core and user set `enabled`
+in early parameter, amd pstate driver supports preferred core featue.
+
+Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
+Reviewed-by: Huang Rui <ray.huang@amd.com>
+Reviewed-by: Wyes Karny <wyes.karny@amd.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Co-developed-by: Perry Yuan <Perry.Yuan@amd.com>
+Signed-off-by: Perry Yuan <Perry.Yuan@amd.com>
+Signed-off-by: Meng Li <li.meng@amd.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/amd-pstate.c |  131 ++++++++++++++++++++++++++++++++++++++++---
+ include/linux/amd-pstate.h   |    4 +
+ 2 files changed, 127 insertions(+), 8 deletions(-)
+
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -37,6 +37,7 @@
+ #include <linux/uaccess.h>
+ #include <linux/static_call.h>
+ #include <linux/amd-pstate.h>
++#include <linux/topology.h>
+ #include <acpi/processor.h>
+ #include <acpi/cppc_acpi.h>
+@@ -49,6 +50,7 @@
+ #define AMD_PSTATE_TRANSITION_LATENCY 20000
+ #define AMD_PSTATE_TRANSITION_DELAY   1000
++#define AMD_PSTATE_PREFCORE_THRESHOLD 166
+ /*
+  * TODO: We need more time to fine tune processors with shared memory solution
+@@ -64,6 +66,7 @@ static struct cpufreq_driver amd_pstate_
+ static struct cpufreq_driver amd_pstate_epp_driver;
+ static int cppc_state = AMD_PSTATE_UNDEFINED;
+ static bool cppc_enabled;
++static bool amd_pstate_prefcore = true;
+ /*
+  * AMD Energy Preference Performance (EPP)
+@@ -320,13 +323,14 @@ static int pstate_init_perf(struct amd_c
+       if (ret)
+               return ret;
+-      /*
+-       * TODO: Introduce AMD specific power feature.
+-       *
+-       * CPPC entry doesn't indicate the highest performance in some ASICs.
++      /* For platforms that do not support the preferred core feature, the
++       * highest_pef may be configured with 166 or 255, to avoid max frequency
++       * calculated wrongly. we take the AMD_CPPC_HIGHEST_PERF(cap1) value as
++       * the default max perf.
+        */
+-      highest_perf = amd_get_highest_perf();
+-      if (highest_perf > AMD_CPPC_HIGHEST_PERF(cap1))
++      if (cpudata->hw_prefcore)
++              highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD;
++      else
+               highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
+       WRITE_ONCE(cpudata->highest_perf, highest_perf);
+@@ -347,8 +351,9 @@ static int cppc_init_perf(struct amd_cpu
+       if (ret)
+               return ret;
+-      highest_perf = amd_get_highest_perf();
+-      if (highest_perf > cppc_perf.highest_perf)
++      if (cpudata->hw_prefcore)
++              highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD;
++      else
+               highest_perf = cppc_perf.highest_perf;
+       WRITE_ONCE(cpudata->highest_perf, highest_perf);
+@@ -709,6 +714,80 @@ static void amd_perf_ctl_reset(unsigned
+       wrmsrl_on_cpu(cpu, MSR_AMD_PERF_CTL, 0);
+ }
++/*
++ * Set amd-pstate preferred core enable can't be done directly from cpufreq callbacks
++ * due to locking, so queue the work for later.
++ */
++static void amd_pstste_sched_prefcore_workfn(struct work_struct *work)
++{
++      sched_set_itmt_support();
++}
++static DECLARE_WORK(sched_prefcore_work, amd_pstste_sched_prefcore_workfn);
++
++/*
++ * Get the highest performance register value.
++ * @cpu: CPU from which to get highest performance.
++ * @highest_perf: Return address.
++ *
++ * Return: 0 for success, -EIO otherwise.
++ */
++static int amd_pstate_get_highest_perf(int cpu, u32 *highest_perf)
++{
++      int ret;
++
++      if (boot_cpu_has(X86_FEATURE_CPPC)) {
++              u64 cap1;
++
++              ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &cap1);
++              if (ret)
++                      return ret;
++              WRITE_ONCE(*highest_perf, AMD_CPPC_HIGHEST_PERF(cap1));
++      } else {
++              u64 cppc_highest_perf;
++
++              ret = cppc_get_highest_perf(cpu, &cppc_highest_perf);
++              if (ret)
++                      return ret;
++              WRITE_ONCE(*highest_perf, cppc_highest_perf);
++      }
++
++      return (ret);
++}
++
++#define CPPC_MAX_PERF U8_MAX
++
++static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata)
++{
++      int ret, prio;
++      u32 highest_perf;
++
++      ret = amd_pstate_get_highest_perf(cpudata->cpu, &highest_perf);
++      if (ret)
++              return;
++
++      cpudata->hw_prefcore = true;
++      /* check if CPPC preferred core feature is enabled*/
++      if (highest_perf < CPPC_MAX_PERF)
++              prio = (int)highest_perf;
++      else {
++              pr_debug("AMD CPPC preferred core is unsupported!\n");
++              cpudata->hw_prefcore = false;
++              return;
++      }
++
++      if (!amd_pstate_prefcore)
++              return;
++
++      /*
++       * The priorities can be set regardless of whether or not
++       * sched_set_itmt_support(true) has been called and it is valid to
++       * update them at any time after it has been called.
++       */
++      sched_set_itmt_core_prio(prio, cpudata->cpu);
++
++      schedule_work(&sched_prefcore_work);
++}
++
+ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+ {
+       int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
+@@ -730,6 +809,8 @@ static int amd_pstate_cpu_init(struct cp
+       cpudata->cpu = policy->cpu;
++      amd_pstate_init_prefcore(cpudata);
++
+       ret = amd_pstate_init_perf(cpudata);
+       if (ret)
+               goto free_cpudata1;
+@@ -880,6 +961,17 @@ static ssize_t show_amd_pstate_highest_p
+       return sysfs_emit(buf, "%u\n", perf);
+ }
++static ssize_t show_amd_pstate_hw_prefcore(struct cpufreq_policy *policy,
++                                         char *buf)
++{
++      bool hw_prefcore;
++      struct amd_cpudata *cpudata = policy->driver_data;
++
++      hw_prefcore = READ_ONCE(cpudata->hw_prefcore);
++
++      return sysfs_emit(buf, "%s\n", str_enabled_disabled(hw_prefcore));
++}
++
+ static ssize_t show_energy_performance_available_preferences(
+                               struct cpufreq_policy *policy, char *buf)
+ {
+@@ -1077,18 +1169,27 @@ static ssize_t status_store(struct devic
+       return ret < 0 ? ret : count;
+ }
++static ssize_t prefcore_show(struct device *dev,
++                           struct device_attribute *attr, char *buf)
++{
++      return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore));
++}
++
+ cpufreq_freq_attr_ro(amd_pstate_max_freq);
+ cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
+ cpufreq_freq_attr_ro(amd_pstate_highest_perf);
++cpufreq_freq_attr_ro(amd_pstate_hw_prefcore);
+ cpufreq_freq_attr_rw(energy_performance_preference);
+ cpufreq_freq_attr_ro(energy_performance_available_preferences);
+ static DEVICE_ATTR_RW(status);
++static DEVICE_ATTR_RO(prefcore);
+ static struct freq_attr *amd_pstate_attr[] = {
+       &amd_pstate_max_freq,
+       &amd_pstate_lowest_nonlinear_freq,
+       &amd_pstate_highest_perf,
++      &amd_pstate_hw_prefcore,
+       NULL,
+ };
+@@ -1096,6 +1197,7 @@ static struct freq_attr *amd_pstate_epp_
+       &amd_pstate_max_freq,
+       &amd_pstate_lowest_nonlinear_freq,
+       &amd_pstate_highest_perf,
++      &amd_pstate_hw_prefcore,
+       &energy_performance_preference,
+       &energy_performance_available_preferences,
+       NULL,
+@@ -1103,6 +1205,7 @@ static struct freq_attr *amd_pstate_epp_
+ static struct attribute *pstate_global_attributes[] = {
+       &dev_attr_status.attr,
++      &dev_attr_prefcore.attr,
+       NULL
+ };
+@@ -1154,6 +1257,8 @@ static int amd_pstate_epp_cpu_init(struc
+       cpudata->cpu = policy->cpu;
+       cpudata->epp_policy = 0;
++      amd_pstate_init_prefcore(cpudata);
++
+       ret = amd_pstate_init_perf(cpudata);
+       if (ret)
+               goto free_cpudata1;
+@@ -1577,7 +1682,17 @@ static int __init amd_pstate_param(char
+       return amd_pstate_set_driver(mode_idx);
+ }
++
++static int __init amd_prefcore_param(char *str)
++{
++      if (!strcmp(str, "disable"))
++              amd_pstate_prefcore = false;
++
++      return 0;
++}
++
+ early_param("amd_pstate", amd_pstate_param);
++early_param("amd_prefcore", amd_prefcore_param);
+ MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>");
+ MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver");
+--- a/include/linux/amd-pstate.h
++++ b/include/linux/amd-pstate.h
+@@ -52,6 +52,9 @@ struct amd_aperf_mperf {
+  * @prev: Last Aperf/Mperf/tsc count value read from register
+  * @freq: current cpu frequency value
+  * @boost_supported: check whether the Processor or SBIOS supports boost mode
++ * @hw_prefcore: check whether HW supports preferred core featue.
++ *              Only when hw_prefcore and early prefcore param are true,
++ *              AMD P-State driver supports preferred core featue.
+  * @epp_policy: Last saved policy used to set energy-performance preference
+  * @epp_cached: Cached CPPC energy-performance preference value
+  * @policy: Cpufreq policy value
+@@ -85,6 +88,7 @@ struct amd_cpudata {
+       u64     freq;
+       bool    boost_supported;
++      bool    hw_prefcore;
+       /* EPP feature related attributes*/
+       s16     epp_policy;
diff --git a/queue-6.6/cpufreq-amd-pstate-fix-the-highest-frequency-issue-which-limits-performance.patch b/queue-6.6/cpufreq-amd-pstate-fix-the-highest-frequency-issue-which-limits-performance.patch
new file mode 100644 (file)
index 0000000..4018916
--- /dev/null
@@ -0,0 +1,92 @@
+From bf202e654bfa57fb8cf9d93d4c6855890b70b9c4 Mon Sep 17 00:00:00 2001
+From: Perry Yuan <perry.yuan@amd.com>
+Date: Wed, 8 May 2024 13:47:03 +0800
+Subject: cpufreq: amd-pstate: fix the highest frequency issue which limits performance
+
+From: Perry Yuan <perry.yuan@amd.com>
+
+commit bf202e654bfa57fb8cf9d93d4c6855890b70b9c4 upstream.
+
+To address the performance drop issue, an optimization has been
+implemented. The incorrect highest performance value previously set by the
+low-level power firmware for AMD CPUs with Family ID 0x19 and Model ID
+ranging from 0x70 to 0x7F series has been identified as the cause.
+
+To resolve this, a check has been implemented to accurately determine the
+CPU family and model ID. The correct highest performance value is now set
+and the performance drop caused by the incorrect highest performance value
+are eliminated.
+
+Before the fix, the highest frequency was set to 4200MHz, now it is set
+to 4971MHz which is correct.
+
+CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE    MAXMHZ   MINMHZ       MHZ
+  0    0      0    0 0:0:0:0          yes 4971.0000 400.0000  400.0000
+  1    0      0    0 0:0:0:0          yes 4971.0000 400.0000  400.0000
+  2    0      0    1 1:1:1:0          yes 4971.0000 400.0000 4865.8140
+  3    0      0    1 1:1:1:0          yes 4971.0000 400.0000  400.0000
+
+Fixes: f3a052391822 ("cpufreq: amd-pstate: Enable amd-pstate preferred core support")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218759
+Signed-off-by: Perry Yuan <perry.yuan@amd.com>
+Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Tested-by: Gaha Bana <gahabana@gmail.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/amd-pstate.c |   22 +++++++++++++++++++---
+ 1 file changed, 19 insertions(+), 3 deletions(-)
+
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -50,7 +50,8 @@
+ #define AMD_PSTATE_TRANSITION_LATENCY 20000
+ #define AMD_PSTATE_TRANSITION_DELAY   1000
+-#define AMD_PSTATE_PREFCORE_THRESHOLD 166
++#define CPPC_HIGHEST_PERF_PERFORMANCE 196
++#define CPPC_HIGHEST_PERF_DEFAULT     166
+ /*
+  * TODO: We need more time to fine tune processors with shared memory solution
+@@ -313,6 +314,21 @@ static inline int amd_pstate_enable(bool
+       return static_call(amd_pstate_enable)(enable);
+ }
++static u32 amd_pstate_highest_perf_set(struct amd_cpudata *cpudata)
++{
++      struct cpuinfo_x86 *c = &cpu_data(0);
++
++      /*
++       * For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f,
++       * the highest performance level is set to 196.
++       * https://bugzilla.kernel.org/show_bug.cgi?id=218759
++       */
++      if (c->x86 == 0x19 && (c->x86_model >= 0x70 && c->x86_model <= 0x7f))
++              return CPPC_HIGHEST_PERF_PERFORMANCE;
++
++      return CPPC_HIGHEST_PERF_DEFAULT;
++}
++
+ static int pstate_init_perf(struct amd_cpudata *cpudata)
+ {
+       u64 cap1;
+@@ -329,7 +345,7 @@ static int pstate_init_perf(struct amd_c
+        * the default max perf.
+        */
+       if (cpudata->hw_prefcore)
+-              highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD;
++              highest_perf = amd_pstate_highest_perf_set(cpudata);
+       else
+               highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
+@@ -352,7 +368,7 @@ static int cppc_init_perf(struct amd_cpu
+               return ret;
+       if (cpudata->hw_prefcore)
+-              highest_perf = AMD_PSTATE_PREFCORE_THRESHOLD;
++              highest_perf = amd_pstate_highest_perf_set(cpudata);
+       else
+               highest_perf = cppc_perf.highest_perf;
index 39ba09414191fc752b5f364e0ee4a648b1d7c42d..0a6bb06df947f8fa3e616265f3b3871f134c5efe 100644 (file)
@@ -200,3 +200,6 @@ riscv-use-write_once-when-setting-page-table-entries.patch
 mm-introduce-pudp-p4dp-pgdp_get-functions.patch
 riscv-mm-only-compile-pgtable.c-if-mmu.patch
 riscv-use-accessors-to-page-table-entries-instead-of-direct-dereference.patch
+acpi-cppc-add-helper-to-get-the-highest-performance-value.patch
+cpufreq-amd-pstate-enable-amd-pstate-preferred-core-support.patch
+cpufreq-amd-pstate-fix-the-highest-frequency-issue-which-limits-performance.patch