Linux Power Management development
 help / color / mirror / Atom feed
* Re: [PATCH] power: sequencing: pcie-m2: enforce PCI and OF dependencies
From: Arnd Bergmann @ 2026-04-02  9:01 UTC (permalink / raw)
  To: Bartosz Golaszewski, Arnd Bergmann, Rob Herring
  Cc: Manivannan Sadhasivam, Ulf Hansson, Michal Wilczynski, linux-pm,
	linux-kernel
In-Reply-To: <CAMRc=McYdb-R6QpEKn+VoB4KNKLUJzT82BVzBUYdX+HEqhyB1w@mail.gmail.com>

On Thu, Apr 2, 2026, at 10:39, Bartosz Golaszewski wrote:
> On Wed, Apr 1, 2026 at 11:19 AM Arnd Bergmann <arnd@kernel.org> wrote:
>
> Hi Arnd,
>
> Mani posted the following series[1]. It seems to me it fixes at least
> some of the build issues.

I don't think that covers the case of CONFIG_SERIAL_DEV_BUS=m
with POWER_SEQUENCING_PCIE_M2. Trying to make this work with
compile testing adds a lot of complexity for little benefit,
so I think my second patch is better there. SERIAL_DEV_BUS
is visible on all architectures, so compile-testing works
fine on allmodconfig and randconfig builds either way.

For PCI it's similar: while you can't build test this on
architectures without PCI (m68k, hexagon, ...), nobody
cares, and you just make the driver uglier, though there is
less risk of introducing additional regressions here.

Obviously the m2 pwrseq driver has a real dependency on pcie,
so there is no point trying to make it build with PCI=n,
the same way we don't allow building normal PCI device drivers
without PCI support.

> I would really prefer to keep the COMPILE_TEST option here. I'm seeing
> that only some of the symbols depending on OF_DYNAMIC are stubbed out.
> Rob: is there any reason for that? Would you be willing to Ack a patch
> adding stubs for the remainder and me taking it along with the pwrseq
> changes?

The idea with OF_DYNAMIC is that any driver that uses it should
'select' that symbol, so there is no need for stubs.

More generally: I think the stub helpers in headers are useful
for features that are truly optional, e.g. a driver may be
able to light LEDs if they are enabled but still work fine without
that. COMPILE_TEST in turn is nice when it enables building
platform specific drivers on other platforms. The combination of
the two causes more problems than it helps: if a driver has
a clear dependency on a particular subsystem, we should just
enforce that in Kconfig and not artificially allow compile
testing a configuration that is neither useful in practice
nor hard to build test already.

      Arnd

^ permalink raw reply

* [PATCH] thermal/core: Remove pointless variable when registering a cooling device
From: Daniel Lezcano @ 2026-04-02  8:44 UTC (permalink / raw)
  To: rafael; +Cc: Daniel Lezcano, Zhang Rui, Lukasz Luba, open list:THERMAL,
	open list

From: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>

The 'id' variable is set to store the ida_alloc() value which is
already stored into cdev->id. It is pointless to use it because
cdev->id can be used instead.

Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
---
 drivers/thermal/thermal_core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index b7d706ed7ed9..02ce58223f9f 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1061,7 +1061,7 @@ __thermal_cooling_device_register(struct device_node *np,
 {
 	struct thermal_cooling_device *cdev;
 	unsigned long current_state;
-	int id, ret;
+	int ret;
 
 	if (!ops || !ops->get_max_state || !ops->get_cur_state ||
 	    !ops->set_cur_state)
@@ -1078,7 +1078,6 @@ __thermal_cooling_device_register(struct device_node *np,
 	if (ret < 0)
 		goto out_kfree_cdev;
 	cdev->id = ret;
-	id = ret;
 
 	cdev->type = kstrdup_const(type ? type : "", GFP_KERNEL);
 	if (!cdev->type) {
@@ -1135,7 +1134,7 @@ __thermal_cooling_device_register(struct device_node *np,
 out_cdev_type:
 	kfree_const(cdev->type);
 out_ida_remove:
-	ida_free(&thermal_cdev_ida, id);
+	ida_free(&thermal_cdev_ida, cdev->id);
 out_kfree_cdev:
 	kfree(cdev);
 	return ERR_PTR(ret);
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH] power: sequencing: pcie-m2: enforce PCI and OF dependencies
From: Bartosz Golaszewski @ 2026-04-02  8:39 UTC (permalink / raw)
  To: Arnd Bergmann, Rob Herring
  Cc: Manivannan Sadhasivam, Arnd Bergmann, Ulf Hansson,
	Michal Wilczynski, linux-pm, linux-kernel
In-Reply-To: <20260401091847.305294-1-arnd@kernel.org>

On Wed, Apr 1, 2026 at 11:19 AM Arnd Bergmann <arnd@kernel.org> wrote:
>
> From: Arnd Bergmann <arnd@arndb.de>
>
> The driver fails to build when PCI is disabled:
>
> drivers/power/sequencing/pwrseq-pcie-m2.c: In function 'pwrseq_pcie_m2_register_notifier':
> drivers/power/sequencing/pwrseq-pcie-m2.c:368:54: error: 'pci_bus_type' undeclared (first use in this function); did you mean 'pci_pcie_type'?
>   368 |                         ret = bus_register_notifier(&pci_bus_type, &ctx->nb);
>       |                                                      ^~~~~~~~~~~~
>       |                                                      pci_pcie_type
>
> Similarly, when CONFIG_OF is disabled:
>
> drivers/power/sequencing/pwrseq-pcie-m2.c: In function 'pwrseq_m2_pcie_create_bt_node':
> drivers/power/sequencing/pwrseq-pcie-m2.c:191:9: error: implicit declaration of function 'of_changeset_init' [-Wimplicit-function-declaration]
>   191 |         of_changeset_init(ctx->ocs);
>       |         ^~~~~~~~~~~~~~~~~
>
> Make both dependencies unconditional to prevent compile-testing
> in either configuration.
>
> Fixes: 3f736aecbdc8 ("power: sequencing: pcie-m2: Create serdev device for WCN7850 bluetooth")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Hi Arnd,

Mani posted the following series[1]. It seems to me it fixes at least
some of the build issues.

I would really prefer to keep the COMPILE_TEST option here. I'm seeing
that only some of the symbols depending on OF_DYNAMIC are stubbed out.
Rob: is there any reason for that? Would you be willing to Ack a patch
adding stubs for the remainder and me taking it along with the pwrseq
changes?

> ---
>  drivers/power/sequencing/Kconfig | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
> index 1ec142525a4a..77c6d9227251 100644
> --- a/drivers/power/sequencing/Kconfig
> +++ b/drivers/power/sequencing/Kconfig
> @@ -37,8 +37,9 @@ config POWER_SEQUENCING_TH1520_GPU
>
>  config POWER_SEQUENCING_PCIE_M2
>         tristate "PCIe M.2 connector power sequencing driver"
> -       depends on (PCI && OF) || COMPILE_TEST
> -       select OF_DYNAMIC if OF
> +       depends on OF
> +       depends on PCI
> +       select OF_DYNAMIC
>         help
>           Say Y here to enable the power sequencing driver for PCIe M.2
>           connectors. This driver handles the power sequencing for the M.2
> --
> 2.39.5
>

Bart

[1] https://lore.kernel.org/all/20260401070735.107162-1-manivannan.sadhasivam@oss.qualcomm.com/

^ permalink raw reply

* Re: [PATCH] ACPI: processor: Add acpi_processor_start() back to parse _CPC tables before CPU online
From: zhenglifeng (A) @ 2026-04-02  8:36 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Jonathan Cameron, catalin.marinas, linux-acpi, linux-kernel,
	linuxarm, gshan, miguel.luis, guohanjun, zhanjie9, lihuisong,
	yubowen8, zhangpengjie2, wangzhi12, linhongye, salil.mehta,
	Viresh Kumar, Linux PM
In-Reply-To: <4257cdb1-c18b-4274-95b4-617f1da76518@huawei.com>

On 2/6/2026 5:57 PM, zhenglifeng (A) wrote:
> On 2026/1/29 20:45, zhenglifeng (A) wrote:
>>
>>
>> On 2026/1/28 2:00, Rafael J. Wysocki wrote:
>>> +linux-pm and Viresh
>>>
>>> On Tue, Jan 27, 2026 at 5:58 PM Jonathan Cameron
>>> <jonathan.cameron@huawei.com> wrote:
>>>>
>>>> On Tue, 27 Jan 2026 15:42:16 +0100
>>>> "Rafael J. Wysocki" <rafael@kernel.org> wrote:
>>>>
>>>>> On Tue, Jan 20, 2026 at 12:33 PM Lifeng Zheng <zhenglifeng1@huawei.com> wrote:
>>>>>>
>>>>>> Currently, if boot with maxcpus less than NR_CPUS, the cppc_cpufreq driver
>>>>>> will fail to register. Because it requires the domain information of all
>>>>>> possible CPUs to construct shared_cpu_map, which shows the CPUs that share
>>>>>> the same domain.
>>>>>>
>>>>>> Commit c1385c1f0ba3 ("ACPI: processor: Simplify initial onlining to use
>>>>>> same path for cold and hotplug") removes probe() of acpi_processor_driver
>>>>>> and makes acpi_cppc_processor_probe() only being called the first time CPU
>>>>>> goes online. This means that CPUs that haven't yet gone online will not
>>>>>> have pre-parsed _CPC objects and causes cppc_cpufreq driver register fail.
>>>>>>
>>>>>> Add acpi_processor_start() back as the probe() callback of
>>>>>> acpi_processor_driver and call acpi_cppc_processor_probe() in it to make
>>>>>> sure all _CPC tables will be parsed when acpi_processor_driver registered.
>>>>>>
>>>>>> Fixes: c1385c1f0ba3 ("ACPI: processor: Simplify initial onlining to use same path for cold and hotplug")
>>>>>> Signed-off-by: Lifeng Zheng <zhenglifeng1@huawei.com>
>>>>>> ---
>>>>>>  drivers/acpi/processor_driver.c | 30 ++++++++++++++++++++++++++----
>>>>>>  1 file changed, 26 insertions(+), 4 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
>>>>>> index 65e779be64ff..c8b4daf580b0 100644
>>>>>> --- a/drivers/acpi/processor_driver.c
>>>>>> +++ b/drivers/acpi/processor_driver.c
>>>>>> @@ -33,6 +33,7 @@ MODULE_AUTHOR("Paul Diefenbaugh");
>>>>>>  MODULE_DESCRIPTION("ACPI Processor Driver");
>>>>>>  MODULE_LICENSE("GPL");
>>>>>>
>>>>>> +static int acpi_processor_start(struct device *dev);
>>>>>>  static int acpi_processor_stop(struct device *dev);
>>>>>>
>>>>>>  static const struct acpi_device_id processor_device_ids[] = {
>>>>>> @@ -46,6 +47,7 @@ static struct device_driver acpi_processor_driver = {
>>>>>>         .name = "processor",
>>>>>>         .bus = &cpu_subsys,
>>>>>>         .acpi_match_table = processor_device_ids,
>>>>>> +       .probe = acpi_processor_start,
>>>>>>         .remove = acpi_processor_stop,
>>>>>>  };
>>>>>>
>>>>>> @@ -162,10 +164,6 @@ static int __acpi_processor_start(struct acpi_device *device)
>>>>>>         if (!pr)
>>>>>>                 return -ENODEV;
>>>>>>
>>>>>> -       result = acpi_cppc_processor_probe(pr);
>>>>>> -       if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
>>>>>> -               dev_dbg(&device->dev, "CPPC data invalid or not present\n");
>>>>>> -
>>>>>>         if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
>>>>>>                 acpi_processor_power_init(pr);
>>>>>>
>>>>>> @@ -192,6 +190,30 @@ static int __acpi_processor_start(struct acpi_device *device)
>>>>>>         return result;
>>>>>>  }
>>>>>>
>>>>>> +static int acpi_processor_start(struct device *dev)
>>>>>> +{
>>>>>> +       struct acpi_device *device = ACPI_COMPANION(dev);
>>>>>> +       struct acpi_processor *pr;
>>>>>> +       int result;
>>>>>> +
>>>>>> +       if (!device)
>>>>>> +               return -ENODEV;
>>>>>> +
>>>>>> +       pr = acpi_driver_data(device);
>>>>>> +       if (!pr)
>>>>>> +               return -ENODEV;
>>>>>> +
>>>>>> +       /* Protect against concurrent CPU hotplug operations */
>>>>>> +       cpu_hotplug_disable();
>>>>>> +       result = acpi_cppc_processor_probe(pr);
>>>>>> +       cpu_hotplug_enable();
>>>>>
>>>>> This means that CPPC will be initialized for vCPUs that are not
>>>>> enabled on ARM if I'm not mistaken.
>>>>
>>>> If we are just talking powered down at boot it used to do that
>>>> so I assume it was fine. The corner case is ones we are explicitly
>>>> saying are not onlineable yet but marked online capable and will
>>>> turn up later.
>>>>
>>>>>
>>>>> I'm not sure if it is valid to do so.
>>>>
>>>> The conclusion of the following is I think this is fine but I'm not
>>>> entirely confident about it.
>>>>
>>>> I'm struggling to figure out the right answer to this and
>>>> it's not easy to test. I vaguely recall having some nasty emulation
>>>> hacks to poke some x86 related _CPC stuff a while back.
>>>> I might be able to hack something up for this as well and try to
>>>> create pathological corner cases.
>>>>
>>>> The short answer is CPPC + hotplug isn't a thing today in KVM + QEMU,
>>>> but that's not to say it never will be if someone virtualizes CPC for
>>>> a guest.  Let's consider that hypothetical virtualization / emulation.
>>>>
>>>> So the questions:
>>>> 1) Does simply making this acpi_cppc_processor_probe() result in any
>>>>    register accesses to the registers that might be found in _CPC or
>>>>    used via other ACPI methods?
>>>> 2) Can we rely on a a VMM not do something nasty if those are accessed
>>>>    on CPUs that haven't been instantiated yet?  e.g. Bus error.
>>>>    A related useful question is: Can we assume these registers are
>>>>    accessible on offlined CPUs?  If they can be unsafe to access from
>>>>    CPUs that are temporary powered down / offline then I think we are fine because
>>>>    the CPPC code must guarantee not to access them. (I'm relying on this!)
>>>>
>>>> For the particular case Lifeng has run into, I think the code that matters
>>>> (beyond instantiation of the infrastructure) is the creation of the
>>>> domain info in acpi_get_psd(). I think _PSD can only be static data so
>>>> shouldn't cause any register accesses to the powered down CPUs.
>>>>
>>>> So 'probably' fine + we'll not really know unless we get CPU HP and
>>>> CPC.
>>>>
>>>> Alternative much more complex change would be to separate the grabbing of
>>>> static data (done here) from setting up anything dynamic which would remain
>>>> in the hotplug handler.  If those registers haven't been discovered we definitely
>>>> can't access them from the cpu freq driver.
>>>
>>> I'm thinking that maybe cppc_cpufreq should be updated instead.
>>>
>>> I'm not really sure why it needs to collect information on offline
>>> CPUs.  Surely, they don't matter until they are brought online.
>>
>> This information is collected in order to generate related_cpus. Without
>> doing so, a new policy will be created when the second CPU in the same
>> domain comes online, instead of reusing the existing policy. And this will
>> make a mess.
>>
>> I can't find a good way to solve this problem in cppc_cpufreq or cpufreq.
> 
> Hi Rafael,
> 
> If we have to make sure not to use the information on offline CPUs, there
> will be many things that need to be modified:
> 
> 1. acpi_get_psd_map() in cppc_acpi.c: only use the information on online
> CPUs, and update shared_cpu_map when a new CPU in the same domain goes
> online.
> 
> 2. cpufreq_online() in cpufreq.c: create a new policy and decide whether it
> should be kept because it may turns out that the CPU should share an
> already exist policy with other CPUs.
> 
> 3. The init() callbacks in cppc_cpufreq, acpi-cpufreq and maybe other
> drivers: verify whether the newly generated policy is necessary and return
> the result.
> 
> ...
> 
> Is it necessary to make such a big change for solving this problem? It
> seems to me that it is reasonable and fewer changes to parse the _CPC table
> for all CPUs in advance because it never change, isn't it?
> 

Hi Rafael,

Although some time has passed, I still look forward to your advice.

Thanks.


^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: power: qcom,rpmpd: Add Hawi RPMh power domain
From: Krzysztof Kozlowski @ 2026-04-02  8:35 UTC (permalink / raw)
  To: Fenglin Wu
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Konrad Dybcio, Subbaraman Narayanamurthy,
	linux-arm-msm, devicetree, linux-kernel, linux-pm, kernel
In-Reply-To: <20260401-haw-rpmhpd-v1-1-c830c79ed8f9@oss.qualcomm.com>

On Wed, Apr 01, 2026 at 02:15:29AM -0700, Fenglin Wu wrote:
> Document the RPMh power domain for Hawi SoC.
> 
> Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
> ---
>  Documentation/devicetree/bindings/power/qcom,rpmpd.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Missing new power domains, no?

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 2/3] dt-bindings: power: qcom,rpmhpd: Add new power domains and new levels
From: Krzysztof Kozlowski @ 2026-04-02  8:34 UTC (permalink / raw)
  To: Fenglin Wu
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Ulf Hansson, Konrad Dybcio, Subbaraman Narayanamurthy,
	linux-arm-msm, devicetree, linux-kernel, linux-pm, kernel
In-Reply-To: <20260401-haw-rpmhpd-v1-2-c830c79ed8f9@oss.qualcomm.com>

On Wed, Apr 01, 2026 at 02:15:30AM -0700, Fenglin Wu wrote:
> Add definitions for the new power domains which present in Hawi SoC:
>  - RPMHPD_DCX (Display Core X): supplies VDD_DISP for the display
>    subsystem
>  - RPMHPD_GBX (Graphics Box): supplies VDD_GFX_BX for the GPU/graphics
>    subsystem
> 
> Also, add constants for new power domain levels that supported in Hawi
> SoC, including: LOW_SVS_D3_0, LOW_SVS_D1_0, LOW_SVS_D0_0, SVS_L2_0,
> TURBO_L1_0/1/2, TURBO_L1_0/1/2.
> 
> Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>

This belongs to the binding change. Unless you are not doing it for
Hawi...

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2 2/6] dt-bindings: opp: ti-cpu: Add ti,soc-info property
From: Krzysztof Kozlowski @ 2026-04-02  7:39 UTC (permalink / raw)
  To: Akashdeep Kaur
  Cc: praneeth, nm, vigneshr, kristo, robh, krzk+dt, conor+dt, rafael,
	viresh.kumar, linux-arm-kernel, devicetree, linux-kernel,
	linux-pm, d-gole, vishalm, sebin.francis, k-willis
In-Reply-To: <20260401105404.1194717-3-a-kaur@ti.com>

On Wed, Apr 01, 2026 at 04:24:00PM +0530, Akashdeep Kaur wrote:
> Add ti,soc-info property to allow OPP tables to reference the SoC info
> device (chipid) for establishing device link dependencies.
> 
> This is used on K3 SoCs (AM625, AM62A7, AM62L3, AM62P5) to ensure proper
> probe ordering between ti-cpufreq and k3-socinfo drivers. The ti-cpufreq

Nope, sorry, DT purpose is not to perform probe ordering.

If I change Linux to load k3-socinfo before ti-cpufreq, then the binding
becomes invalid?

Not a DT property, drop.

Best regards,
Krzysztof


^ permalink raw reply

* [PATCH] power: supply: max77759_charger: fix voltage scale (mV -> uV)
From: Amit Sunil Dhamne via B4 Relay @ 2026-04-02  7:15 UTC (permalink / raw)
  To: Amit Sunil Dhamne, Sebastian Reichel, Greg Kroah-Hartman,
	André Draszik
  Cc: linux-kernel, linux-pm, linux-usb, Badhri Jagan Sridharan

From: Amit Sunil Dhamne <amitsd@google.com>

CONSTANT_CHARGE_VOLTAGE_MAX property incorrectly uses mV instead of uV.
Add fix to use uV as per the power-supply subsystem convention.

Also, add a note indicating all the properties use non negative values.
A negative value indicates failure with the appropriate error value. In
that case, it should not be taken as a measurement value or status.

Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
---
This patch is a follow-up to the series [1]. [1] has been accepted in
the USB subsystem tree (usb-next). However, since Sebastian has additional
feedback [2], I am sending this patch to address it. Please note that this
patch is based out of usb-next branch on usb tree. This patch should be
applied on top of 70d7dd27f6dc ("power: supply: max77759: add charger driver").

[1] https://lore.kernel.org/all/20260325-max77759-charger-v9-0-4486dd297adc@google.com/
[2] https://lore.kernel.org/all/ac2jYUA2F5oQsA2g@venus/#t
---
Output of power supply selftest:
root@google-gs:/data/power_supply# ./test_power_supply_properties.sh
TAP version 13
1..66
 # Testing device max77759-charger
ok 1 max77759-charger.exists
ok 2 max77759-charger.uevent.NAME
ok 3 max77759-charger.sysfs.type
ok 4 max77759-charger.uevent.TYPE
ok 5 max77759-charger.sysfs.usb_type # SKIP
 # Reported: '1' ()
ok 6 max77759-charger.sysfs.online
 # Reported: '1' ()
ok 7 max77759-charger.sysfs.present
 # Reported: 'Charging'
ok 8 max77759-charger.sysfs.status
ok 9 max77759-charger.sysfs.capacity # SKIP
ok 10 max77759-charger.sysfs.capacity_level # SKIP
ok 11 max77759-charger.sysfs.model_name # SKIP
ok 12 max77759-charger.sysfs.manufacturer # SKIP
ok 13 max77759-charger.sysfs.serial_number # SKIP
ok 14 max77759-charger.sysfs.technology # SKIP
ok 15 max77759-charger.sysfs.cycle_count # SKIP
ok 16 max77759-charger.sysfs.scope # SKIP
 # Reported: '3000000' uA (3000 mA)
ok 17 max77759-charger.sysfs.input_current_limit
ok 18 max77759-charger.sysfs.input_voltage_limit # SKIP
ok 19 max77759-charger.sysfs.voltage_now # SKIP
ok 20 max77759-charger.sysfs.voltage_min # SKIP
ok 21 max77759-charger.sysfs.voltage_max # SKIP
ok 22 max77759-charger.sysfs.voltage_min_design # SKIP
ok 23 max77759-charger.sysfs.voltage_max_design # SKIP
ok 24 max77759-charger.sysfs.current_now # SKIP
ok 25 max77759-charger.sysfs.current_max # SKIP
ok 26 max77759-charger.sysfs.charge_now # SKIP
ok 27 max77759-charger.sysfs.charge_full # SKIP
ok 28 max77759-charger.sysfs.charge_full_design # SKIP
ok 29 max77759-charger.sysfs.power_now # SKIP
ok 30 max77759-charger.sysfs.energy_now # SKIP
ok 31 max77759-charger.sysfs.energy_full # SKIP
ok 32 max77759-charger.sysfs.energy_full_design # SKIP
ok 33 max77759-charger.sysfs.energy_full_design # SKIP
 # Testing device tcpm-source-psy-1-0025
ok 34 tcpm-source-psy-1-0025.exists
ok 35 tcpm-source-psy-1-0025.uevent.NAME
ok 36 tcpm-source-psy-1-0025.sysfs.type
ok 37 tcpm-source-psy-1-0025.uevent.TYPE
 # Reported: 'C [PD] PD_PPS PD_SPR_AVS PD_PPS_SPR_AVS' ()
ok 38 tcpm-source-psy-1-0025.sysfs.usb_type
 # Reported: '1' ()
ok 39 tcpm-source-psy-1-0025.sysfs.online
ok 40 tcpm-source-psy-1-0025.sysfs.present # SKIP
ok 41 tcpm-source-psy-1-0025.sysfs.status # SKIP
ok 42 tcpm-source-psy-1-0025.sysfs.capacity # SKIP
ok 43 tcpm-source-psy-1-0025.sysfs.capacity_level # SKIP
ok 44 tcpm-source-psy-1-0025.sysfs.model_name # SKIP
ok 45 tcpm-source-psy-1-0025.sysfs.manufacturer # SKIP
ok 46 tcpm-source-psy-1-0025.sysfs.serial_number # SKIP
ok 47 tcpm-source-psy-1-0025.sysfs.technology # SKIP
ok 48 tcpm-source-psy-1-0025.sysfs.cycle_count # SKIP
ok 49 tcpm-source-psy-1-0025.sysfs.scope # SKIP
ok 50 tcpm-source-psy-1-0025.sysfs.input_current_limit # SKIP
ok 51 tcpm-source-psy-1-0025.sysfs.input_voltage_limit # SKIP
 # Reported: '5000000' uV (5 V)
ok 52 tcpm-source-psy-1-0025.sysfs.voltage_now
 # Reported: '5000000' uV (5 V)
ok 53 tcpm-source-psy-1-0025.sysfs.voltage_min
 # Reported: '5000000' uV (5 V)
ok 54 tcpm-source-psy-1-0025.sysfs.voltage_max
ok 55 tcpm-source-psy-1-0025.sysfs.voltage_min_design # SKIP
ok 56 tcpm-source-psy-1-0025.sysfs.voltage_max_design # SKIP
 # Reported: '3000000' uA (3000 mA)
ok 57 tcpm-source-psy-1-0025.sysfs.current_now
 # Reported: '3000000' uA (3000 mA)
ok 58 tcpm-source-psy-1-0025.sysfs.current_max
ok 59 tcpm-source-psy-1-0025.sysfs.charge_now # SKIP
ok 60 tcpm-source-psy-1-0025.sysfs.charge_full # SKIP
ok 61 tcpm-source-psy-1-0025.sysfs.charge_full_design # SKIP
ok 62 tcpm-source-psy-1-0025.sysfs.power_now # SKIP
ok 63 tcpm-source-psy-1-0025.sysfs.energy_now # SKIP
ok 64 tcpm-source-psy-1-0025.sysfs.energy_full # SKIP
ok 65 tcpm-source-psy-1-0025.sysfs.energy_full_design # SKIP
ok 66 tcpm-source-psy-1-0025.sysfs.energy_full_design # SKIP
 # 47 skipped test(s) detected.  Consider enabling relevant config options to improve coverage.
 # Totals: pass:19 fail:0 xfail:0 xpass:0 skip:47 error:0
---
 drivers/power/supply/max77759_charger.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/power/supply/max77759_charger.c b/drivers/power/supply/max77759_charger.c
index 9bb414599f16..58594bb78426 100644
--- a/drivers/power/supply/max77759_charger.c
+++ b/drivers/power/supply/max77759_charger.c
@@ -26,7 +26,7 @@
 
 /* Default values for Fast Charge Current & Float Voltage */
 #define CHG_CC_DEFAULT_UA			2266770
-#define CHG_FV_DEFAULT_MV			4300
+#define CHG_FV_DEFAULT_UV			4300000
 
 #define MAX_NUM_RETRIES				3
 #define PSY_WORK_RETRY_DELAY_MS			10
@@ -61,10 +61,10 @@ static const struct linear_range chgcc_limit_ranges[] = {
 	LINEAR_RANGE(200000, 0x3, 0x3C, 66670),
 };
 
-/* Charge Termination Voltage Limits (in mV) */
+/* Charge Termination Voltage Limits (in uV) */
 static const struct linear_range chg_cv_prm_ranges[] = {
-	LINEAR_RANGE(3800, 0x38, 0x39, 100),
-	LINEAR_RANGE(4000, 0x0, 0x32, 10),
+	LINEAR_RANGE(3800000, 0x38, 0x39, 100000),
+	LINEAR_RANGE(4000000, 0x0, 0x32, 10000),
 };
 
 /* USB input current limits (in uA) */
@@ -310,14 +310,14 @@ static int get_float_voltage(struct max77759_charger *chg)
 	return ret ? ret : val;
 }
 
-static int set_float_voltage_limit(struct max77759_charger *chg, u32 fv_mv)
+static int set_float_voltage_limit(struct max77759_charger *chg, u32 fv_uv)
 {
 	u32 regval;
 	bool found;
 
 	linear_range_get_selector_high_array(chg_cv_prm_ranges,
 					     ARRAY_SIZE(chg_cv_prm_ranges),
-					     fv_mv, &regval, &found);
+					     fv_uv, &regval, &found);
 	if (!found)
 		return -EINVAL;
 
@@ -370,6 +370,11 @@ static const enum power_supply_property max77759_charger_props[] = {
 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 };
 
+/*
+ * Note: None of the properties in this driver support usage of negative values.
+ * If you do see one, it's because the function is reporting an error value and
+ * should not be taken as a measurement value or status.
+ */
 static int max77759_charger_get_property(struct power_supply *psy,
 					 enum power_supply_property psp,
 					 union power_supply_propval *pval)
@@ -557,10 +562,10 @@ static int max77759_charger_init(struct max77759_charger *chg)
 		return ret;
 
 	if (power_supply_get_battery_info(chg->psy, &info)) {
-		fv = CHG_FV_DEFAULT_MV;
+		fv = CHG_FV_DEFAULT_UV;
 		fast_chg_curr = CHG_CC_DEFAULT_UA;
 	} else {
-		fv = info->constant_charge_voltage_max_uv / 1000;
+		fv = info->constant_charge_voltage_max_uv;
 		fast_chg_curr = info->constant_charge_current_max_ua;
 	}
 

---
base-commit: 81ebd43cc0d6d106ce7b6ccbf7b5e40ca7f5503d
change-id: 20260402-fix-psy-max77759-usb-next-15a4f86a08ce

Best regards,
-- 
Amit Sunil Dhamne <amitsd@google.com>



^ permalink raw reply related

* Re: [PATCH v10 00/12] barrier: Add smp_cond_load_{relaxed,acquire}_timeout()
From: Ankur Arora @ 2026-04-02  7:01 UTC (permalink / raw)
  To: Ankur Arora
  Cc: linux-kernel, linux-arch, linux-arm-kernel, linux-pm, bpf, arnd,
	catalin.marinas, will, peterz, akpm, mark.rutland, harisokn, cl,
	ast, rafael, daniel.lezcano, memxor, zhenglifeng1, xueshuai,
	rdunlap, david.laight.linux, joao.m.martins, boris.ostrovsky,
	konrad.wilk
In-Reply-To: <20260316013651.3225328-1-ankur.a.arora@oracle.com>


Ankur Arora <ankur.a.arora@oracle.com> writes:

> Hi,
>
> This series adds waited variants of the smp_cond_load() primitives:
> smp_cond_load_relaxed_timeout(), and smp_cond_load_acquire_timeout().
>
> With this version, the main remaining things are:
>
>   - Review by PeterZ of the new interface tif_need_resched_relaxed_wait()
>     (patch 11, "sched: add need-resched timed wait interface").
>
>   - Review of the BPF changes. This version simplifies the rqspinlock
>     changes by reusing the original error handling path
>     (patches 9, 10 "bpf/rqspinlock: switch check_timeout() to a clock
>     interface", "bpf/rqspinlock: Use smp_cond_load_acquire_timeout()").
>
>   - Review of WFET handling. (patch 4, "arm64: support WFET in
>     smp_cond_load_relaxed_timeout()").

Received Acks/R-bys for the two above.

Will send out an updated v11 which adds a testcase and a comment
mentioning that smp_cond_load_*_timeout on MMIO addresses might
break in interesting platform specific ways.

Thanks
Ankur

> The new interfaces are meant for contexts where you want to wait on a
> condition variable for a finite duration. This is easy enough to do with
> a loop around cpu_relax(). There are, however, architectures (ex. arm64)
> that allow waiting on a cacheline instead.
>
> So, these interfaces handle a mixture of spin/wait with a
> smp_cond_load() thrown in. The interfaces are:
>
>    smp_cond_load_relaxed_timeout(ptr, cond_expr, time_expr, timeout)
>    smp_cond_load_acquire_timeout(ptr, cond_expr, time_expr, timeout)
>
> The parameters, time_expr, timeout determine when to bail out.
>
> Also add tif_need_resched_relaxed_wait() which wraps the pattern used
> in poll_idle() and abstracts out details of the interface and those
> of the scheduler.
>
> In addition add atomic_cond_read_*_timeout(), atomic64_cond_read_*_timeout(),
> and atomic_long wrappers to the interfaces.
>
> Finally update poll_idle() and resilient queued spinlocks to use them.
>
> Changelog:
>   v9 [9]:
>    - s/@cond/@cond_expr/ (Randy Dunlap)
>    - Clarify that SMP_TIMEOUT_POLL_COUNT is only around memory
>      addresses. (David Laight)
>    - Add the missing config ARCH_HAS_CPU_RELAX in arch/arm64/Kconfig.
>      (Catalin Marinas).
>    - Switch to arch_counter_get_cntvct_stable() (via __delay_cycles())
>      in the cmpwait path instead of using arch_timer_read_counter().
>      (Catalin Marinas)
>
>   v8 [0]:
>    - Defer evaluation of @time_expr_ns to when we hit the slowpath.
>       (comment from Alexei Starovoitov).
>
>    - Mention that cpu_poll_relax() is better than raw CPU polling
>      only where ARCH_HAS_CPU_RELAX is defined.
>      - also define ARCH_HAS_CPU_RELAX for arm64.
>       (Came out of a discussion with Will Deacon.)
>
>    - Split out WFET and WFE handling. I was doing both of these
>      in a common handler.
>      (From Will Deacon and in an earlier revision by Catalin Marinas.)
>
>    - Add mentions of atomic_cond_read_{relaxed,acquire}(),
>      atomic_cond_read_{relaxed,acquire}_timeout() in
>      Documentation/atomic_t.txt.
>
>    - Use the BIT() macro to do the checking in tif_bitset_relaxed_wait().
>
>    - Cleanup unnecessary assignments, casts etc in poll_idle().
>      (From Rafael Wysocki.)
>
>    - Fixup warnings from kernel build robot
>
>
>   v7 [1]:
>    - change the interface to separately provide the timeout. This is
>      useful for supporting WFET and similar primitives which can do
>      timed waiting (suggested by Arnd Bergmann).
>
>    - Adapting rqspinlock code to this changed interface also
>      necessitated allowing time_expr to fail.
>    - rqspinlock changes to adapt to the new smp_cond_load_acquire_timeout().
>
>    - add WFET support (suggested by Arnd Bergmann).
>    - add support for atomic-long wrappers.
>    - add a new scheduler interface tif_need_resched_relaxed_wait() which
>      encapsulates the polling logic used by poll_idle().
>      - interface suggested by (Rafael J. Wysocki).
>
>
>   v6 [2]:
>    - fixup missing timeout parameters in atomic64_cond_read_*_timeout()
>    - remove a race between setting of TIF_NEED_RESCHED and the call to
>      smp_cond_load_relaxed_timeout(). This would mean that dev->poll_time_limit
>      would be set even if we hadn't spent any time waiting.
>      (The original check compared against local_clock(), which would have been
>      fine, but I was instead using a cheaper check against _TIF_NEED_RESCHED.)
>    (Both from meta-CI bot)
>
>
>   v5 [3]:
>    - use cpu_poll_relax() instead of cpu_relax().
>    - instead of defining an arm64 specific
>      smp_cond_load_relaxed_timeout(), just define the appropriate
>      cpu_poll_relax().
>    - re-read the target pointer when we exit due to the time-check.
>    - s/SMP_TIMEOUT_SPIN_COUNT/SMP_TIMEOUT_POLL_COUNT/
>    (Suggested by Will Deacon)
>
>    - add atomic_cond_read_*_timeout() and atomic64_cond_read_*_timeout()
>      interfaces.
>    - rqspinlock: use atomic_cond_read_acquire_timeout().
>    - cpuidle: use smp_cond_load_relaxed_tiemout() for polling.
>    (Suggested by Catalin Marinas)
>
>    - rqspinlock: define SMP_TIMEOUT_POLL_COUNT to be 16k for non arm64
>
>
>   v4 [4]:
>     - naming change 's/timewait/timeout/'
>     - resilient spinlocks: get rid of res_smp_cond_load_acquire_waiting()
>       and fixup use of RES_CHECK_TIMEOUT().
>     (Both suggested by Catalin Marinas)
>
>   v3 [5]:
>     - further interface simplifications (suggested by Catalin Marinas)
>
>   v2 [6]:
>     - simplified the interface (suggested by Catalin Marinas)
>        - get rid of wait_policy, and a multitude of constants
>        - adds a slack parameter
>       This helped remove a fair amount of duplicated code duplication and in
>       hindsight unnecessary constants.
>
>   v1 [7]:
>      - add wait_policy (coarse and fine)
>      - derive spin-count etc at runtime instead of using arbitrary
>        constants.
>
> Haris Okanovic tested v4 of this series with poll_idle()/haltpoll patches. [8]
>
> Comments appreciated!
>
> Thanks
> Ankur
>
>  [0] https://lore.kernel.org/lkml/20251215044919.460086-1-ankur.a.arora@oracle.com/
>  [1] https://lore.kernel.org/lkml/20251028053136.692462-1-ankur.a.arora@oracle.com/
>  [2] https://lore.kernel.org/lkml/20250911034655.3916002-1-ankur.a.arora@oracle.com/
>  [3] https://lore.kernel.org/lkml/20250911034655.3916002-1-ankur.a.arora@oracle.com/
>  [4] https://lore.kernel.org/lkml/20250829080735.3598416-1-ankur.a.arora@oracle.com/
>  [5] https://lore.kernel.org/lkml/20250627044805.945491-1-ankur.a.arora@oracle.com/
>  [6] https://lore.kernel.org/lkml/20250502085223.1316925-1-ankur.a.arora@oracle.com/
>  [7] https://lore.kernel.org/lkml/20250203214911.898276-1-ankur.a.arora@oracle.com/
>  [8] https://lore.kernel.org/lkml/2cecbf7fb23ee83a4ce027e1be3f46f97efd585c.camel@amazon.com/
>  [9] https://lore.kernel.org/lkml/20260209023153.2661784-1-ankur.a.arora@oracle.com/
>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Will Deacon <will@kernel.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: bpf@vger.kernel.org
> Cc: linux-arch@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-pm@vger.kernel.org
>
> Ankur Arora (12):
>   asm-generic: barrier: Add smp_cond_load_relaxed_timeout()
>   arm64: barrier: Support smp_cond_load_relaxed_timeout()
>   arm64/delay: move some constants out to a separate header
>   arm64: support WFET in smp_cond_load_relaxed_timeout()
>   arm64: rqspinlock: Remove private copy of
>     smp_cond_load_acquire_timewait()
>   asm-generic: barrier: Add smp_cond_load_acquire_timeout()
>   atomic: Add atomic_cond_read_*_timeout()
>   locking/atomic: scripts: build atomic_long_cond_read_*_timeout()
>   bpf/rqspinlock: switch check_timeout() to a clock interface
>   bpf/rqspinlock: Use smp_cond_load_acquire_timeout()
>   sched: add need-resched timed wait interface
>   cpuidle/poll_state: Wait for need-resched via
>     tif_need_resched_relaxed_wait()
>
>  Documentation/atomic_t.txt           | 14 +++--
>  arch/arm64/Kconfig                   |  3 +
>  arch/arm64/include/asm/barrier.h     | 23 +++++++
>  arch/arm64/include/asm/cmpxchg.h     | 62 +++++++++++++++----
>  arch/arm64/include/asm/delay-const.h | 27 +++++++++
>  arch/arm64/include/asm/rqspinlock.h  | 85 --------------------------
>  arch/arm64/lib/delay.c               | 15 ++---
>  drivers/cpuidle/poll_state.c         | 21 +------
>  drivers/soc/qcom/rpmh-rsc.c          |  8 +--
>  include/asm-generic/barrier.h        | 90 ++++++++++++++++++++++++++++
>  include/linux/atomic.h               | 10 ++++
>  include/linux/atomic/atomic-long.h   | 18 +++---
>  include/linux/sched/idle.h           | 29 +++++++++
>  kernel/bpf/rqspinlock.c              | 77 +++++++++++++++---------
>  scripts/atomic/gen-atomic-long.sh    | 16 +++--
>  15 files changed, 320 insertions(+), 178 deletions(-)
>  create mode 100644 arch/arm64/include/asm/delay-const.h


--
ankur

^ permalink raw reply

* Re: [PATCH 3/3] pmdomain: qcom: rpmhpd: Add power domains for Hawi SoC
From: Taniya Das @ 2026-04-02  7:02 UTC (permalink / raw)
  To: Fenglin Wu, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Ulf Hansson, Konrad Dybcio
  Cc: Subbaraman Narayanamurthy, linux-arm-msm, devicetree,
	linux-kernel, linux-pm, kernel
In-Reply-To: <20260401-haw-rpmhpd-v1-3-c830c79ed8f9@oss.qualcomm.com>



On 4/1/2026 2:45 PM, Fenglin Wu wrote:
> Add the RPMh power domains required for the Hawi SoC. This includes
> new definitions for domains supplying specific hardware components:
> - DCX: supplies VDD_DISP
> - GBX: supplies VDD_GFX_BX
> 
> Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
> ---
>  drivers/pmdomain/qcom/rpmhpd.c | 38 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 38 insertions(+)
> 
> diff --git a/drivers/pmdomain/qcom/rpmhpd.c b/drivers/pmdomain/qcom/rpmhpd.c
> index 19849703be4a..f5ae2a63765d 100644
> --- a/drivers/pmdomain/qcom/rpmhpd.c
> +++ b/drivers/pmdomain/qcom/rpmhpd.c
> @@ -102,11 +102,21 @@ static struct rpmhpd cx_ao_w_mx_parent = {
>  	.res_name = "cx.lvl",
>  };
>  

Reviewed-by: Taniya Das <taniya.das@oss.qualcomm.com>

-- 
Thanks,
Taniya Das


^ permalink raw reply

* [rafael-pm:bleeding-edge] BUILD SUCCESS baf86598b2220d2710045bb15efadba7af276049
From: kernel test robot @ 2026-04-02  2:01 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: linux-acpi, linux-pm

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git bleeding-edge
branch HEAD: baf86598b2220d2710045bb15efadba7af276049  Merge branch 'experimental/acpi-driver-conversion' into bleeding-edge

elapsed time: 2266m

configs tested: 154
configs skipped: 3

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    gcc-15.2.0
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    gcc-15.2.0
arc                                 defconfig    gcc-15.2.0
arc                   randconfig-001-20260401    gcc-8.5.0
arc                   randconfig-002-20260401    gcc-11.5.0
arm                               allnoconfig    clang-23
arm                              allyesconfig    gcc-15.2.0
arm                                 defconfig    clang-23
arm                   randconfig-001-20260401    clang-23
arm                   randconfig-002-20260401    clang-23
arm                   randconfig-003-20260401    clang-23
arm                   randconfig-004-20260401    gcc-12.5.0
arm64                            allmodconfig    clang-19
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260401    clang-18
arm64                 randconfig-002-20260401    gcc-8.5.0
arm64                 randconfig-003-20260401    gcc-8.5.0
arm64                 randconfig-004-20260401    gcc-11.5.0
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260401    gcc-13.4.0
csky                  randconfig-002-20260401    gcc-15.2.0
hexagon                          allmodconfig    clang-17
hexagon                           allnoconfig    clang-23
hexagon                             defconfig    clang-23
hexagon               randconfig-001-20260401    clang-23
hexagon               randconfig-002-20260401    clang-17
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260401    gcc-14
i386        buildonly-randconfig-002-20260401    clang-20
i386        buildonly-randconfig-003-20260401    gcc-14
i386        buildonly-randconfig-004-20260401    gcc-14
i386        buildonly-randconfig-005-20260401    gcc-14
i386        buildonly-randconfig-006-20260401    clang-20
i386                                defconfig    clang-20
i386                  randconfig-001-20260401    gcc-14
i386                  randconfig-002-20260401    clang-20
i386                  randconfig-003-20260401    clang-20
i386                  randconfig-004-20260401    gcc-12
i386                  randconfig-005-20260401    gcc-14
i386                  randconfig-006-20260401    gcc-14
i386                  randconfig-007-20260401    gcc-14
i386                  randconfig-011-20260401    clang-20
i386                  randconfig-012-20260401    clang-20
i386                  randconfig-013-20260401    clang-20
i386                  randconfig-014-20260401    clang-20
i386                  randconfig-015-20260401    clang-20
i386                  randconfig-016-20260401    gcc-14
i386                  randconfig-017-20260401    gcc-14
loongarch                        allmodconfig    clang-19
loongarch                         allnoconfig    clang-23
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260401    gcc-15.2.0
loongarch             randconfig-002-20260401    clang-23
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    gcc-15.2.0
m68k                                defconfig    gcc-15.2.0
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    gcc-15.2.0
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    gcc-11.5.0
nios2                 randconfig-001-20260401    gcc-8.5.0
nios2                 randconfig-002-20260401    gcc-9.5.0
openrisc                         allmodconfig    gcc-15.2.0
openrisc                          allnoconfig    gcc-15.2.0
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    gcc-15.2.0
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260401    gcc-8.5.0
parisc                randconfig-002-20260401    gcc-8.5.0
parisc64                            defconfig    gcc-15.2.0
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    gcc-15.2.0
powerpc               randconfig-001-20260401    gcc-8.5.0
powerpc               randconfig-002-20260401    clang-18
powerpc64             randconfig-001-20260401    gcc-14.3.0
powerpc64             randconfig-002-20260401    gcc-8.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    gcc-15.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    clang-23
riscv                 randconfig-001-20260401    gcc-8.5.0
riscv                 randconfig-002-20260401    gcc-11.5.0
s390                             allmodconfig    clang-18
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    clang-23
s390                  randconfig-001-20260401    gcc-9.5.0
s390                  randconfig-002-20260401    gcc-8.5.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    gcc-15.2.0
sh                               allyesconfig    gcc-15.2.0
sh                    randconfig-001-20260401    gcc-10.5.0
sh                    randconfig-002-20260401    gcc-15.2.0
sh                            shmin_defconfig    gcc-15.2.0
sparc                             allnoconfig    gcc-15.2.0
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260401    gcc-8.5.0
sparc                 randconfig-002-20260401    gcc-8.5.0
sparc64                          allmodconfig    clang-23
sparc64               randconfig-001-20260401    clang-23
sparc64               randconfig-002-20260401    clang-23
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                    randconfig-001-20260401    clang-16
um                    randconfig-002-20260401    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-20
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260401    gcc-14
x86_64      buildonly-randconfig-002-20260401    gcc-14
x86_64      buildonly-randconfig-003-20260401    gcc-12
x86_64      buildonly-randconfig-004-20260401    gcc-12
x86_64      buildonly-randconfig-005-20260401    clang-20
x86_64      buildonly-randconfig-006-20260401    gcc-14
x86_64                randconfig-001-20260401    gcc-14
x86_64                randconfig-002-20260401    clang-20
x86_64                randconfig-003-20260401    gcc-14
x86_64                randconfig-004-20260401    gcc-14
x86_64                randconfig-005-20260401    clang-20
x86_64                randconfig-006-20260401    clang-20
x86_64                randconfig-011-20260401    gcc-14
x86_64                randconfig-012-20260401    gcc-14
x86_64                randconfig-013-20260401    gcc-14
x86_64                randconfig-014-20260401    clang-20
x86_64                randconfig-015-20260401    clang-20
x86_64                randconfig-016-20260401    gcc-14
x86_64                randconfig-071-20260401    gcc-14
x86_64                randconfig-072-20260401    clang-20
x86_64                randconfig-073-20260401    gcc-14
x86_64                randconfig-074-20260401    gcc-14
x86_64                randconfig-075-20260401    clang-20
x86_64                randconfig-076-20260401    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    gcc-15.2.0
xtensa                randconfig-001-20260401    gcc-9.5.0
xtensa                randconfig-002-20260401    gcc-14.3.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v2 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Jie Zhan @ 2026-04-02  6:52 UTC (permalink / raw)
  To: Yaxiong Tian, myungjoo.ham, kyungmin.park, cw00.choi, nm
  Cc: linux-pm, linux-kernel
In-Reply-To: <daa71f81-cb36-4a9a-abf8-6a435ae79676@kylinos.cn>



On 4/2/2026 1:47 PM, Yaxiong Tian wrote:
> 
> 在 2026/4/2 11:21, Jie Zhan 写道:
>>
>> On 4/1/2026 11:31 AM, Yaxiong Tian wrote:
>>> Since devfreq_remove_governor() may clear the device's current governor
>>> in certain situations, while governors actually exist independently
>>> of the device, directly returning EINVAL in this case is inaccurate.
>>>
>>> To fix this issue, remove this check and add relevant logic for when
>>> df->governor is NULL.
>>>
>>> Fixes: 483d557ee9a3 ("PM / devfreq: Clean up the devfreq instance name in sysfs attr")
>>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>>> ---
>>>   drivers/devfreq/devfreq.c | 17 ++++++++++++++---
>>>   1 file changed, 14 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>> index 2977b07be939..975f82d7a9d1 100644
>>> --- a/drivers/devfreq/devfreq.c
>>> +++ b/drivers/devfreq/devfreq.c
>>> @@ -1390,9 +1390,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>>       char str_governor[DEVFREQ_NAME_LEN + 1];
>>>       const struct devfreq_governor *governor, *prev_governor;
>>>   -    if (!df->governor)
>>> -        return -EINVAL;
>>> -
>>>       ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>>>       if (ret != 1)
>>>           return -EINVAL;
>>> @@ -1403,6 +1400,20 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>>           ret = PTR_ERR(governor);
>>>           goto out;
>>>       }
>>> +
>>> +    if (!df->governor) {
>>> +        df->governor = governor;
>>> +        ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>>> +        if (ret) {
>>> +            dev_warn(dev, "%s: Governor %s not started(%d)\n",
>>> +                __func__, df->governor->name, ret);
>>> +            df->governor = NULL;
>>> +        } else {
>>> +            ret = sysfs_update_group(&df->dev.kobj, &gov_attr_group);
>>> +        }
>>> +        goto out;
>>> +    }
>>> +
>>>       if (df->governor == governor) {
>>>           ret = 0;
>>>           goto out;
>> Hi Yaxiong,
>>
>> I'd suggest something like this, such that the main body of the function is
>> not changed.
>>
>> Note that this is just an example. Not tested or carefully checked.
> "I still prefer my modification. It's clearer and more straightforward, and the increase in code size is very small compared to the alternatives. Moreover, if we later want to implement 'cannot unload the last governor' (which might be the module reference approach you mentioned), we can simply remove this code."
> 
OK.  I'm fine with the above.
Reviewed-by: Jie Zhan <zhanjie9@hisilicon.com>
> 
>>
>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>> index 2977b07be939..aa0f1db3225c 100644
>> --- a/drivers/devfreq/devfreq.c
>> +++ b/drivers/devfreq/devfreq.c
>> @@ -1390,9 +1390,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>          char str_governor[DEVFREQ_NAME_LEN + 1];
>>          const struct devfreq_governor *governor, *prev_governor;
>>
>> -       if (!df->governor)
>> -               return -EINVAL;
>> -
>>          ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>>          if (ret != 1)
>>                  return -EINVAL;
>> @@ -1403,6 +1400,10 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>                  ret = PTR_ERR(governor);
>>                  goto out;
>>          }
>> +
>> +       if (!df->governor)
>> +               goto skip_stop;
>> +
>>          if (df->governor == governor) {
>>                  ret = 0;
>>                  goto out;
>> @@ -1423,6 +1424,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>                  goto out;
>>          }
>>
>> +skip_stop:
>>          /*
>>           * Start the new governor and create the specific sysfs files
>>           * which depend on the new governor.
>> @@ -1435,6 +1437,8 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>                           __func__, df->governor->name, ret);
>>
>>                  /* Restore previous governor */
>> +               if (!prev_governor)
>> +                       goto out;
>>                  df->governor = prev_governor;
>>                  ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>>                  if (ret) {

^ permalink raw reply

* Re: [PATCH v4 2/2] cpufreq: Pass the policy to cpufreq_driver->adjust_perf()
From: Zhongqiu Han @ 2026-04-02  6:52 UTC (permalink / raw)
  To: K Prateek Nayak, Rafael J. Wysocki, Viresh Kumar, Huang Rui,
	Gautham R. Shenoy, Mario Limonciello, Sebastian Andrzej Siewior,
	Clark Williams, Steven Rostedt, Srinivas Pandruvada, Len Brown,
	Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot,
	Miguel Ojeda
  Cc: Perry Yuan, linux-pm, linux-kernel, rust-for-linux,
	linux-rt-devel, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Valentin Schneider, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Bert Karwatzki, zhongqiu.han
In-Reply-To: <20260316081849.19368-3-kprateek.nayak@amd.com>

On 3/16/2026 4:18 PM, K Prateek Nayak wrote:
> cpufreq_cpu_get() can sleep on PREEMPT_RT in presence of concurrent
> writer(s), however amd-pstate depends on fetching the cpudata via the
> policy's driver data which necessitates grabbing the reference.
> 
> Since schedutil governor can call "cpufreq_driver->update_perf()"
> during sched_tick/enqueue/dequeue with rq_lock held and IRQs disabled,
> fetching the policy object using the cpufreq_cpu_get() helper in the
> scheduler fast-path leads to "BUG: scheduling while atomic" on
> PREEMPT_RT [1].
> 
> Pass the cached cpufreq policy object in sg_policy to the update_perf()
> instead of just the CPU. The CPU can be inferred using "policy->cpu".
> 
> The lifetime of cpufreq_policy object outlasts that of the governor and
> the cpufreq driver (allocated when the CPU is onlined and only reclaimed
> when the CPU is offlined / the CPU device is removed) which makes it
> safe to be referenced throughout the governor's lifetime.
> 
> Fixes: 1d215f0319c2 ("cpufreq: amd-pstate: Add fast switch function for AMD P-State")
> Reported-by: Bert Karwatzki <spasswolf@web.de>
> Closes:https://lore.kernel.org/all/20250731092316.3191-1-spasswolf@web.de/ [1]
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
> ---
> changelog v3..v4:
> 
> o Added the Fixes tag. (Gautham, Chris Mason's review-prompts)
> ---
>   drivers/cpufreq/amd-pstate.c     |  3 +--
>   drivers/cpufreq/cpufreq.c        |  6 +++---
>   drivers/cpufreq/intel_pstate.c   |  4 ++--
>   include/linux/cpufreq.h          |  4 ++--
>   kernel/sched/cpufreq_schedutil.c |  5 +++--
>   rust/kernel/cpufreq.rs           | 13 ++++++-------
>   6 files changed, 17 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index 5faccb3d6b14..ad4b5f84773a 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -710,13 +710,12 @@ static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
>   	return policy->cur;
>   }
>   
> -static void amd_pstate_adjust_perf(unsigned int cpu,
> +static void amd_pstate_adjust_perf(struct cpufreq_policy *policy,
>   				   unsigned long _min_perf,
>   				   unsigned long target_perf,
>   				   unsigned long capacity)
>   {
>   	u8 max_perf, min_perf, des_perf, cap_perf;
> -	struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu);
>   	struct amd_cpudata *cpudata;
>   	union perf_cached perf;


Original code before the patch:

static void amd_pstate_adjust_perf(unsigned int cpu,
				   unsigned long _min_perf,
				   unsigned long target_perf,
				   unsigned long capacity)
{
	u8 max_perf, min_perf, des_perf, cap_perf;
	struct cpufreq_policy *policy __free(put_cpufreq_policy) = 
cpufreq_cpu_get(cpu);
	struct amd_cpudata *cpudata;
	union perf_cached perf;

	if (!policy)
		return;

Nit: Post-patch, the policy NULL check should no longer be necessary.

Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>


>   
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 2082a9e4384f..17a5b8e0ea1e 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -2231,7 +2231,7 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch);
>   
>   /**
>    * cpufreq_driver_adjust_perf - Adjust CPU performance level in one go.
> - * @cpu: Target CPU.
> + * @policy: cpufreq policy object of the target CPU.
>    * @min_perf: Minimum (required) performance level (units of @capacity).
>    * @target_perf: Target (desired) performance level (units of @capacity).
>    * @capacity: Capacity of the target CPU.
> @@ -2250,12 +2250,12 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch);
>    * parallel with either ->target() or ->target_index() or ->fast_switch() for
>    * the same CPU.
>    */
> -void cpufreq_driver_adjust_perf(unsigned int cpu,
> +void cpufreq_driver_adjust_perf(struct cpufreq_policy *policy,
>   				 unsigned long min_perf,
>   				 unsigned long target_perf,
>   				 unsigned long capacity)
>   {
> -	cpufreq_driver->adjust_perf(cpu, min_perf, target_perf, capacity);
> +	cpufreq_driver->adjust_perf(policy, min_perf, target_perf, capacity);
>   }
>   
>   /**
> diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
> index 51938c5a47ca..1552b2d32a34 100644
> --- a/drivers/cpufreq/intel_pstate.c
> +++ b/drivers/cpufreq/intel_pstate.c
> @@ -3239,12 +3239,12 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
>   	return target_pstate * cpu->pstate.scaling;
>   }
>   
> -static void intel_cpufreq_adjust_perf(unsigned int cpunum,
> +static void intel_cpufreq_adjust_perf(struct cpufreq_policy *policy,
>   				      unsigned long min_perf,
>   				      unsigned long target_perf,
>   				      unsigned long capacity)
>   {
> -	struct cpudata *cpu = all_cpu_data[cpunum];
> +	struct cpudata *cpu = all_cpu_data[policy->cpu];
>   	u64 hwp_cap = READ_ONCE(cpu->hwp_cap_cached);
>   	int old_pstate = cpu->pstate.current_pstate;
>   	int cap_pstate, min_pstate, max_pstate, target_pstate;
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index cc894fc38971..4317c5a312bd 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -372,7 +372,7 @@ struct cpufreq_driver {
>   	 * conditions) scale invariance can be disabled, which causes the
>   	 * schedutil governor to fall back to the latter.
>   	 */
> -	void		(*adjust_perf)(unsigned int cpu,
> +	void		(*adjust_perf)(struct cpufreq_policy *policy,
>   				       unsigned long min_perf,
>   				       unsigned long target_perf,
>   				       unsigned long capacity);
> @@ -617,7 +617,7 @@ struct cpufreq_governor {
>   /* Pass a target to the cpufreq driver */
>   unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
>   					unsigned int target_freq);
> -void cpufreq_driver_adjust_perf(unsigned int cpu,
> +void cpufreq_driver_adjust_perf(struct cpufreq_policy *policy,
>   				unsigned long min_perf,
>   				unsigned long target_perf,
>   				unsigned long capacity);
> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> index 153232dd8276..ae9fd211cec1 100644
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -461,6 +461,7 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time,
>   				     unsigned int flags)
>   {
>   	struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util);
> +	struct sugov_policy *sg_policy = sg_cpu->sg_policy;
>   	unsigned long prev_util = sg_cpu->util;
>   	unsigned long max_cap;
>   
> @@ -482,10 +483,10 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time,
>   	if (sugov_hold_freq(sg_cpu) && sg_cpu->util < prev_util)
>   		sg_cpu->util = prev_util;
>   
> -	cpufreq_driver_adjust_perf(sg_cpu->cpu, sg_cpu->bw_min,
> +	cpufreq_driver_adjust_perf(sg_policy->policy, sg_cpu->bw_min,
>   				   sg_cpu->util, max_cap);
>   
> -	sg_cpu->sg_policy->last_freq_update_time = time;
> +	sg_policy->last_freq_update_time = time;
>   }
>   
>   static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
> diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs
> index 76faa1ac8501..a83aec198336 100644
> --- a/rust/kernel/cpufreq.rs
> +++ b/rust/kernel/cpufreq.rs
> @@ -1256,18 +1256,17 @@ impl<T: Driver> Registration<T> {
>       /// # Safety
>       ///
>       /// - This function may only be called from the cpufreq C infrastructure.
> +    /// - The pointer arguments must be valid pointers.
>       unsafe extern "C" fn adjust_perf_callback(
> -        cpu: c_uint,
> +        ptr: *mut bindings::cpufreq_policy,
>           min_perf: c_ulong,
>           target_perf: c_ulong,
>           capacity: c_ulong,
>       ) {
> -        // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number.
> -        let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) };
> -
> -        if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) {
> -            T::adjust_perf(&mut policy, min_perf, target_perf, capacity);
> -        }
> +        // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the
> +        // lifetime of `policy`.
> +        let policy = unsafe { Policy::from_raw_mut(ptr) };
> +        T::adjust_perf(policy, min_perf, target_perf, capacity);
>       }
>   
>       /// Driver's `get_intermediate` callback.


-- 
Thx and BRs,
Zhongqiu Han

^ permalink raw reply

* [amd-pstate:bleeding-edge] BUILD SUCCESS WITH UNVERIFIED WARNING a2db5f18169f8d80bae411c10d29272029a174ae
From: kernel test robot @ 2026-04-02  1:59 UTC (permalink / raw)
  To: Mario Limonciello (AMD); +Cc: linux-pm

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/superm1/linux.git bleeding-edge
branch HEAD: a2db5f18169f8d80bae411c10d29272029a174ae  cpufreq/amd-pstate-ut: Add a unit test for raw EPP

Unverified Warning (likely false positive, kindly check if interested):

    drivers/cpufreq/amd-pstate.c:1335:5-8: WARNING: Unsigned expression compared with zero: epp > 0

Warning ids grouped by kconfigs:

recent_errors
`-- i386-randconfig-054-20260401
    `-- drivers-cpufreq-amd-pstate.c:WARNING:Unsigned-expression-compared-with-zero:epp

elapsed time: 1532m

configs tested: 160
configs skipped: 3

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                   randconfig-001-20260401    clang-23
arc                   randconfig-002-20260401    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                   randconfig-001-20260401    clang-23
arm                   randconfig-002-20260401    clang-23
arm                   randconfig-003-20260401    clang-23
arm                   randconfig-004-20260401    clang-23
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                 randconfig-001-20260401    gcc-15.2.0
arm64                 randconfig-002-20260401    gcc-15.2.0
arm64                 randconfig-003-20260401    gcc-15.2.0
arm64                 randconfig-004-20260401    gcc-15.2.0
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                  randconfig-001-20260401    gcc-15.2.0
csky                  randconfig-002-20260401    gcc-15.2.0
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    gcc-15.2.0
hexagon               randconfig-001-20260401    gcc-15.2.0
hexagon               randconfig-002-20260401    gcc-15.2.0
i386                             allmodconfig    clang-20
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    clang-20
i386        buildonly-randconfig-001-20260401    gcc-14
i386        buildonly-randconfig-002-20260401    gcc-14
i386        buildonly-randconfig-003-20260401    gcc-14
i386        buildonly-randconfig-004-20260401    gcc-14
i386        buildonly-randconfig-005-20260401    gcc-14
i386        buildonly-randconfig-006-20260401    gcc-14
i386                  randconfig-001-20260401    gcc-14
i386                  randconfig-002-20260401    gcc-14
i386                  randconfig-003-20260401    gcc-14
i386                  randconfig-004-20260401    gcc-14
i386                  randconfig-005-20260401    gcc-14
i386                  randconfig-006-20260401    gcc-14
i386                  randconfig-007-20260401    gcc-14
i386                  randconfig-011-20260401    clang-20
i386                  randconfig-012-20260401    clang-20
i386                  randconfig-013-20260401    clang-20
i386                  randconfig-014-20260401    clang-20
i386                  randconfig-015-20260401    clang-20
i386                  randconfig-016-20260401    clang-20
i386                  randconfig-017-20260401    clang-20
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260401    gcc-15.2.0
loongarch             randconfig-002-20260401    gcc-15.2.0
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            allmodconfig    clang-23
nios2                             allnoconfig    clang-23
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260401    gcc-15.2.0
nios2                 randconfig-002-20260401    gcc-15.2.0
openrisc                         allmodconfig    clang-23
openrisc                          allnoconfig    clang-23
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                           allyesconfig    clang-19
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260401    gcc-8.5.0
parisc                randconfig-002-20260401    gcc-8.5.0
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                       holly_defconfig    clang-23
powerpc               randconfig-001-20260401    gcc-8.5.0
powerpc               randconfig-002-20260401    gcc-8.5.0
powerpc64             randconfig-001-20260401    gcc-8.5.0
powerpc64             randconfig-002-20260401    gcc-8.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260401    gcc-9.5.0
riscv                 randconfig-002-20260401    gcc-9.5.0
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260401    gcc-9.5.0
s390                  randconfig-002-20260401    gcc-9.5.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                               allyesconfig    clang-19
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260401    gcc-9.5.0
sh                    randconfig-002-20260401    gcc-9.5.0
sparc                             allnoconfig    clang-23
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260401    clang-16
sparc                 randconfig-002-20260401    clang-16
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260401    clang-16
sparc64               randconfig-002-20260401    clang-16
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260401    clang-16
um                    randconfig-002-20260401    clang-16
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260401    gcc-12
x86_64      buildonly-randconfig-002-20260401    gcc-12
x86_64      buildonly-randconfig-003-20260401    gcc-12
x86_64      buildonly-randconfig-004-20260401    gcc-12
x86_64      buildonly-randconfig-005-20260401    gcc-12
x86_64      buildonly-randconfig-006-20260401    gcc-12
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20260401    clang-20
x86_64                randconfig-002-20260401    clang-20
x86_64                randconfig-003-20260401    clang-20
x86_64                randconfig-004-20260401    clang-20
x86_64                randconfig-005-20260401    clang-20
x86_64                randconfig-006-20260401    clang-20
x86_64                randconfig-011-20260401    gcc-14
x86_64                randconfig-012-20260401    gcc-14
x86_64                randconfig-013-20260401    gcc-14
x86_64                randconfig-014-20260401    gcc-14
x86_64                randconfig-015-20260401    gcc-14
x86_64                randconfig-016-20260401    gcc-14
x86_64                randconfig-071-20260401    gcc-14
x86_64                randconfig-072-20260401    gcc-14
x86_64                randconfig-073-20260401    gcc-14
x86_64                randconfig-074-20260401    gcc-14
x86_64                randconfig-075-20260401    gcc-14
x86_64                randconfig-076-20260401    gcc-14
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                           allyesconfig    clang-23
xtensa                randconfig-001-20260401    clang-16
xtensa                randconfig-002-20260401    clang-16

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v4 1/2] cpufreq/amd-pstate: Pass the policy to amd_pstate_update()
From: Viresh Kumar @ 2026-04-02  6:39 UTC (permalink / raw)
  To: K Prateek Nayak
  Cc: Rafael J. Wysocki, Huang Rui, Gautham R. Shenoy,
	Mario Limonciello, Sebastian Andrzej Siewior, Clark Williams,
	Steven Rostedt, Perry Yuan, linux-pm, linux-kernel,
	rust-for-linux, linux-rt-devel, Mario Limonciello
In-Reply-To: <hin33mzxwjjycw7oonq4klqmgmgavqpoe7r2ml6qalytxfpntk@me7d6q6yiec7>

On 02-04-26, 12:07, Viresh Kumar wrote:
> On 16-03-26, 08:18, K Prateek Nayak wrote:
> > All callers of amd_pstate_update() already have a reference to the
> > cpufreq_policy object.
> > 
> > Pass the entire policy object and grab the cpudata using
> > "policy->driver_data" instead of passing the cpudata and unnecessarily
> > grabbing another read-side reference to the cpufreq policy object when
> > it is already available in the caller.
> > 
> > No functional changes intended.
> > 
> > Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> > Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
> > ---
> > changelog v3..v4:
> > 
> > o No changes.
> > ---
> >  drivers/cpufreq/amd-pstate.c | 11 ++++-------
> >  1 file changed, 4 insertions(+), 7 deletions(-)
> 
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

Oops, I already Acked it once :)

It is ready for Rafael to pick now.

-- 
viresh

^ permalink raw reply

* Re: [PATCH v4 1/2] cpufreq/amd-pstate: Pass the policy to amd_pstate_update()
From: Viresh Kumar @ 2026-04-02  6:37 UTC (permalink / raw)
  To: K Prateek Nayak
  Cc: Rafael J. Wysocki, Huang Rui, Gautham R. Shenoy,
	Mario Limonciello, Sebastian Andrzej Siewior, Clark Williams,
	Steven Rostedt, Perry Yuan, linux-pm, linux-kernel,
	rust-for-linux, linux-rt-devel, Mario Limonciello
In-Reply-To: <20260316081849.19368-2-kprateek.nayak@amd.com>

On 16-03-26, 08:18, K Prateek Nayak wrote:
> All callers of amd_pstate_update() already have a reference to the
> cpufreq_policy object.
> 
> Pass the entire policy object and grab the cpudata using
> "policy->driver_data" instead of passing the cpudata and unnecessarily
> grabbing another read-side reference to the cpufreq policy object when
> it is already available in the caller.
> 
> No functional changes intended.
> 
> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> Signed-off-by: K Prateek Nayak <kprateek.nayak@amd.com>
> ---
> changelog v3..v4:
> 
> o No changes.
> ---
>  drivers/cpufreq/amd-pstate.c | 11 ++++-------
>  1 file changed, 4 insertions(+), 7 deletions(-)

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

-- 
viresh

^ permalink raw reply

* Re: [PATCH v20 01/10] power: reset: reboot-mode: Remove devres based allocations
From: Shivendra Pratap @ 2026-04-02  6:15 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Lorenzo Pieralisi, Arnd Bergmann,
	Bjorn Andersson, Sebastian Reichel, Rob Herring,
	Souvik Chakravarty, Krzysztof Kozlowski, Andy Yan,
	Matthias Brugger, Mark Rutland, Conor Dooley, Konrad Dybcio,
	John Stultz, Moritz Fischer, Bartosz Golaszewski, Sudeep Holla
  Cc: Florian Fainelli, Dmitry Baryshkov, Mukesh Ojha, Andre Draszik,
	Kathiravan Thirumoorthy, linux-pm, linux-kernel, linux-arm-kernel,
	linux-arm-msm, devicetree, Srinivas Kandagatla
In-Reply-To: <be9db30a-ee64-4457-8722-b9f456911ad3@kernel.org>



On 01-04-2026 20:49, Krzysztof Kozlowski wrote:
> On 04/03/2026 19:03, Shivendra Pratap wrote:
>> Devres APIs are intended for use in drivers, where the managed lifetime
>> of resources is tied directly to the driver attach/detach cycle. In
>> shared subsystem code, there is no guarantee that the subsystem
>> functions will only be called after a driver has been attached, nor that
>> they will not be referenced after the managed resources have been
>> released during driver detach.
>>
>> To ensure correct lifetime handling, avoid using devres-based
>> allocations in the reboot-mode and explicitly handle allocation and
>> cleanup of resources.
>>
>> Fixes: 4fcd504edbf7 ("power: reset: add reboot mode driver")
> 
> I don't think this is correct tag.
> 
> That commit added code which was a driver, not subsystem level things.
> Using devres, as you pointed out, in platform_driver is correct.

sure. thanks. will remove the Fixes tag.

thanks,
Shivendra

^ permalink raw reply

* Re: [PATCH v4 0/2] cpufreq/amd-pstate: Prevent scheduling when atomic on PREEMPT_RT
From: K Prateek Nayak @ 2026-04-02  6:00 UTC (permalink / raw)
  To: Rafael J. Wysocki, Viresh Kumar, Huang Rui, Gautham R. Shenoy,
	Mario Limonciello, Sebastian Andrzej Siewior, Clark Williams,
	Steven Rostedt, Srinivas Pandruvada, Len Brown, Ingo Molnar,
	Peter Zijlstra, Juri Lelli, Vincent Guittot, Miguel Ojeda
  Cc: Perry Yuan, linux-pm, linux-kernel, rust-for-linux,
	linux-rt-devel, Dietmar Eggemann, Ben Segall, Mel Gorman,
	Valentin Schneider, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
In-Reply-To: <20260316081849.19368-1-kprateek.nayak@amd.com>

Hello Rafael, Viresh,

On 3/16/2026 1:48 PM, K Prateek Nayak wrote:
> Patches are based on:
> 
>   git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git bleeding-edge
> 
> at commit 18ca40891b83 ("Merge branch 'pm-cpuidle-fixes' into
> bleeding-edge") (14-03-2026).

Gentle ping!

They still apply cleanly on top of bleeding-edge at commit 8afc50268253
("Merge branch 'experimental/acpi-driver-conversion' into
bleeding-edge")

If you are looking for specific Acks from other maintainers, please let
me know and I'll try to coax them into taking a look at the series :-)

-- 
Thanks and Regards,
Prateek


^ permalink raw reply

* Re: [PATCH v2 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Yaxiong Tian @ 2026-04-02  5:47 UTC (permalink / raw)
  To: Jie Zhan, myungjoo.ham, kyungmin.park, cw00.choi, nm
  Cc: linux-pm, linux-kernel
In-Reply-To: <a9edebc1-6a28-4ab3-8016-793c585da9c4@hisilicon.com>


在 2026/4/2 11:21, Jie Zhan 写道:
>
> On 4/1/2026 11:31 AM, Yaxiong Tian wrote:
>> Since devfreq_remove_governor() may clear the device's current governor
>> in certain situations, while governors actually exist independently
>> of the device, directly returning EINVAL in this case is inaccurate.
>>
>> To fix this issue, remove this check and add relevant logic for when
>> df->governor is NULL.
>>
>> Fixes: 483d557ee9a3 ("PM / devfreq: Clean up the devfreq instance name in sysfs attr")
>> Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
>> ---
>>   drivers/devfreq/devfreq.c | 17 ++++++++++++++---
>>   1 file changed, 14 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>> index 2977b07be939..975f82d7a9d1 100644
>> --- a/drivers/devfreq/devfreq.c
>> +++ b/drivers/devfreq/devfreq.c
>> @@ -1390,9 +1390,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>   	char str_governor[DEVFREQ_NAME_LEN + 1];
>>   	const struct devfreq_governor *governor, *prev_governor;
>>   
>> -	if (!df->governor)
>> -		return -EINVAL;
>> -
>>   	ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>>   	if (ret != 1)
>>   		return -EINVAL;
>> @@ -1403,6 +1400,20 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>   		ret = PTR_ERR(governor);
>>   		goto out;
>>   	}
>> +
>> +	if (!df->governor) {
>> +		df->governor = governor;
>> +		ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>> +		if (ret) {
>> +			dev_warn(dev, "%s: Governor %s not started(%d)\n",
>> +				__func__, df->governor->name, ret);
>> +			df->governor = NULL;
>> +		} else {
>> +			ret = sysfs_update_group(&df->dev.kobj, &gov_attr_group);
>> +		}
>> +		goto out;
>> +	}
>> +
>>   	if (df->governor == governor) {
>>   		ret = 0;
>>   		goto out;
> Hi Yaxiong,
>
> I'd suggest something like this, such that the main body of the function is
> not changed.
>
> Note that this is just an example. Not tested or carefully checked.
"I still prefer my modification. It's clearer and more straightforward, 
and the increase in code size is very small compared to the 
alternatives. Moreover, if we later want to implement 'cannot unload the 
last governor' (which might be the module reference approach you 
mentioned), we can simply remove this code."


>
> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
> index 2977b07be939..aa0f1db3225c 100644
> --- a/drivers/devfreq/devfreq.c
> +++ b/drivers/devfreq/devfreq.c
> @@ -1390,9 +1390,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>          char str_governor[DEVFREQ_NAME_LEN + 1];
>          const struct devfreq_governor *governor, *prev_governor;
>
> -       if (!df->governor)
> -               return -EINVAL;
> -
>          ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>          if (ret != 1)
>                  return -EINVAL;
> @@ -1403,6 +1400,10 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>                  ret = PTR_ERR(governor);
>                  goto out;
>          }
> +
> +       if (!df->governor)
> +               goto skip_stop;
> +
>          if (df->governor == governor) {
>                  ret = 0;
>                  goto out;
> @@ -1423,6 +1424,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>                  goto out;
>          }
>
> +skip_stop:
>          /*
>           * Start the new governor and create the specific sysfs files
>           * which depend on the new governor.
> @@ -1435,6 +1437,8 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>                           __func__, df->governor->name, ret);
>
>                  /* Restore previous governor */
> +               if (!prev_governor)
> +                       goto out;
>                  df->governor = prev_governor;
>                  ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>                  if (ret) {

^ permalink raw reply

* Re: [PATCH RESEND 0/5] bitmap: cleanup bitmaps printing
From: Madhavan Srinivasan @ 2026-04-02  5:41 UTC (permalink / raw)
  To: Yury Norov, linux-kernel, Christophe Leroy (CS GROUP),
	Peter Zijlstra (Intel), Rafael J. Wysocki, Alexander Shishkin,
	Daniel Lezcano, Ingo Molnar, James Clark, Kees Cook, Lukasz Luba,
	Michael Ellerman, Mike Leach, Moritz Fischer, Nicholas Piggin,
	Russ Weight, Shrikanth Hegde, Suki K Poulose, Tom Rix,
	Thomas Weißschuh, Xu Yilun, Yury Norov, Zhang Rui, coresight,
	linux-arm-kernel, linux-fpga, linux-pm, linuxppc-dev
  Cc: Jakub Kicinski
In-Reply-To: <ac2_EzO-uCaLqTlg@yury>


On 4/2/26 6:27 AM, Yury Norov wrote:
> On Thu, Mar 19, 2026 at 04:18:40PM -0400, Yury Norov wrote:
>> Ping?
> OK, taking 1-4 in bitmap-for-next.

Acked-by: Madhavan Srinivasan <maddy@linux.ibm.com> for powerpc patch


>
> Thanks,
> Yury
>   
>> On Tue, Mar 03, 2026 at 03:08:36PM -0500, Yury Norov wrote:
>>> Bitmap API has a bitmap_print_to_pagebuf() function that is intended to
>>> print bitmap into a human readable format, making sure that the output
>>> string will not get big enough to cross the current page limit.
>>>
>>> Some drivers use this function immediately before passing the result to
>>> scnprintf() with no modification. This is useless because scnprintf(),
>>> and helpers based on it like seq_pritf() and sysfs_emit(), take care of
>>> not overflowing the buffer by itself, and perfectly print bitmaps with
>>> "%*pb[l]".
>>>
>>> This is a resend of non-networking part of [1]. Patches #3,5 switch from
>>> plain scnprintf() to sysfs_emit(), as pointed out by Thomas Weißschuh.
>>>
>>> [1] https://lore.kernel.org/all/20260219181407.290201-1-ynorov@nvidia.com/
>>>
>>> The networking part, for reference:
>>>
>>> https://lore.kernel.org/all/20260303185507.111841-1-ynorov@nvidia.com/
>>>
>>> Each patch can be applied individually per corresponding subsystem.
>>>
>>> Yury Norov (5):
>>>    powerpc/xive: simplify xive_spapr_debug_show()
>>>    thermal: intel: switch cpumask_get() to using
>>>      cpumask_print_to_pagebuf()
>>>    coresight: don't use bitmap_print_to_pagebuf()
>>>    lib/prime_numbers: drop temporary buffer in dump_primes()
>>>    fpga: m10bmc-sec: switch show_canceled_csk() to using sysfs_emit()
>>>
>>>   arch/powerpc/sysdev/xive/spapr.c              | 12 ++-----
>>>   drivers/fpga/intel-m10-bmc-sec-update.c       |  3 +-
>>>   .../hwtracing/coresight/coresight-cti-sysfs.c | 32 ++++++++-----------
>>>   drivers/thermal/intel/intel_powerclamp.c      |  3 +-
>>>   lib/math/tests/prime_numbers_kunit.c          |  6 ++--
>>>   5 files changed, 21 insertions(+), 35 deletions(-)
>>>
>>> -- 
>>> 2.43.0

^ permalink raw reply

* [PATCH v8 5/5] cpufreq/amd-pstate-ut: Add a unit test for raw EPP
From: Mario Limonciello (AMD) @ 2026-04-02  5:02 UTC (permalink / raw)
  To: Gautham R . Shenoy
  Cc: Perry Yuan, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	open list:CPU FREQUENCY SCALING FRAMEWORK,
	Mario Limonciello (AMD)
In-Reply-To: <20260402050214.1238624-1-superm1@kernel.org>

Ensure that all supported raw EPP values work properly.

Export the driver helpers used by the test module so the test can drive
raw EPP writes and temporarily disable dynamic EPP while it runs.

Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
---
 drivers/cpufreq/amd-pstate-ut.c | 109 ++++++++++++++++++++++++++++++++
 drivers/cpufreq/amd-pstate.c    |  11 ++--
 drivers/cpufreq/amd-pstate.h    |   4 ++
 3 files changed, 120 insertions(+), 4 deletions(-)

diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c
index 1f62ab6438b4e..aa8a464fab47a 100644
--- a/drivers/cpufreq/amd-pstate-ut.c
+++ b/drivers/cpufreq/amd-pstate-ut.c
@@ -28,6 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/cleanup.h>
 
@@ -41,6 +42,7 @@ static char *test_list;
 module_param(test_list, charp, 0444);
 MODULE_PARM_DESC(test_list,
 	"Comma-delimited list of tests to run (empty means run all tests)");
+DEFINE_FREE(cleanup_page, void *, if (_T) free_page((unsigned long)_T))
 
 struct amd_pstate_ut_struct {
 	const char *name;
@@ -54,6 +56,7 @@ static int amd_pstate_ut_acpi_cpc_valid(u32 index);
 static int amd_pstate_ut_check_enabled(u32 index);
 static int amd_pstate_ut_check_perf(u32 index);
 static int amd_pstate_ut_check_freq(u32 index);
+static int amd_pstate_ut_epp(u32 index);
 static int amd_pstate_ut_check_driver(u32 index);
 static int amd_pstate_ut_check_freq_attrs(u32 index);
 
@@ -62,6 +65,7 @@ static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = {
 	{"amd_pstate_ut_check_enabled",     amd_pstate_ut_check_enabled    },
 	{"amd_pstate_ut_check_perf",        amd_pstate_ut_check_perf       },
 	{"amd_pstate_ut_check_freq",        amd_pstate_ut_check_freq       },
+	{"amd_pstate_ut_epp",               amd_pstate_ut_epp              },
 	{"amd_pstate_ut_check_driver",      amd_pstate_ut_check_driver     },
 	{"amd_pstate_ut_check_freq_attrs",  amd_pstate_ut_check_freq_attrs },
 };
@@ -268,6 +272,111 @@ static int amd_pstate_set_mode(enum amd_pstate_mode mode)
 	return amd_pstate_update_status(mode_str, strlen(mode_str));
 }
 
+static int amd_pstate_ut_epp(u32 index)
+{
+	struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL;
+	char *buf __free(cleanup_page) = NULL;
+	static const char * const epp_strings[] = {
+		"performance",
+		"balance_performance",
+		"balance_power",
+		"power",
+	};
+	struct amd_cpudata *cpudata;
+	enum amd_pstate_mode orig_mode;
+	bool orig_dynamic_epp;
+	int ret, cpu = 0;
+	int i;
+	u16 epp;
+
+	policy = cpufreq_cpu_get(cpu);
+	if (!policy)
+		return -ENODEV;
+
+	cpudata = policy->driver_data;
+	orig_mode = amd_pstate_get_status();
+	orig_dynamic_epp = cpudata->dynamic_epp;
+
+	/* disable dynamic EPP before running test */
+	if (cpudata->dynamic_epp) {
+		pr_debug("Dynamic EPP is enabled, disabling it\n");
+		amd_pstate_clear_dynamic_epp(policy);
+	}
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = amd_pstate_set_mode(AMD_PSTATE_ACTIVE);
+	if (ret)
+		goto out;
+
+	for (epp = 0; epp <= U8_MAX; epp++) {
+		u8 val;
+
+		/* write all EPP values */
+		memset(buf, 0, PAGE_SIZE);
+		snprintf(buf, PAGE_SIZE, "%d", epp);
+		ret = store_energy_performance_preference(policy, buf, strlen(buf));
+		if (ret < 0)
+			goto out;
+
+		/* check if the EPP value reads back correctly for raw numbers */
+		memset(buf, 0, PAGE_SIZE);
+		ret = show_energy_performance_preference(policy, buf);
+		if (ret < 0)
+			goto out;
+		strreplace(buf, '\n', '\0');
+		ret = kstrtou8(buf, 0, &val);
+		if (!ret && epp != val) {
+			pr_err("Raw EPP value mismatch: %d != %d\n", epp, val);
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(epp_strings); i++) {
+		memset(buf, 0, PAGE_SIZE);
+		snprintf(buf, PAGE_SIZE, "%s", epp_strings[i]);
+		ret = store_energy_performance_preference(policy, buf, strlen(buf));
+		if (ret < 0)
+			goto out;
+
+		memset(buf, 0, PAGE_SIZE);
+		ret = show_energy_performance_preference(policy, buf);
+		if (ret < 0)
+			goto out;
+		strreplace(buf, '\n', '\0');
+
+		if (strcmp(buf, epp_strings[i])) {
+			pr_err("String EPP value mismatch: %s != %s\n", buf, epp_strings[i]);
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	ret = 0;
+
+out:
+	if (orig_dynamic_epp) {
+		int ret2;
+
+		ret2 = amd_pstate_set_mode(AMD_PSTATE_DISABLE);
+		if (!ret && ret2)
+			ret = ret2;
+	}
+
+	if (orig_mode != amd_pstate_get_status()) {
+		int ret2;
+
+		ret2 = amd_pstate_set_mode(orig_mode);
+		if (!ret && ret2)
+			ret = ret2;
+	}
+
+	return ret;
+}
+
 static int amd_pstate_ut_check_driver(u32 index)
 {
 	enum amd_pstate_mode mode1, mode2 = AMD_PSTATE_DISABLE;
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 40340b5d1278b..d0bba84158e6b 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1257,7 +1257,7 @@ static const struct platform_profile_ops amd_pstate_profile_ops = {
 	.profile_get = amd_pstate_profile_get,
 };
 
-static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
+void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
 {
 	struct amd_cpudata *cpudata = policy->driver_data;
 
@@ -1270,6 +1270,7 @@ static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
 	kfree(cpudata->profile_name);
 	cpudata->dynamic_epp = false;
 }
+EXPORT_SYMBOL_GPL(amd_pstate_clear_dynamic_epp);
 
 static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
 {
@@ -1406,8 +1407,8 @@ static ssize_t show_energy_performance_available_preferences(
 	return offset;
 }
 
-static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
-					   const char *buf, size_t count)
+ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
+				    const char *buf, size_t count)
 {
 	struct amd_cpudata *cpudata = policy->driver_data;
 	ssize_t ret;
@@ -1448,8 +1449,9 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
 
 	return count;
 }
+EXPORT_SYMBOL_GPL(store_energy_performance_preference);
 
-static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
+ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
 {
 	struct amd_cpudata *cpudata = policy->driver_data;
 	u8 preference, epp;
@@ -1478,6 +1480,7 @@ static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy,
 
 	return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]);
 }
+EXPORT_SYMBOL_GPL(show_energy_performance_preference);
 
 static ssize_t store_amd_pstate_floor_freq(struct cpufreq_policy *policy,
 					   const char *buf, size_t count)
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
index f7461d1b6bf3c..e4722e54387b0 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -150,6 +150,10 @@ enum amd_pstate_mode {
 const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode);
 int amd_pstate_get_status(void);
 int amd_pstate_update_status(const char *buf, size_t size);
+ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
+				    const char *buf, size_t count);
+ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf);
+void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy);
 
 struct freq_attr;
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 4/5] cpufreq/amd-pstate: Add support for raw EPP writes
From: Mario Limonciello (AMD) @ 2026-04-02  5:02 UTC (permalink / raw)
  To: Gautham R . Shenoy
  Cc: Perry Yuan, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	open list:CPU FREQUENCY SCALING FRAMEWORK,
	Mario Limonciello (AMD)
In-Reply-To: <20260402050214.1238624-1-superm1@kernel.org>

The energy performance preference field of the CPPC request MSR
supports values from 0 to 255, but the strings only offer 4 values.

The other values are useful for tuning the performance of some
workloads.

Add support for writing the raw energy performance preference value
to the sysfs file.  If the last value written was an integer then
an integer will be returned.  If the last value written was a string
then a string will be returned.

Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
---
v6->v7:
 * Correct documentation
---
 Documentation/admin-guide/pm/amd-pstate.rst | 16 ++++++---
 drivers/cpufreq/amd-pstate.c                | 36 +++++++++++++++------
 drivers/cpufreq/amd-pstate.h                |  1 +
 3 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index d68ddfea6a9da..f8e7050fc7623 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -316,16 +316,22 @@ A list of all the supported EPP preferences that could be used for
 These profiles represent different hints that are provided
 to the low-level firmware about the user's desired energy vs efficiency
 tradeoff.  ``default`` represents the epp value is set by platform
-firmware. This attribute is read-only.
+firmware. ``custom`` designates that integer values 0-255 may be written
+as well.  This attribute is read-only.
 
 ``energy_performance_preference``
 
 The current energy performance preference can be read from this attribute.
 and user can change current preference according to energy or performance needs
-Please get all support profiles list from
-``energy_performance_available_preferences`` attribute, all the profiles are
-integer values defined between 0 to 255 when EPP feature is enabled by platform
-firmware, but if the dynamic EPP feature is enabled, driver will block writes.
+Coarse named profiles are available in the attribute
+``energy_performance_available_preferences``.
+Users can also write individual integer values between 0 to 255.
+When dynamic EPP is enabled, writes to energy_performance_preference are blocked
+even when EPP feature is enabled by platform firmware. Lower epp values shift the bias
+towards improved performance while a higher epp value shifts the bias towards
+power-savings. The exact impact can change from one platform to the other.
+If a valid integer was last written, then a number will be returned on future reads.
+If a valid string was last written then a string will be returned on future reads.
 This attribute is read-write.
 
 ``boost``
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 74715f9c7af23..40340b5d1278b 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -109,6 +109,7 @@ static struct quirk_entry *quirks;
  *	2		balance_performance
  *	3		balance_power
  *	4		power
+ *	5		custom (for raw EPP values)
  */
 enum energy_perf_value_index {
 	EPP_INDEX_DEFAULT = 0,
@@ -116,6 +117,7 @@ enum energy_perf_value_index {
 	EPP_INDEX_BALANCE_PERFORMANCE,
 	EPP_INDEX_BALANCE_POWERSAVE,
 	EPP_INDEX_POWERSAVE,
+	EPP_INDEX_CUSTOM,
 	EPP_INDEX_MAX,
 };
 
@@ -125,6 +127,7 @@ static const char * const energy_perf_strings[] = {
 	[EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance",
 	[EPP_INDEX_BALANCE_POWERSAVE] = "balance_power",
 	[EPP_INDEX_POWERSAVE] = "power",
+	[EPP_INDEX_CUSTOM] = "custom",
 };
 static_assert(ARRAY_SIZE(energy_perf_strings) == EPP_INDEX_MAX);
 
@@ -135,7 +138,7 @@ static unsigned int epp_values[] = {
 	[EPP_INDEX_BALANCE_POWERSAVE] = AMD_CPPC_EPP_BALANCE_POWERSAVE,
 	[EPP_INDEX_POWERSAVE] = AMD_CPPC_EPP_POWERSAVE,
 };
-static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX);
+static_assert(ARRAY_SIZE(epp_values) == EPP_INDEX_MAX - 1);
 
 typedef int (*cppc_mode_transition_fn)(int);
 
@@ -1408,6 +1411,7 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
 {
 	struct amd_cpudata *cpudata = policy->driver_data;
 	ssize_t ret;
+	bool raw_epp = false;
 	u8 epp;
 
 	if (cpudata->dynamic_epp) {
@@ -1415,14 +1419,21 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
 		return -EBUSY;
 	}
 
-	ret = sysfs_match_string(energy_perf_strings, buf);
-	if (ret < 0)
-		return -EINVAL;
-
-	if (ret)
-		epp = epp_values[ret];
-	else
-		epp = amd_pstate_get_balanced_epp(policy);
+	/*
+	 * if the value matches a number, use that, otherwise see if
+	 * matches an index in the energy_perf_strings array
+	 */
+	ret = kstrtou8(buf, 0, &epp);
+	raw_epp = !ret;
+	if (ret) {
+		ret = sysfs_match_string(energy_perf_strings, buf);
+		if (ret < 0 || ret == EPP_INDEX_CUSTOM)
+			return -EINVAL;
+		if (ret)
+			epp = epp_values[ret];
+		else
+			epp = amd_pstate_get_balanced_epp(policy);
+	}
 
 	if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
 		pr_debug("EPP cannot be set under performance policy\n");
@@ -1433,7 +1444,9 @@ static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy
 	if (ret)
 		return ret;
 
-	return ret ? ret : count;
+	cpudata->raw_epp = raw_epp;
+
+	return count;
 }
 
 static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
@@ -1443,6 +1456,9 @@ static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy,
 
 	epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached);
 
+	if (cpudata->raw_epp)
+		return sysfs_emit(buf, "%u\n", epp);
+
 	switch (epp) {
 	case AMD_CPPC_EPP_PERFORMANCE:
 		preference = EPP_INDEX_PERFORMANCE;
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
index a7e52f79a8029..f7461d1b6bf3c 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -127,6 +127,7 @@ struct amd_cpudata {
 	u8	epp_default_ac;
 	u8	epp_default_dc;
 	bool	dynamic_epp;
+	bool	raw_epp;
 	struct notifier_block power_nb;
 
 	/* platform profile */
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 3/5] cpufreq/amd-pstate: Add support for platform profile class
From: Mario Limonciello (AMD) @ 2026-04-02  5:02 UTC (permalink / raw)
  To: Gautham R . Shenoy
  Cc: Perry Yuan, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	open list:CPU FREQUENCY SCALING FRAMEWORK,
	Mario Limonciello (AMD)
In-Reply-To: <20260402050214.1238624-1-superm1@kernel.org>

The platform profile core allows multiple drivers and devices to
register platform profile support.

When the legacy platform profile interface is used all drivers will
adjust the platform profile as well.

Add support for registering every CPU with the platform profile handler
when dynamic EPP is enabled.

The end result will be that changing the platform profile will modify
EPP accordingly.

Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
---
v8:
 * Don't try to change cpufreq policy
---
 Documentation/admin-guide/pm/amd-pstate.rst |   4 +-
 drivers/cpufreq/Kconfig.x86                 |   1 +
 drivers/cpufreq/amd-pstate.c                | 106 ++++++++++++++++++--
 drivers/cpufreq/amd-pstate.h                |   6 ++
 4 files changed, 110 insertions(+), 7 deletions(-)

diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index 01e6ab10f996e..d68ddfea6a9da 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -357,7 +357,9 @@ config option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be ove
 at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
 
 When set to enabled, the driver will select a different energy performance
-profile when the machine is running on battery or AC power.
+profile when the machine is running on battery or AC power. The driver will
+also register with the platform profile handler to receive notifications of
+user desired power state and react to those.
 When set to disabled, the driver will not change the energy performance profile
 based on the power source and will not react to user desired power state.
 
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index cdaa8d858045a..a0dbb9808ae99 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -40,6 +40,7 @@ config X86_AMD_PSTATE
 	select ACPI_PROCESSOR
 	select ACPI_CPPC_LIB if X86_64
 	select CPU_FREQ_GOV_SCHEDUTIL if SMP
+	select ACPI_PLATFORM_PROFILE
 	help
 	  This driver adds a CPUFreq driver which utilizes a fine grain
 	  processor performance frequency control range instead of legacy
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 301e603e49660..74715f9c7af23 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1182,6 +1182,10 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
 	if (event != PSY_EVENT_PROP_CHANGED)
 		return NOTIFY_OK;
 
+	/* dynamic actions are only applied while platform profile is in balanced */
+	if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED)
+		return 0;
+
 	epp = amd_pstate_get_balanced_epp(policy);
 
 	ret = amd_pstate_set_epp(policy, epp);
@@ -1190,12 +1194,77 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
 
 	return NOTIFY_OK;
 }
+
+static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices)
+{
+	set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+	set_bit(PLATFORM_PROFILE_BALANCED, choices);
+	set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+	return 0;
+}
+
+static int amd_pstate_profile_get(struct device *dev,
+				  enum platform_profile_option *profile)
+{
+	struct amd_cpudata *cpudata = dev_get_drvdata(dev);
+
+	*profile = cpudata->current_profile;
+
+	return 0;
+}
+
+static int amd_pstate_profile_set(struct device *dev,
+				  enum platform_profile_option profile)
+{
+	struct amd_cpudata *cpudata = dev_get_drvdata(dev);
+	struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
+	int ret;
+
+	switch (profile) {
+	case PLATFORM_PROFILE_LOW_POWER:
+		ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE);
+		if (ret)
+			return ret;
+		break;
+	case PLATFORM_PROFILE_BALANCED:
+		ret = amd_pstate_set_epp(policy,
+					 amd_pstate_get_balanced_epp(policy));
+		if (ret)
+			return ret;
+		break;
+	case PLATFORM_PROFILE_PERFORMANCE:
+		ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_PERFORMANCE);
+		if (ret)
+			return ret;
+		break;
+	default:
+		pr_err("Unknown Platform Profile %d\n", profile);
+		return -EOPNOTSUPP;
+	}
+
+	cpudata->current_profile = profile;
+
+	return 0;
+}
+
+static const struct platform_profile_ops amd_pstate_profile_ops = {
+	.probe = amd_pstate_profile_probe,
+	.profile_set = amd_pstate_profile_set,
+	.profile_get = amd_pstate_profile_get,
+};
+
 static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
 {
 	struct amd_cpudata *cpudata = policy->driver_data;
 
 	if (cpudata->power_nb.notifier_call)
 		power_supply_unreg_notifier(&cpudata->power_nb);
+	if (cpudata->ppdev) {
+		platform_profile_remove(cpudata->ppdev);
+		cpudata->ppdev = NULL;
+	}
+	kfree(cpudata->profile_name);
 	cpudata->dynamic_epp = false;
 }
 
