* Re: [PATCH v8 05/10] pmdomain: samsung: convert to using regmap
From: André Draszik @ 2026-03-19 11:58 UTC (permalink / raw)
To: Marek Szyprowski, Ulf Hansson
Cc: Krzysztof Kozlowski, Alim Akhtar, Rob Herring, Conor Dooley,
Krzysztof Kozlowski, Liam Girdwood, Mark Brown, Peter Griffin,
Tudor Ambarus, Juan Yescas, Will McVicker, kernel-team,
linux-arm-kernel, linux-samsung-soc, devicetree, linux-kernel,
linux-pm
In-Reply-To: <c5ba58fb-50f1-4067-a099-97169ea81f68@samsung.com>
Hi Marek,
On Thu, 2026-03-19 at 11:29 +0100, Marek Szyprowski wrote:
> On 19.03.2026 11:13, Ulf Hansson wrote:
> > As a follow-up patch on top, please consider converting the open-coded
> > polling loop above into a readx_poll_timeout_atomic().
>
> This has been tried and it doesn't work in all cases required for power
> domain driver:
>
> https://lore.kernel.org/all/5c19e4ef-c4fd-4bf5-88b3-46c86751b14e@samsung.com/
>
> Probably a comment about that could be added directly to this code to
> avoid such conversion and breakage in the future.
I am planning to revisit this in the future and am hoping that we can
figure out what goes wrong when using regmap_read_poll_timeout().
Hopefully such a comment would only be short-lived, so maybe not really
worth it? I can add it, though, if you prefer.
Cheers,
Andre'
^ permalink raw reply
* Re: [PATCH/RFC] PM: domains: Call pm_runtime_barrier() before dev_pm_domain_{attach*,detach}()
From: Ulf Hansson @ 2026-03-19 10:59 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Rafael J . Wysocki, Pavel Machek, Len Brown, Greg Kroah-Hartman,
Danilo Krummrich, Frank Binns, Matt Coster, Marek Vasut, linux-pm,
driver-core, linux-renesas-soc, linux-kernel
In-Reply-To: <15510cee649959281d9554965cacd0c06531c1f3.1773308898.git.geert+renesas@glider.be>
On Thu, 12 Mar 2026 at 10:54, Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
>
> If a device has multiple PM Domains, dev_pm_domain_detach() is called
> multiple times on unbind or probe failure. If the PM Domain is also a
> Clock Domain, and thus calls pm_clk_destroy() from its .detach()
> callback, dev_pm_put_subsys_data() will set dev->power.subsys_data to
> NULL when psd->refcount reaches zero.
>
> Later/in parallel, default_suspend_ok() calls dev_gpd_data():
>
> static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
> {
> return to_gpd_data(dev->power.subsys_data->domain_data);
> }
>
> which may trigger a NULL pointer dereference.
>
> All dev_pm_domain_{at,de}tach*() functions document that callers must
> ensure proper synchronization of these functions with power management
> callbacks. Unfortunately no callers seem to actually do so. This
> includes dev_pm_domain_attach_list() and dev_pm_domain_detach_list():
> they call dev_pm_domain_{attach*,detach}() internally, which means they
> should take care of this synchronization themselves.
>
> Add synchronization to dev_pm_domain_{at,de}tach_list() by calling
> pm_runtime_barrier() before dev_pm_domain_{attach*,detach}(), and drop
> the now obsolete comments.
My apologies for not being able to respond earlier to your
suggestions/questions. I have started looking into this now, and I
will follow up with more replies and perhaps a patch shortly.
Anyway, the principle is that callers of dev_pm_domain_detach() must
manage the runtime PM enabling/disabling for its device. If runtime PM
was enabled, it must typically be disabled before calling
dev_pm_domain_detach().
What makes this a bit more complicated is that we have two different
scenarious to consider.
1) The legacy case, attachment via dev_pm_domain_attach() for the
single PM domain case. Runtime PM should be enabled/disabled for the
device, from its corresponding driver/bus. I assume this isn't the
problem you are facing, right?
2) Attachment via dev_pm_domain_attach_by_id|name() (which is called
for the *attach_list() case too), for the single/multi PM domain
cases. In these cases, runtime PM is enabled in
genpd_dev_pm_attach_by_id().
For 2), I am inclined to think that the proper action is to call
pm_runtime_disable() in genpd_dev_pm_detach() before it calls
genpd_remove_device(). Although, I need to check more closely how
suitable that would be.
Kind regards
Uffe
>
> Suggested-by: Marek Vasut <marek.vasut@mailbox.org>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> This issue was reported first in "drm/imagination:
> genpd_runtime_suspend() crash"[1] and "Re: [PATCH 2/5] arm64: dts:
> renesas: r8a77960-salvator-x: Enable GPU support"[2].
> Unfortunately this patch does not fix the issue for good, it just
> becomes much harder to trigger (like needing tens of thousands of
> tries).
>
> How to trigger:
>
> 1. Check out drm-next[3]
>
> 2. Enable the gpu node in one of the following DTS files, depending on
> your board (Salvator-X(S), ULCB, or Falcon):
>
> arch/arm64/boot/dts/renesas/r8a77960.dtsi
> arch/arm64/boot/dts/renesas/r8a77961.dtsi
> arch/arm64/boot/dts/renesas/r8a77965.dtsi
> arch/arm64/boot/dts/renesas/r8a779a0.dtsi
>
> These nodes are not yet enabled in any board DTS because of this
> crash.
>
> 3. Build and boot a kernel using renesas_defconfig[4]
>
> 4. The PowerVR driver will fail to probe (since [5], which is IMHO a
> regression):
>
> powervr fd000000.gpu: [drm] *ERROR* Unknown GPU! Set 'exp_hw_support' to bypass this check.
>
> 5. Try to bind the driver again:
>
> $ for i in $(seq 1000000); do echo $i; echo fd000000.gpu > /sys/bus/platform/drivers/powervr/bind; done
>
> Eventually, the kernel will crash:
>
> [...]
> powervr fd000000.gpu: [drm] *ERROR* Unknown GPU! Set 'exp_hw_support' to bypass this check.
> Unable to handle kernel NULL pointer dereference at virtual address 0000000000000040
> Mem abort info:
> ESR = 0x0000000096000004
> EC = 0x25: DABT (current EL), IL = 32 bits
> SET = 0, FnV = 0
> EA = 0, S1PTW = 0
> FSC = 0x04: level 0 translation fault
> Data abort info:
> ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
> CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> user pgtable: 4k pages, 48-bit VAs, pgdp=0000000049993000
> [0000000000000040] pgd=0000000000000000, p4d=0000000000000000
> Internal error: Oops: 0000000096000004 [#1] SMP
> CPU: 1 UID: 0 PID: 12 Comm: kworker/u8:0 Not tainted 7.0.0-rc2-arm64-renesas-00540-g5f0a63f81a02-dirty #3502 PREEMPT
> Hardware name: Renesas Salvator-X 2nd version board based on r8a77965 (DT)
> Workqueue: pm pm_runtime_work
> pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> pc : genpd_runtime_suspend+0x134/0x28c
> lr : genpd_runtime_suspend+0x124/0x28c
> sp : ffff80008174bc50
> x29: ffff80008174bc50 x28: 0000000000000000 x27: 0000000000000000
> x26: 0000003ca1f7104b x25: ffff0000090ba580 x24: ffff00000e7d92a0
> x23: ffff0000081612f8 x22: 0000000000000001 x21: ffff000008161000
> x20: 0000000000000000 x19: ffff00000b6ef400 x18: 0000000000000000
> x17: 0000000000000000 x16: 0000000000000000 x15: ffff000008065600
> x14: 0000000000000058 x13: ffff0000080254e0 x12: 0000000000000000
> x11: ffff000008065608 x10: 00000000001343d0 x9 : ffff0000080656c0
> x8 : ffff000008161800 x7 : 000001f3fffffc18 x6 : 0000000000000000
> x5 : ffff000008161c10 x4 : 0000000000000000 x3 : 0000000000000000
> x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000
> Call trace:
> genpd_runtime_suspend+0x134/0x28c (P)
> __rpm_callback+0x44/0x1cc
> rpm_callback+0x6c/0x78
> rpm_suspend+0x108/0x564
> pm_runtime_work+0xb8/0xbc
> process_one_work+0x144/0x280
> worker_thread+0x180/0x2f8
> kthread+0x114/0x120
> ret_from_fork+0x10/0x20
> Code: d503201f f940fe60 52800002 f9410e61 (f9402003)
> ---[ end trace 0000000000000000 ]---
>
> The issue is easier to trigger, and may prevent the kernel from booting
> at all, by adding extra debug prints like:
>
> diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
> index 52ea84e548ff6d27..2fe666c2170194ab 100644
> --- a/drivers/pmdomain/core.c
> +++ b/drivers/pmdomain/core.c
> @@ -256,12 +256,14 @@ struct device *dev_to_genpd_dev(struct device *dev)
> static int genpd_stop_dev(const struct generic_pm_domain *genpd,
> struct device *dev)
> {
> +pr_info("==== %s/%s: stop\n", genpd->name, dev_name(dev));
> return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
> }
>
> static int genpd_start_dev(const struct generic_pm_domain *genpd,
> struct device *dev)
> {
> +pr_info("==== %s/%s: start\n", genpd->name, dev_name(dev));
> return GENPD_DEV_CALLBACK(genpd, int, start, dev);
> }
>
> Thanks for your comments and suggestions!
>
> [1] https://lore.kernel.org/CAMuHMdWapT40hV3c+CSBqFOW05aWcV1a6v_NiJYgoYi0i9_PDQ@mail.gmail.com
> [2] https://lore.kernel.org/CAMuHMdWyKeQq31GEK+-y4BoaZFcCxJNac63S7NoocMj1cYKniw@mail.gmail.com/
> [3] commit 5f0a63f81a027bec ("Merge tag 'drm-misc-next-2026-03-05' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next")
> [4] https://web.git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git/tree/arch/arm64/configs/renesas_defconfig?h=topic/renesas-defconfig
> [5] commit 1c21f240fbc1e47b ("drm/imagination: Warn or error on unsupported hardware") in v7.0-rc1
> ---
> drivers/base/power/common.c | 11 +++++------
> 1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
> index 9bef9248a70529bf..af690ce38ac3a086 100644
> --- a/drivers/base/power/common.c
> +++ b/drivers/base/power/common.c
> @@ -12,6 +12,7 @@
> #include <linux/acpi.h>
> #include <linux/pm_domain.h>
> #include <linux/pm_opp.h>
> +#include <linux/pm_runtime.h>
>
> #include "power.h"
>
> @@ -183,9 +184,6 @@ EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_name);
> * may also provide an empty list, in case the attach should be done for all of
> * the available PM domains.
> *
> - * Callers must ensure proper synchronization of this function with power
> - * management callbacks.
> - *
> * Returns the number of attached PM domains or a negative error code in case of
> * a failure. Note that, to detach the list of PM domains, the driver shall call
> * dev_pm_domain_detach_list(), typically during the remove phase.
> @@ -240,6 +238,7 @@ int dev_pm_domain_attach_list(struct device *dev,
> link_flags |= DL_FLAG_RPM_ACTIVE;
>
> for (i = 0; i < num_pds; i++) {
> + pm_runtime_barrier(dev);
> if (by_id)
> pd_dev = dev_pm_domain_attach_by_id(dev, i);
> else
> @@ -284,12 +283,14 @@ int dev_pm_domain_attach_list(struct device *dev,
>
> err_link:
> dev_pm_opp_clear_config(pds->opp_tokens[i]);
> + pm_runtime_barrier(pd_dev);
> dev_pm_domain_detach(pd_dev, true);
> err_attach:
> while (--i >= 0) {
> dev_pm_opp_clear_config(pds->opp_tokens[i]);
> if (pds->pd_links[i])
> device_link_del(pds->pd_links[i]);
> + pm_runtime_barrier(pds->pd_devs[i]);
> dev_pm_domain_detach(pds->pd_devs[i], true);
> }
> kfree(pds->pd_devs);
> @@ -370,9 +371,6 @@ EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
> *
> * This function reverse the actions from dev_pm_domain_attach_list().
> * Typically it should be invoked during the remove phase from drivers.
> - *
> - * Callers must ensure proper synchronization of this function with power
> - * management callbacks.
> */
> void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
> {
> @@ -385,6 +383,7 @@ void dev_pm_domain_detach_list(struct dev_pm_domain_list *list)
> dev_pm_opp_clear_config(list->opp_tokens[i]);
> if (list->pd_links[i])
> device_link_del(list->pd_links[i]);
> + pm_runtime_barrier(list->pd_devs[i]);
> dev_pm_domain_detach(list->pd_devs[i], true);
> }
>
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH 0/3] thermal: spacemit: Add support for SpacemiT K1 SoC thermal sensor
From: Anand Moon @ 2026-03-19 10:44 UTC (permalink / raw)
To: Shuwei Wu
Cc: Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
Philipp Zabel, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, linux-pm, devicetree, linux-riscv, spacemit,
linux-kernel
In-Reply-To: <20251127-b4-k1-thermal-v1-0-f32ce47b1aba@163.com>
Hi Shuwei,
On Wed, 26 Nov 2025 at 17:27, Shuwei Wu <shuweiwoo@163.com> wrote:
>
> Introduce support for the on-die thermal sensor unit (TSU)
> found on the SpacemiT K1 SoC.
>
> Include the device tree binding documentation in YAML format, the
> thermal sensor driver implementation, and the device tree changes to
> enable the sensor on K1 SoC.
>
> Test logs:
> Hardware: OrangePi-RV2 integrates SpacemiT K1 SoC
> Kernel: 6.18.0-rc4 mainline
>
> Verified that all five thermal sensors are registered and reporting
> valid temperatures.
>
> $ cat /sys/class/thermal/thermal_zone*/type
> soc-thermal
> package-thermal
> gpu-thermal
> cluster0-thermal
> cluster1-thermal
>
> $ cat /sys/class/thermal/thermal_zone3/temp
> 28000
>
> Dynamic threshold and interrupt tests passed via sysfs trip_point
> manipulation.
>
> ---
> Shuwei Wu (3):
> dt-bindings: thermal: Add SpacemiT K1 thermal sensor
> thermal: K1: Add driver for K1 SoC thermal sensor
> riscv: dts: spacemit: Add thermal sensor for K1 SoC
>
> .../bindings/thermal/spacemit,k1-thermal.yaml | 76 +++++
> arch/riscv/boot/dts/spacemit/k1.dtsi | 101 +++++++
> drivers/thermal/Kconfig | 14 +
> drivers/thermal/Makefile | 1 +
> drivers/thermal/k1_thermal.c | 307 +++++++++++++++++++++
> 5 files changed, 499 insertions(+)
> ---
> base-commit: f5f2e20b1cbc5f9ea20b372d15967b24921ede19
> change-id: 20251124-b4-k1-thermal-eca906e6dd7a
>
> Best regards,
Tested-by: Anand Moon <linux.amoon@gmail.com>
Thanks
-Anand
> --
> Shuwei Wu <shuweiwoo@163.com>
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply
* Re: [PATCH v8 05/10] pmdomain: samsung: convert to using regmap
From: Marek Szyprowski @ 2026-03-19 10:29 UTC (permalink / raw)
To: Ulf Hansson, André Draszik
Cc: Krzysztof Kozlowski, Alim Akhtar, Rob Herring, Conor Dooley,
Krzysztof Kozlowski, Liam Girdwood, Mark Brown, Peter Griffin,
Tudor Ambarus, Juan Yescas, Will McVicker, kernel-team,
linux-arm-kernel, linux-samsung-soc, devicetree, linux-kernel,
linux-pm
In-Reply-To: <CAPDyKFrprMSLOBMB_BHbi=j6UXV4dXBn-H8M1BsqDWNSCJwvuA@mail.gmail.com>
On 19.03.2026 11:13, Ulf Hansson wrote:
> On Wed, 18 Mar 2026 at 16:28, André Draszik <andre.draszik@linaro.org> wrote:
>> On platforms such as Google gs101, direct mmio register access to the
>> PMU registers doesn't necessarily work and access must happen via a
>> regmap created by the PMU driver instead.
>>
>> In preparation for supporting such SoCs convert the existing mmio
>> accesses to using a regmap wrapper.
>>
>> With this change in place, a follow-up patch can update the driver to
>> optionally acquire the PMU-created regmap without having to change the
>> rest of the code.
>>
>> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> [...]
>
>> @@ -36,31 +35,42 @@ struct exynos_pm_domain {
>> static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
>> {
>> struct exynos_pm_domain *pd;
>> - void __iomem *base;
>> u32 timeout, pwr;
>> - char *op;
>> + int err;
>>
>> pd = container_of(domain, struct exynos_pm_domain, pd);
>> - base = pd->base;
>>
>> pwr = power_on ? pd->local_pwr_cfg : 0;
>> - writel_relaxed(pwr, base);
>> + err = regmap_write(pd->regmap, 0, pwr);
>> + if (err) {
>> + pr_err("Regmap write for power domain %s %sable failed: %d\n",
>> + domain->name, power_on ? "en" : "dis", err);
>> + return err;
>> + }
>>
>> /* Wait max 1ms */
>> timeout = 10;
>> -
>> - while ((readl_relaxed(base + 0x4) & pd->local_pwr_cfg) != pwr) {
>> - if (!timeout) {
>> - op = (power_on) ? "enable" : "disable";
>> - pr_err("Power domain %s %s failed\n", domain->name, op);
>> - return -ETIMEDOUT;
>> + while (timeout-- > 0) {
>> + unsigned int val;
>> +
>> + err = regmap_read(pd->regmap, 0x4, &val);
>> + if (err || ((val & pd->local_pwr_cfg) != pwr)) {
>> + cpu_relax();
>> + usleep_range(80, 100);
>> + continue;
>> }
>> - timeout--;
>> - cpu_relax();
>> - usleep_range(80, 100);
>> +
>> + break;
>> }
>>
> [...]
>
> As a follow-up patch on top, please consider converting the open-coded
> polling loop above into a readx_poll_timeout_atomic().
This has been tried and it doesn't work in all cases required for power
domain driver:
https://lore.kernel.org/all/5c19e4ef-c4fd-4bf5-88b3-46c86751b14e@samsung.com/
Probably a comment about that could be added directly to this code to
avoid such conversion and breakage in the future.
> That said, the series looks ready to me, but I am awaiting an ack from
> a DT maintainer on patch4 before applying.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* Re: [PATCH v8 05/10] pmdomain: samsung: convert to using regmap
From: Ulf Hansson @ 2026-03-19 10:13 UTC (permalink / raw)
To: André Draszik
Cc: Krzysztof Kozlowski, Alim Akhtar, Rob Herring, Conor Dooley,
Krzysztof Kozlowski, Liam Girdwood, Mark Brown, Peter Griffin,
Tudor Ambarus, Juan Yescas, Will McVicker, kernel-team,
linux-arm-kernel, linux-samsung-soc, devicetree, linux-kernel,
linux-pm, Marek Szyprowski
In-Reply-To: <20260318-gs101-pd-v8-5-241523460b10@linaro.org>
On Wed, 18 Mar 2026 at 16:28, André Draszik <andre.draszik@linaro.org> wrote:
>
> On platforms such as Google gs101, direct mmio register access to the
> PMU registers doesn't necessarily work and access must happen via a
> regmap created by the PMU driver instead.
>
> In preparation for supporting such SoCs convert the existing mmio
> accesses to using a regmap wrapper.
>
> With this change in place, a follow-up patch can update the driver to
> optionally acquire the PMU-created regmap without having to change the
> rest of the code.
>
> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
[...]
> @@ -36,31 +35,42 @@ struct exynos_pm_domain {
> static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
> {
> struct exynos_pm_domain *pd;
> - void __iomem *base;
> u32 timeout, pwr;
> - char *op;
> + int err;
>
> pd = container_of(domain, struct exynos_pm_domain, pd);
> - base = pd->base;
>
> pwr = power_on ? pd->local_pwr_cfg : 0;
> - writel_relaxed(pwr, base);
> + err = regmap_write(pd->regmap, 0, pwr);
> + if (err) {
> + pr_err("Regmap write for power domain %s %sable failed: %d\n",
> + domain->name, power_on ? "en" : "dis", err);
> + return err;
> + }
>
> /* Wait max 1ms */
> timeout = 10;
> -
> - while ((readl_relaxed(base + 0x4) & pd->local_pwr_cfg) != pwr) {
> - if (!timeout) {
> - op = (power_on) ? "enable" : "disable";
> - pr_err("Power domain %s %s failed\n", domain->name, op);
> - return -ETIMEDOUT;
> + while (timeout-- > 0) {
> + unsigned int val;
> +
> + err = regmap_read(pd->regmap, 0x4, &val);
> + if (err || ((val & pd->local_pwr_cfg) != pwr)) {
> + cpu_relax();
> + usleep_range(80, 100);
> + continue;
> }
> - timeout--;
> - cpu_relax();
> - usleep_range(80, 100);
> +
> + break;
> }
>
[...]
As a follow-up patch on top, please consider converting the open-coded
polling loop above into a readx_poll_timeout_atomic().
That said, the series looks ready to me, but I am awaiting an ack from
a DT maintainer on patch4 before applying.
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH v2 2/8] dt-bindings: thermal: Add qcom,qmi-cooling yaml bindings
From: Konrad Dybcio @ 2026-03-19 9:51 UTC (permalink / raw)
To: Gaurav Kohli, Daniel Lezcano, Krzysztof Kozlowski
Cc: andersson, mathieu.poirier, robh, krzk+dt, conor+dt, rui.zhang,
lukasz.luba, konradybcio, mani, casey.connolly, amit.kucheria,
linux-arm-msm, devicetree, linux-kernel, linux-pm,
manaf.pallikunhi
In-Reply-To: <3922012f-25e6-4b75-9183-f9277ef5d040@oss.qualcomm.com>
On 3/18/26 11:17 AM, Gaurav Kohli wrote:
>
>
> On 3/17/2026 1:27 AM, Daniel Lezcano wrote:
>> On Tue, Feb 24, 2026 at 01:17:22PM +0100, Krzysztof Kozlowski wrote:
>>> On 24/02/2026 13:09, Gaurav Kohli wrote:
>>
>> [ ... ]
>>
>>>>>> As a result, each core requires its own cooling device, which must be
>>>>>> linked to its TSENS thermal zone. Because of this, we introduced
>>>>>> multiple child nodes—one for each cooling device.
>>>>>
>>>>> So you have one device with cooling cells=1+2, no?
>>>>>
>>>>
>>>> This will be a bigger framework change which is not supported, i can see
>>>
>>> I don't think that changing open source frameworks is "not supported". I
>>> am pretty sure that changing is not only supported, but actually desired.
>>
>> Yes, IMO it could make sense. There are the thermal zones with phandle
>> to a sensor and a sensor id. We can have the same with a phandle to a
>> cooling device and a cooling device id.
>>
>> (... or several ids because the thermal sensor can also have multiple
>> ids ?)
>>
>> May be an array of names corresponding to the TMD names at the 'id'
>> position ?
>>
>
> I am using dt node like below to use with cooling-cells = <3> approach, will post new patches with that.
>
> cdsp_tmd: cdsp-tmd {
> compatible = "qcom,qmi-cooling-cdsp";
> tmd-names = "cdsp_sw", "cdsp_hw";
> #cooling-cells = <3>;
> };
>
> please let me know, if you are expecting something like this only.
My question about the need of a separate node still remains, i.e.
why can't this be:
remoteproc_cdsp: remoteproc@cafebabe {
compatible = "qcom,foo-cdsp"
...
tmd-names = "abc", "xyz";
#cooling-cells = <3>;
};
foo-thermal {
cooling-maps {
map0 {
cooling-device = <&remoteproc_cdsp CDSP_COOLING_XYZ
THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
where you'd presumably call something like qmi_cooling_register(...) from
the remoteproc driver, making your added code essentially a library, not a
separate platform device
Konrad
^ permalink raw reply
* Re: [PATCH v6 1/4] cpufreq: Remove per-CPU QoS constraint
From: Pierre Gondois @ 2026-03-19 9:30 UTC (permalink / raw)
To: Viresh Kumar, Lifeng Zheng
Cc: linux-kernel, Jie Zhan, Ionela Voinescu, Sumit Gupta, Huang Rui,
Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
Rafael J. Wysocki, Srinivas Pandruvada, Len Brown,
Saravana Kannan, linux-pm
In-Reply-To: <46wu76e25pscn5tkes6uabtgsqxev6wvi5pihrlozobyadmuqq@ffvqv43nys23>
On 3/18/26 12:13, Viresh Kumar wrote:
> On 17-03-26, 11:17, Pierre Gondois wrote:
>> policy->max_freq_req represents the maximum allowed frequency as
>> requested by the policyX/scaling_max_freq sysfs file. This request
>> applies to all CPUs of the policy. It is not possible to request
>> a per-CPU maximum frequency.
>>
>> Thus, the interaction between the policy boost and scaling_max_freq
>> settings should be handled by adding a boost specific QoS constraint.
>> This will be handled in the following patches.
> I don't think the above is required anymore. This patch is removing stale code
> now which isn't useful anymore. It has nothing to do with a boost specific QOS
> constraint.
Yes ok
> And it would be better to know for sure why this isn't required anymore and
> which patch exactly fixed this issue.
>
On a kernel based on 1608f0230510~, and replicating the
process described in the commit message of
commit 1608f0230510 ("cpufreq: Fix re-boost issue after hotplugging
a CPU")
I could not see any issue regarding the values of:
- policy1/cpuinfo_max_freq
- policy1/scaling_max_freq
The following sequence however had an issue:
1. echo 0 > /sys/devices/system/cpu/cpu1/online
2. echo 1 > /sys/devices/system/cpu/cpufreq/boost
3. echo 1 > /sys/devices/system/cpu/cpu1/online
as after 1.:
cpufreq_boost_trigger_state()
\-for_each_active_policy()
doesn't enable boost for inactive policies. This leads to
CPU1 having the non-boosted frequency as its max freq.
The above sequence is fixed by:
commit a153c6049ab8 ("cpufreq: Introduce a more
generic way to set default per-policy boost flag")
---
@Lifeng, should I check something else than the value of:
- policy1/cpuinfo_max_freq
- policy1/scaling_max_freq
in order to reproduce the issue fixed by:
commit 1608f0230510 ("cpufreq: Fix re-boost issue after hotplugging
a CPU")
?
^ permalink raw reply
* [rafael-pm:fixes] BUILD SUCCESS 989846451544c0330ee498cfdfc0183a4baf4270
From: kernel test robot @ 2026-03-19 9:25 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 fixes
branch HEAD: 989846451544c0330ee498cfdfc0183a4baf4270 Merge branch 'acpi-bus' into fixes
elapsed time: 1038m
configs tested: 168
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 clang-16
arc allnoconfig gcc-15.2.0
arc allyesconfig clang-23
arc defconfig gcc-15.2.0
arc randconfig-001-20260319 gcc-11.5.0
arc randconfig-002-20260319 gcc-11.5.0
arm allnoconfig gcc-15.2.0
arm allyesconfig clang-16
arm defconfig gcc-15.2.0
arm randconfig-001-20260319 gcc-11.5.0
arm randconfig-002-20260319 gcc-11.5.0
arm randconfig-003-20260319 gcc-11.5.0
arm randconfig-004-20260319 gcc-11.5.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-15.2.0
arm64 defconfig gcc-15.2.0
arm64 randconfig-001-20260319 gcc-15.2.0
arm64 randconfig-002-20260319 gcc-15.2.0
arm64 randconfig-003-20260319 gcc-15.2.0
arm64 randconfig-004-20260319 gcc-15.2.0
csky allmodconfig gcc-15.2.0
csky allnoconfig gcc-15.2.0
csky defconfig gcc-15.2.0
csky randconfig-001-20260319 gcc-15.2.0
csky randconfig-002-20260319 gcc-15.2.0
hexagon allmodconfig gcc-15.2.0
hexagon allnoconfig gcc-15.2.0
hexagon defconfig gcc-15.2.0
hexagon randconfig-001-20260319 gcc-11.5.0
hexagon randconfig-002-20260319 gcc-11.5.0
i386 allmodconfig clang-20
i386 allnoconfig gcc-15.2.0
i386 allyesconfig clang-20
i386 buildonly-randconfig-001-20260319 gcc-14
i386 buildonly-randconfig-002-20260319 gcc-14
i386 buildonly-randconfig-003-20260319 gcc-14
i386 buildonly-randconfig-004-20260319 gcc-14
i386 buildonly-randconfig-005-20260319 gcc-14
i386 buildonly-randconfig-006-20260319 gcc-14
i386 defconfig gcc-15.2.0
i386 randconfig-001-20260319 gcc-14
i386 randconfig-002-20260319 gcc-14
i386 randconfig-003-20260319 gcc-14
i386 randconfig-004-20260319 gcc-14
i386 randconfig-005-20260319 gcc-14
i386 randconfig-006-20260319 gcc-14
i386 randconfig-007-20260319 gcc-14
i386 randconfig-011-20260319 clang-20
i386 randconfig-012-20260319 clang-20
i386 randconfig-013-20260319 clang-20
i386 randconfig-014-20260319 clang-20
i386 randconfig-015-20260319 clang-20
i386 randconfig-016-20260319 clang-20
i386 randconfig-017-20260319 clang-20
loongarch allmodconfig clang-23
loongarch allnoconfig gcc-15.2.0
loongarch defconfig clang-19
loongarch randconfig-001-20260319 gcc-11.5.0
loongarch randconfig-002-20260319 gcc-11.5.0
m68k allmodconfig gcc-15.2.0
m68k allnoconfig gcc-15.2.0
m68k allyesconfig clang-16
m68k defconfig clang-19
m68k sun3x_defconfig gcc-15.2.0
microblaze allnoconfig gcc-15.2.0
microblaze allyesconfig gcc-15.2.0
microblaze defconfig clang-19
mips allmodconfig gcc-15.2.0
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-20260319 gcc-11.5.0
nios2 randconfig-002-20260319 gcc-11.5.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-20260319 clang-19
parisc randconfig-002-20260319 clang-19
parisc64 defconfig clang-19
powerpc allmodconfig gcc-15.2.0
powerpc allnoconfig clang-23
powerpc chrp32_defconfig clang-19
powerpc randconfig-001-20260319 clang-19
powerpc randconfig-002-20260319 clang-19
powerpc64 randconfig-001-20260319 clang-19
powerpc64 randconfig-002-20260319 clang-19
riscv allmodconfig clang-23
riscv allnoconfig clang-23
riscv allyesconfig clang-16
riscv defconfig gcc-15.2.0
riscv randconfig-001-20260319 gcc-10.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-20260319 gcc-10.5.0
s390 randconfig-002-20260319 gcc-10.5.0
sh allmodconfig gcc-15.2.0
sh allnoconfig clang-23
sh allyesconfig clang-19
sh defconfig gcc-14
sh randconfig-001-20260319 gcc-10.5.0
sh randconfig-002-20260319 gcc-10.5.0
sparc allnoconfig clang-23
sparc defconfig gcc-15.2.0
sparc randconfig-001-20260319 gcc-8.5.0
sparc randconfig-002-20260319 gcc-8.5.0
sparc64 allmodconfig clang-23
sparc64 defconfig gcc-14
sparc64 randconfig-001-20260319 gcc-8.5.0
sparc64 randconfig-002-20260319 gcc-8.5.0
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-20260319 gcc-8.5.0
um randconfig-002-20260319 gcc-8.5.0
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-20260319 clang-20
x86_64 buildonly-randconfig-002-20260319 clang-20
x86_64 buildonly-randconfig-003-20260319 clang-20
x86_64 buildonly-randconfig-004-20260319 clang-20
x86_64 buildonly-randconfig-005-20260319 clang-20
x86_64 buildonly-randconfig-006-20260319 clang-20
x86_64 defconfig gcc-14
x86_64 kexec clang-20
x86_64 randconfig-001-20260319 gcc-14
x86_64 randconfig-002-20260319 gcc-14
x86_64 randconfig-003-20260319 gcc-14
x86_64 randconfig-004-20260319 gcc-14
x86_64 randconfig-005-20260319 gcc-14
x86_64 randconfig-006-20260319 gcc-14
x86_64 randconfig-011-20260319 gcc-13
x86_64 randconfig-012-20260319 gcc-13
x86_64 randconfig-013-20260319 gcc-13
x86_64 randconfig-014-20260319 gcc-13
x86_64 randconfig-015-20260319 gcc-13
x86_64 randconfig-016-20260319 gcc-13
x86_64 randconfig-071-20260319 clang-20
x86_64 randconfig-072-20260319 clang-20
x86_64 randconfig-073-20260319 clang-20
x86_64 randconfig-074-20260319 clang-20
x86_64 randconfig-075-20260319 clang-20
x86_64 randconfig-076-20260319 clang-20
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-20260319 gcc-8.5.0
xtensa randconfig-002-20260319 gcc-8.5.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH RESEND 4/4] PM / devfreq: Optimize error return value of governor_show()
From: Yaxiong Tian @ 2026-03-19 9:17 UTC (permalink / raw)
To: myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel, Yaxiong Tian
In-Reply-To: <20260319091409.998397-1-tianyaxiong@kylinos.cn>
When df->governor is NULL, governor_show() returns -EINVAL, which
confuses users.
To fix this issue, return -ENOENT to indicate that no governor is
currently set for the device.
Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
---
drivers/devfreq/devfreq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 4a312f3c2421..7cc60711fafd 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1412,7 +1412,7 @@ static ssize_t governor_show(struct device *dev,
struct devfreq *df = to_devfreq(dev);
if (!df->governor)
- return -EINVAL;
+ return -ENOENT;
return sprintf(buf, "%s\n", df->governor->name);
}
--
2.25.1
^ permalink raw reply related
* [PATCH RESEND 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor
From: Yaxiong Tian @ 2026-03-19 9:17 UTC (permalink / raw)
To: myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel, Yaxiong Tian
In-Reply-To: <20260319091409.998397-1-tianyaxiong@kylinos.cn>
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 | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 0bf320123e3a..4a312f3c2421 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1425,9 +1425,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;
@@ -1438,6 +1435,18 @@ 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;
+ }
+ goto out;
+ }
+
if (df->governor == governor) {
ret = 0;
goto out;
--
2.25.1
^ permalink raw reply related
* [PATCH RESEND 2/4] PM / devfreq: Fix available_governors_show() when no governor is set
From: Yaxiong Tian @ 2026-03-19 9:17 UTC (permalink / raw)
To: myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel, Yaxiong Tian
In-Reply-To: <20260319091409.998397-1-tianyaxiong@kylinos.cn>
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 use df->governor for validity
verification in the following code.
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 | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 63ce6e25abe2..0bf320123e3a 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1504,16 +1504,13 @@ static ssize_t available_governors_show(struct device *d,
struct devfreq *df = to_devfreq(d);
ssize_t count = 0;
- if (!df->governor)
- return -EINVAL;
-
mutex_lock(&devfreq_list_lock);
/*
* The devfreq with immutable governor (e.g., passive) shows
* only own governor.
*/
- if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)) {
+ if (df->governor && IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)) {
count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
"%s ", df->governor->name);
/*
--
2.25.1
^ permalink raw reply related
* [PATCH RESEND 1/4] PM / devfreq: Fix possible null pointer issue in devfreq_add_governor()
From: Yaxiong Tian @ 2026-03-19 9:16 UTC (permalink / raw)
To: myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel, Yaxiong Tian
In-Reply-To: <20260319091409.998397-1-tianyaxiong@kylinos.cn>
When a user removes a governor using devfreq_remove_governor(), if
the current device is using this governor, devfreq->governor will
be set to NULL. When the user registers any governor
using devfreq_add_governor(), since devfreq->governor is NULL, a
null pointer error occurs in strncmp().
For example: A user loads the userspace gov through a module, then
a device selects userspace. When unloading the userspace module and
then loading it again, the null pointer error occurs:
Unable to handle kernel NULL pointer dereference at virtual address
0000000000000010
Mem abort info:
ESR = 0x0000000096000004
EC = 0x25: DABT (current EL), IL = 32 bits
*******************skip *********************
Call trace:
__pi_strncmp+0x20/0x1b8
devfreq_userspace_init+0x1c/0xff8 [governor_userspace]
do_one_initcall+0x4c/0x278
do_init_module+0x5c/0x218
load_module+0x1f1c/0x1fc8
init_module_from_file+0x8c/0xd0
__arm64_sys_finit_module+0x220/0x3d8
invoke_syscall+0x48/0x110
el0_svc_common.constprop.0+0xbc/0xe8
do_el0_svc+0x20/0x30
el0_svc+0x24/0xb8
el0t_64_sync_handler+0xb8/0xc0
el0t_64_sync+0x14c/0x150
To fix this issue, modify the relevant logic in devfreq_add_governor():
Only check whether the new governor matches the existing one when
devfreq->governor exists. When devfreq->governor is NULL, directly
select the new governor and perform the DEVFREQ_GOV_START operation.
Fixes: 1b5c1be2c88e ("PM / devfreq: map devfreq drivers to governor using name")
Signed-off-by: Yaxiong Tian <tianyaxiong@kylinos.cn>
---
drivers/devfreq/devfreq.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 54f0b18536db..63ce6e25abe2 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1288,23 +1288,21 @@ int devfreq_add_governor(struct devfreq_governor *governor)
int ret = 0;
struct device *dev = devfreq->dev.parent;
- if (!strncmp(devfreq->governor->name, governor->name,
+ if (devfreq->governor && !strncmp(devfreq->governor->name, governor->name,
DEVFREQ_NAME_LEN)) {
/* The following should never occur */
- if (devfreq->governor) {
+ dev_warn(dev,
+ "%s: Governor %s already present\n",
+ __func__, devfreq->governor->name);
+ ret = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
dev_warn(dev,
- "%s: Governor %s already present\n",
- __func__, devfreq->governor->name);
- ret = devfreq->governor->event_handler(devfreq,
- DEVFREQ_GOV_STOP, NULL);
- if (ret) {
- dev_warn(dev,
- "%s: Governor %s stop = %d\n",
- __func__,
- devfreq->governor->name, ret);
- }
- /* Fall through */
+ "%s: Governor %s stop = %d\n",
+ __func__,
+ devfreq->governor->name, ret);
}
+ } else if (!devfreq->governor) {
devfreq->governor = governor;
ret = devfreq->governor->event_handler(devfreq,
DEVFREQ_GOV_START, NULL);
--
2.25.1
^ permalink raw reply related
* [PATCH RESEND 0/4] Fix some errors in the devfreq core layer when governor is NULL
From: Yaxiong Tian @ 2026-03-19 9:14 UTC (permalink / raw)
To: myungjoo.ham, kyungmin.park, cw00.choi, nm
Cc: linux-pm, linux-kernel, Yaxiong Tian
While doing some development work with devfreq_add_governor()/
devfreq_remove_governor(), I discovered several bugs caused when
devfreq->governor is NULL. Specifically:
1) A possible null pointer issue in devfreq_add_governor(), caused
by devfreq_remove_governor() setting devfreq->governor to NULL in
certain situations, while devfreq_add_governor() lacks corresponding
checks for devfreq->governor.
2) When operating on governor and available_governors under /sys,
there are also some unexpected errors.
See the following patches for details.
Yaxiong Tian (4):
PM / devfreq: Fix possible null pointer issue in
devfreq_add_governor()
PM / devfreq: Fix available_governors_show() when no governor is set
PM / devfreq: Fix governor_store() failing when device has no current
governor
PM / devfreq: Optimize error return value of governor_show()
drivers/devfreq/devfreq.c | 46 +++++++++++++++++++++------------------
1 file changed, 25 insertions(+), 21 deletions(-)
--
2.25.1
^ permalink raw reply
* Re: [PATCH v4 09/21] mm: swap: allocate a virtual swap slot for each swapped out page
From: Peter Zijlstra @ 2026-03-19 7:56 UTC (permalink / raw)
To: Nhat Pham
Cc: kasong, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
corbet, david, dev.jain, gourry, hannes, hughd, jannh,
joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
muchun.song, npache, pavel, peterx, pfalcato, rafael, rakie.kim,
roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed, yuanchu,
zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <20260318222953.441758-10-nphamcs@gmail.com>
On Wed, Mar 18, 2026 at 03:29:40PM -0700, Nhat Pham wrote:
> diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
> index 62cd7b35a29c9..85cb45022e796 100644
> --- a/include/linux/cpuhotplug.h
> +++ b/include/linux/cpuhotplug.h
> @@ -86,6 +86,7 @@ enum cpuhp_state {
> CPUHP_FS_BUFF_DEAD,
> CPUHP_PRINTK_DEAD,
> CPUHP_MM_MEMCQ_DEAD,
> + CPUHP_MM_VSWAP_DEAD,
> CPUHP_PERCPU_CNT_DEAD,
> CPUHP_RADIX_DEAD,
> CPUHP_PAGE_ALLOC,
> +static int vswap_cpu_dead(unsigned int cpu)
> +{
> + struct vswap_cluster *cluster;
> + int order;
> +
> + rcu_read_lock();
nit:
guard(rcu)();
> + for (order = 0; order < SWAP_NR_ORDERS; order++) {
> + cluster = per_cpu(percpu_vswap_cluster.clusters[order], cpu);
> + if (cluster) {
> + per_cpu(percpu_vswap_cluster.clusters[order], cpu) = NULL;
> + spin_lock(&cluster->lock);
This breaks on PREEMPT_RT as this is ran with IRQs disabled. This must
be a raw_spinlock_t.
> + cluster->cached = false;
> + if (refcount_dec_and_test(&cluster->refcnt))
> + vswap_cluster_free(cluster);
And this... below.
> + spin_unlock(&cluster->lock);
> + }
> + }
> + rcu_read_unlock();
> +
> + return 0;
> +}
> +static void vswap_cluster_free(struct vswap_cluster *cluster)
> +{
> + VM_WARN_ON(cluster->count || cluster->cached);
> + VM_WARN_ON(!spin_is_locked(&cluster->lock));
This is terrible, please use:
lockdep_assert_held(&cluster->lock);
> + xa_lock(&vswap_cluster_map);
This is again broken, this cannot be from a DEAD callback with IRQs
disabled.
> + list_del_init(&cluster->list);
> + __xa_erase(&vswap_cluster_map, cluster->id);
Strictly speaking this can end up in xas_alloc(), which is again, not
allowed in a DEAD callback.
> + xa_unlock(&vswap_cluster_map);
> + rcu_head_init(&cluster->rcu);
> + kvfree_rcu(cluster, rcu);
> +}
^ permalink raw reply
* Re: [PATCH v3 3/9] dt-bindings: regulator: Document MediaTek MT6392 PMIC Regulators
From: Krzysztof Kozlowski @ 2026-03-19 7:23 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Luca Leonardo Scorcia, linux-mediatek, Dmitry Torokhov,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sen Chu,
Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Liam Girdwood,
Mark Brown, Julien Massot, Gary Bisson, Louis-Alexis Eyraud,
Val Packett, Fabien Parent, Chen Zhong, linux-input, devicetree,
linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <CAGXv+5EqUhJ62fjE0R9nLcu6tsfXan8ZEYe7hvkofKnFM7W8NQ@mail.gmail.com>
On 19/03/2026 05:53, Chen-Yu Tsai wrote:
>>> I understood this is that electrical constraints are a matter of the
>>> actual board layout, so if adjustments are needed they have to be in
>>> the board dts. But you also specify "If fixed", so maybe there's an
>>> exception to this rule when the constraint is "absolute" and boards
>>> can't actually set a different value?
>>
>> Now I am confused. You wrote - LDOs with fixed 1.8V output - so board
>> cannot set it to 2.0V for example. They are affixed. This regulator
>> CANNOT physically produce anything else.
>
> As you said, it cannot physically produce anything else. IMO it doesn't
> even need voltage constraints as it is already implied by the model and
> regulator output, in which case I would actually recommend rejecting
> min/max voltage being added to this node.
But the text is not helping and not doing much good here. So either this
should be schema or nothing. I agree though that having here no
constraints in final DTS is valid.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v7 3/7] dax/cxl, hmem: Initialize hmem early and defer dax_cxl binding
From: Alison Schofield @ 2026-03-19 5:48 UTC (permalink / raw)
To: Smita Koralahalli
Cc: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm,
Ard Biesheuvel, Vishal Verma, Ira Weiny, Dan Williams,
Jonathan Cameron, Yazen Ghannam, Dave Jiang, Davidlohr Bueso,
Matthew Wilcox, Jan Kara, Rafael J . Wysocki, Len Brown,
Pavel Machek, Li Ming, Jeff Johnson, Ying Huang, Yao Xingtao,
Peter Zijlstra, Greg Kroah-Hartman, Nathan Fontenot, Terry Bowman,
Robert Richter, Benjamin Cheatham, Zhijian Li, Borislav Petkov,
Tomasz Wolski
In-Reply-To: <20260319011500.241426-4-Smita.KoralahalliChannabasappa@amd.com>
On Thu, Mar 19, 2026 at 01:14:56AM +0000, Smita Koralahalli wrote:
> From: Dan Williams <dan.j.williams@intel.com>
>
> Move hmem/ earlier in the dax Makefile so that hmem_init() runs before
> dax_cxl.
>
> In addition, defer registration of the dax_cxl driver to a workqueue
> instead of using module_cxl_driver(). This ensures that dax_hmem has
> an opportunity to initialize and register its deferred callback and make
> ownership decisions before dax_cxl begins probing and claiming Soft
> Reserved ranges.
>
> Mark the dax_cxl driver as PROBE_PREFER_ASYNCHRONOUS so its probe runs
> out of line from other synchronous probing avoiding ordering
> dependencies while coordinating ownership decisions with dax_hmem.
Hi Smita,
Replying to this patch, as it's my best guess as to why I may be
seeing this WARN when I modprobe cxl-test.
We are able to pass all the CXL unit tests because it is only that
first load that causes the WARN. All subsequent reloads of cxl-test
do not unload dax_cxl and dax_hmem so they chug happily along.
I can reproduce by unloading each piece before reloading cxl-test
# modprobe -r cxl-test
# modprobe -r dax_cxl
# modprobe -r dax_hmem
# modprobe cxl-test
and the WARN repeats.
Guessing you may recognize what is going on. Let me know if I can
try anything else out.
# dmesg (trimmed to just the init calls)
[ 34.229033] calling fwctl_init+0x0/0xff0 [fwctl] @ 1057
[ 34.230616] initcall fwctl_init+0x0/0xff0 [fwctl] returned 0 after 186 usecs
[ 34.257096] calling cxl_core_init+0x0/0x100 [cxl_core] @ 1057
[ 34.258395] initcall cxl_core_init+0x0/0x100 [cxl_core] returned 0 after 538 usecs
[ 34.264170] calling cxl_port_init+0x0/0xff0 [cxl_port] @ 1057
[ 34.264982] initcall cxl_port_init+0x0/0xff0 [cxl_port] returned 0 after 110 usecs
[ 34.268058] calling cxl_mem_driver_init+0x0/0xff0 [cxl_mem] @ 1057
[ 34.268743] initcall cxl_mem_driver_init+0x0/0xff0 [cxl_mem] returned 0 after 110 usecs
[ 34.274670] calling cxl_pmem_init+0x0/0xff0 [cxl_pmem] @ 1057
[ 34.277835] initcall cxl_pmem_init+0x0/0xff0 [cxl_pmem] returned 0 after 1671 usecs
[ 34.285807] calling cxl_acpi_init+0x0/0xff0 [cxl_acpi] @ 1057
[ 34.287105] initcall cxl_acpi_init+0x0/0xff0 [cxl_acpi] returned 0 after 262 usecs
[ 34.292967] calling cxl_test_init+0x0/0xff0 [cxl_test] @ 1057
[ 34.339841] initcall cxl_test_init+0x0/0xff0 [cxl_test] returned 0 after 45832 usecs
[ 34.342259] calling cxl_mock_mem_driver_init+0x0/0xff0 [cxl_mock_mem] @ 1063
[ 34.343459] initcall cxl_mock_mem_driver_init+0x0/0xff0 [cxl_mock_mem] returned 0 after 356 usecs
[ 34.658602] calling dax_hmem_init+0x0/0xff0 [dax_hmem] @ 1059
[ 34.670106] calling cxl_pci_driver_init+0x0/0xff0 [cxl_pci] @ 1100
[ 34.671023] initcall cxl_pci_driver_init+0x0/0xff0 [cxl_pci] returned 0 after 197 usecs
[ 34.673051] initcall dax_hmem_init+0x0/0xff0 [dax_hmem] returned 0 after 2225 usecs
[ 34.676011] calling cxl_dax_region_init+0x0/0xff0 [dax_cxl] @ 1059
[ 34.676856] ------------[ cut here ]------------
[ 34.677533] WARNING: kernel/workqueue.c:4289 at __flush_work+0x4f9/0x550, CPU#3: kworker/3:2/136
[ 34.678596] Modules linked in: dax_cxl(+) cxl_pci dax_hmem cxl_mock_mem(O) cxl_test(O) cxl_acpi(O) cxl_pmem(O) cxl_mem(O) cxl_port(O) cxl_mock(O) cxl_core(O) fwctl nd_pmem nd_btt dax_pmem nfit nd_e820 libnvdimm
[ 34.680632] initcall cxl_dax_region_init+0x0/0xff0 [dax_cxl] returned 0 after 3842 usecs
[ 34.680918] CPU: 3 UID: 0 PID: 136 Comm: kworker/3:2 Tainted: G O 7.0.0-rc4+ #156 PREEMPT(full)
[ 34.684368] Tainted: [O]=OOT_MODULE
[ 34.684993] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
[ 34.686098] Workqueue: events_long cxl_dax_region_driver_register [dax_cxl]
[ 34.687108] RIP: 0010:__flush_work+0x4f9/0x550
That addr is this line in flush_work()
if (WARN_ON(!work->func))
return false;
[ 34.687811] Code: ff 49 8b 45 00 49 8b 55 08 89 c7 48 c1 e8 04 83 e7 08 83 e0 0f 83 cf 02 49 0f ba 6d 00 03 e9 a1 fc ff ff 0f 0b e9 e6 fe ff ff <0f> 0b e9 df fe ff ff e8 9b 48 15 01 85 c0 0f 84 26 ff ff ff 80 3d
[ 34.690107] RSP: 0018:ffffc900020b7cf8 EFLAGS: 00010246
[ 34.690673] RAX: 0000000000000000 RBX: ffffffffa0ea2088 RCX: ffff8880088b2b78
[ 34.691388] RDX: 00000000834fb194 RSI: 0000000000000000 RDI: ffffffffa0ea2088
[ 34.692135] RBP: ffffc900020b7de0 R08: 0000000031ab93b0 R09: 00000000effb42e8
[ 34.692876] R10: 000000008effb42e R11: 0000000000000000 R12: ffff88807d9bb340
[ 34.693588] R13: ffffffffa0ea2088 R14: ffffffffa0ed2020 R15: 0000000000000001
[ 34.694358] FS: 0000000000000000(0000) GS:ffff8880fa45f000(0000) knlGS:0000000000000000
[ 34.695179] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 34.695775] CR2: 00007fe888b4e34c CR3: 00000000090ed004 CR4: 0000000000370ef0
[ 34.696494] Call Trace:
[ 34.696889] <TASK>
[ 34.697238] ? __lock_acquire+0xb08/0x2930
[ 34.697730] ? __this_cpu_preempt_check+0x13/0x20
[ 34.698277] flush_work+0x17/0x30
[ 34.698705] dax_hmem_flush_work+0x10/0x20 [dax_hmem]
[ 34.699270] cxl_dax_region_driver_register+0x9/0x30 [dax_cxl]
[ 34.699943] process_one_work+0x203/0x6c0
[ 34.700452] worker_thread+0x197/0x350
[ 34.700942] ? __pfx_worker_thread+0x10/0x10
[ 34.701455] kthread+0x108/0x140
[ 34.701915] ? __pfx_kthread+0x10/0x10
[ 34.702396] ret_from_fork+0x28a/0x310
[ 34.702880] ? __pfx_kthread+0x10/0x10
[ 34.703363] ret_from_fork_asm+0x1a/0x30
[ 34.703872] </TASK>
[ 34.704227] irq event stamp: 11015
[ 34.704656] hardirqs last enabled at (11025): [<ffffffff813486de>] __up_console_sem+0x5e/0x80
[ 34.705493] hardirqs last disabled at (11036): [<ffffffff813486c3>] __up_console_sem+0x43/0x80
[ 34.706354] softirqs last enabled at (10500): [<ffffffff812ab9f3>] __irq_exit_rcu+0xc3/0x120
[ 34.707197] softirqs last disabled at (10495): [<ffffffff812ab9f3>] __irq_exit_rcu+0xc3/0x120
[ 34.708015] ---[ end trace 0000000000000000 ]---
[ 34.752127] calling dax_init+0x0/0xff0 [device_dax] @ 1089
[ 34.754006] initcall dax_init+0x0/0xff0 [device_dax] returned 0 after 422 usecs
[ 34.759609] calling dax_kmem_init+0x0/0xff0 [kmem] @ 1089
[ 37.338377] initcall dax_kmem_init+0x0/0xff0 [kmem] returned 0 after 2577658 usecs
>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> ---
> drivers/dax/Makefile | 3 +--
> drivers/dax/cxl.c | 27 ++++++++++++++++++++++++++-
> 2 files changed, 27 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/dax/Makefile b/drivers/dax/Makefile
> index 5ed5c39857c8..70e996bf1526 100644
> --- a/drivers/dax/Makefile
> +++ b/drivers/dax/Makefile
> @@ -1,4 +1,5 @@
> # SPDX-License-Identifier: GPL-2.0
> +obj-y += hmem/
> obj-$(CONFIG_DAX) += dax.o
> obj-$(CONFIG_DEV_DAX) += device_dax.o
> obj-$(CONFIG_DEV_DAX_KMEM) += kmem.o
> @@ -10,5 +11,3 @@ dax-y += bus.o
> device_dax-y := device.o
> dax_pmem-y := pmem.o
> dax_cxl-y := cxl.o
> -
> -obj-y += hmem/
> diff --git a/drivers/dax/cxl.c b/drivers/dax/cxl.c
> index 13cd94d32ff7..a2136adfa186 100644
> --- a/drivers/dax/cxl.c
> +++ b/drivers/dax/cxl.c
> @@ -38,10 +38,35 @@ static struct cxl_driver cxl_dax_region_driver = {
> .id = CXL_DEVICE_DAX_REGION,
> .drv = {
> .suppress_bind_attrs = true,
> + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
> },
> };
>
> -module_cxl_driver(cxl_dax_region_driver);
> +static void cxl_dax_region_driver_register(struct work_struct *work)
> +{
> + cxl_driver_register(&cxl_dax_region_driver);
> +}
> +
> +static DECLARE_WORK(cxl_dax_region_driver_work, cxl_dax_region_driver_register);
> +
> +static int __init cxl_dax_region_init(void)
> +{
> + /*
> + * Need to resolve a race with dax_hmem wanting to drive regions
> + * instead of CXL
> + */
> + queue_work(system_long_wq, &cxl_dax_region_driver_work);
> + return 0;
> +}
> +module_init(cxl_dax_region_init);
> +
> +static void __exit cxl_dax_region_exit(void)
> +{
> + flush_work(&cxl_dax_region_driver_work);
> + cxl_driver_unregister(&cxl_dax_region_driver);
> +}
> +module_exit(cxl_dax_region_exit);
> +
> MODULE_ALIAS_CXL(CXL_DEVICE_DAX_REGION);
> MODULE_DESCRIPTION("CXL DAX: direct access to CXL regions");
> MODULE_LICENSE("GPL");
> --
> 2.17.1
>
>
^ permalink raw reply
* Re: [PATCH v3 7/9] regulator: mt6392: Add support for MT6392 regulator
From: Chen-Yu Tsai @ 2026-03-19 5:04 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: linux-mediatek, Fabien Parent, Val Packett, Dmitry Torokhov,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sen Chu,
Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Liam Girdwood,
Mark Brown, Gary Bisson, Louis-Alexis Eyraud, Julien Massot,
Chen Zhong, linux-input, devicetree, linux-kernel, linux-pm,
linux-arm-kernel, linux-gpio
In-Reply-To: <20260317184507.523060-8-l.scorcia@gmail.com>
On Wed, Mar 18, 2026 at 2:46 AM Luca Leonardo Scorcia
<l.scorcia@gmail.com> wrote:
>
> From: Fabien Parent <parent.f@gmail.com>
>
> The MT6392 is a regulator found on boards based on the MediaTek
> MT8167, MT8516, and probably other SoCs. It is a so called PMIC and
> connects as a slave to a SoC using SPI, wrapped inside PWRAP.
>
> Signed-off-by: Fabien Parent <parent.f@gmail.com>
> Co-developed-by: Val Packett <val@packett.cool>
> Signed-off-by: Val Packett <val@packett.cool>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
> ---
> drivers/regulator/Kconfig | 9 +
> drivers/regulator/Makefile | 1 +
> drivers/regulator/mt6392-regulator.c | 487 +++++++++++++++++++++
> include/linux/regulator/mt6392-regulator.h | 40 ++
> 4 files changed, 537 insertions(+)
> create mode 100644 drivers/regulator/mt6392-regulator.c
> create mode 100644 include/linux/regulator/mt6392-regulator.h
>
> diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
> index d2335276cce5..66876d730807 100644
> --- a/drivers/regulator/Kconfig
> +++ b/drivers/regulator/Kconfig
> @@ -991,6 +991,15 @@ config REGULATOR_MT6380
> This driver supports the control of different power rails of device
> through regulator interface.
>
> +config REGULATOR_MT6392
> + tristate "MediaTek MT6392 PMIC"
> + depends on MFD_MT6397
> + help
> + Say y here to select this option to enable the power regulator of
> + MediaTek MT6392 PMIC.
> + This driver supports the control of different power rails of device
> + through regulator interface.
> +
> config REGULATOR_MT6397
> tristate "MediaTek MT6397 PMIC"
> depends on MFD_MT6397
> diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
> index 1beba1493241..db5145cfcf36 100644
> --- a/drivers/regulator/Makefile
> +++ b/drivers/regulator/Makefile
> @@ -117,6 +117,7 @@ obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
> obj-$(CONFIG_REGULATOR_MT6363) += mt6363-regulator.o
> obj-$(CONFIG_REGULATOR_MT6370) += mt6370-regulator.o
> obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
> +obj-$(CONFIG_REGULATOR_MT6392) += mt6392-regulator.o
> obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
> obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
> obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o
> diff --git a/drivers/regulator/mt6392-regulator.c b/drivers/regulator/mt6392-regulator.c
> new file mode 100644
> index 000000000000..50cc0019f48a
> --- /dev/null
> +++ b/drivers/regulator/mt6392-regulator.c
> @@ -0,0 +1,487 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Copyright (c) 2020 MediaTek Inc.
> +// Copyright (c) 2020 BayLibre, SAS.
> +// Author: Chen Zhong <chen.zhong@mediatek.com>
> +// Author: Fabien Parent <fparent@baylibre.com>
> +//
> +// Based on mt6397-regulator.c
> +
> +#include <linux/module.h>
> +#include <linux/linear_range.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/mt6397/core.h>
> +#include <linux/mfd/mt6392/registers.h>
> +#include <linux/regulator/driver.h>
> +#include <linux/regulator/machine.h>
> +#include <linux/regulator/mt6392-regulator.h>
> +#include <linux/regulator/of_regulator.h>
> +#include <dt-bindings/regulator/mediatek,mt6392-regulator.h>
> +
> +/*
> + * MT6392 regulators' information
> + *
> + * @desc: standard fields of regulator description.
> + * @qi: Mask for query enable signal status of regulators
> + * @vselon_reg: Register sections for hardware control mode of bucks
> + * @vselctrl_reg: Register for controlling the buck control mode.
> + * @vselctrl_mask: Mask for query buck's voltage control mode.
> + */
> +struct mt6392_regulator_info {
> + struct regulator_desc desc;
> + u32 qi;
> + u32 vselon_reg;
> + u32 vselctrl_reg;
> + u32 vselctrl_mask;
> + u32 modeset_reg;
> + u32 modeset_mask;
> +};
> +
> +#define MT6392_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
> + vosel, vosel_mask, voselon, vosel_ctrl, \
> + _modeset_reg, _modeset_mask, rampdelay) \
> +[MT6392_ID_##vreg] = { \
> + .desc = { \
> + .name = #vreg, \
> + .of_match = of_match_ptr(match), \
> + .ops = &mt6392_volt_range_ops, \
> + .type = REGULATOR_VOLTAGE, \
> + .id = MT6392_ID_##vreg, \
> + .owner = THIS_MODULE, \
> + .n_voltages = ((max) - (min)) / (step) + 1, \
> + .linear_ranges = volt_ranges, \
> + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
> + .vsel_reg = vosel, \
> + .vsel_mask = vosel_mask, \
> + .enable_reg = enreg, \
> + .enable_mask = BIT(0), \
> + .ramp_delay = rampdelay, \
Please add the supply names.
> + }, \
> + .qi = BIT(13), \
> + .vselon_reg = voselon, \
> + .vselctrl_reg = vosel_ctrl, \
> + .vselctrl_mask = BIT(1), \
> + .modeset_reg = _modeset_reg, \
> + .modeset_mask = _modeset_mask, \
> +}
> +
> +#define MT6392_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
> + vosel_mask, _modeset_reg, _modeset_mask, entime) \
> +[MT6392_ID_##vreg] = { \
> + .desc = { \
> + .name = #vreg, \
> + .of_match = of_match_ptr(match), \
> + .ops = &mt6392_volt_table_ops, \
> + .type = REGULATOR_VOLTAGE, \
> + .id = MT6392_ID_##vreg, \
> + .owner = THIS_MODULE, \
> + .n_voltages = ARRAY_SIZE(ldo_volt_table), \
> + .volt_table = ldo_volt_table, \
> + .vsel_reg = vosel, \
> + .vsel_mask = vosel_mask, \
> + .enable_reg = enreg, \
> + .enable_mask = BIT(enbit), \
> + .enable_time = entime, \
> + }, \
> + .qi = BIT(15), \
> + .modeset_reg = _modeset_reg, \
> + .modeset_mask = _modeset_mask, \
> +}
> +
> +#define MT6392_LDO_LINEAR(match, vreg, min, max, step, volt_ranges, \
> + enreg, enbit, vosel, vosel_mask, _modeset_reg, \
> + _modeset_mask, entime) \
> +[MT6392_ID_##vreg] = { \
> + .desc = { \
> + .name = #vreg, \
> + .of_match = of_match_ptr(match), \
> + .ops = &mt6392_volt_ldo_range_ops, \
> + .type = REGULATOR_VOLTAGE, \
> + .id = MT6392_ID_##vreg, \
> + .owner = THIS_MODULE, \
> + .n_voltages = ((max) - (min)) / (step) + 1, \
> + .linear_ranges = volt_ranges, \
> + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
> + .vsel_reg = vosel, \
> + .vsel_mask = vosel_mask, \
> + .enable_reg = enreg, \
> + .enable_mask = BIT(enbit), \
> + .enable_time = entime, \
> + }, \
> + .qi = BIT(15), \
> + .modeset_reg = _modeset_reg, \
> + .modeset_mask = _modeset_mask, \
> +}
> +
> +#define MT6392_REG_FIXED(match, vreg, enreg, enbit, volt, \
> + _modeset_reg, _modeset_mask, entime) \
> +[MT6392_ID_##vreg] = { \
> + .desc = { \
> + .name = #vreg, \
> + .of_match = of_match_ptr(match), \
> + .ops = &mt6392_volt_fixed_ops, \
> + .type = REGULATOR_VOLTAGE, \
> + .id = MT6392_ID_##vreg, \
> + .owner = THIS_MODULE, \
> + .n_voltages = 1, \
> + .enable_reg = enreg, \
> + .enable_mask = BIT(enbit), \
> + .enable_time = entime, \
> + .min_uV = volt, \
> + }, \
> + .qi = BIT(15), \
> + .modeset_reg = _modeset_reg, \
> + .modeset_mask = _modeset_mask, \
> +}
> +
> +#define MT6392_REG_FIXED_NO_MODE(match, vreg, enreg, enbit, volt, \
> + entime) \
> +[MT6392_ID_##vreg] = { \
> + .desc = { \
> + .name = #vreg, \
> + .of_match = of_match_ptr(match), \
> + .ops = &mt6392_volt_fixed_no_mode_ops, \
> + .type = REGULATOR_VOLTAGE, \
> + .id = MT6392_ID_##vreg, \
> + .owner = THIS_MODULE, \
> + .n_voltages = 1, \
> + .enable_reg = enreg, \
> + .enable_mask = BIT(enbit), \
> + .enable_time = entime, \
> + .min_uV = volt, \
> + }, \
> + .qi = BIT(15), \
> +}
> +
> +static const struct linear_range buck_volt_range1[] = {
> + REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
> +};
> +
> +static const struct linear_range buck_volt_range2[] = {
> + REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
> +};
> +
> +static const u32 ldo_volt_table1[] = {
> + 1800000, 1900000, 2000000, 2200000,
> +};
> +
> +static const struct linear_range ldo_volt_range2[] = {
> + REGULATOR_LINEAR_RANGE(3300000, 0, 3, 100000),
> +};
> +
> +static const u32 ldo_volt_table3[] = {
> + 1800000, 3300000,
> +};
> +
> +static const u32 ldo_volt_table4[] = {
> + 3000000, 3300000,
> +};
> +
> +static const u32 ldo_volt_table5[] = {
> + 1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000, 3300000,
> +};
> +
> +static const u32 ldo_volt_table6[] = {
> + 1240000, 1390000,
> +};
> +
> +static const u32 ldo_volt_table7[] = {
> + 1200000, 1300000, 1500000, 1800000,
> +};
> +
> +static const u32 ldo_volt_table8[] = {
> + 1800000, 2000000,
> +};
If this PMIC is anything like the MT6358, then it has 0.01V fine
tuning for most if not all the LDOs. It is sometimes needed as
a rail may have a 0.04V boost that would otherwise be invisible
to the system. And then if you have something like 3.04V set in
the DT constraints, you end up with something the regulator driver
doesn't support, but the hardware does.
Please see how it's done in the MT6358 driver. I spent a lot of
time on that driver to make it actually support the full range
of voltages, and describing the supplies.
ChenYu
^ permalink raw reply
* Re: [PATCH v3 3/9] dt-bindings: regulator: Document MediaTek MT6392 PMIC Regulators
From: Chen-Yu Tsai @ 2026-03-19 4:56 UTC (permalink / raw)
To: Luca Leonardo Scorcia
Cc: linux-mediatek, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Sen Chu, Sean Wang, Macpaul Lin, Lee Jones,
Matthias Brugger, AngeloGioacchino Del Regno, Linus Walleij,
Liam Girdwood, Mark Brown, Julien Massot, Gary Bisson,
Louis-Alexis Eyraud, Val Packett, Fabien Parent, Chen Zhong,
linux-input, devicetree, linux-kernel, linux-pm, linux-arm-kernel,
linux-gpio
In-Reply-To: <20260317184507.523060-4-l.scorcia@gmail.com>
On Wed, Mar 18, 2026 at 2:46 AM Luca Leonardo Scorcia
<l.scorcia@gmail.com> wrote:
>
> Add bindings for the regulators found in the MediaTek MT6392 PMIC,
> usually found in board designs using the MediaTek MT8516/MT8167 SoCs.
>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
> ---
> .../regulator/mediatek,mt6392-regulator.yaml | 318 ++++++++++++++++++
> .../regulator/mediatek,mt6392-regulator.h | 24 ++
> 2 files changed, 342 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6392-regulator.yaml
> create mode 100644 include/dt-bindings/regulator/mediatek,mt6392-regulator.h
>
> diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6392-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6392-regulator.yaml
> new file mode 100644
> index 000000000000..fa4aad2dcbe8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6392-regulator.yaml
> @@ -0,0 +1,318 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/regulator/mediatek,mt6392-regulator.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek MT6392 Regulator
> +
> +description:
> + Regulator node of the PMIC. This node should under the PMIC's device node.
> + All voltage regulators provided by the PMIC are described as sub-nodes of
> + this node.
> +
> +properties:
> + compatible:
> + items:
> + - const: mediatek,mt6392-regulator
Please add the various supply rails. This allows you to properly describe
regulator dependencies and have a complete power supply tree.
They can be found in the datasheet.
ChenYu
^ permalink raw reply
* Re: [PATCH v3 3/9] dt-bindings: regulator: Document MediaTek MT6392 PMIC Regulators
From: Chen-Yu Tsai @ 2026-03-19 4:53 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Luca Leonardo Scorcia, linux-mediatek, Dmitry Torokhov,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sen Chu,
Sean Wang, Macpaul Lin, Lee Jones, Matthias Brugger,
AngeloGioacchino Del Regno, Linus Walleij, Liam Girdwood,
Mark Brown, Julien Massot, Gary Bisson, Louis-Alexis Eyraud,
Val Packett, Fabien Parent, Chen Zhong, linux-input, devicetree,
linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <ad0d1ea1-4c5d-4cfc-af0d-8d843e7e0e9e@kernel.org>
On Thu, Mar 19, 2026 at 6:14 AM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On 18/03/2026 22:25, Luca Leonardo Scorcia wrote:
> >>
> >> Drop compatible. Regulator nodes do not have compatibles.
> >
> > Thanks for this comment. It took me a while to understand what you
> > meant as most of the MediaTek PMIC regulator drivers still require the
> > compatible node to probe, including MT6397 that was the template for
> > this patch. I compared the driver to MT6359 that does not use it and I
> > am now working on the driver to not rely on it.
> >
> >> With this, you can also drop example as it won't be used.
> >
> > Just to be sure - do you mean remove the compatible attribute from the
> > example, or the whole example section?
>
> The entire example because without the compatible it will be no-op.
>
> >
> >>> +
> >>> +patternProperties:
> >>> + "^(buck_)?v(core|proc|sys)$":
> >>
> >> Nope, underscores are not allowed. Use only hyphens.
> >
> > Got it. I will actually completely remove the (buck_|ldo_) prefix
> > altogether as suggested in another comment.
> >
> >>> + "^(ldo_)?v(adc18|camio|cn18|io18)$":
> >>> + description: LDOs with fixed 1.8V output
> >>
> >> If fixed, then encode it in the schema - min/max microvolt.
> >
> > If possible I'd like some clarification here. According to Chen-Yu
> > Tsai comment [1], dtsi shouldn't contain voltage constraints. The way
>
> That's odd, because long time in the past I heard that DTS must
> absolutely set min/max constraints, because these are real hardware
> (board) constraints for each regulator, unlike the generic and broad
> ones from the driver.
>
> IOW, driver has what datasheet tells. DTS has what actually should be used.
>
> Also, I did not actually require to make min/max required, just they
> have to be specific/constrained.
>
> > I understood this is that electrical constraints are a matter of the
> > actual board layout, so if adjustments are needed they have to be in
> > the board dts. But you also specify "If fixed", so maybe there's an
> > exception to this rule when the constraint is "absolute" and boards
> > can't actually set a different value?
>
> Now I am confused. You wrote - LDOs with fixed 1.8V output - so board
> cannot set it to 2.0V for example. They are affixed. This regulator
> CANNOT physically produce anything else.
As you said, it cannot physically produce anything else. IMO it doesn't
even need voltage constraints as it is already implied by the model and
regulator output, in which case I would actually recommend rejecting
min/max voltage being added to this node.
ChenYu
^ permalink raw reply
* Re: [PATCH 6/7] soc: qcom: pd-mapper: Convert to of_machine_get_match()
From: Bjorn Andersson @ 2026-03-19 3:36 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Bartosz Golaszewski, Rob Herring, Saravana Kannan,
Rafael J . Wysocki, Viresh Kumar, Ilia Lin, Konrad Dybcio,
Magnus Damm, devicetree, linux-pm, linux-arm-msm,
linux-renesas-soc, linux-kernel
In-Reply-To: <0d23a449e62ac85f04ff07bc2758efbaa709c9d1.1772468323.git.geert+renesas@glider.be>
On Mon, Mar 02, 2026 at 05:29:10PM +0100, Geert Uytterhoeven wrote:
> Use the of_machine_get_match() helper instead of open-coding the same
> operation.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Bjorn Andersson <andersson@kernel.org>
Regards,
Bjorn
> ---
> Compile-tested only.
> ---
> drivers/soc/qcom/qcom_pd_mapper.c | 8 +-------
> 1 file changed, 1 insertion(+), 7 deletions(-)
>
> diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
> index dc10bc859ff4170c..8a1a18f8c859496f 100644
> --- a/drivers/soc/qcom/qcom_pd_mapper.c
> +++ b/drivers/soc/qcom/qcom_pd_mapper.c
> @@ -615,15 +615,9 @@ static struct qcom_pdm_data *qcom_pdm_start(void)
> const struct qcom_pdm_domain_data * const *domains;
> const struct of_device_id *match;
> struct qcom_pdm_data *data;
> - struct device_node *root;
> int ret, i;
>
> - root = of_find_node_by_path("/");
> - if (!root)
> - return ERR_PTR(-ENODEV);
> -
> - match = of_match_node(qcom_pdm_domains, root);
> - of_node_put(root);
> + match = of_machine_get_match(qcom_pdm_domains);
> if (!match) {
> pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
> return ERR_PTR(-ENODEV);
> --
> 2.43.0
>
^ permalink raw reply
* [PATCH v7 7/7] dax/hmem: Reintroduce Soft Reserved ranges back into the iomem tree
From: Smita Koralahalli @ 2026-03-19 1:15 UTC (permalink / raw)
To: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm
Cc: Ard Biesheuvel, Alison Schofield, Vishal Verma, Ira Weiny,
Dan Williams, Jonathan Cameron, Yazen Ghannam, Dave Jiang,
Davidlohr Bueso, Matthew Wilcox, Jan Kara, Rafael J . Wysocki,
Len Brown, Pavel Machek, Li Ming, Jeff Johnson, Ying Huang,
Yao Xingtao, Peter Zijlstra, Greg Kroah-Hartman, Nathan Fontenot,
Terry Bowman, Robert Richter, Benjamin Cheatham, Zhijian Li,
Borislav Petkov, Smita Koralahalli, Tomasz Wolski
In-Reply-To: <20260319011500.241426-1-Smita.KoralahalliChannabasappa@amd.com>
Reworked from a patch by Alison Schofield <alison.schofield@intel.com>
Reintroduce Soft Reserved range into the iomem_resource tree for HMEM
to consume.
This restores visibility in /proc/iomem for ranges actively in use, while
avoiding the early-boot conflicts that occurred when Soft Reserved was
published into iomem before CXL window and region discovery.
Link: https://lore.kernel.org/linux-cxl/29312c0765224ae76862d59a17748c8188fb95f1.1692638817.git.alison.schofield@intel.com/
Co-developed-by: Alison Schofield <alison.schofield@intel.com>
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
Co-developed-by: Zhijian Li <lizhijian@fujitsu.com>
Signed-off-by: Zhijian Li <lizhijian@fujitsu.com>
Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/dax/hmem/hmem.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c
index 8c574123bd3b..15e462589b92 100644
--- a/drivers/dax/hmem/hmem.c
+++ b/drivers/dax/hmem/hmem.c
@@ -72,6 +72,34 @@ void dax_hmem_flush_work(void)
}
EXPORT_SYMBOL_GPL(dax_hmem_flush_work);
+static void remove_soft_reserved(void *r)
+{
+ remove_resource(r);
+ kfree(r);
+}
+
+static int add_soft_reserve_into_iomem(struct device *host,
+ const struct resource *res)
+{
+ int rc;
+
+ struct resource *soft __free(kfree) =
+ kmalloc(sizeof(*res), GFP_KERNEL);
+ if (!soft)
+ return -ENOMEM;
+
+ *soft = DEFINE_RES_NAMED_DESC(res->start, (res->end - res->start + 1),
+ "Soft Reserved", IORESOURCE_MEM,
+ IORES_DESC_SOFT_RESERVED);
+
+ rc = insert_resource(&iomem_resource, soft);
+ if (rc)
+ return rc;
+
+ return devm_add_action_or_reset(host, remove_soft_reserved,
+ no_free_ptr(soft));
+}
+
static int hmem_register_device(struct device *host, int target_nid,
const struct resource *res)
{
@@ -94,7 +122,9 @@ static int hmem_register_device(struct device *host, int target_nid,
if (rc != REGION_INTERSECTS)
return 0;
- /* TODO: Add Soft-Reserved memory back to iomem */
+ rc = add_soft_reserve_into_iomem(host, res);
+ if (rc)
+ return rc;
id = memregion_alloc(GFP_KERNEL);
if (id < 0) {
--
2.17.1
^ permalink raw reply related
* [PATCH v7 6/7] dax/hmem, cxl: Defer and resolve Soft Reserved ownership
From: Smita Koralahalli @ 2026-03-19 1:14 UTC (permalink / raw)
To: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm
Cc: Ard Biesheuvel, Alison Schofield, Vishal Verma, Ira Weiny,
Dan Williams, Jonathan Cameron, Yazen Ghannam, Dave Jiang,
Davidlohr Bueso, Matthew Wilcox, Jan Kara, Rafael J . Wysocki,
Len Brown, Pavel Machek, Li Ming, Jeff Johnson, Ying Huang,
Yao Xingtao, Peter Zijlstra, Greg Kroah-Hartman, Nathan Fontenot,
Terry Bowman, Robert Richter, Benjamin Cheatham, Zhijian Li,
Borislav Petkov, Smita Koralahalli, Tomasz Wolski
In-Reply-To: <20260319011500.241426-1-Smita.KoralahalliChannabasappa@amd.com>
The current probe time ownership check for Soft Reserved memory based
solely on CXL window intersection is insufficient. dax_hmem probing is not
always guaranteed to run after CXL enumeration and region assembly, which
can lead to incorrect ownership decisions before the CXL stack has
finished publishing windows and assembling committed regions.
Introduce deferred ownership handling for Soft Reserved ranges that
intersect CXL windows. When such a range is encountered during the
initial dax_hmem probe, schedule deferred work to wait for the CXL stack
to complete enumeration and region assembly before deciding ownership.
Once the deferred work runs, evaluate each Soft Reserved range
individually: if a CXL region fully contains the range, skip it and let
dax_cxl bind. Otherwise, register it with dax_hmem. This per-range
ownership model avoids the need for CXL region teardown and
alloc_dax_region() resource exclusion prevents double claiming.
Introduce a boolean flag dax_hmem_initial_probe to live inside device.c
so it survives module reload. Ensure dax_cxl defers driver registration
until dax_hmem has completed ownership resolution. dax_cxl calls
dax_hmem_flush_work() before cxl_driver_register(), which both waits for
the deferred work to complete and creates a module symbol dependency that
forces dax_hmem.ko to load before dax_cxl.
Co-developed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
---
drivers/dax/bus.h | 7 +++++
drivers/dax/cxl.c | 1 +
drivers/dax/hmem/device.c | 3 ++
drivers/dax/hmem/hmem.c | 66 +++++++++++++++++++++++++++++++++++++--
4 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h
index cbbf64443098..ebbfe2d6da14 100644
--- a/drivers/dax/bus.h
+++ b/drivers/dax/bus.h
@@ -49,6 +49,13 @@ void dax_driver_unregister(struct dax_device_driver *dax_drv);
void kill_dev_dax(struct dev_dax *dev_dax);
bool static_dev_dax(struct dev_dax *dev_dax);
+#if IS_ENABLED(CONFIG_DEV_DAX_HMEM)
+extern bool dax_hmem_initial_probe;
+void dax_hmem_flush_work(void);
+#else
+static inline void dax_hmem_flush_work(void) { }
+#endif
+
#define MODULE_ALIAS_DAX_DEVICE(type) \
MODULE_ALIAS("dax:t" __stringify(type) "*")
#define DAX_DEVICE_MODALIAS_FMT "dax:t%d"
diff --git a/drivers/dax/cxl.c b/drivers/dax/cxl.c
index a2136adfa186..3ab39b77843d 100644
--- a/drivers/dax/cxl.c
+++ b/drivers/dax/cxl.c
@@ -44,6 +44,7 @@ static struct cxl_driver cxl_dax_region_driver = {
static void cxl_dax_region_driver_register(struct work_struct *work)
{
+ dax_hmem_flush_work();
cxl_driver_register(&cxl_dax_region_driver);
}
diff --git a/drivers/dax/hmem/device.c b/drivers/dax/hmem/device.c
index 56e3cbd181b5..991a4bf7d969 100644
--- a/drivers/dax/hmem/device.c
+++ b/drivers/dax/hmem/device.c
@@ -8,6 +8,9 @@
static bool nohmem;
module_param_named(disable, nohmem, bool, 0444);
+bool dax_hmem_initial_probe;
+EXPORT_SYMBOL_GPL(dax_hmem_initial_probe);
+
static bool platform_initialized;
static DEFINE_MUTEX(hmem_resource_lock);
static struct resource hmem_active = {
diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c
index 1e3424358490..8c574123bd3b 100644
--- a/drivers/dax/hmem/hmem.c
+++ b/drivers/dax/hmem/hmem.c
@@ -3,6 +3,7 @@
#include <linux/memregion.h>
#include <linux/module.h>
#include <linux/dax.h>
+#include <cxl/cxl.h>
#include "../bus.h"
static bool region_idle;
@@ -58,6 +59,19 @@ static void release_hmem(void *pdev)
platform_device_unregister(pdev);
}
+struct dax_defer_work {
+ struct platform_device *pdev;
+ struct work_struct work;
+};
+
+static struct dax_defer_work dax_hmem_work;
+
+void dax_hmem_flush_work(void)
+{
+ flush_work(&dax_hmem_work.work);
+}
+EXPORT_SYMBOL_GPL(dax_hmem_flush_work);
+
static int hmem_register_device(struct device *host, int target_nid,
const struct resource *res)
{
@@ -69,8 +83,11 @@ static int hmem_register_device(struct device *host, int target_nid,
if (IS_ENABLED(CONFIG_DEV_DAX_CXL) &&
region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
IORES_DESC_CXL) != REGION_DISJOINT) {
- dev_dbg(host, "deferring range to CXL: %pr\n", res);
- return 0;
+ if (!dax_hmem_initial_probe) {
+ dev_dbg(host, "deferring range to CXL: %pr\n", res);
+ queue_work(system_long_wq, &dax_hmem_work.work);
+ return 0;
+ }
}
rc = region_intersects_soft_reserve(res->start, resource_size(res));
@@ -123,8 +140,48 @@ static int hmem_register_device(struct device *host, int target_nid,
return rc;
}
+static int hmem_register_cxl_device(struct device *host, int target_nid,
+ const struct resource *res)
+{
+ if (region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
+ IORES_DESC_CXL) == REGION_DISJOINT)
+ return 0;
+
+ if (cxl_region_contains_resource((struct resource *)res)) {
+ dev_dbg(host, "CXL claims resource, dropping: %pr\n", res);
+ return 0;
+ }
+
+ dev_dbg(host, "CXL did not claim resource, registering: %pr\n", res);
+ return hmem_register_device(host, target_nid, res);
+}
+
+static void process_defer_work(struct work_struct *w)
+{
+ struct dax_defer_work *work = container_of(w, typeof(*work), work);
+ struct platform_device *pdev = work->pdev;
+
+ wait_for_device_probe();
+
+ guard(device)(&pdev->dev);
+ if (!pdev->dev.driver)
+ return;
+
+ dax_hmem_initial_probe = true;
+ walk_hmem_resources(&pdev->dev, hmem_register_cxl_device);
+}
+
static int dax_hmem_platform_probe(struct platform_device *pdev)
{
+ if (work_pending(&dax_hmem_work.work))
+ return -EBUSY;
+
+ if (!dax_hmem_work.pdev) {
+ get_device(&pdev->dev);
+ dax_hmem_work.pdev = pdev;
+ INIT_WORK(&dax_hmem_work.work, process_defer_work);
+ }
+
return walk_hmem_resources(&pdev->dev, hmem_register_device);
}
@@ -162,6 +219,11 @@ static __init int dax_hmem_init(void)
static __exit void dax_hmem_exit(void)
{
+ flush_work(&dax_hmem_work.work);
+
+ if (dax_hmem_work.pdev)
+ put_device(&dax_hmem_work.pdev->dev);
+
platform_driver_unregister(&dax_hmem_driver);
platform_driver_unregister(&dax_hmem_platform_driver);
}
--
2.17.1
^ permalink raw reply related
* [PATCH v7 5/7] cxl/region: Add helper to check Soft Reserved containment by CXL regions
From: Smita Koralahalli @ 2026-03-19 1:14 UTC (permalink / raw)
To: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm
Cc: Ard Biesheuvel, Alison Schofield, Vishal Verma, Ira Weiny,
Dan Williams, Jonathan Cameron, Yazen Ghannam, Dave Jiang,
Davidlohr Bueso, Matthew Wilcox, Jan Kara, Rafael J . Wysocki,
Len Brown, Pavel Machek, Li Ming, Jeff Johnson, Ying Huang,
Yao Xingtao, Peter Zijlstra, Greg Kroah-Hartman, Nathan Fontenot,
Terry Bowman, Robert Richter, Benjamin Cheatham, Zhijian Li,
Borislav Petkov, Smita Koralahalli, Tomasz Wolski
In-Reply-To: <20260319011500.241426-1-Smita.KoralahalliChannabasappa@amd.com>
Add a helper to determine whether a given Soft Reserved memory range is
fully contained within the committed CXL region.
This helper provides a primitive for policy decisions in subsequent
patches such as co-ordination with dax_hmem to determine whether CXL has
fully claimed ownership of Soft Reserved memory ranges.
Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/cxl/core/region.c | 30 ++++++++++++++++++++++++++++++
include/cxl/cxl.h | 15 +++++++++++++++
2 files changed, 45 insertions(+)
create mode 100644 include/cxl/cxl.h
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 42874948b589..f7b20f60ac5c 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -12,6 +12,7 @@
#include <linux/idr.h>
#include <linux/memory-tiers.h>
#include <linux/string_choices.h>
+#include <cxl/cxl.h>
#include <cxlmem.h>
#include <cxl.h>
#include "core.h"
@@ -4173,6 +4174,35 @@ static int cxl_region_setup_poison(struct cxl_region *cxlr)
return devm_add_action_or_reset(dev, remove_debugfs, dentry);
}
+static int region_contains_resource(struct device *dev, void *data)
+{
+ struct resource *res = data;
+ struct cxl_region *cxlr;
+ struct cxl_region_params *p;
+
+ if (!is_cxl_region(dev))
+ return 0;
+
+ cxlr = to_cxl_region(dev);
+ p = &cxlr->params;
+
+ if (p->state != CXL_CONFIG_COMMIT)
+ return 0;
+
+ if (!p->res)
+ return 0;
+
+ return resource_contains(p->res, res) ? 1 : 0;
+}
+
+bool cxl_region_contains_resource(struct resource *res)
+{
+ guard(rwsem_read)(&cxl_rwsem.region);
+ return bus_for_each_dev(&cxl_bus_type, NULL, res,
+ region_contains_resource) != 0;
+}
+EXPORT_SYMBOL_GPL(cxl_region_contains_resource);
+
static int cxl_region_can_probe(struct cxl_region *cxlr)
{
struct cxl_region_params *p = &cxlr->params;
diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
new file mode 100644
index 000000000000..b12d3d0f6658
--- /dev/null
+++ b/include/cxl/cxl.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2026 Advanced Micro Devices, Inc. */
+#ifndef _CXL_H_
+#define _CXL_H_
+
+#ifdef CONFIG_CXL_REGION
+bool cxl_region_contains_resource(struct resource *res);
+#else
+static inline bool cxl_region_contains_resource(struct resource *res)
+{
+ return false;
+}
+#endif
+
+#endif /* _CXL_H_ */
--
2.17.1
^ permalink raw reply related
* [PATCH v7 4/7] dax: Track all dax_region allocations under a global resource tree
From: Smita Koralahalli @ 2026-03-19 1:14 UTC (permalink / raw)
To: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm
Cc: Ard Biesheuvel, Alison Schofield, Vishal Verma, Ira Weiny,
Dan Williams, Jonathan Cameron, Yazen Ghannam, Dave Jiang,
Davidlohr Bueso, Matthew Wilcox, Jan Kara, Rafael J . Wysocki,
Len Brown, Pavel Machek, Li Ming, Jeff Johnson, Ying Huang,
Yao Xingtao, Peter Zijlstra, Greg Kroah-Hartman, Nathan Fontenot,
Terry Bowman, Robert Richter, Benjamin Cheatham, Zhijian Li,
Borislav Petkov, Smita Koralahalli, Tomasz Wolski
In-Reply-To: <20260319011500.241426-1-Smita.KoralahalliChannabasappa@amd.com>
Introduce a global "DAX Regions" resource root and register each
dax_region->res under it via request_resource(). Release the resource on
dax_region teardown.
By enforcing a single global namespace for dax_region allocations, this
ensures only one of dax_hmem or dax_cxl can successfully register a
dax_region for a given range.
Suggested-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
---
drivers/dax/bus.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index c94c09622516..448e2bc285c3 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -10,6 +10,7 @@
#include "dax-private.h"
#include "bus.h"
+static struct resource dax_regions = DEFINE_RES_MEM_NAMED(0, -1, "DAX Regions");
static DEFINE_MUTEX(dax_bus_lock);
/*
@@ -625,6 +626,7 @@ static void dax_region_unregister(void *region)
{
struct dax_region *dax_region = region;
+ release_resource(&dax_region->res);
sysfs_remove_groups(&dax_region->dev->kobj,
dax_region_attribute_groups);
dax_region_put(dax_region);
@@ -635,6 +637,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
unsigned long flags)
{
struct dax_region *dax_region;
+ int rc;
/*
* The DAX core assumes that it can store its private data in
@@ -667,14 +670,25 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
.flags = IORESOURCE_MEM | flags,
};
- if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
- kfree(dax_region);
- return NULL;
+ rc = request_resource(&dax_regions, &dax_region->res);
+ if (rc) {
+ dev_dbg(parent, "dax_region resource conflict for %pR\n",
+ &dax_region->res);
+ goto err_res;
}
+ if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups))
+ goto err_sysfs;
+
if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region))
return NULL;
return dax_region;
+
+err_sysfs:
+ release_resource(&dax_region->res);
+err_res:
+ kfree(dax_region);
+ return NULL;
}
EXPORT_SYMBOL_GPL(alloc_dax_region);
--
2.17.1
^ permalink raw reply related
* [PATCH v7 1/7] dax/hmem: Request cxl_acpi and cxl_pci before walking Soft Reserved ranges
From: Smita Koralahalli @ 2026-03-19 1:14 UTC (permalink / raw)
To: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm
Cc: Ard Biesheuvel, Alison Schofield, Vishal Verma, Ira Weiny,
Dan Williams, Jonathan Cameron, Yazen Ghannam, Dave Jiang,
Davidlohr Bueso, Matthew Wilcox, Jan Kara, Rafael J . Wysocki,
Len Brown, Pavel Machek, Li Ming, Jeff Johnson, Ying Huang,
Yao Xingtao, Peter Zijlstra, Greg Kroah-Hartman, Nathan Fontenot,
Terry Bowman, Robert Richter, Benjamin Cheatham, Zhijian Li,
Borislav Petkov, Smita Koralahalli, Tomasz Wolski
In-Reply-To: <20260319011500.241426-1-Smita.KoralahalliChannabasappa@amd.com>
From: Dan Williams <dan.j.williams@intel.com>
Ensure cxl_acpi has published CXL Window resources before HMEM walks Soft
Reserved ranges.
Replace MODULE_SOFTDEP("pre: cxl_acpi") with an explicit, synchronous
request_module("cxl_acpi"). MODULE_SOFTDEP() only guarantees eventual
loading, it does not enforce that the dependency has finished init
before the current module runs. This can cause HMEM to start before
cxl_acpi has populated the resource tree, breaking detection of overlaps
between Soft Reserved and CXL Windows.
Also, request cxl_pci before HMEM walks Soft Reserved ranges. Unlike
cxl_acpi, cxl_pci attach is asynchronous and creates dependent devices
that trigger further module loads. Asynchronous probe flushing
(wait_for_device_probe()) is added later in the series in a deferred
context before HMEM makes ownership decisions for Soft Reserved ranges.
Add an additional explicit Kconfig ordering so that CXL_ACPI and CXL_PCI
must be initialized before DEV_DAX_HMEM. This prevents HMEM from consuming
Soft Reserved ranges before CXL drivers have had a chance to claim them.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
---
drivers/dax/Kconfig | 2 ++
drivers/dax/hmem/hmem.c | 17 ++++++++++-------
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/dax/Kconfig b/drivers/dax/Kconfig
index d656e4c0eb84..3683bb3f2311 100644
--- a/drivers/dax/Kconfig
+++ b/drivers/dax/Kconfig
@@ -48,6 +48,8 @@ config DEV_DAX_CXL
tristate "CXL DAX: direct access to CXL RAM regions"
depends on CXL_BUS && CXL_REGION && DEV_DAX
default CXL_REGION && DEV_DAX
+ depends on CXL_ACPI >= DEV_DAX_HMEM
+ depends on CXL_PCI >= DEV_DAX_HMEM
help
CXL RAM regions are either mapped by platform-firmware
and published in the initial system-memory map as "System RAM", mapped
diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c
index 1cf7c2a0ee1c..008172fc3607 100644
--- a/drivers/dax/hmem/hmem.c
+++ b/drivers/dax/hmem/hmem.c
@@ -139,6 +139,16 @@ static __init int dax_hmem_init(void)
{
int rc;
+ /*
+ * Ensure that cxl_acpi and cxl_pci have a chance to kick off
+ * CXL topology discovery at least once before scanning the
+ * iomem resource tree for IORES_DESC_CXL resources.
+ */
+ if (IS_ENABLED(CONFIG_DEV_DAX_CXL)) {
+ request_module("cxl_acpi");
+ request_module("cxl_pci");
+ }
+
rc = platform_driver_register(&dax_hmem_platform_driver);
if (rc)
return rc;
@@ -159,13 +169,6 @@ static __exit void dax_hmem_exit(void)
module_init(dax_hmem_init);
module_exit(dax_hmem_exit);
-/* Allow for CXL to define its own dax regions */
-#if IS_ENABLED(CONFIG_CXL_REGION)
-#if IS_MODULE(CONFIG_CXL_ACPI)
-MODULE_SOFTDEP("pre: cxl_acpi");
-#endif
-#endif
-
MODULE_ALIAS("platform:hmem*");
MODULE_ALIAS("platform:hmem_platform*");
MODULE_DESCRIPTION("HMEM DAX: direct access to 'specific purpose' memory");
--
2.17.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox