Linux Power Management development
 help / color / mirror / Atom feed
* Re: [PATCH 4/6] mfd: sprd-sc27xx: Switch to devm_mfd_add_devices()
From: Lee Jones @ 2026-03-25 11:22 UTC (permalink / raw)
  To: Otto Pflüger
  Cc: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Pavel Machek,
	Liam Girdwood, Mark Brown, Sebastian Reichel, linux-rtc,
	devicetree, linux-kernel, linux-leds, linux-pm
In-Reply-To: <ab2i6i2D5q0t0xZ5@abscue.de>

> Could you clarify what should be changed?

Sure.

> On Mon, Mar 09, 2026 at 06:58:56PM +0000, Lee Jones wrote:
> > On Sun, 22 Feb 2026, Otto Pflüger wrote:
> > 
> > > To allow instantiating subdevices such as the regulator and poweroff
> > > devices that do not have corresponding device tree nodes with a
> > > "compatible" property, use devm_mfd_add_devices() with MFD cells instead
> > > of devm_of_platform_populate(). Since different PMICs in the SC27xx
> > > series contain different components, use separate MFD cell tables for
> > > each PMIC model. Define cells for all components that have upstream
> > > drivers at this point.
> > 
> > We're not passing one device registration API's data (MFD)
> > through another (Device Tree).
> > 
> > Pass an identifier through and match on that instead.
> > 
> > Look at how all of the other drivers in MFD do it.
> >
> > [...]
> > > +static const struct mfd_cell sc2730_devices[] = {
> > > +	MFD_CELL_OF("sc2730-adc", NULL, NULL, 0, 0, "sprd,sc2730-adc"),
> > > +	MFD_CELL_OF("sc2730-bltc", NULL, NULL, 0, 0, "sprd,sc2730-bltc"),
> > > +	MFD_CELL_OF("sc2730-efuse", NULL, NULL, 0, 0, "sprd,sc2730-efuse"),
> > > +	MFD_CELL_OF("sc2730-eic", NULL, NULL, 0, 0, "sprd,sc2730-eic"),
> > > +	MFD_CELL_OF("sc2730-fgu", NULL, NULL, 0, 0, "sprd,sc2730-fgu"),
> > > +	MFD_CELL_OF("sc2730-rtc", NULL, NULL, 0, 0, "sprd,sc2730-rtc"),
> > > +	MFD_CELL_OF("sc2730-vibrator", NULL, NULL, 0, 0, "sprd,sc2730-vibrator"),
> > > +};
> > > +
> > > +static const struct mfd_cell sc2731_devices[] = {
> > > +	MFD_CELL_OF("sc2731-adc", NULL, NULL, 0, 0, "sprd,sc2731-adc"),
> > > +	MFD_CELL_OF("sc2731-bltc", NULL, NULL, 0, 0, "sprd,sc2731-bltc"),
> > > +	MFD_CELL_OF("sc2731-charger", NULL, NULL, 0, 0, "sprd,sc2731-charger"),
> > > +	MFD_CELL_OF("sc2731-efuse", NULL, NULL, 0, 0, "sprd,sc2731-efuse"),
> > > +	MFD_CELL_OF("sc2731-eic", NULL, NULL, 0, 0, "sprd,sc2731-eic"),
> > > +	MFD_CELL_OF("sc2731-fgu", NULL, NULL, 0, 0, "sprd,sc2731-fgu"),
> > > +	MFD_CELL_NAME("sc2731-poweroff"),
> > > +	MFD_CELL_NAME("sc2731-regulator"),
> > > +	MFD_CELL_OF("sc2731-rtc", NULL, NULL, 0, 0, "sprd,sc2731-rtc"),
> > > +	MFD_CELL_OF("sc2731-vibrator", NULL, NULL, 0, 0, "sprd,sc2731-vibrator"),
> > >  };
> 
> Assuming that these tables are the "registration API's data", I don't
> see where it is being passed through the device tree. The device tree
> contains nodes for some of these MFD components, and I've listed their
> compatibles here so that the MFD core finds these nodes and registers
> them with the corresponding devices (which was previously done
> automatically by devm_of_platform_populate).
> 
> > >  
> > >  /*
> > > @@ -59,12 +84,16 @@ static const struct sprd_pmic_data sc2730_data = {
> > >  	.irq_base = SPRD_SC2730_IRQ_BASE,
> > >  	.num_irqs = SPRD_SC2730_IRQ_NUMS,
> > >  	.charger_det = SPRD_SC2730_CHG_DET,
> > > +	.cells = sc2730_devices,
> > > +	.num_cells = ARRAY_SIZE(sc2730_devices),

Remove these from here.

Either replace them with an ID that you can match on or stop passing
'sc2730_data' through .data and pass an ID through there instead.  Then
choose 'sc2730_data' and 'sc2730_devices' in an switch() statement
instead, just like the vast majority of existing MFD drivers do.

> > >  };
> > >  
> > >  static const struct sprd_pmic_data sc2731_data = {
> > >  	.irq_base = SPRD_SC2731_IRQ_BASE,
> > >  	.num_irqs = SPRD_SC2731_IRQ_NUMS,
> > >  	.charger_det = SPRD_SC2731_CHG_DET,
> > > +	.cells = sc2731_devices,
> > > +	.num_cells = ARRAY_SIZE(sc2731_devices),
> > >  };
> 
> Here I am simply referencing the tables above in the device-specific
> MFD data. These structs containing device-specific data already exist,
> they are private to the MFD driver, and I wouldn't consider them part
> of the device tree.
> 
> I've looked at mt6397-core.c and it seems to be doing the exact same
> thing with its "struct chip_data".

That was a momentary oversight.  It's also passing a driver-level
call-back which I despise.  However, past mistakes are not good
justifications for new ones.

> Some other drivers use a numeric ID
> for this purpose, but how would that be different from a pointer as long
> as it identifies the same data within the MFD driver?

The point is that sc2731_data->cells would be passed through the Device
Tree's .data attribute, which is not allowed.

-- 
Lee Jones [李琼斯]

^ permalink raw reply

* Re: [PATCH 3/9] interconnect: qcom: drop unused is_on flag
From: Konrad Dybcio @ 2026-03-25 11:01 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Georgi Djakov, Konrad Dybcio, Bjorn Andersson, Luca Weiss,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Brian Masney,
	linux-arm-msm, linux-pm, devicetree, linux-kernel
In-Reply-To: <ky6o64toksq4ozbbad4i7mrmrqjkq5ffphrwdruejq6godxco5@ds2een4mht2v>

On 3/24/26 12:12 AM, Dmitry Baryshkov wrote:
> On Mon, Mar 23, 2026 at 11:26:47AM +0100, Konrad Dybcio wrote:
>> On 3/23/26 2:17 AM, Dmitry Baryshkov wrote:
>>> The commit 2e2113c8a64f ("interconnect: qcom: rpm: Handle interface
>>> clocks") has added the is_on flag to the qcom_icc_provider, but failed
>>> to actually utilize it. Drop the flag.
>>>
>>> Fixes: 2e2113c8a64f ("interconnect: qcom: rpm: Handle interface clocks")
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
>>> ---
>>>  drivers/interconnect/qcom/icc-rpm.h | 2 --
>>>  1 file changed, 2 deletions(-)
>>>
>>> diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
>>> index f4883d43eae4..3366531f66fc 100644
>>> --- a/drivers/interconnect/qcom/icc-rpm.h
>>> +++ b/drivers/interconnect/qcom/icc-rpm.h
>>> @@ -51,7 +51,6 @@ struct rpm_clk_resource {
>>>   * @bus_clk: a pointer to a HLOS-owned bus clock
>>>   * @intf_clks: a clk_bulk_data array of interface clocks
>>>   * @keep_alive: whether to always keep a minimum vote on the bus clocks
>>> - * @is_on: whether the bus is powered on
>>>   */
>>>  struct qcom_icc_provider {
>>>  	struct icc_provider provider;
>>> @@ -66,7 +65,6 @@ struct qcom_icc_provider {
>>>  	struct clk *bus_clk;
>>>  	struct clk_bulk_data *intf_clks;
>>>  	bool keep_alive;
>>> -	bool is_on;
>>
>> Hm, looks like the clock vote is kept all the way from .probe()
>> to .remove(). I wonder if that's really what should happen..
> 
> Well, it's probably up to you to decide. I've a bit lost my way in the
> vendor's adhoc / bus / etc. code.
> 
>>
>> That's what drivers/interconnect/qcom/holi.c does on msm-5.10
>>
>> Maybe "iface clocks" are only needed to execute a ->set() on a node?
> 
> Hmm, I don't know. AXI clocks seems to describe the clocking between the
> NoC and a particular device. So maybe it's required for as long as there
> is something using the NoC.

I'll keep this on my infinite todolist

Konrad

^ permalink raw reply

* Re: [PATCH v2 6/9] interconnect: qcom: let platforms declare their bugginess
From: Konrad Dybcio @ 2026-03-25 10:52 UTC (permalink / raw)
  To: Luca Weiss, Dmitry Baryshkov, Georgi Djakov, Konrad Dybcio,
	Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Brian Masney
  Cc: linux-arm-msm, linux-pm, devicetree, linux-kernel, Brian Masney
In-Reply-To: <DHB05UJMTAVN.17X2QI6XGHB37@fairphone.com>

On 3/24/26 1:14 PM, Luca Weiss wrote:
> On Tue Mar 24, 2026 at 1:10 AM CET, Dmitry Baryshkov wrote:
>> On MSM8974 programming some of the RPM resources results in the
>> "resource does not exist" messages from the firmware. This occurs even
>> with the downstream bus driver, which happily ignores the errors. My
>> assumption is that these resources existed in the earlier firmware
>> revisions but were later switched to be programmed differently (for the
>> later platforms corresponding nodes use qos.ap_owned, which prevents
>> those resources from being programmed.
>>
>> In preparation for conversion of the MSM8974 driver (which doesn't have
>> QoS code yet) to the main icc-rpm set of helpers, let the driver declare
>> that those -ENXIO errors must be ignored (for now). Later, when the QoS
>> programming is sorted out (and more interconnects are added to the DT),
>> this quirk might be removed.
> 
> For reference, these are the errors I see on fairphone-fp2
> 
> [    5.534806] qcom_icc_rpm_smd_send mas 8 error -6
> [    5.535010] qcom_icc_rpm_smd_send mas 8 error -6
> [    5.535218] qcom_icc_rpm_smd_send slv 16 error -6
> [    5.535445] qcom_icc_rpm_smd_send slv 16 error -6

I only checked these two, but 8994 (basically largely reused design
thought) sets them as AP owned intentionally

https://android.googlesource.com/kernel/msm/+/android-msm-angler-3.10-nougat/arch/arm/boot/dts/qcom/msm8994-bus.dtsi

so I suppose the fix is to simply denote all of them as such and go on
with our life!

Konrad


^ permalink raw reply

* Re: [PATCH 2/3] pmdomain: core: add support for power-domains-child-ids
From: Ulf Hansson @ 2026-03-25 10:22 UTC (permalink / raw)
  To: Kevin Hilman (TI)
  Cc: Rob Herring, Geert Uytterhoeven, linux-pm, devicetree,
	linux-kernel, arm-scmi, linux-arm-kernel
In-Reply-To: <20260310-topic-lpm-pmdomain-child-ids-v1-2-5361687a18ff@baylibre.com>

On Wed, 11 Mar 2026 at 01:19, Kevin Hilman (TI) <khilman@baylibre.com> wrote:
>
> Currently, PM domains can only support hierarchy for simple
> providers (e.g. ones with #power-domain-cells = 0).
>
> Add support for oncell providers as well by adding a new property
> `power-domains-child-ids` to describe the parent/child relationship.
>
> For example, an SCMI PM domain provider has multiple domains, each of
> which might be a child of diffeent parent domains. In this example,
> the parent domains are MAIN_PD and WKUP_PD:
>
>     scmi_pds: protocol@11 {
>         reg = <0x11>;
>         #power-domain-cells = <1>;
>         power-domains = <&MAIN_PD>, <&WKUP_PD>;
>         power-domains-child-ids = <15>, <19>;
>     };
>
> With this example using the new property, SCMI PM domain 15 becomes a
> child domain of MAIN_PD, and SCMI domain 19 becomes a child domain of
> WKUP_PD.
>
> To support this feature, add two new core functions
>
> - of_genpd_add_child_ids()
> - of_genpd_remove_child_ids()
>
> which can be called by pmdomain providers to add/remove child domains
> if they support the new property power-domains-child-ids.
>
> Signed-off-by: Kevin Hilman (TI) <khilman@baylibre.com>

Thanks for working on this! It certainly is a missing feature!

> ---
>  drivers/pmdomain/core.c   | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_domain.h |  16 ++++++++++++++++
>  2 files changed, 185 insertions(+)
>
> diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
> index 61c2277c9ce3..acb45dd540b7 100644
> --- a/drivers/pmdomain/core.c
> +++ b/drivers/pmdomain/core.c
> @@ -2909,6 +2909,175 @@ static struct generic_pm_domain *genpd_get_from_provider(
>         return genpd;
>  }
>
> +/**
> + * of_genpd_add_child_ids() - Parse power-domains-child-ids property
> + * @np: Device node pointer associated with the PM domain provider.
> + * @data: Pointer to the onecell data associated with the PM domain provider.
> + *
> + * Parse the power-domains and power-domains-child-ids properties to establish
> + * parent-child relationships for PM domains. The power-domains property lists
> + * parent domains, and power-domains-child-ids lists which child domain IDs
> + * should be associated with each parent.
> + *
> + * Returns 0 on success, -ENOENT if properties don't exist, or negative error code.

I think we should avoid returning specific error codes for specific
errors, simply because it usually becomes messy.

If I understand correctly the intent here is to allow the caller to
check for -ENOENT and potentially avoid bailing out as it may not
really be an error, right?

Perhaps a better option is to return the number of children for whom
we successfully assigned parents. Hence 0 or a positive value allows
the caller to understand what happened. More importantly, a negative
error code then really becomes an error for the caller to consider.

> + */
> +int of_genpd_add_child_ids(struct device_node *np,
> +                          struct genpd_onecell_data *data)
> +{
> +       struct of_phandle_args parent_args;
> +       struct generic_pm_domain *parent_genpd, *child_genpd;
> +       struct of_phandle_iterator it;
> +       const struct property *prop;
> +       const __be32 *item;
> +       u32 child_id;
> +       int ret;
> +
> +       /* Check if both properties exist */
> +       if (of_count_phandle_with_args(np, "power-domains", "#power-domain-cells") <= 0)
> +               return -ENOENT;
> +
> +       prop = of_find_property(np, "power-domains-child-ids", NULL);
> +       if (!prop)
> +               return -ENOENT;
> +
> +       item = of_prop_next_u32(prop, NULL, &child_id);

Perhaps it's easier to check if of_property_count_u32_elems() returns
the same number as of_count_phandle_with_args() above? If it doesn't,
something is wrong, and there is no need to continue.

This way you also know the number of loops upfront that must iterate
through all indexes. This should allow us to use a simpler for-loop
below, I think. In this case you can also use
of_property_read_u32_index() instead.

> +
> +       /* Iterate over power-domains phandles and power-domains-child-ids in lockstep */
> +       of_for_each_phandle(&it, ret, np, "power-domains", "#power-domain-cells", 0) {
> +               if (!item) {
> +                       pr_err("power-domains-child-ids shorter than power-domains for %pOF\n", np);
> +                       ret = -EINVAL;
> +                       goto err_put_node;
> +               }
> +
> +               /*
> +                * Fill parent_args from the iterator. it.node is released by
> +                * the next of_phandle_iterator_next() call at the top of the
> +                * loop, or by the of_node_put() on the error path below.
> +                */
> +               parent_args.np = it.node;
> +               parent_args.args_count = of_phandle_iterator_args(&it, parent_args.args,
> +                                                                 MAX_PHANDLE_ARGS);
> +
> +               /* Get the parent domain */
> +               parent_genpd = genpd_get_from_provider(&parent_args);

Before getting the parent_genpd like this, we need to take the
gpd_list_lock. The lock must be held when genpd_add_subdomain() is
being called.

> +               if (IS_ERR(parent_genpd)) {
> +                       pr_err("Failed to get parent domain for %pOF: %ld\n",
> +                              np, PTR_ERR(parent_genpd));
> +                       ret = PTR_ERR(parent_genpd);
> +                       goto err_put_node;
> +               }
> +
> +               /* Validate child ID is within bounds */
> +               if (child_id >= data->num_domains) {
> +                       pr_err("Child ID %u out of bounds (max %u) for %pOF\n",
> +                              child_id, data->num_domains - 1, np);
> +                       ret = -EINVAL;
> +                       goto err_put_node;
> +               }
> +
> +               /* Get the child domain */
> +               child_genpd = data->domains[child_id];
> +               if (!child_genpd) {
> +                       pr_err("Child domain %u is NULL for %pOF\n", child_id, np);
> +                       ret = -EINVAL;
> +                       goto err_put_node;
> +               }
> +
> +               /* Establish parent-child relationship */
> +               ret = genpd_add_subdomain(parent_genpd, child_genpd);
> +               if (ret) {
> +                       pr_err("Failed to add child domain %u to parent in %pOF: %d\n",
> +                              child_id, np, ret);
> +                       goto err_put_node;
> +               }
> +
> +               pr_debug("Added child domain %u (%s) to parent %s for %pOF\n",
> +                        child_id, child_genpd->name, parent_genpd->name, np);
> +
> +               item = of_prop_next_u32(prop, item, &child_id);
> +       }
> +
> +       /* of_for_each_phandle returns -ENOENT at natural end-of-list */
> +       if (ret && ret != -ENOENT)
> +               return ret;
> +
> +       /* All power-domains phandles were consumed; check for trailing child IDs */
> +       if (item) {
> +               pr_err("power-domains-child-ids longer than power-domains for %pOF\n", np);
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +
> +err_put_node:

This isn't a suffient error handling.

If we successfully added child domains using genpd_add_subdomain(), we
must remove them here, by calling pm_genpd_remove_subdomain() in the
reverse order as we just added them.

> +       of_node_put(it.node);
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(of_genpd_add_child_ids);
> +
> +/**
> + * of_genpd_remove_child_ids() - Remove parent-child PM domain relationships
> + * @np: Device node pointer associated with the PM domain provider.
> + * @data: Pointer to the onecell data associated with the PM domain provider.
> + *
> + * Reverses the effect of of_genpd_add_child_ids() by parsing the same
> + * power-domains and power-domains-child-ids properties and calling
> + * pm_genpd_remove_subdomain() for each established relationship.
> + *
> + * Returns 0 on success, -ENOENT if properties don't exist, or negative error
> + * code on failure.
> + */
> +int of_genpd_remove_child_ids(struct device_node *np,
> +                          struct genpd_onecell_data *data)
> +{
> +       struct of_phandle_args parent_args;
> +       struct generic_pm_domain *parent_genpd, *child_genpd;
> +       struct of_phandle_iterator it;
> +       const struct property *prop;
> +       const __be32 *item;
> +       u32 child_id;
> +       int ret;
> +
> +       /* Check if both properties exist */
> +       if (of_count_phandle_with_args(np, "power-domains", "#power-domain-cells") <= 0)
> +               return -ENOENT;
> +
> +       prop = of_find_property(np, "power-domains-child-ids", NULL);
> +       if (!prop)
> +               return -ENOENT;
> +
> +       item = of_prop_next_u32(prop, NULL, &child_id);

Similar comments as for of_genpd_add_child_ids().

Moreover, I think we should remove the children in the reverse order
of how we added them.

> +
> +       of_for_each_phandle(&it, ret, np, "power-domains", "#power-domain-cells", 0) {
> +               if (!item)
> +                       break;
> +
> +               parent_args.np = it.node;
> +               parent_args.args_count = of_phandle_iterator_args(&it, parent_args.args,
> +                                                                 MAX_PHANDLE_ARGS);
> +
> +               if (child_id >= data->num_domains || !data->domains[child_id]) {
> +                       item = of_prop_next_u32(prop, item, &child_id);
> +                       continue;
> +               }
> +
> +               parent_genpd = genpd_get_from_provider(&parent_args);
> +               if (IS_ERR(parent_genpd)) {
> +                       item = of_prop_next_u32(prop, item, &child_id);
> +                       continue;
> +               }
> +
> +               child_genpd = data->domains[child_id];
> +               pm_genpd_remove_subdomain(parent_genpd, child_genpd);
> +
> +               item = of_prop_next_u32(prop, item, &child_id);
> +       }
> +
> +       return (ret == -ENOENT) ? 0 : ret;
> +}
> +EXPORT_SYMBOL_GPL(of_genpd_remove_child_ids);
> +
>  /**
>   * of_genpd_add_device() - Add a device to an I/O PM domain
>   * @genpdspec: OF phandle args to use for look-up PM domain
> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
> index f67a2cb7d781..b44615d79af6 100644
> --- a/include/linux/pm_domain.h
> +++ b/include/linux/pm_domain.h
> @@ -465,6 +465,10 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
>  int of_genpd_parse_idle_states(struct device_node *dn,
>                                struct genpd_power_state **states, int *n);
>  void of_genpd_sync_state(struct device_node *np);
> +int of_genpd_add_child_ids(struct device_node *np,
> +                          struct genpd_onecell_data *data);
> +int of_genpd_remove_child_ids(struct device_node *np,
> +                             struct genpd_onecell_data *data);
>
>  int genpd_dev_pm_attach(struct device *dev);
>  struct device *genpd_dev_pm_attach_by_id(struct device *dev,
> @@ -534,6 +538,18 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
>  {
>         return ERR_PTR(-EOPNOTSUPP);
>  }
> +
> +static inline int of_genpd_add_child_ids(struct device_node *np,
> +                                        struct genpd_onecell_data *data)
> +{
> +       return -EOPNOTSUPP;
> +}
> +
> +static inline int of_genpd_remove_child_ids(struct device_node *np,
> +                                           struct genpd_onecell_data *data)
> +{
> +       return -EOPNOTSUPP;
> +}
>  #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
>
>  #ifdef CONFIG_PM
>
> --
> 2.51.0
>

Kind regards
Uffe

^ permalink raw reply

* [rafael-pm:fixes] BUILD SUCCESS 4354f16141fb93bdea922285dfbdbe997cdfba15
From: kernel test robot @ 2026-03-25 10:15 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: 4354f16141fb93bdea922285dfbdbe997cdfba15  Merge branch 'thermal-intel-fixes' into fixes

elapsed time: 939m

configs tested: 176
configs skipped: 2

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-20260325    gcc-8.5.0
arc                   randconfig-002-20260325    gcc-8.5.0
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                                 defconfig    gcc-15.2.0
arm                       netwinder_defconfig    gcc-15.2.0
arm                           omap1_defconfig    gcc-15.2.0
arm                   randconfig-001-20260325    gcc-8.5.0
arm                   randconfig-002-20260325    gcc-8.5.0
arm                   randconfig-003-20260325    gcc-8.5.0
arm                   randconfig-004-20260325    gcc-8.5.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260325    clang-23
arm64                 randconfig-002-20260325    clang-23
arm64                 randconfig-003-20260325    clang-23
arm64                 randconfig-004-20260325    clang-23
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260325    clang-23
csky                  randconfig-002-20260325    clang-23
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260325    gcc-11.5.0
hexagon               randconfig-002-20260325    gcc-11.5.0
i386                             allmodconfig    clang-20
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    clang-20
i386        buildonly-randconfig-001-20260325    gcc-14
i386        buildonly-randconfig-002-20260325    gcc-14
i386        buildonly-randconfig-003-20260325    gcc-14
i386        buildonly-randconfig-004-20260325    gcc-14
i386        buildonly-randconfig-005-20260325    gcc-14
i386        buildonly-randconfig-006-20260325    gcc-14
i386                                defconfig    gcc-15.2.0
i386                  randconfig-001-20260325    clang-20
i386                  randconfig-002-20260325    clang-20
i386                  randconfig-003-20260325    clang-20
i386                  randconfig-004-20260325    clang-20
i386                  randconfig-005-20260325    clang-20
i386                  randconfig-006-20260325    clang-20
i386                  randconfig-007-20260325    clang-20
i386                  randconfig-011-20260325    clang-20
i386                  randconfig-012-20260325    clang-20
i386                  randconfig-013-20260325    clang-20
i386                  randconfig-014-20260325    clang-20
i386                  randconfig-015-20260325    clang-20
i386                  randconfig-016-20260325    clang-20
i386                  randconfig-017-20260325    clang-20
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260325    gcc-11.5.0
loongarch             randconfig-002-20260325    gcc-11.5.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                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            allmodconfig    clang-23
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260325    gcc-11.5.0
nios2                 randconfig-002-20260325    gcc-11.5.0
openrisc                         allmodconfig    clang-23
openrisc                         allmodconfig    gcc-15.2.0
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                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260325    clang-23
parisc                randconfig-002-20260325    clang-23
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc               randconfig-001-20260325    clang-23
powerpc               randconfig-002-20260325    clang-23
powerpc                     taishan_defconfig    clang-17
powerpc64             randconfig-001-20260325    clang-23
powerpc64             randconfig-002-20260325    clang-23
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260325    gcc-8.5.0
riscv                 randconfig-002-20260325    gcc-8.5.0
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260325    gcc-8.5.0
s390                  randconfig-002-20260325    gcc-8.5.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260325    gcc-8.5.0
sh                    randconfig-002-20260325    gcc-8.5.0
sparc                             allnoconfig    clang-23
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260325    gcc-13
sparc                 randconfig-002-20260325    gcc-13
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260325    gcc-13
sparc64               randconfig-002-20260325    gcc-13
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-20260325    gcc-13
um                    randconfig-002-20260325    gcc-13
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-20260325    gcc-14
x86_64      buildonly-randconfig-002-20260325    gcc-14
x86_64      buildonly-randconfig-003-20260325    gcc-14
x86_64      buildonly-randconfig-004-20260325    gcc-14
x86_64      buildonly-randconfig-005-20260325    gcc-14
x86_64      buildonly-randconfig-006-20260325    gcc-14
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20260325    gcc-12
x86_64                randconfig-002-20260325    gcc-12
x86_64                randconfig-003-20260325    gcc-12
x86_64                randconfig-004-20260325    gcc-12
x86_64                randconfig-005-20260325    gcc-12
x86_64                randconfig-006-20260325    gcc-12
x86_64                randconfig-011-20260325    clang-20
x86_64                randconfig-012-20260325    clang-20
x86_64                randconfig-013-20260325    clang-20
x86_64                randconfig-014-20260325    clang-20
x86_64                randconfig-015-20260325    clang-20
x86_64                randconfig-016-20260325    clang-20
x86_64                randconfig-071-20260325    gcc-14
x86_64                randconfig-072-20260325    gcc-14
x86_64                randconfig-073-20260325    gcc-14
x86_64                randconfig-074-20260325    gcc-14
x86_64                randconfig-075-20260325    gcc-14
x86_64                randconfig-076-20260325    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                           allyesconfig    gcc-15.2.0
xtensa                randconfig-001-20260325    gcc-13
xtensa                randconfig-002-20260325    gcc-13

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

^ permalink raw reply

* Re: [PATCH RESEND 0/4] Fix some errors in the devfreq core layer when governor is NULL
From: Jie Zhan @ 2026-03-25 10:06 UTC (permalink / raw)
  To: Yaxiong Tian, myungjoo.ham, kyungmin.park, cw00.choi, nm
  Cc: linux-pm, linux-kernel
In-Reply-To: <20260319091409.998397-1-tianyaxiong@kylinos.cn>



On 3/19/2026 5:14 PM, Yaxiong Tian wrote:
> 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.
Hi Yaxiong,

Sorry for catching this late.

I happen to be working on the same issues recently on a local tree, though
delayed for quite a while due to other business.

It would be a totally different approach by reworking the locking logic,
which, I supposed, can make the devfreq framework cleaner to maintain.

I'll send it out shortly.  Hopefully it can be a reference for us to
discuss with.

Thanks!
Jie
> 
> 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(-)
> 

^ permalink raw reply

* Re: [RFC PATCH 1/2] thermal/cpufreq_cooling: remove unused cpu_idx in get_load()
From: Lukasz Luba @ 2026-03-25  8:31 UTC (permalink / raw)
  To: Xuewen Yan
  Cc: Viresh Kumar, Xuewen Yan, rui.zhang, rafael, linux-pm,
	amit.kachhap, daniel.lezcano, linux-kernel, ke.wang, di.shen,
	jeson.gao
In-Reply-To: <CAB8ipk_VftSn4U+Vzdv_ST7apiONVoYy4PTe7usRetXry6uSOQ@mail.gmail.com>



On 3/24/26 12:03, Xuewen Yan wrote:
> On Tue, Mar 24, 2026 at 6:45 PM Lukasz Luba <lukasz.luba@arm.com> wrote:
>>
>>
>>
>> On 3/24/26 02:20, Xuewen Yan wrote:
>>> On Mon, Mar 23, 2026 at 9:25 PM Lukasz Luba <lukasz.luba@arm.com> wrote:
>>>>
>>>>
>>>>
>>>> On 3/23/26 11:06, Viresh Kumar wrote:
>>>>> On 23-03-26, 10:52, Lukasz Luba wrote:
>>>>>>> How is that okay ? What am I missing ?
>>>>>
>>>>> I was missing !SMP :)
>>>>>
>>>>>> Right, there is a mix of two things.
>>>>>> The 'i' left but should be removed as well, since
>>>>>> this is !SMP code with only 1 cpu and i=0.
>>>
>>> That's also why we sent out patch 1/2; after all, it is always 0 on
>>> !SMP systems.
>>>
>>>>>>
>>>>>> The whole split which has been made for getting
>>>>>> the load or utilization from CPU(s) needs to be
>>>>>> cleaned. The compiled code looks different since
>>>>>> it knows there is non-SMP config used.
>>>>>
>>>>> Right, we are allocating that for num_cpus (which should be 1 CPU
>>>>> anyway). The entire thing must be cleaned.
>>>>>
>>>>>> Do you want to clean that or I should do this?
>>>>>
>>>>> It would be helpful if you can do it :)
>>>>>
>>>>
>>>> OK, I will. Thanks for your involvement Viresh!
>>>>
>>>> Xuewen please wait with your v2, I will send
>>>> a redesign of this left code today.
>>>
>>> Okay, and Qais's point is also worth considering: do we actually need
>>> sched_cpu_util()?
>>> The way I see it, generally speaking, the request_power derived from
>>> idle_time might be higher than what we get from sched_cpu_util().
>>> Take this scenario as an example:
>>> Consider a CPU running at the lowest frequency with 50% idle time,
>>> versus one running at the highest frequency with the same 50% idle
>>> time.
>>> In this case, using idle_time yields the same load value for both.
>>> However, sched_cpu_util() would report a lower load when the CPU
>>> frequency is low. This results in a smaller request_power...
>>
>> Right, there are 2 things to consider:
>> 1. what is the utilization when the CPU still have idle time, e.g.
>>      this 50% that you mentioned
>> 2. what is the utilization when there is no idle time and CPU
>>      is fully busy (and starts throttling due to heat)
>>
>> In this thermal fwk we are mostly in the 2nd case. In that case the
>> utilization on CPU's runqueue goes to 1024 no mater the CPU's frequency.
> 
> Haha, indeed. When we debug IPA, we also keep the CPU constantly
> running with basically no idle time.
> In this scenario, we tested using both sched_cpu_util() and idle_time,
> and for thermal control purposes, there was basically no difference
> (likely because the load was at 100%).
> Maybe we can cook up a test case where the CPU is overheating despite
> having some idle time? That way we can compare how the two interfaces
> perform.

I wish we could involve the GPU in those stress scenarios. Then we could
have some load (e.g. 70% on CPUs) and heavy computation on GPU which
heats up the whole silicon. In such experiment you could observe the
difference from those two methods of input power estimation.

Unfortunately, for the GPU it's hard to craft such benchmark
(at least for me lacking GPU programming experience at that level).
Ideally we could have something which controls the amount of GPU
computation and created heat...


> 
>> We know which highest frequency was allowed to run and we pick the power
>> value from EM for it. That's why the estimation is not that bad (apart
>> from power variation for different flavors of workloads: heavy SIMD vs.
>> normal integer/load).
>>
>> In 1st case scenario we might underestimate the power, but that
>> is not the thermal stress situation anyway, so the max OPP is
>> still allowed.
>>
>> So far it is hard to find the best power model to use and robust CPU
>> load mechanisms. Adding more complexity and creating some
>> over-engineered code in the kernel to maintain might not have sense.
>> The thermal solutions are solved in the Firmware nowadays since the
>> kernel won't react that fast for some rapid changes.
>>
>> We have to balance the complexity here.
>> Let's improve the situation a bit. It would be very much appreciated if
>> you could share information if those changes help your platform
>> (some older boards might not show any benefit with the new code).
>>
> Understood. We appreciate the balance between complexity and accuracy.
> We could test these changes on our platforms and let you know if we
> see any improvements in thermal stability or power estimation. Expect
> an update from us in a few days.
> 

Sounds great, thanks!

^ permalink raw reply

* [PATCH] thermal: fix error condition for reading st,thermal-flags
From: Gopi Krishna Menon @ 2026-03-25  8:18 UTC (permalink / raw)
  To: rafael, daniel.lezcano, rui.zhang, lukasz.luba
  Cc: Gopi Krishna Menon, daniel.baluta, simona.toaca, d-gole,
	m-chawdhry, linux-pm, linux-kernel

of_property_read_u32 returns 0 on success. The current check returns
-EINVAL if the property is read successfully.

Fix the check by removing ! from of_property_read_u32

Suggested-by: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Gopi Krishna Menon <krishnagopi487@gmail.com>
---
Note:
* This patch is part of the GSoC2026 application process for device tree bindings conversions
* https://github.com/LinuxFoundationGSoC/ProjectIdeas/wiki/GSoC-2026-Device-Tree-Bindings
* Changes have only been compile tested

 drivers/thermal/spear_thermal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 603dadcd3df5..5e3e9c1f32f8 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -93,7 +93,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	int ret = 0, val;
 
-	if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) {
+	if (!np || of_property_read_u32(np, "st,thermal-flags", &val)) {
 		dev_err(&pdev->dev, "Failed: DT Pdata not passed\n");
 		return -EINVAL;
 	}
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH 5/5] fpga: m10bmc-sec: switch show_canceled_csk() to using sysfs_emit()
From: Xu Yilun @ 2026-03-25  7:25 UTC (permalink / raw)
  To: Yury Norov
  Cc: linux-kernel, Christophe Leroy (CS GROUP), Peter Zijlstra (Intel),
	Rafael J. Wysocki, Alexander Shishkin, Daniel Lezcano,
	Ingo Molnar, James Clark, Kees Cook, Lukasz Luba,
	Madhavan Srinivasan, 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,
	Jakub Kicinski
In-Reply-To: <acLaDFuCzt0d33Q_@yury>

On Tue, Mar 24, 2026 at 02:38:04PM -0400, Yury Norov wrote:
> On Tue, Mar 24, 2026 at 05:15:33PM +0800, Xu Yilun wrote:
> > On Tue, Mar 03, 2026 at 03:08:41PM -0500, Yury Norov wrote:
> > > Switch show_canceled_csk() to use the proper sysfs_emit("%*pbl").
> > > 
> > > Reviewed-by: Russ Weight <russ.weight@linux.dev>
> > > Suggested-by: Thomas Weißschuh <linux@weissschuh.net>
> > > Signed-off-by: Yury Norov <ynorov@nvidia.com>
> > > ---
> > >  drivers/fpga/intel-m10-bmc-sec-update.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
> > > index 10f678b9ed36..ae364c6636eb 100644
> > > --- a/drivers/fpga/intel-m10-bmc-sec-update.c
> > > +++ b/drivers/fpga/intel-m10-bmc-sec-update.c
> > > @@ -10,6 +10,7 @@
> > >  #include <linux/firmware.h>
> > >  #include <linux/mfd/intel-m10-bmc.h>
> > >  #include <linux/mod_devicetable.h>
> > > +#include <linux/mm.h>
> > 
> > Why add this header file?
> 
> When I was preparing the series, I had build issues without this. But
> now I checked it against -rc5, and it's clean. Would you like me to
> resend?

No need. Given that I'll pick this patch alone to fpga for-next with the
fix.

Reviewed-by: Xu Yilun <yilun.xu@intel.com>

> 
> > >  #include <linux/module.h>
> > >  #include <linux/platform_device.h>
> > >  #include <linux/slab.h>
> > > @@ -183,7 +184,7 @@ show_canceled_csk(struct device *dev, u32 addr, char *buf)
> > >  
> > >  	bitmap_from_arr32(csk_map, csk32, CSK_BIT_LEN);
> > >  	bitmap_complement(csk_map, csk_map, CSK_BIT_LEN);
> > > -	return bitmap_print_to_pagebuf(1, buf, csk_map, CSK_BIT_LEN);
> > > +	return sysfs_emit(buf, "%*pbl\n", CSK_BIT_LEN, csk_map);
> > >  }
> > >  
> > >  #define DEVICE_ATTR_SEC_CSK_RO(_name)						\
> > > -- 
> > > 2.43.0
> > > 
> > > 

^ permalink raw reply

* Re: [PATCH v6 3/4] cpufreq: Set policy->min and max as real QoS constraints
From: Viresh Kumar @ 2026-03-25  6:49 UTC (permalink / raw)
  To: Pierre Gondois
  Cc: linux-kernel, Jie Zhan, Lifeng Zheng, 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: <ab06e8d6-d430-483b-a2a4-9e7d197aa6b6@arm.com>

On 24-03-26, 12:40, Pierre Gondois wrote:
> Being able to set the min/max_freq_req from the driver might be
> something that is needed, cf:
> https://lore.kernel.org/lkml/20260213100633.15413-1-zhangpengjie2@huawei.com/
> 
> It would also allow to have a common way to set policy->min/max values
> as they are set to the the cpuinfo.min/max_freq.
> 
> On the other hand I agree that I didn't test all the possible paths
> for this change, so this is a bit audacious.
> 
> 
> What about adding the following to have the values set for all drivers:
> 
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> 
> index 70814c567243b..3a1e5f58a301f 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -1530,6 +1530,9 @@ static int cpufreq_policy_online(struct cpufreq_policy
> *policy,
>                                 CPUFREQ_CREATE_POLICY, policy);
>         }
> 
> +       policy->max = policy->cpuinfo.max_freq;
> +       policy->min = policy->cpuinfo.min_freq;
> +
>         if (cpufreq_driver->get && has_target()) {
>                 policy->cur = cpufreq_driver->get(policy->cpu);
>                 if (!policy->cur) {

I am okay with a separate series doing all these cleanups. We can set some sort
of rule on what is expected from the driver here and what is left from the core.
For example driver only sets cpuinfo.max/min and core takes care of rest. This
series would cleanup all the drivers, etc.

-- 
viresh

^ permalink raw reply

* Re: [PATCH 1/5] pwm: tegra: Avoid hard-coded max clock frequency
From: Viresh Kumar @ 2026-03-25  6:42 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Mikko Perttunen, Thierry Reding, Jonathan Hunter, linux-pwm,
	linux-tegra, linux-kernel, Yi-Wei Wang, Viresh Kumar,
	Nishanth Menon, Stephen Boyd, linux-pm
In-Reply-To: <acN7pSjuMkZl2yhV@monoceros>

On 25-03-26, 07:12, Uwe Kleine-König wrote:
> On Wed, Mar 25, 2026 at 09:34:55AM +0900, Mikko Perttunen wrote:
> > On Wednesday, March 25, 2026 1:45 AM Uwe Kleine-König wrote:
> > > On Mon, Mar 23, 2026 at 11:36:37AM +0900, Mikko Perttunen wrote:
> > > > @@ -303,7 +300,7 @@ static int tegra_pwm_probe(struct platform_device
> > > > *pdev)> 
> > > >  		return ret;
> > > >  	
> > > >  	/* Set maximum frequency of the IP */
> > > > 
> > > > -	ret = dev_pm_opp_set_rate(&pdev->dev, pc->soc->max_frequency);
> > > > +	ret = dev_pm_opp_set_rate(&pdev->dev, S64_MAX);
> > > 
> > > The documentation comment for dev_pm_opp_set_rate() reads:
> > > 
> > > 	Device wanting to run at fmax provided by the opp, should have
> > > 	already rounded to the target OPP's frequency.

And that is correct, right ? This comment is talking about the max freq possible
with each OPP and not the highest freq possible with the device. If a device
supports 5 OPPs (0-4) and if we want to run at the freq mentioned in the OPP3
entry in DT, then the caller must send a frequency such that clk_round_rate()
returns the frequency of the OPP3.

In the above case though, we will end up running at the highest freq returned
by clk_round_rate() and an OPP corresponding to that.

> > > I think using S64_MAX is technically fine (assuming there are no issues
> > > with big numbers in that function), but still it feels wrong to use
> > > something simpler than the comment suggests. Am I missing something?

I think S64_MAX will work as well, unless clk_round_rate() returns a frequency
higher than what the OPP table mentions. It may still work, but the values may
be confusing and inconsistent.

> > Looking at the history of the function, the comment was added in the commit 
> > below. It seems like it used to be that the opp framework always used the fmax 
> > of each OPP even if a lower rate was specified, but after the change, the 
> > caller has to specify the fmax rate if they want that rate specifically. As 
> > such I don't think it should be an issue in our case, as we're just using the 
> > rate to find an OPP and don't have a specific one in mind.

Right.

> So the comment describing dev_pm_opp_set_rate() needs an update, right?

Maybe, not sure. But as I mentioned earlier, it is written with the context of
each OPP's highest freq.

-- 
viresh

^ permalink raw reply

* Re: [PATCH v6 1/4] cpufreq: Remove per-CPU QoS constraint
From: Viresh Kumar @ 2026-03-25  6:28 UTC (permalink / raw)
  To: Pierre Gondois
  Cc: Lifeng Zheng, 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: <86aab895-5945-47a1-bc58-12747c7d8f48@arm.com>

On 24-03-26, 12:39, Pierre Gondois wrote:
> I experimented a bit more and it seems the following happens:
> 
> 1. boost all CPUs: echo 1 > /sys/devices/system/cpu/cpufreq/boost
> 2. offline one CPU: echo 0 > /sys/devices/system/cpu/cpuX/online
> 3. deboost all CPUs: echo 0 > /sys/devices/system/cpu/cpufreq/boost
> 
> cpufreq_boost_trigger_state()
> \-for_each_active_policy()
>   \-cpufreq_driver->set_boost()
> doesn't act on the policy where there are no more online CPUs,
> so the max/cpuinfo.max/max_freq_req is left to the actual
> boost freq.

Right.

> 4. online CPUX: echo 1 > /sys/devices/system/cpu/cpuX/online
> 
> cpufreq_online()
> \-cpufreq_driver->init()
>   \-cppc_cpufreq_cpu_init()
> There:
> - policy->max
> - policy->cpuinfo.max_freq
> are set to the maximal non-boost freq., which is the correct value.

Right, but that is true only for CPPC. Not all drivers would set max freq from
there and depend on cpufreq_table_validate_and_sort() to fix this. Which was
broken earlier, but with my patch it should be fixed now.

So yes, we will have max/cpuinfo.max_freq set at this point (with my patch
applied) for all drivers.

> However, max_freq_req is left to the boosted frequency, so this
> is effectively an incorrect state.

Right.

> Also in cpufreq_set_policy(), policy->max is set to:
>   min(max_freq_req, cpuinfo.max_freq)
> (cf. verify() cb), so the incorrect state of max_freq_req is not
> visible.
> 
> 5. boost all CPUs again: echo 1 > /sys/devices/system/cpu/cpufreq/boost
> 
> As the max_freq_req value and the new boost value are equal,
> cpufreq_notifier_max() won't be called, which means that if the
> CPU needed to raise its freq., it won't be notified until another
> event trigger a re-evaluation of the freq. selection.

Right and max/cpuinfo.max_freq will be incorrect here. This was the issue the
commit 1608f0230510 was trying to fix.

> To observe that, I had to:
> - use the performance governor to be sure to select the max. available
>   freq.
> - observe scaling_cur_freq to see the last requested freq. for the CPU
> 
> So IMO the issue was actually fixed by:
> dd016f379ebc ("cpufreq: Introduce a more generic way to set default
> per-policy boost flag")
> which sets the correct max_freq_req value when putting back an
> inactive policy.

Right. This patch fixes the issue I think. Your patch is fine I guess, just
mention this reason and we are good to go.

-- 
viresh

^ permalink raw reply

* Re: [PATCH 1/5] pwm: tegra: Avoid hard-coded max clock frequency
From: Uwe Kleine-König @ 2026-03-25  6:12 UTC (permalink / raw)
  To: Mikko Perttunen
  Cc: Thierry Reding, Jonathan Hunter, linux-pwm, linux-tegra,
	linux-kernel, Yi-Wei Wang, Viresh Kumar, Nishanth Menon,
	Stephen Boyd, linux-pm
In-Reply-To: <4405239.kQq0lBPeGt@senjougahara>

[-- Attachment #1: Type: text/plain, Size: 4525 bytes --]

[ Adding OPP maintainers to Cc: ]

Helle Mikko,

On Wed, Mar 25, 2026 at 09:34:55AM +0900, Mikko Perttunen wrote:
> On Wednesday, March 25, 2026 1:45 AM Uwe Kleine-König wrote:
> > On Mon, Mar 23, 2026 at 11:36:37AM +0900, Mikko Perttunen wrote:
> > > @@ -303,7 +300,7 @@ static int tegra_pwm_probe(struct platform_device
> > > *pdev)> 
> > >  		return ret;
> > >  	
> > >  	/* Set maximum frequency of the IP */
> > > 
> > > -	ret = dev_pm_opp_set_rate(&pdev->dev, pc->soc->max_frequency);
> > > +	ret = dev_pm_opp_set_rate(&pdev->dev, S64_MAX);
> > 
> > The documentation comment for dev_pm_opp_set_rate() reads:
> > 
> > 	Device wanting to run at fmax provided by the opp, should have
> > 	already rounded to the target OPP's frequency.
> > 
> > I think using S64_MAX is technically fine (assuming there are no issues
> > with big numbers in that function), but still it feels wrong to use
> > something simpler than the comment suggests. Am I missing something?
> 
> Looking at the history of the function, the comment was added in the commit 
> below. It seems like it used to be that the opp framework always used the fmax 
> of each OPP even if a lower rate was specified, but after the change, the 
> caller has to specify the fmax rate if they want that rate specifically. As 
> such I don't think it should be an issue in our case, as we're just using the 
> rate to find an OPP and don't have a specific one in mind.
> 
> commit b3e3759ee4abd72bedbf4b109ff1749d3aea6f21
> Author: Stephen Boyd <swboyd@chromium.org>
> Date:   Wed Mar 20 15:19:08 2019 +0530
> 
>     opp: Don't overwrite rounded clk rate
>     
>     The OPP table normally contains 'fmax' values corresponding to the
>     voltage or performance levels of each OPP, but we don't necessarily want
>     all the devices to run at fmax all the time. Running at fmax makes sense
>     for devices like CPU/GPU, which have a finite amount of work to do and
>     since a specific amount of energy is consumed at an OPP, its better to
>     run at the highest possible frequency for that voltage value.
>     
>     On the other hand, we have IO devices which need to run at specific
>     frequencies only for their proper functioning, instead of maximum
>     possible frequency.
>     
>     The OPP core currently roundup to the next possible OPP for a frequency
>     and select the fmax value. To support the IO devices by the OPP core,
>     lets do the roundup to fetch the voltage or performance state values,
>     but not use the OPP frequency value. Rather use the value returned by
>     clk_round_rate().
>     
>     The current user, cpufreq, of dev_pm_opp_set_rate() already does the
>     rounding to the next OPP before calling this routine and it won't
>     have any side affects because of this change.
>     
>     Signed-off-by: Stephen Boyd <swboyd@chromium.org>
>     Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
>     [ Viresh: Massaged changelog, added comment and use temp_opp variable
>               instead ]
>     Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

So the comment describing dev_pm_opp_set_rate() needs an update, right?

> > >  	if (ret < 0) {
> > >  	
> > >  		dev_err(&pdev->dev, "Failed to set max frequency: %d\n", 
> ret);
> > >  		goto put_pm;
> > > 
> > > @@ -318,7 +315,7 @@ static int tegra_pwm_probe(struct platform_device
> > > *pdev)> 
> > >  	/* Set minimum limit of PWM period for the IP */
> > >  	pc->min_period_ns =
> > > 
> > > -	    (NSEC_PER_SEC / (pc->soc->max_frequency >> PWM_DUTY_WIDTH)) + 1;
> > > +	    (NSEC_PER_SEC / (pc->clk_rate >> PWM_DUTY_WIDTH)) + 1;
> > 
> > Orthogonal to this patch: Should this be
> > 
> > 	DIV_ROUND_UP(NSEC_PER_SEC, pc->clk_rate >> PWM_DUTY_WIDTH)
> > 
> > ? Or even
> > 
> > 	DIV_ROUND_UP(NSEC_PER_SEC < PWM_DUTY_WIDTH, pc->clk_rate);
> > 
> > ? (Note, the latter doesn't work as is, as the first parameter has an
> > overflow, I guess you're still getting my question.)
> 
> Indeed, it would be overestimating the minimum period right now. It's not 
> quite part of Tegra264 support but I can include a patch in the next revision 
> if you'd like. Otherwise I could include it in the followup series or as a 
> separate patch.

If you know it and feel responsible to address it at some point that's
fine. We lived with that issue for some time now, so a separate and if
you prefer later series is fine for me.

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v10 05/12] arm64: rqspinlock: Remove private copy of smp_cond_load_acquire_timewait()
From: Ankur Arora @ 2026-03-25  5:58 UTC (permalink / raw)
  To: Kumar Kartikeya Dwivedi
  Cc: Ankur Arora, linux-kernel, linux-arch, linux-arm-kernel, linux-pm,
	bpf, arnd, catalin.marinas, will, peterz, akpm, mark.rutland,
	harisokn, cl, ast, rafael, daniel.lezcano, zhenglifeng1, xueshuai,
	rdunlap, david.laight.linux, joao.m.martins, boris.ostrovsky,
	konrad.wilk
In-Reply-To: <CAP01T75VaNGk+adULuX3q_8uxc0z78J5B_5ECLy2VR=i7pBi0g@mail.gmail.com>


Kumar Kartikeya Dwivedi <memxor@gmail.com> writes:

> On Mon, 16 Mar 2026 at 02:37, Ankur Arora <ankur.a.arora@oracle.com> wrote:
>>
>> In preparation for defining smp_cond_load_acquire_timeout(), remove
>> the private copy. Lacking this, the rqspinlock code falls back to using
>> smp_cond_load_acquire().
>
> nit: This temporarily breaks bisection (or rather, leaves things
> broken until later commits), but I don't care too much.

Yeah. Would have avoided it if I easily could. But given that there
was a private interface involved this seemed the cleanest way.

>> Cc: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>> Cc: Alexei Starovoitov <ast@kernel.org>
>> Cc: bpf@vger.kernel.org
>> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>> Reviewed-by: Haris Okanovic <harisokn@amazon.com>
>> Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
>> ---
>
> Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>

Thanks.

--
ankur

^ permalink raw reply

* Re: [PATCH v10 09/12] bpf/rqspinlock: switch check_timeout() to a clock interface
From: Ankur Arora @ 2026-03-25  5:57 UTC (permalink / raw)
  To: Kumar Kartikeya Dwivedi
  Cc: Ankur Arora, linux-kernel, linux-arch, linux-arm-kernel, linux-pm,
	bpf, arnd, catalin.marinas, will, peterz, akpm, mark.rutland,
	harisokn, cl, ast, rafael, daniel.lezcano, zhenglifeng1, xueshuai,
	rdunlap, david.laight.linux, joao.m.martins, boris.ostrovsky,
	konrad.wilk
In-Reply-To: <CAP01T76iJAtfovOAhm+9-QwtbVJRbiQgUPWLBZZXYFozLFK=uw@mail.gmail.com>


Kumar Kartikeya Dwivedi <memxor@gmail.com> writes:

> On Mon, 16 Mar 2026 at 02:37, Ankur Arora <ankur.a.arora@oracle.com> wrote:
>>
>> check_timeout() gets the current time value and depending on how
>> much time has passed, checks for deadlock or times out, returning 0
>> or -errno on deadlock or timeout.
>>
>> Switch this out to a clock style interface, where it functions as a
>> clock in the "lock-domain", returning the current time until a
>> deadlock or timeout occurs. Once a deadlock or timeout has occurred,
>> it stops functioning as a clock and returns error.
>>
>> Also adjust the RES_CHECK_TIMEOUT macro to discard the clock value
>> when updating the explicit return status.
>>
>> Cc: bpf@vger.kernel.org
>> Cc: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>> Cc: Alexei Starovoitov <ast@kernel.org>
>> Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
>> --
>
> Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>

Thanks Kumar.

--
ankur

^ permalink raw reply

* Re: [PATCH] cpuidle: Deny idle entry when CPU already have IPI interrupt pending
From: Maulik Shah (mkshah) @ 2026-03-25  5:37 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Daniel Lezcano, Christian Loehle, Ulf Hansson, linux-pm,
	linux-kernel, linux-arm-msm
In-Reply-To: <CAJZ5v0jL6ms3jaB5Ra9h5FA4WY6J7sGgFLnXTOEC+dvVpW7eaA@mail.gmail.com>



On 3/24/2026 9:37 PM, Rafael J. Wysocki wrote:
> On Mon, Mar 23, 2026 at 1:13 PM Maulik Shah (mkshah)
> <maulik.shah@oss.qualcomm.com> wrote:
>>
>>
>>
>> On 3/20/2026 11:59 PM, Rafael J. Wysocki wrote:
>>> On Mon, Mar 16, 2026 at 8:38 AM Maulik Shah
>>> <maulik.shah@oss.qualcomm.com> wrote:
>>>>
>>>> CPU can get IPI interrupt from another CPU while it is executing
>>>> cpuidle_select() or about to execute same. The selection do not account
>>>> for pending interrupts and may continue to enter selected idle state only
>>>> to exit immediately.
>>>>
>>>> Example trace collected when there is cross CPU IPI.
>>>>
>>>>  [000] 154.892148: sched_waking: comm=sugov:4 pid=491 prio=-1 target_cpu=007
>>>>  [000] 154.892148: ipi_raise: target_mask=00000000,00000080 (Function call interrupts)
>>>>  [007] 154.892162: cpu_idle: state=2 cpu_id=7
>>>>  [007] 154.892208: cpu_idle: state=4294967295 cpu_id=7
>>>>  [007] 154.892211: irq_handler_entry: irq=2 name=IPI
>>>>  [007] 154.892211: ipi_entry: (Function call interrupts)
>>>>  [007] 154.892213: sched_wakeup: comm=sugov:4 pid=491 prio=-1 target_cpu=007
>>>>  [007] 154.892214: ipi_exit: (Function call interrupts)
>>>>
>>>> This impacts performance and the above count increments.
>>>>
>>>> commit ccde6525183c ("smp: Introduce a helper function to check for pending
>>>> IPIs") already introduced a helper function to check the pending IPIs and
>>>> it is used in pmdomain governor to deny the cluster level idle state when
>>>> there is a pending IPI on any of cluster CPUs.
>>>
>>> You seem to be overlooking the fact that resched wakeups need not be
>>> signaled via IPIs, but they may be updates of a monitored cache line.
>>>
>>>> This however does not stop CPU to enter CPU level idle state. Make use of
>>>> same at CPUidle to deny the idle entry when there is already IPI pending.
>>>>
>>>> With change observing glmark2 [1] off screen scores improving in the range
>>>> of 25% to 30% on Qualcomm lemans-evk board which is arm64 based having two
>>>> clusters each with 4 CPUs.
>>>>
>>>> [1] https://github.com/glmark2/glmark2
>>>>
>>>> Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
>>>> ---
>>>>  drivers/cpuidle/cpuidle.c | 3 +++
>>>>  1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
>>>> index c7876e9e024f9076663063ad21cfc69343fdbbe7..c88c0cbf910d6c2c09697e6a3ac78c081868c2ad 100644
>>>> --- a/drivers/cpuidle/cpuidle.c
>>>> +++ b/drivers/cpuidle/cpuidle.c
>>>> @@ -224,6 +224,9 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev,
>>>>         bool broadcast = !!(target_state->flags & CPUIDLE_FLAG_TIMER_STOP);
>>>>         ktime_t time_start, time_end;
>>>>
>>>> +       if (cpus_peek_for_pending_ipi(drv->cpumask))
>>>> +               return -EBUSY;
>>>> +
>>>
>>> So what if the driver handles all CPUs in the system and there are
>>> many of them (say ~500) and if IPIs occur rarely (because resched
>>> events are not IPIs)?
>>
>> Missed the case of driver handling multiple CPUs,
>> In v2 would fix this as below, which checks pending IPI on single
>> CPU trying to enter idle.
>>
>>      if (cpus_peek_for_pending_ipi(cpumask_of(dev->cpu)))
> 
> And the for_each_cpu() loop in cpus_peek_for_pending_ipi() would then
> become useless overhead, wouldn't ir?

Given that mask in loop for_each_cpu(cpu, mask) will have a single cpu, overhead should be minor.
or May be we can have new API for a single CPU case.

> 
>> I see IPIs do occur often, in the glmark2 offscreen case
>> mentioned in commit text, out of total ~12.2k IPIs across all 8 CPUs,
>> ~9.6k are function call IPIs, ~2k are IRQ work IPIs, ~560 Timer broadcast
>> IPIs while rescheduling IPIs are only 82.
> 
> So how many of those IPIs actually wake up CPUs from idle prematurely?

282 times out of total 12.2k IPIs (~2.3%) hitting the newly added condition.

Thanks,
Maulik

^ permalink raw reply

* Re: [PATCH v3 08/12] amd-pstate-ut: Add ability to run a single testcase
From: K Prateek Nayak @ 2026-03-25  4:28 UTC (permalink / raw)
  To: Gautham R. Shenoy, Mario Limonciello (AMD) (kernel.org)
  Cc: Rafael J . Wysocki, Viresh Kumar, linux-kernel, linux-pm
In-Reply-To: <acITFNYfjSMc/K1I@BLRRASHENOY1.amd.com>

Hello Gautham,

On 3/24/2026 9:59 AM, Gautham R. Shenoy wrote:
> +static bool test_in_list(const char *list, const char *name)
> +{
> +       size_t name_len = strlen(name);
> +       const char *p = list;
> +
> +       while (*p) {
> +               const char *sep = strchr(p, ';');

Any particular reason for using a ";" as the separator instead of ","?

I personally prefer "," because with ";", I need to explicitly add
'' around the test_list otherwise bash thinks the command ends at ";"
but with "," that is avoided.

Thoughts?

> +               size_t token_len = sep ? sep - p : strlen(p);
> +
> +               if (token_len == name_len && !strncmp(p, name, token_len))
> +                       return true;
> +
> +               if (!sep)
> +                       break;
> +               p = sep + 1;
> +       }
> +
> +       return false;
> +}
-- 
Thanks and Regards,
Prateek


^ permalink raw reply

* Re: [PATCH v3 05/12] amd-pstate: Add support for CPPC_REQ2 and FLOOR_PERF
From: K Prateek Nayak @ 2026-03-25  4:18 UTC (permalink / raw)
  To: Mario Limonciello, Gautham R. Shenoy, Rafael J . Wysocki,
	Viresh Kumar
  Cc: linux-kernel, linux-pm
In-Reply-To: <17bd7fa9-bf01-4ee5-b3aa-cc75d6409cf9@amd.com>

On 3/25/2026 9:39 AM, K Prateek Nayak wrote:
> Hello Mario,
> 
> On 3/25/2026 3:08 AM, Mario Limonciello wrote:
>>>    * @nominal_freq: the frequency (in khz) that mapped to nominal_perf
>>> @@ -87,10 +90,13 @@ struct amd_cpudata {
>>>         struct    freq_qos_request req[2];
>>>       u64    cppc_req_cached;
>>> +    u64    cppc_req2_cached;
>>>         union perf_cached perf;
>>>         u8    prefcore_ranking;
>>> +    u8    floor_perf_cnt;
>>> +    u8    bios_floor_perf;
>>
>> It looks like you forgot to update doc for bios_floor_perf

Me realizes you meant the comment above the stuct! Sorry for the noise.

_Me goes and grabs a coffee to wake myself up_

> 
> "bios_floor_perf" is an internal detail that caches the initial state of
> "FloorPerf" from CPPC_REQ2 when the driver is loaded.
> 
> It is only used to restore the FloorPerf to the original when the CPU is
> offlined, the driver unloaded, or when the CPU is suspended. This
> essentially resets the state of the CPU to what it was at the boot so a
> kexec, driver switch can start off afresh from the BIOS defaults.
> 
> User can read amd_pstate_floor_freq just after the boot to know what the
> default is. Do we really need to expose this?
> 
>>
>>>       u32    min_limit_freq;
>>>       u32    max_limit_freq;
>>>       u32    nominal_freq;
>>
> 

-- 
Thanks and Regards,
Prateek


^ permalink raw reply

* Re: [PATCH v3 05/12] amd-pstate: Add support for CPPC_REQ2 and FLOOR_PERF
From: K Prateek Nayak @ 2026-03-25  4:09 UTC (permalink / raw)
  To: Mario Limonciello, Gautham R. Shenoy, Rafael J . Wysocki,
	Viresh Kumar
  Cc: linux-kernel, linux-pm
In-Reply-To: <48262f07-a852-44e0-92a0-1215bc48e9cf@amd.com>

Hello Mario,

On 3/25/2026 3:08 AM, Mario Limonciello wrote:
>>    * @nominal_freq: the frequency (in khz) that mapped to nominal_perf
>> @@ -87,10 +90,13 @@ struct amd_cpudata {
>>         struct    freq_qos_request req[2];
>>       u64    cppc_req_cached;
>> +    u64    cppc_req2_cached;
>>         union perf_cached perf;
>>         u8    prefcore_ranking;
>> +    u8    floor_perf_cnt;
>> +    u8    bios_floor_perf;
> 
> It looks like you forgot to update doc for bios_floor_perf

"bios_floor_perf" is an internal detail that caches the initial state of
"FloorPerf" from CPPC_REQ2 when the driver is loaded.

It is only used to restore the FloorPerf to the original when the CPU is
offlined, the driver unloaded, or when the CPU is suspended. This
essentially resets the state of the CPU to what it was at the boot so a
kexec, driver switch can start off afresh from the BIOS defaults.

User can read amd_pstate_floor_freq just after the boot to know what the
default is. Do we really need to expose this?

> 
>>       u32    min_limit_freq;
>>       u32    max_limit_freq;
>>       u32    nominal_freq;
> 

-- 
Thanks and Regards,
Prateek


^ permalink raw reply

* Re: [PATCH v5 00/21] Virtual Swap Space
From: Askar Safin @ 2026-03-25  2:35 UTC (permalink / raw)
  To: nphamcs
  Cc: Liam.Howlett, akpm, apopple, axelrasmussen, baohua, baolin.wang,
	bhe, byungchul, cgroups, chengming.zhou, chrisl, corbet, david,
	dev.jain, gourry, hannes, hughd, jannh, joshua.hahnjy, kasong,
	kernel-team, lance.yang, lenb, linux-doc, linux-kernel, linux-mm,
	linux-pm, lorenzo.stoakes, matthew.brost, mhocko, muchun.song,
	npache, pavel, peterx, peterz, pfalcato, rafael, rakie.kim, riel,
	roman.gushchin, rppt, ryan.roberts, ryncsn, shakeel.butt,
	shikemeng, surenb, tglx, vbabka, weixugc, willy, ying.huang,
	yosry.ahmed, yuanchu, zhengqi.arch, ziy
In-Reply-To: <CAKEwX=MgoPmiFdBQXK_4=XuR-8mVpGr+3Ku2MfjPmHCeuUdGJg@mail.gmail.com>

Nhat Pham <nphamcs@gmail.com>:
> I'm aware of that work. It's an improvement, but my understanding is:

Thank you for answer!

Also, is it possible to have checksummed swap?

I want to have checksummed swap to be protected from disk bit-rot
(I already have ECC memory, so RAM is protected).

And hibernation image should be protected, too.

I tried to put swap on top of dm-integrity, but this is
incompatible with hibernation in mainline kernel.

-- 
Askar Safin

^ permalink raw reply

* Re: [PATCH v6 3/9] cxl/region: Skip decoder reset on detach for autodiscovered regions
From: Alison Schofield @ 2026-03-25  1:51 UTC (permalink / raw)
  To: Dan Williams
  Cc: Smita Koralahalli, linux-cxl, linux-kernel, nvdimm, linux-fsdevel,
	linux-pm, Ard Biesheuvel, Vishal Verma, Ira Weiny,
	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: <69c2ea1ea24e1_51621100a1@dwillia2-mobl4.notmuch>

On Tue, Mar 24, 2026 at 12:46:38PM -0700, Dan Williams wrote:
> Alison Schofield wrote:

I didn't snip, but lucky for someone, I only appended. Goto EOF.


> > On Wed, Mar 11, 2026 at 02:37:46PM -0700, Dan Williams wrote:
> > > Smita Koralahalli wrote:
> > > > __cxl_decoder_detach() currently resets decoder programming whenever a
> > > > region is detached if cxl_config_state is beyond CXL_CONFIG_ACTIVE. For
> > > > autodiscovered regions, this can incorrectly tear down decoder state
> > > > that may be relied upon by other consumers or by subsequent ownership
> > > > decisions.
> > > > 
> > > > Skip cxl_region_decode_reset() during detach when CXL_REGION_F_AUTO is
> > > > set.
> > > > 
> > > > 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: Alejandro Lucero <alucerop@amd.com>
> > > > ---
> > > >  drivers/cxl/core/region.c | 4 +++-
> > > >  1 file changed, 3 insertions(+), 1 deletion(-)
> > > > 
> > > > diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
> > > > index ae899f68551f..45ee598daf95 100644
> > > > --- a/drivers/cxl/core/region.c
> > > > +++ b/drivers/cxl/core/region.c
> > > > @@ -2178,7 +2178,9 @@ __cxl_decoder_detach(struct cxl_region *cxlr,
> > > >  		cxled->part = -1;
> > > >  
> > > >  	if (p->state > CXL_CONFIG_ACTIVE) {
> > > > -		cxl_region_decode_reset(cxlr, p->interleave_ways);
> > > > +		if (!test_bit(CXL_REGION_F_AUTO, &cxlr->flags))
> > > > +			cxl_region_decode_reset(cxlr, p->interleave_ways);
> > > > +
> > > >  		p->state = CXL_CONFIG_ACTIVE;
> > > 
> > 
> > Hi Dan,
> > 
> > > tl;dr: I do not think we need this, I do think we need to clarify to
> > > users what enable/disable and/or hot remove violence is handled and not
> > > handled by the CXL core.
> > 
> > I'm chiming in here because although this patch is no longer needed for
> > this series, it has become a dependency for the Type 2 series.
> 
> Like I replied to Alejandro it is not a dependency for the type-2 series
> [1]. It *is* a fix for the issue reported by PJ, but it can go in
> independent of the base type-2 work as a standalone capability.
> 
> [1]: http://lore.kernel.org/69b8b9181bafd_452b100cb@dwillia2-mobl4.notmuch
> 
> > So this
> > follow-up focuses on the hot-remove, endpoint-detach case where
> > preserving decoders across detach is still needed for later recovery.
> > 
> > Some inline responses to you, and then a diff is appended for a
> > direction check.
> > 
> > > So this looks deceptively simple, but I think it is incomplete or at
> > > least adds to the current confusion. A couple points to consider:
> > > 
> > > 1/ There is no corresponding clear_bit(CXL_REGION_F_AUTO, ...) anywhere in
> > > the driver. Yes, admin can still force cxl_region_decode_reset() via
> > > commit_store() path, but admin can not force
> > > cxl_region_teardown_targets() in the __cxl_decoder_detach() path. I do
> > > not like that this causes us to end up with 2 separate considerations
> > > for when __cxl_decoder_detach() skips cleanup actions
> > > (cxl_region_teardown_targets() and cxl_region_decode_reset()). See
> > > below, I think the cxl_region_teardown_targets() check is probably
> > > bogus.
> > 
> > Rather than repurposing CXL_REGION_F_AUTO, this splits decode-reset policy
> > from AUTO. A new region-scoped CXL_REGION_F_PRESERVE_DECODE flag is introduced
> > and cleared on explicit decommit in commit_store(). AUTO remains origin/assembly
> > state.
> 
> Just like the decoder LOCK bit the preservation setting is a decoder
> property, not a region property. Region auto-assembly is then just an
> automatic way to set that decoder policy.
> 
> So, no, I would not expect a new region flag for this policy.
> 
> > This does still leave two cleanup decisions:
> > 1) decode reset (now keyed off PRESERVE_DECODE)
> > 2) target teardown (still using existing AUTO behavior)
> > 
> > No change to cxl_region_teardown_targets() in this step.
> 
> Turns out that cxl_region_teardown_targets() never needed to consider
> the CXL_F_REGION_AUTO flag.
> 
> > > At a minimum I think commit_store() should clear CXL_REGION_F_AUTO on
> > > decommit such that cleaning up decoders and targets later proceeds as
> > > expected.
> > 
> > This point is addressed by clearing CXL_REGION_F_PRESERVE_DECODE instead.
> > Explicit decommit is treated as destructive and disables decode preservation
> > before unbind/reset.
> > 
> > > 
> > > 2/ The hard part about CXL region cleanup is that it needs to be prepared
> > > for:
> > > 
> > >  a/ user manually removes the region via sysfs
> > > 
> > >  b/ user manually disables cxl_port, cxl_mem, or cxl_acpi causing the
> > >     endpoint port to be removed
> > > 
> > >  c/ user physically removes the memdev causing the endpoint port to be
> > >     removed (CXL core can not tell the difference with 2b/ it just sees
> > >     cxl_mem_driver::remove() operation invocation)
> > > 
> > >  d/ setup action fails and region setup is unwound
> > 
> > Agreed. This change targets 2b, 2c.
> > 
> > >  
> > > The cxl_region_decode_reset() is in __cxl_decoder_detach() because of
> > > 2b/ and 2c/. No other chance to cleanup the decode topology once the
> > > endpoint decoders are on their way out of the system.
> > 
> > Agreed. The reset remains. Proposed change only makes it conditional on
> > explicit region policy rather than AUTO.
> > 
> > > 
> > > In this case though the patch was generated back when we were committed
> > > to cleaning up failed to assemble regions, a new 2d/ case, right?
> > > However, in that case the decoder is not leaving the system. The
> > > questions that arrive from that analysis are:
> > > 
> > > * Is this patch still needed now that there is no auto-cleanup?
> > 
> > Not for this Soft Reserved series, but yes for Type2 hotplug.
> 
> Type-2 hotplug is not the issue, it is boot-time configuration
> preservation over device reset which is a different challenge.
> 
> > > * If this patch is still needed is it better to skip
> > >   cxl_region_decode_reset() based on the 'enum cxl_detach_mode' rather
> > >   than the CXL_REGION_F_AUTO flag? I.e. skip reset in the 2d/ case, or
> > >   some other new general flag that says "please preserve hardware
> > >   configuration".
> > 
> > I looked at using and expanding the cxl_detach_mode enum and rejected as
> > not the right scope. The current detach mode is attached to an individual
> > detach operation, whereas preserve vs reset decision applies to the region
> > decode topology as a whole. If we expand detach mode for this region
> > wide policy, then may risk inconsistent handling across endpoint of the
> > same region. Just seemed wrong place. I could be missing another reason
> > why you looked at it.
> 
> Regions are an emergent property from decoder settings. Decoder settings
> come from firmware, user actions, and with the type-2 series driver
> actions. Firmware, user and driver actions are per-decoder especially
> because the behavior needed here is similar to the decoder LOCK bit.
> 
> Region assembly can set a default decoder policy, but the management of
> that decoder policy need not go through the region.
> 
> Either way, settling this question can be post type-2 base series event,
> not a lead-in dependency.
> 
> [..]
> > > It is helpful that violence has been the default so far. So it allows to
> > > introduce a decoder shutdown policy toggle where CXL_REGION_F_AUTO flags
> > > decoders as "preserve" by default. Region decommit clears that flag,
> > > and/or userspace can toggle that per endpoint decoder flag to determine
> > > what happens when decoders leave the system. That probably also wants
> > > some lockdown interaction such that root can not force unplug memory by
> > > unbinding a driver.
> > 
> > As a step in the direction you suggest, AND  aiming to address Type2
> > need, here is what I'd like a direction check on:
> > 
> > Start separating decode-reset policy rom CXL_REGION_F_AUTO:
> > - keep CXL_REGION_F_AUTO as origin / assembly semantics
> > - introduce CXL_REGION_F_PRESERVE_DECODE as a region-scoped policy
> 
> Not yet convinced about this.
> 
> > - initialize that policy from auto-assembly
> > - clear it on explicit decommit in commit_store()
> 
> My expectation is still clear it on decoder configuration change, add an
> attribute to toggle it independent of changing the decoder
> configuration.
> 
> > - use it to gate cxl_region_decode_reset() in __cxl_decoder_detach()
> 
> cxl_region_decode_reset() just automates asking each decoder to carry
> out reset if the decoder policy allows.
> 
> > The decode-reset decision is factored through a small helper,
> > cxl_region_preserve_decode(), so the policy can be extended independent
> > of the detach mechanics. Maybe overkill in this simple case, but I
> > wanted to acknowledge the 'policy' direction.
> 
> Appreciate you pulling this together. I want to land type-2 with the
> existing expectation that unload is always destructive then circle back
> to address this additional detail because it is more than just decoder
> policy that needs to be managed. The type-2 driver may need help finding
> its platform firmware configured address range if a device reset
> destroyed the decoder settings.

I did go first for decoder policy, but switched to region thinking
that this has to be managed at region level because region decode topology
is programmed as a unit so mixed preserve/reset policy across decoders
partitipating in a single active region seems scary.

I can switch to a decoder policy where region auto assembly still inits
a uniform preserve policy across participating programmed decoders and
teardown paths would clear the policy.

The other angle was future userspace access. It seems user intent would
likely be at region scope, with the kernel applying the policy across
the decoders that make up the region. So, sort of a control surface
that is region oriented, but implementation that lives on decoders.

I'll let the dust settle and see if there is anything I can pick up.



^ permalink raw reply

* [PATCH] thermal: core: fix use-after-free due to init/cancel delayed_work race
From: Mauricio Faria de Oliveira @ 2026-03-24 23:50 UTC (permalink / raw)
  To: Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba
  Cc: linux-pm, linux-kernel, kernel-dev, syzbot+3b3852c6031d0f30dfaf

If INIT_DELAYED_WORK() is called for a currently running work item,
cancel_delayed_work_sync() is unable to cancel/wait for it anymore,
as the work item's data bits required for that are cleared.

In the resume path, INIT_DELAYED_WORK() is called twice:
1) to replace the work function: thermal_zone_device_check/resume()
2) to restore it.

Both cases might race with the unregister path and bypass the call to
cancel_delayed_work_sync(), after which struct thermal_zone_device *tz
is freed, and the non-canceled/non-waited for work hits use-after-free.

Fix the first case with a dedicated work item for the resume function,
and the second case by initializing the work item(s) only during init.

Case 1 (reported by syzbot):

  Thread A:
    WORK: tz->poll_queue
      thermal_zone_device_check()
        ...

  Thread B:
    thermal_pm_notify() // syzbot reaches this with snapshot_release()
      thermal_pm_notify_complete()
        thermal_zone_pm_complete()
          INIT_DELAYED_WORK(&tz->poll_queue, ...)

  Thread C:
    thermal_zone_device_unregister()
      cancel_delayed_work_sync(&tz->poll_queue) // does not cancel/wait
      kfree(tz)

  Thread A:
        ...
        thermal_zone_device_update()
          guard(thermal_zone)(tz) // use-after-free!

Case 2:

  Thread A:
    WORK: tz_poll_queue
      thermal_zone_device_resume()
        thermal_zone_device_init()
          INIT_DELAYED_WORK(&tz->poll_queue, ...)
          ...

  Thread B:
    thermal_zone_device_unregister()
      cancel_delayed_work_sync(&tz->poll_queue) // does not cancel/wait
      kfree(tz)

  Thread A:
          ...
          tz->temperature = ... // use-after-free!

Note: in Case 1, thermal_zone_pm_complete() calls cancel_delayed_work()
before INIT_DELAYED_WORK(), but that does not wait for the work item to
finish (which could avoid the issue in that case), as it is not _sync().
Indeed, it should _not_ be _sync(), as it could block for a significant
time in __thermal_zone_device_update(); the reason of the Fixes: commit.

Fixes: 5a5efdaffda5 ("thermal: core: Resume thermal zones asynchronously")
Reported-by: syzbot+3b3852c6031d0f30dfaf@syzkaller.appspotmail.com
Closes: https://syzbot.org/bug?extid=3b3852c6031d0f30dfaf
Signed-off-by: Mauricio Faria de Oliveira <mfo@igalia.com>
---
These are the KASAN reports observed with synthetic reproducers.
(If you're interested, I can send them as well.)

This patch has been tested on v7.0-rc5 with the synthethic reproducers
and with these steps:
- Set polling_delay to 1000 ms to periodically start tz->poll_queue;
- Access /dev/snapshot in loop to periodically start tz->resume_queue;
- Manually unload test_power.ko to unregister and free memory
  while both work items were periodically started.
- Each test ran for ~1 minute until unregistering. Repeated 3 times.

Case 1:

This matches the syzbot report, except for the driver (unrelated).
- use-after-free in thermal_zone_device_check() callee
- allocated by thermal_zone_device_register_with_trips()
- freed by thermal_zone_device_unregister()
- last potentially related work creation: thermal_pm_notify()
- driver:
  - original: hid-nvidia-shield.ko
  - reproducer: test_power.ko
  - common: power_supply_register()

[   30.611925] ==================================================================
[   30.616232] BUG: KASAN: slab-use-after-free in mutex_lock+0x76/0xe0
[   30.618698] Write of size 8 at addr ffff888006f8b460 by task kworker/0:1/11
[   30.622799]
[   30.624803] CPU: 0 UID: 0 PID: 11 Comm: kworker/0:1 Not tainted 7.0.0-rc5+ #12 PREEMPT(lazy)
[   30.624835] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[   30.624875] Workqueue: events_freezable_pwr_efficient thermal_zone_device_check
[   30.624914] Call Trace:
[   30.624929]  <TASK>
[   30.624941]  dump_stack_lvl+0x4d/0x70
[   30.624970]  print_report+0x170/0x4f3
[   30.625027]  kasan_report+0xda/0x110
[   30.625094]  kasan_check_range+0x125/0x200
[   30.625119]  mutex_lock+0x76/0xe0
[   30.625180]  thermal_zone_device_check+0x40/0xb0
[   30.625203]  process_one_work+0x617/0xf00
[   30.625251]  worker_thread+0x422/0xbb0
[   30.625345]  kthread+0x2cb/0x3a0
[   30.625405]  ret_from_fork+0x357/0x540
[   30.625485]  ret_from_fork_asm+0x1a/0x30
[   30.625516]  </TASK>
[   30.625525]
[   30.661253] Allocated by task 248:
[   30.661484]  kasan_save_stack+0x30/0x50
[   30.661770]  kasan_save_track+0x14/0x30
[   30.662260]  __kasan_kmalloc+0x7f/0x90
[   30.662716]  __kmalloc_noprof+0x180/0x4b0
[   30.663211]  thermal_zone_device_register_with_trips+0xf4/0x11d0
[   30.663674]  thermal_tripless_zone_device_register+0x1f/0x30
[   30.664238]  __power_supply_register.part.0+0x887/0xcf0
[   30.664618]  0xffffffffc040204f
[   30.664952]  do_one_initcall+0x9f/0x3b0
[   30.665253]  do_init_module+0x281/0x820
[   30.665509]  load_module+0x4a5c/0x6300
[   30.665975]  init_module_from_file+0x161/0x180
[   30.666480]  idempotent_init_module+0x224/0x750
[   30.667180]  __x64_sys_finit_module+0xbf/0x130
[   30.667700]  do_syscall_64+0x101/0x4c0
[   30.668217]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   30.668621]
[   30.668713] Freed by task 261:
[   30.669036]  kasan_save_stack+0x30/0x50
[   30.669608]  kasan_save_track+0x14/0x30
[   30.670757]  kasan_save_free_info+0x3b/0x70
[   30.671293]  __kasan_slab_free+0x47/0x70
[   30.671591]  kfree+0x147/0x3b0
[   30.671901]  thermal_zone_device_unregister+0x305/0x3f0
[   30.672287]  power_supply_unregister+0xdd/0x120
[   30.672628]  0xffffffffc0401ac7
[   30.672924]  __do_sys_delete_module+0x2d3/0x480
[   30.673366]  do_syscall_64+0x101/0x4c0
[   30.673583]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   30.673926]
[   30.674079] Last potentially related work creation:
[   30.674531]  kasan_save_stack+0x30/0x50
[   30.674947]  kasan_record_aux_stack+0x8c/0xa0
[   30.675341]  __queue_work+0x69b/0x1010
[   30.675750]  mod_delayed_work_on+0xf3/0x100
[   30.676057]  thermal_pm_notify+0x2d1/0x420
[   30.676274]  notifier_call_chain+0xc1/0x2b0
[   30.676509]  blocking_notifier_call_chain+0x69/0xb0
[   30.676762]  snapshot_release+0x13b/0x1b0
[   30.677102]  __fput+0x35f/0xac0
[   30.677291]  task_work_run+0x116/0x1f0
[   30.677490]  exit_to_user_mode_loop+0xad/0x420
[   30.677724]  do_syscall_64+0x385/0x4c0
[   30.678062]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   30.678478]
[   30.678626] Second to last potentially related work creation:
[   30.680309]  kasan_save_stack+0x30/0x50
[   30.680657]  kasan_record_aux_stack+0x8c/0xa0
[   30.681084]  __queue_work+0x69b/0x1010
[   30.681427]  call_timer_fn+0x2c/0x270
[   30.681767]  __run_timers+0x437/0x880
[   30.682205]  run_timer_softirq+0x14b/0x280
[   30.682622]  handle_softirqs+0x18e/0x520
[   30.684318]  irq_exit_rcu+0xa5/0xe0
[   30.684660]  sysvec_apic_timer_interrupt+0x6b/0x80
[   30.685784]  asm_sysvec_apic_timer_interrupt+0x1a/0x20
[   30.686516]
[   30.686619] The buggy address belongs to the object at ffff888006f8b000
[   30.686619]  which belongs to the cache kmalloc-2k of size 2048
[   30.688109] The buggy address is located 1120 bytes inside of
[   30.688109]  freed 2048-byte region [ffff888006f8b000, ffff888006f8b800)
[   30.689309]
[   30.689446] The buggy address belongs to the physical page:
[   30.690192] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x6f88
[   30.690715] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[   30.692023] flags: 0x100000000000040(head|node=0|zone=1)
[   30.692604] page_type: f5(slab)
[   30.693162] raw: 0100000000000040 ffff888001042000 dead000000000100 dead000000000122
[   30.693747] raw: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000
[   30.694407] head: 0100000000000040 ffff888001042000 dead000000000100 dead000000000122
[   30.695338] head: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000
[   30.696115] head: 0100000000000003 ffffea00001be201 00000000ffffffff 00000000ffffffff
[   30.696779] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
[   30.697418] page dumped because: kasan: bad access detected
[   30.697794]
[   30.697983] Memory state around the buggy address:
[   30.698390]  ffff888006f8b300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   30.699047]  ffff888006f8b380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   30.699696] >ffff888006f8b400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   30.700237]                                                        ^
[   30.700727]  ffff888006f8b480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   30.702005]  ffff888006f8b500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   30.702739] ==================================================================
[   30.703531] Disabling lock debugging due to kernel taint

Case 2:

This was found during the analysis of Case 1.

[   28.879799] ==================================================================
[   28.880509] BUG: KASAN: slab-use-after-free in thermal_zone_device_init+0x6ae/0x760
[   28.881456] Write of size 4 at addr ffff8880020503d0 by task kworker/1:1/37
[   28.882215]
[   28.882339] CPU: 1 UID: 0 PID: 37 Comm: kworker/1:1 Not tainted 7.0.0-rc5+ #17 PREEMPT(lazy)
[   28.882345] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[   28.882348] Workqueue: events_freezable_pwr_efficient thermal_zone_device_resume
[   28.882356] Call Trace:
[   28.882360]  <TASK>
[   28.882363]  dump_stack_lvl+0x4d/0x70
[   28.882372]  print_report+0x170/0x4f3
[   28.882392]  kasan_report+0xda/0x110
[   28.882415]  thermal_zone_device_init+0x6ae/0x760
[   28.882423]  thermal_zone_device_resume+0x83/0xcb
[   28.882429]  process_one_work+0x617/0xf00
[   28.882444]  worker_thread+0x422/0xbb0
[   28.882471]  kthread+0x2cb/0x3a0
[   28.882489]  ret_from_fork+0x357/0x540
[   28.882513]  ret_from_fork_asm+0x1a/0x30
[   28.882522]  </TASK>
[   28.882525]
[   28.895017] Allocated by task 229:
[   28.895213]  kasan_save_stack+0x30/0x50
[   28.895431]  kasan_save_track+0x14/0x30
[   28.895757]  __kasan_kmalloc+0x7f/0x90
[   28.896109]  __kmalloc_noprof+0x180/0x4b0
[   28.896409]  thermal_zone_device_register_with_trips+0xf4/0x11d0
[   28.897214]  thermal_tripless_zone_device_register+0x1f/0x30
[   28.897583]  __power_supply_register.part.0+0x887/0xcf0
[   28.898127]  0xffffffffc040204f
[   28.898445]  do_one_initcall+0x9f/0x3b0
[   28.898874]  do_init_module+0x281/0x820
[   28.899260]  load_module+0x4a5c/0x6300
[   28.899609]  init_module_from_file+0x161/0x180
[   28.900058]  idempotent_init_module+0x224/0x750
[   28.900504]  __x64_sys_finit_module+0xbf/0x130
[   28.900973]  do_syscall_64+0x101/0x4c0
[   28.901287]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   28.901772]
[   28.901904] Freed by task 235:
[   28.902157]  kasan_save_stack+0x30/0x50
[   28.902451]  kasan_save_track+0x14/0x30
[   28.902828]  kasan_save_free_info+0x3b/0x70
[   28.903218]  __kasan_slab_free+0x47/0x70
[   28.903533]  kfree+0x147/0x3b0
[   28.903889]  thermal_zone_device_unregister+0x436/0x464
[   28.904440]  power_supply_unregister+0xdd/0x120
[   28.904939]  0xffffffffc0401ac7
[   28.905245]  __do_sys_delete_module+0x2d3/0x480
[   28.905681]  do_syscall_64+0x101/0x4c0
[   28.906082]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   28.906434]
[   28.906527] Last potentially related work creation:
[   28.907126]  kasan_save_stack+0x30/0x50
[   28.907507]  kasan_record_aux_stack+0x8c/0xa0
[   28.908025]  __queue_work+0x69b/0x1010
[   28.908439]  mod_delayed_work_on+0xf3/0x100
[   28.908989]  thermal_pm_notify+0x2d1/0x420
[   28.909463]  notifier_call_chain+0xc1/0x2b0
[   28.909981]  blocking_notifier_call_chain+0x69/0xb0
[   28.910472]  snapshot_release+0x13b/0x1b0
[   28.910868]  __fput+0x35f/0xac0
[   28.911239]  task_work_run+0x116/0x1f0
[   28.911704]  exit_to_user_mode_loop+0xad/0x420
[   28.912187]  do_syscall_64+0x385/0x4c0
[   28.912455]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   28.912951]
[   28.913132] Second to last potentially related work creation:
[   28.913663]  kasan_save_stack+0x30/0x50
[   28.913864]  kasan_record_aux_stack+0x8c/0xa0
[   28.914150]  __queue_work+0x69b/0x1010
[   28.914481]  call_timer_fn+0x2c/0x270
[   28.914847]  __run_timers+0x437/0x880
[   28.915163]  run_timer_softirq+0x14b/0x280
[   28.915507]  handle_softirqs+0x18e/0x520
[   28.915884]  irq_exit_rcu+0xa5/0xe0
[   28.916163]  sysvec_apic_timer_interrupt+0x6b/0x80
[   28.916641]  asm_sysvec_apic_timer_interrupt+0x1a/0x20
[   28.917206]
[   28.917371] The buggy address belongs to the object at ffff888002050000
[   28.917371]  which belongs to the cache kmalloc-2k of size 2048
[   28.918672] The buggy address is located 976 bytes inside of
[   28.918672]  freed 2048-byte region [ffff888002050000, ffff888002050800)
[   28.919703]
[   28.919804] The buggy address belongs to the physical page:
[   28.920235] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x2050
[   28.920950] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[   28.921553] flags: 0x100000000000040(head|node=0|zone=1)
[   28.922004] page_type: f5(slab)
[   28.922276] raw: 0100000000000040 ffff888001042000 dead000000000100 dead000000000122
[   28.922983] raw: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000
[   28.923673] head: 0100000000000040 ffff888001042000 dead000000000100 dead000000000122
[   28.924444] head: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000
[   28.925140] head: 0100000000000003 ffffea0000081401 00000000ffffffff 00000000ffffffff
[   28.925882] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
[   28.926576] page dumped because: kasan: bad access detected
[   28.927039]
[   28.927172] Memory state around the buggy address:
[   28.927739]  ffff888002050280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   28.928393]  ffff888002050300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   28.929087] >ffff888002050380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   28.929450]                                                  ^
[   28.929878]  ffff888002050400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   28.930472]  ffff888002050480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   28.931067] ==================================================================
[   28.931803] Disabling lock debugging due to kernel taint
---
 drivers/thermal/thermal_core.c | 17 +++++++++--------
 drivers/thermal/thermal_core.h |  2 ++
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index b7d706ed7ed96a4be3a2e2abe9d87d1b72b03651..236192b45e3f0ede54abbf96d517352322fbe023 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1396,11 +1396,16 @@ static void thermal_zone_device_check(struct work_struct *work)
 	thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 }
 
+static void thermal_zone_device_resume(struct work_struct *work);
+
 static void thermal_zone_device_init(struct thermal_zone_device *tz)
 {
 	struct thermal_trip_desc *td, *next;
 
-	INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
+	if (tz->state & TZ_STATE_FLAG_INIT) {
+		INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
+		INIT_DELAYED_WORK(&tz->resume_queue, thermal_zone_device_resume);
+	}
 
 	tz->temperature = THERMAL_TEMP_INIT;
 	tz->passive = 0;
@@ -1721,6 +1726,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 		return;
 
 	cancel_delayed_work_sync(&tz->poll_queue);
+	cancel_delayed_work_sync(&tz->resume_queue);
 
 	thermal_set_governor(tz, NULL);
 
@@ -1781,7 +1787,7 @@ static void thermal_zone_device_resume(struct work_struct *work)
 {
 	struct thermal_zone_device *tz;
 
-	tz = container_of(work, struct thermal_zone_device, poll_queue.work);
+	tz = container_of(work, struct thermal_zone_device, resume_queue.work);
 
 	guard(thermal_zone)(tz);
 
@@ -1834,13 +1840,8 @@ static void thermal_zone_pm_complete(struct thermal_zone_device *tz)
 	reinit_completion(&tz->resume);
 	tz->state |= TZ_STATE_FLAG_RESUMING;
 
-	/*
-	 * Replace the work function with the resume one, which will restore the
-	 * original work function and schedule the polling work if needed.
-	 */
-	INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_resume);
 	/* Queue up the work without a delay. */
-	mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, 0);
+	mod_delayed_work(system_freezable_power_efficient_wq, &tz->resume_queue, 0);
 }
 
 static void thermal_pm_notify_complete(void)
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index d3acff602f9ce1703172540a906c59089c98505d..9e757aa3cbcd1aeaf1537e9bf924b2b67a2a1a66 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -110,6 +110,7 @@ struct thermal_governor {
  * @lock:	lock to protect thermal_instances list
  * @node:	node in thermal_tz_list (in thermal_core.c)
  * @poll_queue:	delayed work for polling
+ * @resume_queue:	delayed work for resuming
  * @notify_event: Last notification event
  * @state: 	current state of the thermal zone
  * @debugfs:	this thermal zone device's thermal zone debug info
@@ -146,6 +147,7 @@ struct thermal_zone_device {
 	struct mutex lock;
 	struct list_head node;
 	struct delayed_work poll_queue;
+	struct delayed_work resume_queue;
 	enum thermal_notify_event notify_event;
 	u8 state;
 #ifdef CONFIG_THERMAL_DEBUGFS

---
base-commit: c369299895a591d96745d6492d4888259b004a9e
change-id: 20260324-thermal-core-uaf-init_delayed_work-5195ef033118

Best regards,
-- 
Mauricio Faria de Oliveira <mfo@igalia.com>


^ permalink raw reply related

* Re: [PATCH v4 0/5] mm: zone lock tracepoint instrumentation
From: Andrew Morton @ 2026-03-24 23:39 UTC (permalink / raw)
  To: Dmitry Ilvokhin
  Cc: Steven Rostedt, Matthew Wilcox, David Hildenbrand,
	Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Masami Hiramatsu, Mathieu Desnoyers, Rafael J. Wysocki,
	Pavel Machek, Len Brown, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Qi Zheng, Shakeel Butt, linux-kernel, linux-mm,
	linux-trace-kernel, linux-pm
In-Reply-To: <abv4riGLlubast8v@shell.ilvokhin.com>

On Thu, 19 Mar 2026 13:22:54 +0000 Dmitry Ilvokhin <d@ilvokhin.com> wrote:

> On Mon, Mar 16, 2026 at 05:40:50PM +0000, Dmitry Ilvokhin wrote:
> 
> [...]
> 
> > A possible generic solution is a trace_contended_release() for spin
> > locks, for example:
> > 
> >     if (trace_contended_release_enabled() &&
> >         atomic_read(&lock->val) & ~_Q_LOCKED_MASK)
> >         trace_contended_release(lock);
> > 
> > This might work on x86, but could increase code size and regress
> > performance on arches where spin_unlock() is inlined, such as arm64
> > under !PREEMPTION.
> 
> I took a stab at this idea and submitted an RFC [1].
> 
> The implementation builds on your earlier observation from Matthew that
> _raw_spin_unlock() is not inlined in most configurations. In those
> cases, when the tracepoint is disabled, this adds a single NOP on the
> fast path, with the conditional check staying out of line. The measured
> text size increase in this configuration is +983 bytes.
> 
> For configurations where _raw_spin_unlock() is inlined, the
> instrumentation does increase code size more noticeably
> (+71 KB in my measurements), since the check and out of line call is
> replicated at each call site.
> 
> This provides a generic release-side signal for contended locks,
> allowing: correlation of lock holders with waiters and measurement of
> contended hold times
> 
> This RFC addressing the same visibility gap without introducing per-lock
> instrumentation.
> 
> If this tradeoff is acceptable, this could be a generic alternative to
> lock-specific tracepoints.
> 
> [1]: https://lore.kernel.org/all/51aad0415b78c5a39f2029722118fa01eac77538.1773858853.git.d@ilvokhin.com 

That submission has met a disappointing response.

How should I proceed with this series "mm: zone lock tracepoint
instrumentation"?  It's not urgent so I'm inclined to put this on hold
while you pursue "locking: Add contended_release tracepoint to spinning
locks"?

Please send that v2 sometime and hopefully Steven can help push it along?

^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: power: Add power-domains-child-ids property
From: Rob Herring @ 2026-03-24 23:25 UTC (permalink / raw)
  To: Kevin Hilman (TI)
  Cc: Ulf Hansson, Geert Uytterhoeven, linux-pm, devicetree,
	linux-kernel, arm-scmi, linux-arm-kernel
In-Reply-To: <20260310-topic-lpm-pmdomain-child-ids-v1-1-5361687a18ff@baylibre.com>

On Tue, Mar 10, 2026 at 05:19:23PM -0700, Kevin Hilman (TI) wrote:
> Add binding documentation for the new power-domains-child-ids property,
> which works in conjunction with the existing power-domains property to
> establish parent-child relationships between a multi-domain power domain
> provider and external parent domains.
> 
> Each element in the uint32 array identifies the child domain
> ID (index) within the provider that should be made a child domain of
> the corresponding phandle entry in power-domains. The two arrays must
> have the same number of elements.
> 
> Signed-off-by: Kevin Hilman (TI) <khilman@baylibre.com>
> ---
>  Documentation/devicetree/bindings/power/power-domain.yaml | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/power/power-domain.yaml b/Documentation/devicetree/bindings/power/power-domain.yaml
> index b1147dbf2e73..a3d2af124d37 100644
> --- a/Documentation/devicetree/bindings/power/power-domain.yaml
> +++ b/Documentation/devicetree/bindings/power/power-domain.yaml
> @@ -68,6 +68,21 @@ properties:
>        by the given provider should be subdomains of the domain specified
>        by this binding.
>  
> +  power-domains-child-ids:
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    description:
> +      An array of child domain IDs that correspond to the power-domains
> +      property. This property is only applicable to power domain providers
> +      with "#power-domain-cells" > 0 (i.e., providers that supply multiple
> +      power domains). It specifies which of the provider's child domains
> +      should be associated with each parent domain listed in the power-domains
> +      property. The number of elements in this array must match the number of
> +      phandles in the power-domains property. Each element specifies the child
> +      domain ID (index) that should be made a child domain of the corresponding
> +      parent domain. This enables hierarchical power domain structures where
> +      different child domains from the same provider can have different
> +      parent domains.

Okay, I guess we stick with this. Sorry for the detour.

With the example fixed,

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>

Rob

^ permalink raw reply

* Re: [PATCH v5 2/4] cpupower-frequency-info.1: use the proper name of the --perf option
From: Shuah Khan @ 2026-03-24 23:11 UTC (permalink / raw)
  To: Roberto Ricci, Thomas Renninger, Shuah Khan, John B. Wyatt IV,
	John Kacur, linux-pm, linux-kernel, Shuah Khan
In-Reply-To: <32cdfa7a-765c-4f74-9839-d2e0b01435dc@linuxfoundation.org>

On 3/24/26 17:06, Shuah Khan wrote:
> On 3/24/26 16:39, Roberto Ricci wrote:
>> The cpupower-frequency-info(1) man page describes a '--perf' option.
>> Even though this form is accepted by the program, its proper name is
>> '--performance'.
>>
>> cpufreq-info.c:
>>     {"performance", no_argument,     NULL,     'c'},
>>
>> Signed-off-by: Roberto Ricci <io@r-ricci.it>
>> ---
>>   tools/power/cpupower/man/cpupower-frequency-info.1 | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
>> index 47fdd7218748..1173d4f31e69 100644
>> --- a/tools/power/cpupower/man/cpupower-frequency-info.1
>> +++ b/tools/power/cpupower/man/cpupower-frequency-info.1
>> @@ -53,7 +53,7 @@ human\-readable output for the \-f, \-w, \-s and \-y parameters.
>>   \fB\-n\fR \fB\-\-no-rounding\fR
>>   Output frequencies and latencies without rounding off values.
>>   .TP
>> -\fB\-c\fR \fB\-\-perf\fR
>> +\fB\-c\fR \fB\-\-performance\fR
> 
> I would keep perf and also add performance since --perf and --performance
> work - it is lot easier to type --perf

You can send just this one patch unless there are dependencies with
others.

thanks,
-- Shuah

^ permalink raw reply


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