@@ -1205,11 +1274,35 @@ static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
 	int ret;
 	u8 epp;
 
-	epp = amd_pstate_get_balanced_epp(policy);
+	switch (cpudata->current_profile) {
+	case PLATFORM_PROFILE_PERFORMANCE:
+		epp = AMD_CPPC_EPP_PERFORMANCE;
+		break;
+	case PLATFORM_PROFILE_LOW_POWER:
+		epp = AMD_CPPC_EPP_POWERSAVE;
+		break;
+	case PLATFORM_PROFILE_BALANCED:
+		epp = amd_pstate_get_balanced_epp(policy);
+		break;
+	default:
+		pr_err("Unknown Platform Profile %d\n", cpudata->current_profile);
+		return -EOPNOTSUPP;
+	}
 	ret = amd_pstate_set_epp(policy, epp);
 	if (ret)
 		return ret;
 
+	cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu);
+
+	cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu),
+						   cpudata->profile_name,
+						   policy->driver_data,
+						   &amd_pstate_profile_ops);
+	if (IS_ERR(cpudata->ppdev)) {
+		ret = PTR_ERR(cpudata->ppdev);
+		goto cleanup;
+	}
+
 	/* only enable notifier if things will actually change */
 	if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
 		cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier;
@@ -1310,8 +1403,8 @@ static ssize_t show_energy_performance_available_preferences(
 	return offset;
 }
 
-static ssize_t store_energy_performance_preference(
-		struct cpufreq_policy *policy, const char *buf, size_t count)
+static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
+					   const char *buf, size_t count)
 {
 	struct amd_cpudata *cpudata = policy->driver_data;
 	ssize_t ret;
@@ -1331,7 +1424,7 @@ static ssize_t store_energy_performance_preference(
 	else
 		epp = amd_pstate_get_balanced_epp(policy);
 
-	if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
+	if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
 		pr_debug("EPP cannot be set under performance policy\n");
 		return -EBUSY;
 	}
@@ -1343,8 +1436,7 @@ static ssize_t store_energy_performance_preference(
 	return ret ? ret : count;
 }
 
-static ssize_t show_energy_performance_preference(
-				struct cpufreq_policy *policy, char *buf)
+static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
 {
 	struct amd_cpudata *cpudata = policy->driver_data;
 	u8 preference, epp;
@@ -1826,10 +1918,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
 	    amd_pstate_acpi_pm_profile_undefined()) {
 		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
 		cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
+		cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE;
 	} else {
 		policy->policy = CPUFREQ_POLICY_POWERSAVE;
 		cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE;
 		cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
+		cpudata->current_profile = PLATFORM_PROFILE_BALANCED;
 	}
 
 	if (dynamic_epp)
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
index d929ae3163b3d..a7e52f79a8029 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -9,6 +9,7 @@
 #define _LINUX_AMD_PSTATE_H
 
 #include <linux/pm_qos.h>
+#include <linux/platform_profile.h>
 
 /*********************************************************************
  *                        AMD P-state INTERFACE                       *
@@ -127,6 +128,11 @@ struct amd_cpudata {
 	u8	epp_default_dc;
 	bool	dynamic_epp;
 	struct notifier_block power_nb;
+
+	/* platform profile */
+	enum platform_profile_option current_profile;
+	struct device *ppdev;
+	char *profile_name;
 };
 
 /*
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp
From: Mario Limonciello (AMD) @ 2026-04-02  5:02 UTC (permalink / raw)
  To: Gautham R . Shenoy
  Cc: Perry Yuan, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	open list:CPU FREQUENCY SCALING FRAMEWORK,
	Mario Limonciello (AMD)
In-Reply-To: <20260402050214.1238624-1-superm1@kernel.org>

Add `amd_dynamic_epp=enable` and `amd_dynamic_epp=disable` to override
the kernel configuration option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`
locally.

Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
---
 Documentation/admin-guide/kernel-parameters.txt |  7 +++++++
 Documentation/admin-guide/pm/amd-pstate.rst     |  7 +++++++
 drivers/cpufreq/amd-pstate.c                    | 11 +++++++++++
 3 files changed, 25 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 03a550630644f..9552819051cd8 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -493,6 +493,13 @@ Kernel parameters
 			disable
 			  Disable amd-pstate preferred core.
 
+	amd_dynamic_epp=
+			[X86]
+			disable
+			  Disable amd-pstate dynamic EPP.
+			enable
+			  Enable amd-pstate dynamic EPP.
+
 	amijoy.map=	[HW,JOY] Amiga joystick support
 			Map of devices attached to JOY0DAT and JOY1DAT
 			Format: <a>,<b>
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index bb1341763882b..01e6ab10f996e 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -474,6 +474,13 @@ For systems that support ``amd-pstate`` preferred core, the core rankings will
 always be advertised by the platform. But OS can choose to ignore that via the
 kernel parameter ``amd_prefcore=disable``.
 
+``amd_dynamic_epp``
+
+When AMD pstate is in auto mode, dynamic EPP will control whether the kernel
+autonomously changes the EPP mode. The default is configured by
+``CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`` but can be explicitly enabled with
+``amd_dynamic_epp=enable`` or disabled with ``amd_dynamic_epp=disable``.
+
 User Space Interface in ``sysfs`` - General
 ===========================================
 
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 379e7dd442522..301e603e49660 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -2227,8 +2227,19 @@ static int __init amd_prefcore_param(char *str)
 	return 0;
 }
 
+static int __init amd_dynamic_epp_param(char *str)
+{
+	if (!strcmp(str, "disable"))
+		dynamic_epp = false;
+	if (!strcmp(str, "enable"))
+		dynamic_epp = true;
+
+	return 0;
+}
+
 early_param("amd_pstate", amd_pstate_param);
 early_param("amd_prefcore", amd_prefcore_param);
+early_param("amd_dynamic_epp", amd_dynamic_epp_param);
 
 MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>");
 MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver");
-- 
2.43.0


^ permalink raw reply related

* [PATCH v8 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
From: Mario Limonciello (AMD) @ 2026-04-02  5:02 UTC (permalink / raw)
  To: Gautham R . Shenoy
  Cc: Perry Yuan, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	open list:CPU FREQUENCY SCALING FRAMEWORK,
	Mario Limonciello (AMD)
In-Reply-To: <20260402050214.1238624-1-superm1@kernel.org>

Dynamic energy performance preference changes the EPP profile based on
whether the machine is running on AC or DC power.

A notification chain from the power supply core is used to adjust EPP
values on plug in or plug out events.

When enabled, the driver exposes a sysfs toggle for dynamic EPP, blocks
manual writes to energy_performance_preference, and keeps the policy in
performance mode while it "owns" the EPP updates.

For non-server systems:
    * the default EPP for AC mode is `performance`.
    * the default EPP for DC mode is `balance_performance`.

For server systems dynamic EPP is mostly a no-op.

Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
v7->v8:
 * Handle failures to enable dynamic epp
 * Don't set policy to CPUFREQ_POLICY_PERFORMANCE in dymamic epp
 * Allow policy governor changes
v6->v7:
 * Fix accidental casualty of floor perf from rebase (Gautham)
 * Adjust documentation (Gautham)
---
 Documentation/admin-guide/pm/amd-pstate.rst |  18 ++-
 drivers/cpufreq/Kconfig.x86                 |  12 ++
 drivers/cpufreq/amd-pstate.c                | 128 +++++++++++++++++++-
 drivers/cpufreq/amd-pstate.h                |  10 +-
 4 files changed, 160 insertions(+), 8 deletions(-)

diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index b43675b7f739b..bb1341763882b 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -325,7 +325,7 @@ and user can change current preference according to energy or performance needs
 Please get all support profiles list from
 ``energy_performance_available_preferences`` attribute, all the profiles are
 integer values defined between 0 to 255 when EPP feature is enabled by platform
-firmware, if EPP feature is disabled, driver will ignore the written value
+firmware, but if the dynamic EPP feature is enabled, driver will block writes.
 This attribute is read-write.
 
 ``boost``
@@ -347,6 +347,22 @@ boost or `1` to enable it, for the respective CPU using the sysfs path
 Other performance and frequency values can be read back from
 ``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`.
 
+Dynamic energy performance profile
+==================================
+The amd-pstate driver supports dynamically selecting the energy performance
+profile based on whether the machine is running on AC or DC power.
+
+Whether this behavior is enabled by default depends on the kernel
+config option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be overridden
+at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
+
+When set to enabled, the driver will select a different energy performance
+profile when the machine is running on battery or AC power.
+When set to disabled, the driver will not change the energy performance profile
+based on the power source and will not react to user desired power state.
+
+Attempting to manually write to the ``energy_performance_preference`` sysfs
+file will fail when ``dynamic_epp`` is enabled.
 
 ``amd-pstate`` vs ``acpi-cpufreq``
 ======================================
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index 2c5c228408bf2..cdaa8d858045a 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -68,6 +68,18 @@ config X86_AMD_PSTATE_DEFAULT_MODE
 	  For details, take a look at:
 	  <file:Documentation/admin-guide/pm/amd-pstate.rst>.
 
+config X86_AMD_PSTATE_DYNAMIC_EPP
+	bool "AMD Processor P-State dynamic EPP support"
+	depends on X86_AMD_PSTATE
+	default n
+	help
+	  Allow the kernel to dynamically change the energy performance
+	  value from events like ACPI platform profile and AC adapter plug
+	  events.
+
+	  This feature can also be changed at runtime, this configuration
+	  option only sets the kernel default value behavior.
+
 config X86_AMD_PSTATE_UT
 	tristate "selftest for AMD Processor P-State driver"
 	depends on X86 && ACPI_PROCESSOR
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index f207252eb5f5f..379e7dd442522 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
+#include <linux/power_supply.h>
 #include <linux/static_call.h>
 #include <linux/topology.h>
 
@@ -86,6 +87,11 @@ static struct cpufreq_driver amd_pstate_driver;
 static struct cpufreq_driver amd_pstate_epp_driver;
 static int cppc_state = AMD_PSTATE_UNDEFINED;
 static bool amd_pstate_prefcore = true;
+#ifdef CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP
+static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP;
+#else
+static bool dynamic_epp;
+#endif
 static struct quirk_entry *quirks;
 
 /*
@@ -1155,6 +1161,73 @@ static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
 	kfree(cpudata);
 }
 
+static int amd_pstate_get_balanced_epp(struct cpufreq_policy *policy)
+{
+	struct amd_cpudata *cpudata = policy->driver_data;
+
+	if (power_supply_is_system_supplied())
+		return cpudata->epp_default_ac;
+	else
+		return cpudata->epp_default_dc;
+}
+
+static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
+					    unsigned long event, void *data)
+{
+	struct amd_cpudata *cpudata = container_of(nb, struct amd_cpudata, power_nb);
+	struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
+	u8 epp;
+	int ret;
+
+	if (event != PSY_EVENT_PROP_CHANGED)
+		return NOTIFY_OK;
+
+	epp = amd_pstate_get_balanced_epp(policy);
+
+	ret = amd_pstate_set_epp(policy, epp);
+	if (ret)
+		pr_warn("Failed to set CPU %d EPP %u: %d\n", cpudata->cpu, epp, ret);
+
+	return NOTIFY_OK;
+}
+static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
+{
+	struct amd_cpudata *cpudata = policy->driver_data;
+
+	if (cpudata->power_nb.notifier_call)
+		power_supply_unreg_notifier(&cpudata->power_nb);
+	cpudata->dynamic_epp = false;
+}
+
+static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
+{
+	struct amd_cpudata *cpudata = policy->driver_data;
+	int ret;
+	u8 epp;
+
+	epp = amd_pstate_get_balanced_epp(policy);
+	ret = amd_pstate_set_epp(policy, epp);
+	if (ret)
+		return ret;
+
+	/* only enable notifier if things will actually change */
+	if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
+		cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier;
+		ret = power_supply_reg_notifier(&cpudata->power_nb);
+		if (ret)
+			goto cleanup;
+	}
+
+	cpudata->dynamic_epp = true;
+
+	return 0;
+
+cleanup:
+	amd_pstate_clear_dynamic_epp(policy);
+
+	return ret;
+}
+
 /* Sysfs attributes */
 
 /*
@@ -1244,14 +1317,19 @@ static ssize_t store_energy_performance_preference(
 	ssize_t ret;
 	u8 epp;
 
+	if (cpudata->dynamic_epp) {
+		pr_debug("EPP cannot be set when dynamic EPP is enabled\n");
+		return -EBUSY;
+	}
+
 	ret = sysfs_match_string(energy_perf_strings, buf);
 	if (ret < 0)
 		return -EINVAL;
 
-	if (!ret)
-		epp = cpudata->epp_default;
-	else
+	if (ret)
 		epp = epp_values[ret];
+	else
+		epp = amd_pstate_get_balanced_epp(policy);
 
 	if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
 		pr_debug("EPP cannot be set under performance policy\n");
@@ -1259,6 +1337,8 @@ static ssize_t store_energy_performance_preference(
 	}
 
 	ret = amd_pstate_set_epp(policy, epp);
+	if (ret)
+		return ret;
 
 	return ret ? ret : count;
 }
@@ -1620,12 +1700,42 @@ static ssize_t prefcore_show(struct device *dev,
 	return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore));
 }
 
+static ssize_t dynamic_epp_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "%s\n", str_enabled_disabled(dynamic_epp));
+}
+
+static ssize_t dynamic_epp_store(struct device *a, struct device_attribute *b,
+				 const char *buf, size_t count)
+{
+	bool enabled;
+	int ret;
+
+	ret = kstrtobool(buf, &enabled);
+	if (ret)
+		return ret;
+
+	if (dynamic_epp == enabled)
+		return -EINVAL;
+
+	/* reinitialize with desired dynamic EPP value */
+	dynamic_epp = enabled;
+	ret = amd_pstate_change_driver_mode(cppc_state);
+	if (ret)
+		dynamic_epp = false;
+
+	return ret ? ret : count;
+}
+
 static DEVICE_ATTR_RW(status);
 static DEVICE_ATTR_RO(prefcore);
+static DEVICE_ATTR_RW(dynamic_epp);
 
 static struct attribute *pstate_global_attributes[] = {
 	&dev_attr_status.attr,
 	&dev_attr_prefcore.attr,
+	&dev_attr_dynamic_epp.attr,
 	NULL
 };
 
@@ -1715,13 +1825,17 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
 	if (amd_pstate_acpi_pm_profile_server() ||
 	    amd_pstate_acpi_pm_profile_undefined()) {
 		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
-		cpudata->epp_default = amd_pstate_get_epp(cpudata);
+		cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
 	} else {
 		policy->policy = CPUFREQ_POLICY_POWERSAVE;
-		cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
+		cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE;
+		cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
 	}
 
-	ret = amd_pstate_set_epp(policy, cpudata->epp_default);
+	if (dynamic_epp)
+		ret = amd_pstate_set_dynamic_epp(policy);
+	else
+		ret = amd_pstate_set_epp(policy, amd_pstate_get_balanced_epp(policy));
 	if (ret)
 		goto free_cpudata1;
 
@@ -1753,6 +1867,8 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
 		amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
 		amd_pstate_set_floor_perf(policy, cpudata->bios_floor_perf);
 
+		if (cpudata->dynamic_epp)
+			amd_pstate_clear_dynamic_epp(policy);
 		kfree(cpudata);
 		policy->driver_data = NULL;
 	}
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
index 32b8b26ce388f..d929ae3163b3d 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -85,6 +85,11 @@ struct amd_aperf_mperf {
  * 		  AMD P-State driver supports preferred core featue.
  * @epp_cached: Cached CPPC energy-performance preference value
  * @policy: Cpufreq policy value
+ * @suspended: If CPU core if offlined
+ * @epp_default_ac: Default EPP value for AC power source
+ * @epp_default_dc: Default EPP value for DC power source
+ * @dynamic_epp: Whether dynamic EPP is enabled
+ * @power_nb: Notifier block for power events
  *
  * The amd_cpudata is key private data for each CPU thread in AMD P-State, and
  * represents all the attributes and goals that AMD P-State requests at runtime.
@@ -118,7 +123,10 @@ struct amd_cpudata {
 	/* EPP feature related attributes*/
 	u32	policy;
 	bool	suspended;
-	u8	epp_default;
+	u8	epp_default_ac;
+	u8	epp_default_dc;
+	bool	dynamic_epp;
+	struct notifier_block power_nb;
 };
 
 /*
-- 
2.43.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox