* Re: [PATCH 0/4] Add i.MX94 remoteproc support and reset vector handling improvements
From: Peng Fan @ 2026-03-26 12:20 UTC (permalink / raw)
To: Daniel Baluta
Cc: Mathieu Poirier, Bjorn Andersson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-remoteproc,
devicetree, imx, linux-arm-kernel, linux-kernel, Peng Fan
In-Reply-To: <80c7815b-26d9-4876-a44f-3e17b6338dc6@oss.nxp.com>
On Wed, Mar 25, 2026 at 10:41:29AM +0200, Daniel Baluta wrote:
>On 3/23/26 16:32, Mathieu Poirier wrote:
>> On Fri, Mar 20, 2026 at 11:19:06AM +0200, Daniel Baluta wrote:
>>> On 3/12/26 14:36, Peng Fan (OSS) wrote:
>>>> This series adds remoteproc support for the i.MX94 family, including the
>>>> CM70, CM71, and CM33S cores, and introduces a new device‑tree property to
>>>> correctly derive the hardware reset vector for Cortex‑M processors whose
>>>> ELF entry point does not directly correspond to the actual reset address.
>>>>
>>>> Background:
>>>> Cortex‑M processors fetch their initial SP and PC from a fixed reset vector
>>>> table. While ELF images embed the entry point (e_entry), this value is
>>>> not always aligned to the hardware reset address. On platforms such as
>>>> i.MX94 CM33S, masking is required to compute the correct reset vector
>>>> address before programming the SoC reset registers.
>>> What happens if the reset vector is at 0 and the e_entry point is at 0x800...?
>>>
>>> In this case masking will no longer work! Can we implement a generic approach?
>>>
>> I will wait to see an R-B from Daniel before looking at this set.
>>
>> Thanks,
>> Mathieu
>>
>>
>Hi Mathieu, Peng,
>
>Patchseries mostly looks good to me. The only blocking issue here is how to correctly specify the hardware reset address.
>
>I see two options here:
>
>1) Create a special section in TCM that holds the PC/Stack initial value as concluded here [1]. But this
>
>doesn't work in all the cases
>
>2) Add a per device data that holds the hardware reset mask that gets applied to entry address read from ELF.
>
>I'm fine going with option 2) and that's because this change is IMX rproc driver specific, it scales well and will be maintained by Peng.
Thanks, I will go with option 2.
Thanks
Peng
>
>thanks,
>
>Daniel.
>
>[1] https://lore.kernel.org/linux-remoteproc/38476dd0-07a6-310f-1fba-2b3021a5b007@kontron.de/
>
^ permalink raw reply
* Re: [PATCH v6 14/40] arm_mpam: resctrl: Add boilerplate cpuhp and domain allocation
From: James Morse @ 2026-03-26 12:20 UTC (permalink / raw)
To: Ben Horgan, Gavin Shan
Cc: amitsinght, baisheng.gao, baolin.wang, carl, dave.martin, david,
dfustini, fenghuay, jonathan.cameron, kobak, lcherian,
linux-arm-kernel, linux-kernel, peternewman, punit.agrawal,
quic_jiles, reinette.chatre, rohit.mathew, scott, sdonthineni,
tan.shaopeng, xhao, catalin.marinas, will, corbet, maz, oupton,
joey.gouly, suzuki.poulose, kvmarm, zengheng4, linux-doc,
Shaopeng Tan
In-Reply-To: <80915f50-b5c9-4790-81c6-4f08b2af1274@arm.com>
Hi Ben, Gavin,
On 23/03/2026 10:13, Ben Horgan wrote:
> On 3/23/26 06:31, Gavin Shan wrote:
>> On 3/14/26 12:45 AM, Ben Horgan wrote:
>>> From: James Morse <james.morse@arm.com>
>>>
>>> resctrl has its own data structures to describe its resources. We can't use
>>> these directly as we play tricks with the 'MBA' resource, picking the MPAM
>>> controls or monitors that best apply. We may export the same component as
>>> both L3 and MBA.
>>>
>>> Add mpam_resctrl_res[] as the array of class->resctrl mappings we are
>>> exporting, and add the cpuhp hooks that allocated and free the resctrl
>>> domain structures. Only the mpam control feature are considered here and
>>> monitor support will be added later.
>>>
>>> While we're here, plumb in a few other obvious things.
>>>
>>> CONFIG_ARM_CPU_RESCTRL is used to allow this code to be built even though
>>> it can't yet be linked against resctrl.
>> With the following two comments addressed. I don't think none of them are critical
>> given the fact that this series has been respinned to v6 and may be ready for Linux
>> v7.1. If there is still a chance for another respin, they may be worthy to be addressed.
>>
>> Reviewed-by: Gavin Shan <gshan@redhat.com>
I've picked up the change from your second comment, I assume you're happy to keep this
tag. (otherwise shout!)
>>> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
>>> new file mode 100644
>>> index 000000000000..e698b534e3db
>>> --- /dev/null
>>> +++ b/drivers/resctrl/mpam_resctrl.c
>>> +static struct mpam_resctrl_dom *
>>> +mpam_resctrl_alloc_domain(unsigned int cpu, struct mpam_resctrl_res *res)
>>> +{
>>> + int err;
>>> + struct mpam_resctrl_dom *dom;
>>> + struct rdt_ctrl_domain *ctrl_d;
>>> + struct mpam_class *class = res->class;
>>> + struct mpam_component *comp_iter, *ctrl_comp;
>>> + struct rdt_resource *r = &res->resctrl_res;
>>> +
>>> + lockdep_assert_held(&domain_list_lock);
>>> +
>>> + ctrl_comp = NULL;
>>> + guard(srcu)(&mpam_srcu);
>>> + list_for_each_entry_srcu(comp_iter, &class->components, class_list,
>>> + srcu_read_lock_held(&mpam_srcu)) {
>>> + if (cpumask_test_cpu(cpu, &comp_iter->affinity)) {
>>> + ctrl_comp = comp_iter;
>>> + break;
>>> + }
>>> + }
>>> +
>>> + /* class has no component for this CPU */
>>> + if (WARN_ON_ONCE(!ctrl_comp))
>>> + return ERR_PTR(-EINVAL);
>>> +
>>> + dom = kzalloc_node(sizeof(*dom), GFP_KERNEL, cpu_to_node(cpu));
>>> + if (!dom)
>>> + return ERR_PTR(-ENOMEM);
>>> +
>>> + if (r->alloc_capable) {
>>> + dom->ctrl_comp = ctrl_comp;
>>> +
>>> + ctrl_d = &dom->resctrl_ctrl_dom;
>>> + mpam_resctrl_domain_hdr_init(cpu, ctrl_comp, r->rid, &ctrl_d->hdr);
>>> + ctrl_d->hdr.type = RESCTRL_CTRL_DOMAIN;
>>> + err = resctrl_online_ctrl_domain(r, ctrl_d);
>>> + if (err)
>>> + goto free_domain;
>>> +
>>> + mpam_resctrl_domain_insert(&r->ctrl_domains, &ctrl_d->hdr);
>>> + } else {
>>> + pr_debug("Skipped control domain online - no controls\n");
>>> + }
>>> + return dom;
>> Even though we will never support "r->alloc_capable == false", it's worthy to maintain
>> the consistence in the code level here, meaning @dom needs to be released with a proper
>> error number returned.
>>
>> if (r->alloc_capable) {
>> :
>> } else {
>> pr_debug("Skipped control domain online - no controls\n");
>> err = -EINVAL;
>> goto free_domain;
>> }
>>
>> Alternatively, the check can be done before locating the component from its calss.
>>
>>
>> lockdep_assert_held(&domain_list_lock);
>>
>> if (!r->alloc_capable) {
>> pr_debug("Skipped control domain online - no controls\n");
>> return ERR_PTR(-EINVAL);
>> }
>>
>> ctrl_comp = NULL;
>
> Once monitor support is added later in the series this is no longer an
> error path as monitor only platforms are valid. In order to avoid adding
> a change and then reverting it later in the series I would like to keep
> this as it is.
I've left this as it is - adding the monitoring support builds on top of this.
>>> +int mpam_resctrl_online_cpu(unsigned int cpu)
>>> +{
>>> + struct mpam_resctrl_res *res;
>>> + enum resctrl_res_level rid;
>>> +
>>> + guard(mutex)(&domain_list_lock);
>>> + for_each_mpam_resctrl_control(res, rid) {
>>> + struct mpam_resctrl_dom *dom;
>>> + struct rdt_resource *r = &res->resctrl_res;
>>> +
>>> + if (!res->class)
>>> + continue; // dummy_resource;
>>> +
>>> + dom = mpam_resctrl_get_domain_from_cpu(cpu, res);
>>> + if (!dom) {
>>> + dom = mpam_resctrl_alloc_domain(cpu, res);
>>> + } else {
>>> + if (r->alloc_capable) {
>>> + struct rdt_ctrl_domain *ctrl_d = &dom->resctrl_ctrl_dom;
>>> +
>>> + mpam_resctrl_online_domain_hdr(cpu, &ctrl_d->hdr);
>>> + }
>>> + }
>>> + if (IS_ERR(dom))
>>> + return PTR_ERR(dom);
>>> + }
>>> +
>>
>> I think the "if (IS_ERR(dom))" check can be moved after "dom = mpam_resctrl_alloc_domain(cpu, res)"
>> because it seems the only path where an erroneous domain can be returned.
>>
>> dom = mpam_resctrl_get_domain_from_cpu(cpu, res);
>> if (!dom) {
>> dom = mpam_resctrl_alloc_domain(cpu, res);
>> if (IS_ERR(dom))
>> return PTR_ERR(dom);
>> } else {
>> ...
>> }
>
> Yes, that would be clearer. I'll make this change if a respin becomes needed.
Applied locally.
Thanks!
James
^ permalink raw reply
* Re: [PATCH v6 1/5] mm: rmap: support batched checks of the references for large folios
From: Lorenzo Stoakes (Oracle) @ 2026-03-26 12:21 UTC (permalink / raw)
To: Baolin Wang
Cc: David Hildenbrand (Arm), Barry Song, akpm, catalin.marinas, will,
lorenzo.stoakes, ryan.roberts, Liam.Howlett, vbabka, rppt, surenb,
mhocko, riel, harry.yoo, jannh, willy, dev.jain, linux-mm,
linux-arm-kernel, linux-kernel
In-Reply-To: <aef474b9-5286-46f4-99d2-43d0b85f7176@linux.alibaba.com>
On Thu, Mar 26, 2026 at 08:04:10PM +0800, Baolin Wang wrote:
>
>
> On 3/26/26 7:10 PM, Lorenzo Stoakes (Oracle) wrote:
> > On Thu, Mar 26, 2026 at 09:47:51AM +0800, Baolin Wang wrote:
> > >
> > >
> > > On 3/25/26 11:06 PM, Lorenzo Stoakes (Oracle) wrote:
> > > > On Wed, Mar 25, 2026 at 03:58:36PM +0100, David Hildenbrand (Arm) wrote:
> > > > > On 3/25/26 15:36, Lorenzo Stoakes (Oracle) wrote:
> > > > > > On Mon, Mar 16, 2026 at 03:15:18PM +0100, David Hildenbrand (Arm) wrote:
> > > > > > > On 3/16/26 07:25, Baolin Wang wrote:
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > Sure. However, after investigating RISC‑V and x86, I found that
> > > > > > > > ptep_clear_flush_young() does not flush the TLB on these architectures:
> > > > > > > >
> > > > > > > > int ptep_clear_flush_young(struct vm_area_struct *vma,
> > > > > > > > unsigned long address, pte_t *ptep)
> > > > > > > > {
> > > > > > > > /*
> > > > > > > > * On x86 CPUs, clearing the accessed bit without a TLB flush
> > > > > > > > * doesn't cause data corruption. [ It could cause incorrect
> > > > > > > > * page aging and the (mistaken) reclaim of hot pages, but the
> > > > > > > > * chance of that should be relatively low. ]
> > > > > > > > *
> > > > > > > > * So as a performance optimization don't flush the TLB when
> > > > > > > > * clearing the accessed bit, it will eventually be flushed by
> > > > > > > > * a context switch or a VM operation anyway. [ In the rare
> > > > > > > > * event of it not getting flushed for a long time the delay
> > > > > > > > * shouldn't really matter because there's no real memory
> > > > > > > > * pressure for swapout to react to. ]
> > > > > > > > */
> > > > > > > > return ptep_test_and_clear_young(vma, address, ptep);
> > > > > > > > }
> > > > > > >
> > > > > > > You'd probably want an arch helper then, that tells you whether
> > > > > > > a flush_tlb_range() after ptep_test_and_clear_young() is required.
> > > > > > >
> > > > > > > Or some special flush_tlb_range() helper.
> > > > > > >
> > > > > > > I agree that it requires more work.
> > >
> > > (Sorry, David. I forgot to reply to your email because I've had a lot to
> > > sort out recently.)
> > >
> > > Rather than adding more arch helpers (we already have plenty for the young
> > > flag check), I think we should try removing the TLB flush, as I mentioned to
> > > Barry[1]. MGLRU reclaim already skips the TLB flush, and it seems to work
> > > fine. What do you think?
> > >
> > > Here are our previous attempts to remove the TLB flush:
> > >
> > > My patch: https://lkml.org/lkml/2023/10/24/533
> > > Barry's patch:
> > > https://lore.kernel.org/lkml/20220617070555.344368-1-21cnbao@gmail.com/
> > >
> > > [1] https://lore.kernel.org/all/6bdc4b03-9631-4717-a3fa-2785a7930aba@linux.alibaba.com/
> > >
> > > > > > Sorry unclear here - does the series need more work or does a follow up patch
> > > > > > need more work?
> > > > >
> > > > > Follow up!
> > > >
> > > > Ok good as in mm-stable now. Sadly means I don't get to review it but there we
> > > > go.
> > >
> > > Actually this patchset has already been merged upstream:)
>
> Let me try to make things clear.
>
> > Err but this revision was sent _during_ the merge window...?
> >
> > Was sent on 9th Feb on Monday in merge window week 1, with a functional change
> > listed:
> >
> > - Skip batched unmapping for uffd case, reported by Dev. Thanks.
> >
> > And then sent in 2nd batch on 18th Feb (see [0]).
> >
> > So we were ok with 1 week of 'testing' (does anybody actually test -next during
> > the merge window? Was it even sent to -next?) for what appears to be a
> > functional change?
>
> I posted v5 on Dec 26th[0], and it collected quite a few Reviewed-by tags
> and sat in mm-unstable for testing.
>
> Later, Dev reported a uffd-related issue (I hope you recall that
> discussion). I posted a fix[1] for it on Jan 16th, which Andrew accepted.
>
> Since then, the v5 series (plus the fix) continued to be tested in
> mm-unstable. We kept it there mainly because David mentioned he wanted to
> review the series, so we were waiting for his time.
>
> On Feb 9th, after returning from vacation, David reviewed the series
> (thanks, David!). I replied to and addressed all his comments, then posted
> v6 on the same day[2].
OK thanks, I see that now.
I still don't think we should have made any changes _during_ the merge window,
even if they were simple code quality things.
Changing patches then seems just crazy to me, as even code quality stuff can
cause unexpected bugs, and now we're having upstream take it.
Also this speaks to -fix patches just being broken in general.
If you'd just respun with the fix as a v6, then we'd know 'v6 sent on 16th Jan
addressed this' and there'd be no isssue.
Now v5 isn't v5, there's v5 and something-not-v5 and to have a sense of the
testing you have to go read a bunch of email chains.
It also means change logs are now really inaccurate:
Changes from v5:
- Collect reviewed tags from Ryan, Harry and David. Thanks.
- Fix some coding style issues (per David).
- Skip batched unmapping for uffd case, reported by Dev. Thanks.
And that to me means 'v5 didn't have this, v6 does'.
And it's really hard to track timelines for testing.
>
> Additionally, v6 had no functional changes compared to v5 + the fix, and it
> mainly addressed some coding style issues pointed out by David. I also
> discussed this with David off-list, and since there were no functional
> changes, my expectation was that it could still make it into the merge
> window. That is why v6 was merged.
Yeah, we still shouldn't have taken changes to a series DURING the merge window,
it's just crazy.
>
> [0] https://lore.kernel.org/linux-mm/cover.1766631066.git.baolin.wang@linux.alibaba.com/#t
> [1] https://lore.kernel.org/linux-mm/20260116162652.176054-1-baolin.wang@linux.alibaba.com/
> [2] https://lore.kernel.org/all/cover.1770645603.git.baolin.wang@linux.alibaba.com/
>
> > And there was ongoing feedback on this and the v5 series (at [1])?
>
> Regarding the feedback on v5, I believe everything has been addressed.
>
> > This doesn't really feel sane?
> >
> > And now I'm confused as to whether mm-stable patches can collect tags, since
> > presumably this was in mm-stable at the point this respin was done?
> >
> > Maybe I'm missing something here but this doesn't feel like a sane process?
>
> Andrew, David, please correct me if I've missed anything. Also, please let
> me know if there's anything in the process that needs to be improved.
> Thanks.
This isn't on you, it's about the process as a whole. We need clear rules about
when changes will be accepted and when not.
And frankly I think we need to do away with fix patches as a whole based on
this, or at least anything even vaguely non-trivial or that potentially impacts
code.
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH net-next v2 3/4] net: phy: air_phy_lib: Factorize BuckPBus register accessors
From: Andrew Lunn @ 2026-03-26 12:30 UTC (permalink / raw)
To: Louis-Alexis Eyraud
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
AngeloGioacchino Del Regno, Heiner Kallweit, Russell King,
kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <20260326-add-airoha-an8801-support-v2-3-1a42d6b6050f@collabora.com>
> @@ -480,8 +287,8 @@ static int en8811h_wait_mcu_ready(struct phy_device *phydev)
> {
> int ret, reg_value;
>
> - ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
> - EN8811H_FW_CTRL_1_FINISH);
> + ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
> + EN8811H_FW_CTRL_1_FINISH);
Is a rename required? Is the namespace air_buckpbus_ used somewhere
else?
Andrew
^ permalink raw reply
* Re: [PATCH 1/3] pinctrl: mediatek: Add gpio-range record in pinctrl driver
From: Fred-WY Chen (陳威宇) @ 2026-03-26 12:33 UTC (permalink / raw)
To: andriy.shevchenko@intel.com, Deep Pani,
Lei Xue (薛磊), Mandeep S
Cc: Yong Mao (毛勇), sean.wang@kernel.org,
Qingliang Li (黎晴亮),
Yaoy Wang (王瑶瑶), AngeloGioacchino Del Regno,
linux-gpio@vger.kernel.org, linus.walleij@linaro.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
Cathy Xu (许华婷),
linux-mediatek@lists.infradead.org, matthias.bgg@gmail.com,
Ye Wang (王叶),
Shunxi Zhang (章顺喜)
In-Reply-To: <aSdBt937C6Cjj_8s@black.igk.intel.com>
On Wed, 2025-11-26 at 19:06 +0100, Andy Shevchenko wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On Tue, Nov 25, 2025 at 10:36:34AM +0800, Lei Xue wrote:
> > Kernel GPIO subsystem mapping hardware pin number to a different
> > range of gpio number. Add gpio-range structure to hold
> > the mapped gpio range in pinctrl driver. That enables the kernel
> > to search a range of mapped gpio range against a pinctrl device.
>
> ...
>
> > static int mtk_build_gpiochip(struct mtk_pinctrl *hw)
> > {
> > struct gpio_chip *chip = &hw->chip;
>
> > if (ret < 0)
> > return ret;
> >
> > + mtk_pinctrl_gpio_range_init(hw, chip);
> > +
> > return 0;
>
> We have a callback for that in struct gpio_chip. Any reason not to
> use it?
>
> > }
>
> ...
>
> > + pinctrl_add_gpio_range(hw->pctrl, &hw->range);
>
> Not sure if this is needed.
>
Hi Deep,
Could you please check this and feedback?
Regards,
Fred-WY Chen
> --
> With Best Regards,
> Andy Shevchenko
>
>
^ permalink raw reply
* Re: [PATCH v2 09/12] arm64: dts: imx8mp-sr-som: Correct PAD settings for PMIC_nINT
From: Josua Mayer @ 2026-03-26 12:33 UTC (permalink / raw)
To: Peng Fan, Laurent Pinchart, Peng Fan (OSS)
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Shawn Guo,
Daniel Scally, Marco Felsch, Gilles Talis, Viorel Suman,
S.J. Wang, Jagan Teki, Manoj Sai, matteo.lisi, Ray Chang,
Richard Hu, Heiko Schocher, Martyn Welch,
Goran Rađenović, Börge Strümpfel,
Christoph Niedermaier, Marek Vasut, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, kernel@dh-electronics.com
In-Reply-To: <PAXPR04MB845972866AB6A7E85D1570CB8856A@PAXPR04MB8459.eurprd04.prod.outlook.com>
Hi Peng,
Am 26.03.26 um 10:55 schrieb Peng Fan:
>> Subject: Re: [PATCH v2 09/12] arm64: dts: imx8mp-sr-som: Correct
>> PAD settings for PMIC_nINT
>>> --- a/arch/arm64/boot/dts/freescale/imx8mp-sr-som.dtsi
>>> +++ b/arch/arm64/boot/dts/freescale/imx8mp-sr-som.dtsi
>>> @@ -174,7 +174,7 @@ pmic: pmic@25 {
>>> pinctrl-0 = <&pmic_pins>;
>>> pinctrl-names = "default";
>>> interrupt-parent = <&gpio1>;
>>> - interrupts = <3 GPIO_ACTIVE_LOW>;
>>> + interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
>> This is a good change, but it should be mentioned in the commit
>> message, or split to a separate patch. Same for other patches in this
>> series where you make the same change.
> Thanks, waiting to see if any board owners would give a test.
> Then I will update in V3.
>
> Thanks,
> Peng.
Looks correct to me.
Reviewed-by: Josua Mayer <josua@solid-run.com>
^ permalink raw reply
* Re: [PATCH v5 2/9] dt-bindings: mmc: amlogic: Add compatible for T7 mmc
From: Ulf Hansson @ 2026-03-26 12:33 UTC (permalink / raw)
To: Ronald Claveau
Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Johannes Berg,
van Spriel, linux-arm-kernel, linux-amlogic, devicetree,
linux-kernel, linux-mmc, linux-wireless, Conor Dooley,
Xianwei Zhao
In-Reply-To: <20260326-add-emmc-t7-vim4-v5-2-d3f182b48e9d@aliel.fr>
On Thu, 26 Mar 2026 at 11:01, Ronald Claveau <linux-kernel-dev@aliel.fr> wrote:
>
> Add amlogic,t7-mmc compatible string, falling back to amlogic,meson-axg-mmc
> as the T7 MMC controller is compatible with the AXG implementation.
>
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Acked-by: Rob Herring (Arm) <robh@kernel.org>
> Reviewed-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
Applied for next, thanks!
Kind regards
Uffe
> ---
> Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
> index 57646575a13f8..976f36de2091c 100644
> --- a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx-mmc.yaml
> @@ -19,6 +19,10 @@ allOf:
> properties:
> compatible:
> oneOf:
> + - items:
> + - enum:
> + - amlogic,t7-mmc
> + - const: amlogic,meson-axg-mmc
> - const: amlogic,meson-axg-mmc
> - items:
> - const: amlogic,meson-gx-mmc
>
> --
> 2.49.0
>
^ permalink raw reply
* Re: [PATCH v2 1/2] dt-bindings: mmc: hisilicon,hi3660-dw-mshc: Convert to DT schema
From: Ulf Hansson @ 2026-03-26 12:34 UTC (permalink / raw)
To: Bhargav Joshi
Cc: devicetree, linux-arm-kernel, xuwei5, robh, krzk+dt, conor+dt,
zhangfei.gao, linux-mmc, daniel.baluta, simona.toaca, d-gole,
m-chawdhry, linux-kernel
In-Reply-To: <20260325225439.68161-2-rougueprince47@gmail.com>
On Wed, 25 Mar 2026 at 23:55, Bhargav Joshi <rougueprince47@gmail.com> wrote:
>
> Convert the Hisilicon DesignWare Mobile Storage Host Controller
> (dw-mshc) bindings from text format to DT schema.
>
> As part of this conversion, the binding file is renamed from
> k3-dw-mshc.txt to hisilicon,hi3660-dw-mshc.yaml to align with compatible
> string naming conventions. Examples have been updated to pass schema
> validation.
>
> Note: synopsys-dw-mshc binding specifies clock names as "biu" followed
> by "ciu". However, this Hisilicon binding reverses the order to 'ciu'
> then 'biu' to match both the legacy text binding and in-kernel Hisilicon
> DTS board files.
>
> Signed-off-by: Bhargav Joshi <rougueprince47@gmail.com>
> Acked-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Applied for next, thanks!
Kind regards
Uffe
> ---
> Changes in v2:
> - Grouped compatible strings into an enum.
> - Replaced raw numbers with proper flags.
> - Fixed property order and removed invalid hex values.
> - Added explanation for clock order change in commit message.
> - Collected Acked-by tag.
>
> .../mmc/hisilicon,hi3660-dw-mshc.yaml | 117 ++++++++++++++++++
> .../devicetree/bindings/mmc/k3-dw-mshc.txt | 73 -----------
> 2 files changed, 117 insertions(+), 73 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml
> delete mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>
> diff --git a/Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml
> new file mode 100644
> index 000000000000..296bd776488e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml
> @@ -0,0 +1,117 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mmc/hisilicon,hi3660-dw-mshc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Hisilicon specific extensions to the Synopsys Designware Mobile Storage Host Controller
> +
> +maintainers:
> + - Zhangfei Gao <zhangfei.gao@linaro.org>
> +
> +description:
> + The Synopsys designware mobile storage host controller is used to interface
> + a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> + differences between the core Synopsys dw mshc controller properties described
> + by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> + extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +allOf:
> + - $ref: /schemas/mmc/synopsys-dw-mshc-common.yaml#
> +
> +properties:
> + compatible:
> + oneOf:
> + - enum:
> + - hisilicon,hi3660-dw-mshc
> + - hisilicon,hi4511-dw-mshc
> + - hisilicon,hi6220-dw-mshc
> + - items:
> + - const: hisilicon,hi3670-dw-mshc
> + - const: hisilicon,hi3660-dw-mshc
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: card interface unit clock
> + - description: bus interface unit clock
> +
> + clock-names:
> + items:
> + - const: ciu
> + - const: biu
> +
> + hisilicon,peripheral-syscon:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description: phandle of syscon used to control peripheral.
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - clocks
> + - clock-names
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/hi3620-clock.h>
> + #include <dt-bindings/gpio/gpio.h>
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> + mmc@fcd03000 {
> + compatible = "hisilicon,hi4511-dw-mshc";
> + reg = <0xfcd03000 0x1000>;
> + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> + clock-names = "ciu", "biu";
> + vmmc-supply = <&ldo12>;
> + fifo-depth = <0x100>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> + bus-width = <4>;
> + disable-wp;
> + cd-gpios = <&gpio10 3 GPIO_ACTIVE_HIGH>;
> + cap-mmc-highspeed;
> + cap-sd-highspeed;
> + };
> +
> + - |
> + #include <dt-bindings/clock/hi6220-clock.h>
> + #include <dt-bindings/gpio/gpio.h>
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + mmc@f723e000 {
> + compatible = "hisilicon,hi6220-dw-mshc";
> + reg = <0x0 0xf723e000 0x0 0x1000>;
> + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clock_sys HI6220_MMC1_CIUCLK>,
> + <&clock_sys HI6220_MMC1_CLK>;
> + clock-names = "ciu", "biu";
> + bus-width = <4>;
> + disable-wp;
> + cap-sd-highspeed;
> + sd-uhs-sdr12;
> + sd-uhs-sdr25;
> + card-detect-delay = <200>;
> + hisilicon,peripheral-syscon = <&ao_ctrl>;
> + cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
> + pinctrl-names = "default", "idle";
> + pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>;
> + pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>;
> + vqmmc-supply = <&ldo7>;
> + vmmc-supply = <&ldo10>;
> + };
> + };
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> deleted file mode 100644
> index 36c4bea675d5..000000000000
> --- a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> +++ /dev/null
> @@ -1,73 +0,0 @@
> -* Hisilicon specific extensions to the Synopsys Designware Mobile
> - Storage Host Controller
> -
> -Read synopsys-dw-mshc.txt for more details
> -
> -The Synopsys designware mobile storage host controller is used to interface
> -a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> -differences between the core Synopsys dw mshc controller properties described
> -by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> -extensions to the Synopsys Designware Mobile Storage Host Controller.
> -
> -Required Properties:
> -
> -* compatible: should be one of the following.
> - - "hisilicon,hi3660-dw-mshc": for controllers with hi3660 specific extensions.
> - - "hisilicon,hi3670-dw-mshc", "hisilicon,hi3660-dw-mshc": for controllers
> - with hi3670 specific extensions.
> - - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extensions.
> - - "hisilicon,hi6220-dw-mshc": for controllers with hi6220 specific extensions.
> -
> -Optional Properties:
> -- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral.
> -
> -Example:
> -
> - /* for Hi3620 */
> -
> - /* SoC portion */
> - dwmmc_0: dwmmc0@fcd03000 {
> - compatible = "hisilicon,hi4511-dw-mshc";
> - reg = <0xfcd03000 0x1000>;
> - interrupts = <0 16 4>;
> - #address-cells = <1>;
> - #size-cells = <0>;
> - clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> - clock-names = "ciu", "biu";
> - };
> -
> - /* Board portion */
> - dwmmc0@fcd03000 {
> - vmmc-supply = <&ldo12>;
> - fifo-depth = <0x100>;
> - pinctrl-names = "default";
> - pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> - bus-width = <4>;
> - disable-wp;
> - cd-gpios = <&gpio10 3 0>;
> - cap-mmc-highspeed;
> - cap-sd-highspeed;
> - };
> -
> - /* for Hi6220 */
> -
> - dwmmc_1: dwmmc1@f723e000 {
> - compatible = "hisilicon,hi6220-dw-mshc";
> - bus-width = <0x4>;
> - disable-wp;
> - cap-sd-highspeed;
> - sd-uhs-sdr12;
> - sd-uhs-sdr25;
> - card-detect-delay = <200>;
> - hisilicon,peripheral-syscon = <&ao_ctrl>;
> - reg = <0x0 0xf723e000 0x0 0x1000>;
> - interrupts = <0x0 0x49 0x4>;
> - clocks = <&clock_sys HI6220_MMC1_CIUCLK>, <&clock_sys HI6220_MMC1_CLK>;
> - clock-names = "ciu", "biu";
> - cd-gpios = <&gpio1 0 1>;
> - pinctrl-names = "default", "idle";
> - pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>;
> - pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>;
> - vqmmc-supply = <&ldo7>;
> - vmmc-supply = <&ldo10>;
> - };
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH RESEND] mmc: mtk-sd: disable new_tx/rx and modify related settings for mt8189
From: Ulf Hansson @ 2026-03-26 12:34 UTC (permalink / raw)
To: Cathy Xu
Cc: Chaotian Jing, Matthias Brugger, AngeloGioacchino Del Regno,
Louis-Alexis Eyraud, linux-mmc, linux-kernel, linux-arm-kernel,
linux-mediatek, Mengqi Zhang, Wenbin Mei, Andy-ld Lu, Axe Yang,
Yong Mao, stable
In-Reply-To: <20260326030759.8107-1-ot_cathy.xu@mediatek.com>
On Thu, 26 Mar 2026 at 04:08, Cathy Xu <ot_cathy.xu@mediatek.com> wrote:
>
> Disable new_tx/rx to avoid data transmission instability, and adjust
> .data_tune, .stop_dly_sel, and .pop_en_cnt to fit the overall
> configuration after disabling new_tx/rx, making it more compatible
> with mt8189.
>
> Fixes: 846a3a2fdff5 ("mmc: mtk-sd: add support for MT8189 SoC")
> Cc: stable@vger.kernel.org
> Tested-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
> Signed-off-by: Cathy Xu <ot_cathy.xu@mediatek.com>
Applied for fixes and by dropping the stable-tag as it's superfluous
in this case. Thanks!
Kind regards
Uffe
> ---
> drivers/mmc/host/mtk-sd.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index 302ac8529c4f..b2680cc054bd 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -682,15 +682,15 @@ static const struct mtk_mmc_compatible mt8189_compat = {
> .needs_top_base = true,
> .pad_tune_reg = MSDC_PAD_TUNE0,
> .async_fifo = true,
> - .data_tune = true,
> + .data_tune = false,
> .busy_check = true,
> .stop_clk_fix = true,
> - .stop_dly_sel = 1,
> - .pop_en_cnt = 2,
> + .stop_dly_sel = 3,
> + .pop_en_cnt = 8,
> .enhance_rx = true,
> .support_64g = true,
> - .support_new_tx = true,
> - .support_new_rx = true,
> + .support_new_tx = false,
> + .support_new_rx = false,
> .support_spm_res_release = true,
> };
>
> --
> 2.45.2
>
^ permalink raw reply
* Re: [PATCH 3/3] pinctrl: mediatek: mt8901: Add pinctrl driver for MT8901
From: Fred-WY Chen (陳威宇) @ 2026-03-26 12:36 UTC (permalink / raw)
To: Mandeep S, AngeloGioacchino Del Regno, Deep Pani,
sean.wang@kernel.org, matthias.bgg@gmail.com,
Lei Xue (薛磊), linus.walleij@linaro.org
Cc: Qingliang Li (黎晴亮),
Ye Wang (王叶), Yaoy Wang (王瑶瑶),
linux-gpio@vger.kernel.org, Yong Mao (毛勇),
Shunxi Zhang (章顺喜),
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
Cathy Xu (许华婷)
In-Reply-To: <df11bbf1-09d1-40fc-be56-6a98d90abcb6@collabora.com>
On Tue, 2025-11-25 at 10:56 +0100, AngeloGioacchino Del Regno wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> Il 25/11/25 03:36, Lei Xue ha scritto:
> > Add mt8901 pinctrl, gpio and eint driver implementation.
> >
> > Signed-off-by: Lei Xue <lei.xue@mediatek.com>
> > ---
> > drivers/pinctrl/mediatek/Kconfig | 12 +
> > drivers/pinctrl/mediatek/Makefile | 1 +
> > drivers/pinctrl/mediatek/mtk-eint.c | 4 +
> > drivers/pinctrl/mediatek/mtk-eint.h | 1 +
> > drivers/pinctrl/mediatek/pinctrl-mt8901.c | 1460 +++++++++++
> > drivers/pinctrl/mediatek/pinctrl-mtk-mt8901.h | 2130
> > +++++++++++++++++
> > 6 files changed, 3608 insertions(+)
> > create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt8901.c
> > create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt8901.h
> >
> > diff --git a/drivers/pinctrl/mediatek/Kconfig
> > b/drivers/pinctrl/mediatek/Kconfig
> > index 4819617d9368..4820ae5197a0 100644
> > --- a/drivers/pinctrl/mediatek/Kconfig
> > +++ b/drivers/pinctrl/mediatek/Kconfig
> > @@ -321,6 +321,18 @@ config PINCTRL_MT8516
> > default ARM64 && ARCH_MEDIATEK
> > select PINCTRL_MTK
> >
> > +config PINCTRL_MT8901
> > + bool "MediaTek MT8901 pin control"
> > + depends on ACPI
> > + depends on ARM64 || COMPILE_TEST
> > + default ARM64 && ARCH_MEDIATEK
> > + select PINCTRL_MTK_PARIS
> > + help
> > + Say yes here to support pin controller and gpio driver
> > + on MediaTek MT8901 SoC.
> > + In MTK platform, we support virtual gpio and use it to
> > + map specific eint which doesn't have real gpio pin.
> > +
> > # For PMIC
> > config PINCTRL_MT6397
> > bool "MediaTek MT6397 pin control"
> > diff --git a/drivers/pinctrl/mediatek/Makefile
> > b/drivers/pinctrl/mediatek/Makefile
> > index ae765bd99965..57c69b1e5c2d 100644
> > --- a/drivers/pinctrl/mediatek/Makefile
> > +++ b/drivers/pinctrl/mediatek/Makefile
> > @@ -43,3 +43,4 @@ obj-$(CONFIG_PINCTRL_MT8196) +=
> > pinctrl-mt8196.o
> > obj-$(CONFIG_PINCTRL_MT8365) += pinctrl-mt8365.o
> > obj-$(CONFIG_PINCTRL_MT8516) += pinctrl-mt8516.o
> > obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o
> > +obj-$(CONFIG_PINCTRL_MT8901) += pinctrl-mt8901.o
> > diff --git a/drivers/pinctrl/mediatek/mtk-eint.c
> > b/drivers/pinctrl/mediatek/mtk-eint.c
> > index c8c5097c11c4..b5a5beebf9cd 100644
> > --- a/drivers/pinctrl/mediatek/mtk-eint.c
> > +++ b/drivers/pinctrl/mediatek/mtk-eint.c
> > @@ -71,6 +71,10 @@ const unsigned int debounce_time_mt6878[] = {
> > };
> > EXPORT_SYMBOL_GPL(debounce_time_mt6878);
> >
> > +const unsigned int debounce_time_mt8901[] = {
> > + 156, 313, 625, 1250, 20000, 40000, 80000, 160000, 320000,
> > 640000, 0};
> > +EXPORT_SYMBOL_GPL(debounce_time_mt8901);
> > +
> > static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint,
> > unsigned int eint_num,
> > unsigned int offset)
> > diff --git a/drivers/pinctrl/mediatek/mtk-eint.h
> > b/drivers/pinctrl/mediatek/mtk-eint.h
> > index 3cdd6f6310cd..1b185f660aff 100644
> > --- a/drivers/pinctrl/mediatek/mtk-eint.h
> > +++ b/drivers/pinctrl/mediatek/mtk-eint.h
> > @@ -53,6 +53,7 @@ extern const unsigned int debounce_time_mt2701[];
> > extern const unsigned int debounce_time_mt6765[];
> > extern const unsigned int debounce_time_mt6795[];
> > extern const unsigned int debounce_time_mt6878[];
> > +extern const unsigned int debounce_time_mt8901[];
> >
> > struct mtk_eint;
> >
> > diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8901.c
> > b/drivers/pinctrl/mediatek/pinctrl-mt8901.c
> > new file mode 100644
> > index 000000000000..77dec85fe29b
> > --- /dev/null
> > +++ b/drivers/pinctrl/mediatek/pinctrl-mt8901.c
> > @@ -0,0 +1,1460 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2025 MediaTek Inc.
> > + *
> > + */
> > +
> > +#include <linux/acpi.h>
> > +#include <linux/module.h>
> > +#include "pinctrl-mtk-mt8901.h"
> > +#include "pinctrl-paris.h"
> > +
>
> ..snip..
>
> > +static const char * const mt8901_pinctrl_register_base_name[] = {
> > + "iocfg0", "iocfg_lt2", "iocfg_lt3", "iocfg_rt1", "iocfg_rt2",
> > "iocfg_rt3",
> > + "iocfg_tr", "iocfg_rt0", "iocfg_lt1", "iocfg_lb", "iocfg_rb",
> > +};
> > +
> > +static const struct mtk_eint_hw mt8901_eint_hw = {
> > + .port_mask = 0xf,
> > + .ports = 7,
> > + .ap_num = 209,
> > + .db_cnt = 32,
> > + .db_time = debounce_time_mt8901,
> > +};
> > +
> > +static const struct mtk_pin_soc mt8901_data = {
> > + .reg_cal = mt8901_reg_cals,
> > + .pins = mtk_pins_mt8901,
> > + .npins = ARRAY_SIZE(mtk_pins_mt8901),
> > + .ngrps = ARRAY_SIZE(mtk_pins_mt8901),
> > + .eint_hw = &mt8901_eint_hw,
> > + .eint_pin = eint_pins_mt8901,
> > + .nfuncs = 8,
> > + .gpio_m = 0,
> > + .base_names = mt8901_pinctrl_register_base_name,
> > + .nbase_names = ARRAY_SIZE(mt8901_pinctrl_register_base_name),
> > + .pull_type = mt8901_pull_type,
> > + .pin_rsel = mt8901_pin_rsel_val_range,
> > + .npin_rsel = ARRAY_SIZE(mt8901_pin_rsel_val_range),
> > /*numsel*/
> > + .bias_set_combo = mtk_pinconf_bias_set_combo,
> > + .bias_get_combo = mtk_pinconf_bias_get_combo,
> > + .drive_set = mtk_pinconf_drive_set_rev1,
> > + .drive_get = mtk_pinconf_drive_get_rev1,
> > + .adv_drive_set = mtk_pinconf_adv_drive_set_raw,
> > + .adv_drive_get = mtk_pinconf_adv_drive_get_raw,
> > +};
> > +
> > +static const struct acpi_device_id mt8901_pinctrl_acpi_match[] = {
> > + {"NVDA9221", (kernel_ulong_t)&mt8901_data },
> > + { }
> > +};
> > +MODULE_DEVICE_TABLE(acpi, mt8901_pinctrl_acpi_match);
> > +
> > +static struct platform_driver mt8901_pinctrl_driver = {
> > + .driver = {
> > + .name = "mt8901-pinctrl",
> > + .acpi_match_table =
> > ACPI_PTR(mt8901_pinctrl_acpi_match),
>
> Please also add support for devicetree - I have a hunch (and I'm sure
> that I am
> not the only one) that ACPI may give some issues at the end of the
> day, on ARM64.
>
> Of course, I'd hope that ACPI is all good on this platform, but
> still.... :-)
>
> static const struct of_device_id mt8901_pinctrl_of_match[] = {
> { .compatible = "mediatek,mt8901-pinctrl", .data =
> &mt8901_data },
> { /* sentinel */ }
> };
>
> .of_match_table = mt8901_pinctrl_of_match,
>
> > + .pm = pm_sleep_ptr(&mtk_paris_pinctrl_pm_ops)
> > + },
> > + .probe = mtk_paris_pinctrl_probe,
> > +};
>
Hi Deep,
Could you please check and feedback to Angelo?
Regards,
Fred-WY Chen
> Cheers,
> Angelo
>
> > +
> > +static int __init mt8901_pinctrl_init(void)
> > +{
> > + return platform_driver_register(&mt8901_pinctrl_driver);
> > +}
> > +
> > +arch_initcall(mt8901_pinctrl_init);
> > +
> > +MODULE_LICENSE("GPL");
> > +MODULE_DESCRIPTION("MediaTek MT8901 Pinctrl Driver");
^ permalink raw reply
* [PATCH v1 10/10] devfreq: Allow setting governor when device governor is NULL
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
From: Zhi Wang <wangzhi12@huawei.com>
When a device's governor is set to NULL, the system should allow
reconfiguring the governor to restore normal operation of devfreq
Before:
$: echo simple_ondemand > governor
$: rmmod -f governor_simpleondemand
$: echo performance > governor
-bash: echo: write error: Invalid argument
After:
$: echo simple_ondemand > governor
$: rmmod -f governor_simpleondemand
$: echo performance > governor
$: cat governor
performance
Signed-off-by: Zhi Wang <wangzhi12@huawei.com>
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 5aebb32e89b0..a61880ff2792 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1435,9 +1435,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
char str_governor[DEVFREQ_NAME_LEN + 1];
const struct devfreq_governor *governor;
- if (!df->governor)
- return -EINVAL;
-
ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
if (ret != 1)
return -EINVAL;
--
2.43.0
^ permalink raw reply related
* [PATCH v1 03/10] devfreq: Add a dedicated mutex for the governor list
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
Accessing the list of available governors ('devfreq_governor_list') is
currently guarded by 'devfreq_list_lock', but 'devfreq_list_lock' is
supposed to protect the list of devfreq devices ('devfreq_list').
The scope of 'devfreq_list_lock' is too broad to maintain.
'devfreq_governor_list' should have its own mutex lock rather than share
with 'devfreq_list'.
Add a governor mutex lock and lock it when accessing the governor list.
Remove locking of 'devfreq_list_lock' around 'devfreq_governor_list'.
This is also a preparation for further refactoring around
try_then_request_governor().
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 31 +++++++++++++------------------
1 file changed, 13 insertions(+), 18 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 83f75dc21c99..e54e3092e0e0 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -49,6 +49,7 @@ static struct workqueue_struct *devfreq_wq;
/* The list of all device-devfreq governors */
static LIST_HEAD(devfreq_governor_list);
+static DEFINE_MUTEX(devfreq_gov_lock);
/* The list of all device-devfreq */
static LIST_HEAD(devfreq_list);
static DEFINE_MUTEX(devfreq_list_lock);
@@ -255,19 +256,18 @@ EXPORT_SYMBOL(devfreq_update_status);
* @name: name of the governor
*
* Search the list of devfreq governors and return the matched
- * governor's pointer. devfreq_list_lock should be held by the caller.
+ * governor's pointer.
*/
static struct devfreq_governor *find_devfreq_governor(const char *name)
{
struct devfreq_governor *tmp_governor;
- lockdep_assert_held(&devfreq_list_lock);
-
if (IS_ERR_OR_NULL(name)) {
pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
return ERR_PTR(-EINVAL);
}
+ guard(mutex)(&devfreq_gov_lock);
list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
return tmp_governor;
@@ -284,16 +284,13 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
* Search the list of devfreq governors and request the module and try again
* if is not found. This can happen when both drivers (the governor driver
* and the driver that call devfreq_add_device) are built as modules.
- * devfreq_list_lock should be held by the caller. Returns the matched
- * governor's pointer or an error pointer.
+ * Returns the matched governor's pointer or an error pointer.
*/
static struct devfreq_governor *try_then_request_governor(const char *name)
{
struct devfreq_governor *governor;
int err = 0;
- lockdep_assert_held(&devfreq_list_lock);
-
if (IS_ERR_OR_NULL(name)) {
pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
return ERR_PTR(-EINVAL);
@@ -301,15 +298,12 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
governor = find_devfreq_governor(name);
if (IS_ERR(governor)) {
- mutex_unlock(&devfreq_list_lock);
-
if (!strncmp(name, DEVFREQ_GOV_SIMPLE_ONDEMAND,
DEVFREQ_NAME_LEN))
err = request_module("governor_%s", "simpleondemand");
else
err = request_module("governor_%s", name);
/* Restore previous state before return */
- mutex_lock(&devfreq_list_lock);
if (err)
return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL);
@@ -933,16 +927,15 @@ struct devfreq *devfreq_add_device(struct device *dev,
if (err)
goto err_devfreq;
- mutex_lock(&devfreq_list_lock);
-
governor = try_then_request_governor(governor_name);
if (IS_ERR(governor)) {
dev_err(dev, "%s: Unable to find governor for the device\n",
__func__);
err = PTR_ERR(governor);
- goto err_init;
+ goto err_devfreq;
}
+ mutex_lock(&devfreq_list_lock);
devfreq->governor = governor;
err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
NULL);
@@ -1269,7 +1262,6 @@ int devfreq_add_governor(struct devfreq_governor *governor)
return -EINVAL;
}
- guard(mutex)(&devfreq_list_lock);
g = find_devfreq_governor(governor->name);
if (!IS_ERR(g)) {
pr_err("%s: governor %s already registered\n", __func__,
@@ -1277,8 +1269,10 @@ int devfreq_add_governor(struct devfreq_governor *governor)
return -EINVAL;
}
- list_add(&governor->node, &devfreq_governor_list);
+ scoped_guard(mutex, &devfreq_gov_lock)
+ list_add(&governor->node, &devfreq_governor_list);
+ guard(mutex)(&devfreq_list_lock);
list_for_each_entry(devfreq, &devfreq_list, node) {
int ret = 0;
struct device *dev = devfreq->dev.parent;
@@ -1355,7 +1349,6 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
return -EINVAL;
}
- guard(mutex)(&devfreq_list_lock);
g = find_devfreq_governor(governor->name);
if (IS_ERR(g)) {
pr_err("%s: governor %s not registered\n", __func__,
@@ -1363,6 +1356,7 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
return PTR_ERR(g);
}
+ guard(mutex)(&devfreq_list_lock);
list_for_each_entry(devfreq, &devfreq_list, node) {
int ret;
struct device *dev = devfreq->dev.parent;
@@ -1383,7 +1377,8 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
}
}
- list_del(&governor->node);
+ scoped_guard(mutex, &devfreq_gov_lock)
+ list_del(&governor->node);
return 0;
}
@@ -1423,11 +1418,11 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
if (ret != 1)
return -EINVAL;
- guard(mutex)(&devfreq_list_lock);
governor = try_then_request_governor(str_governor);
if (IS_ERR(governor))
return PTR_ERR(governor);
+ guard(mutex)(&devfreq_list_lock);
if (df->governor == governor)
return count;
--
2.43.0
^ permalink raw reply related
* [PATCH v1 09/10] devfreq: Allow showing available_governors when device governor is NULL
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
From: Zhi Wang <wangzhi12@huawei.com>
Allow showing available_governors via sysfs when a device's governor is
NULL, enabling reconfiguration of the device's governor.
Before:
$: echo simple_ondemand > governor
$: rmmod -f governor_simpleondemand
$: cat available_governors
cat: available_governors: Invalid argument
After:
$: echo simple_ondemand > governor
$: rmmod -f governor_simpleondemand
$: cat available_governors
hisi_platform userspace powersave performance
Signed-off-by: Zhi Wang <wangzhi12@huawei.com>
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index c6b670b8fd22..5aebb32e89b0 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1461,16 +1461,13 @@ static ssize_t available_governors_show(struct device *d,
struct devfreq *df = to_devfreq(d);
ssize_t count = 0;
- if (!df->governor)
- return -EINVAL;
-
mutex_lock(&devfreq_list_lock);
/*
* The devfreq with immutable governor (e.g., passive) shows
* only own governor.
*/
- if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)) {
+ if (df->governor && IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)) {
count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
"%s ", df->governor->name);
/*
--
2.43.0
^ permalink raw reply related
* [PATCH v1 05/10] devfreq: Remove dead code in devfreq_add_governor()
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
In devfreq_add_governor(), we've already checked the governor list to
see if there's a governor already registered with the same name.
It's impossible that a devfreq device is using such a governor, so the
check can never be true and the error handling is unreachable.
Remove the redundant error handling to simplify the logic.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 34 ----------------------------------
1 file changed, 34 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 378a01f71165..7e71e8c76303 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1300,7 +1300,6 @@ void devfreq_resume(void)
int devfreq_add_governor(struct devfreq_governor *governor)
{
struct devfreq_governor *g;
- struct devfreq *devfreq;
if (!governor) {
pr_err("%s: Invalid parameters.\n", __func__);
@@ -1317,39 +1316,6 @@ int devfreq_add_governor(struct devfreq_governor *governor)
scoped_guard(mutex, &devfreq_gov_lock)
list_add(&governor->node, &devfreq_governor_list);
- guard(mutex)(&devfreq_list_lock);
- list_for_each_entry(devfreq, &devfreq_list, node) {
- int ret = 0;
- struct device *dev = devfreq->dev.parent;
-
- if (!strncmp(devfreq->governor->name, governor->name,
- DEVFREQ_NAME_LEN)) {
- /* The following should never occur */
- if (devfreq->governor) {
- dev_warn(dev,
- "%s: Governor %s already present\n",
- __func__, devfreq->governor->name);
- ret = devfreq->governor->event_handler(devfreq,
- DEVFREQ_GOV_STOP, NULL);
- if (ret) {
- dev_warn(dev,
- "%s: Governor %s stop = %d\n",
- __func__,
- devfreq->governor->name, ret);
- }
- /* Fall through */
- }
- devfreq->governor = governor;
- ret = devfreq->governor->event_handler(devfreq,
- DEVFREQ_GOV_START, NULL);
- if (ret) {
- dev_warn(dev, "%s: Governor %s start=%d\n",
- __func__, devfreq->governor->name,
- ret);
- }
- }
- }
-
return 0;
}
EXPORT_SYMBOL(devfreq_add_governor);
--
2.43.0
^ permalink raw reply related
* [PATCH v1 00/10] devfreq: Fix NULL pointer dereference when a governor module is unloaded
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
When compiled as a kernel module, the governor module can be dynamically
inserted or removed. 'devfreq->governor' would become NULL if the governor
module is removed when it's in use, and NULL pointer dereference would be
triggered. A similar issue was also reported in [1].
To address this issue:
Patch 1-5 rework mutex, factor out a common governor setting function, and
clean up some unreachable code.
Patch 6-8 prevent a governor module in use from being removed (except for
force unload) by getting/putting a refcount of the governor's module when
switching governors.
Patch 9-10 allow 'governor' and 'available_governors' to work normally even
when a governor module in use is force unloaded.
Note that this series is based on [1] or devfreq-next, otherwise code
would conflict.
[1] https://lore.kernel.org/all/20260319091409.998397-1-tianyaxiong@kylinos.cn/
[2] https://lore.kernel.org/all/20251216031153.2242306-1-zhangpengjie2@huawei.com/
Jie Zhan (8):
devfreq: Use mutex guard in governor_store()
devfreq: Use mutex guard in devfreq_add/remove_governor()
devfreq: Add a dedicated mutex for the governor list
devfreq: Factor out devfreq_set_governor[_locked]()
devfreq: Remove dead code in devfreq_add_governor()
devfreq: Add module owner to devfreq governor
devfreq: Get and put module refcount when switching governor
devfreq: Allow find_devfreq_governor() to get module refcount
Zhi Wang (2):
devfreq: Allow showing available_governors when device governor is
NULL
devfreq: Allow setting governor when device governor is NULL
drivers/devfreq/devfreq.c | 287 +++++++++++++------------------
include/linux/devfreq-governor.h | 26 ++-
2 files changed, 143 insertions(+), 170 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH v1 04/10] devfreq: Factor out devfreq_set_governor[_locked]()
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
Factor out common governor setting logic into devfreq_set_governor() to
reduce code duplication in governor_store() and devfreq_add_device().
Additionally, devfreq_set_governor_locked() is used when
'devfreq_list_lock' is already held by the caller, e.g. in
devfreq_set_governor(), to avoid an immediate relock after unlock.
Note that the new functions support setting a governor even if
devfreq->governor is NULL.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 129 +++++++++++++++++++-------------------
1 file changed, 63 insertions(+), 66 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index e54e3092e0e0..378a01f71165 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -313,6 +313,64 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
return governor;
}
+static int devfreq_set_governor_locked(struct devfreq *df,
+ const struct devfreq_governor *new_gov)
+{
+ const struct devfreq_governor *old_gov;
+ struct device *dev;
+ int ret;
+
+ old_gov = df->governor;
+ dev = &df->dev;
+
+ if (old_gov) {
+ if (old_gov == new_gov)
+ return 0;
+
+ if (IS_SUPPORTED_FLAG(old_gov->flags, IMMUTABLE) ||
+ IS_SUPPORTED_FLAG(new_gov->flags, IMMUTABLE))
+ return -EINVAL;
+
+ /* Stop the current governor */
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
+ __func__, df->governor->name, ret);
+ return ret;
+ }
+ }
+
+ /* Start the new governor */
+ df->governor = new_gov;
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s not started(%d)\n",
+ __func__, df->governor->name, ret);
+
+ if (!old_gov)
+ return ret;
+
+ /* Restore previous governor */
+ df->governor = old_gov;
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
+ if (ret) {
+ dev_err(dev, "%s: restore Governor %s failed (%d)\n",
+ __func__, old_gov->name, ret);
+ df->governor = NULL;
+ return ret;
+ }
+ }
+
+ return sysfs_update_group(&df->dev.kobj, &gov_attr_group);
+}
+
+static int devfreq_set_governor(struct devfreq *df,
+ const struct devfreq_governor *new_gov)
+{
+ guard(mutex)(&devfreq_list_lock);
+ return devfreq_set_governor_locked(df, new_gov);
+}
+
static int devfreq_notify_transition(struct devfreq *devfreq,
struct devfreq_freqs *freqs, unsigned int state)
{
@@ -936,22 +994,11 @@ struct devfreq *devfreq_add_device(struct device *dev,
}
mutex_lock(&devfreq_list_lock);
- devfreq->governor = governor;
- err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
- NULL);
- if (err) {
- dev_err_probe(dev, err,
- "%s: Unable to start governor for the device\n",
- __func__);
- goto err_init;
- }
-
- err = sysfs_update_group(&devfreq->dev.kobj, &gov_attr_group);
+ err = devfreq_set_governor_locked(devfreq, governor);
if (err)
- goto err_init;
+ goto err_devfreq;
list_add(&devfreq->node, &devfreq_list);
-
mutex_unlock(&devfreq_list_lock);
if (devfreq->profile->is_cooling_device) {
@@ -962,8 +1009,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
return devfreq;
-err_init:
- mutex_unlock(&devfreq_list_lock);
err_devfreq:
devfreq_remove_device(devfreq);
devfreq = NULL;
@@ -1409,7 +1454,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
struct devfreq *df = to_devfreq(dev);
int ret;
char str_governor[DEVFREQ_NAME_LEN + 1];
- const struct devfreq_governor *governor, *prev_governor;
+ const struct devfreq_governor *governor;
if (!df->governor)
return -EINVAL;
@@ -1422,57 +1467,9 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
if (IS_ERR(governor))
return PTR_ERR(governor);
- guard(mutex)(&devfreq_list_lock);
- if (df->governor == governor)
- return count;
-
- if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE) ||
- IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE))
- return -EINVAL;
-
- /*
- * Stop the current governor and remove the specific sysfs files
- * which depend on current governor.
- */
- ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
- if (ret) {
- dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
- __func__, df->governor->name, ret);
- return ret;
- }
-
- /*
- * Start the new governor and create the specific sysfs files
- * which depend on the new governor.
- */
- prev_governor = df->governor;
- df->governor = governor;
- ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
- if (ret) {
- dev_warn(dev, "%s: Governor %s not started(%d)\n",
- __func__, df->governor->name, ret);
-
- /* Restore previous governor */
- df->governor = prev_governor;
- ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
- if (ret) {
- dev_err(dev,
- "%s: reverting to Governor %s failed (%d)\n",
- __func__, prev_governor->name, ret);
- df->governor = NULL;
- return ret;
- }
- }
-
- /*
- * Create the sysfs files for the new governor. But if failed to start
- * the new governor, restore the sysfs files of previous governor.
- */
- ret = sysfs_update_group(&df->dev.kobj, &gov_attr_group);
- if (ret)
- return ret;
+ ret = devfreq_set_governor(df, governor);
- return count;
+ return ret ? ret : count;
}
static DEVICE_ATTR_RW(governor);
--
2.43.0
^ permalink raw reply related
* [PATCH v1 01/10] devfreq: Use mutex guard in governor_store()
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
Use mutex guard in governor_store() so as to simplify the locking logic.
No functional impact intended.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 36 +++++++++++++++---------------------
1 file changed, 15 insertions(+), 21 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index fcad3edceeea..21aa9661de0b 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1431,20 +1431,17 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
if (ret != 1)
return -EINVAL;
- mutex_lock(&devfreq_list_lock);
+ guard(mutex)(&devfreq_list_lock);
governor = try_then_request_governor(str_governor);
- if (IS_ERR(governor)) {
- ret = PTR_ERR(governor);
- goto out;
- }
- if (df->governor == governor) {
- ret = 0;
- goto out;
- } else if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)
- || IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE)) {
- ret = -EINVAL;
- goto out;
- }
+ if (IS_ERR(governor))
+ return PTR_ERR(governor);
+
+ if (df->governor == governor)
+ return count;
+
+ if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE) ||
+ IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE))
+ return -EINVAL;
/*
* Stop the current governor and remove the specific sysfs files
@@ -1454,7 +1451,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
if (ret) {
dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
__func__, df->governor->name, ret);
- goto out;
+ return ret;
}
/*
@@ -1476,7 +1473,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
"%s: reverting to Governor %s failed (%d)\n",
__func__, prev_governor->name, ret);
df->governor = NULL;
- goto out;
+ return ret;
}
}
@@ -1485,13 +1482,10 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
* the new governor, restore the sysfs files of previous governor.
*/
ret = sysfs_update_group(&df->dev.kobj, &gov_attr_group);
+ if (ret)
+ return ret;
-out:
- mutex_unlock(&devfreq_list_lock);
-
- if (!ret)
- ret = count;
- return ret;
+ return count;
}
static DEVICE_ATTR_RW(governor);
--
2.43.0
^ permalink raw reply related
* [PATCH v1 02/10] devfreq: Use mutex guard in devfreq_add/remove_governor()
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
Use mutex guard in devfreq_add/remove_governor() so as to simplify the
locking logic.
No functional impact intended.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 22 +++++++---------------
1 file changed, 7 insertions(+), 15 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 21aa9661de0b..83f75dc21c99 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1263,20 +1263,18 @@ int devfreq_add_governor(struct devfreq_governor *governor)
{
struct devfreq_governor *g;
struct devfreq *devfreq;
- int err = 0;
if (!governor) {
pr_err("%s: Invalid parameters.\n", __func__);
return -EINVAL;
}
- mutex_lock(&devfreq_list_lock);
+ guard(mutex)(&devfreq_list_lock);
g = find_devfreq_governor(governor->name);
if (!IS_ERR(g)) {
pr_err("%s: governor %s already registered\n", __func__,
g->name);
- err = -EINVAL;
- goto err_out;
+ return -EINVAL;
}
list_add(&governor->node, &devfreq_governor_list);
@@ -1313,10 +1311,7 @@ int devfreq_add_governor(struct devfreq_governor *governor)
}
}
-err_out:
- mutex_unlock(&devfreq_list_lock);
-
- return err;
+ return 0;
}
EXPORT_SYMBOL(devfreq_add_governor);
@@ -1354,21 +1349,20 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
{
struct devfreq_governor *g;
struct devfreq *devfreq;
- int err = 0;
if (!governor) {
pr_err("%s: Invalid parameters.\n", __func__);
return -EINVAL;
}
- mutex_lock(&devfreq_list_lock);
+ guard(mutex)(&devfreq_list_lock);
g = find_devfreq_governor(governor->name);
if (IS_ERR(g)) {
pr_err("%s: governor %s not registered\n", __func__,
governor->name);
- err = PTR_ERR(g);
- goto err_out;
+ return PTR_ERR(g);
}
+
list_for_each_entry(devfreq, &devfreq_list, node) {
int ret;
struct device *dev = devfreq->dev.parent;
@@ -1390,10 +1384,8 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
}
list_del(&governor->node);
-err_out:
- mutex_unlock(&devfreq_list_lock);
- return err;
+ return 0;
}
EXPORT_SYMBOL(devfreq_remove_governor);
--
2.43.0
^ permalink raw reply related
* [PATCH v1 08/10] devfreq: Allow find_devfreq_governor() to get module refcount
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
Add a 'get' parameter for find_devfreq_governor() to optionally get a
refcount of the governor module.
Getting refcount in try_then_request_governor() prevents the governor
module from being removed during the governor setting phase.
However, in devfreq_add/remove_governor(), it doesn't need to get a
refcount of the governor module because it just checks whether a
governor registered with the same name exists or not.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index ba09948915ba..c6b670b8fd22 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -254,11 +254,13 @@ EXPORT_SYMBOL(devfreq_update_status);
/**
* find_devfreq_governor() - find devfreq governor from name
* @name: name of the governor
+ * @get: whether to get a refcount of the governor module
*
* Search the list of devfreq governors and return the matched
* governor's pointer.
*/
-static struct devfreq_governor *find_devfreq_governor(const char *name)
+static struct devfreq_governor *find_devfreq_governor(const char *name,
+ bool get)
{
struct devfreq_governor *tmp_governor;
@@ -269,8 +271,13 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
guard(mutex)(&devfreq_gov_lock);
list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
- if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
- return tmp_governor;
+ if (strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
+ continue;
+
+ if (get && !try_module_get(tmp_governor->owner))
+ return ERR_PTR(-EBUSY);
+
+ return tmp_governor;
}
return ERR_PTR(-ENODEV);
@@ -285,6 +292,9 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
* if is not found. This can happen when both drivers (the governor driver
* and the driver that call devfreq_add_device) are built as modules.
* Returns the matched governor's pointer or an error pointer.
+ * On success, this holds a refcount of the governor module to prevent the
+ * module from being unloaded during usage, so the caller should put a module
+ * refcount after using it.
*/
static struct devfreq_governor *try_then_request_governor(const char *name)
{
@@ -296,7 +306,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
return ERR_PTR(-EINVAL);
}
- governor = find_devfreq_governor(name);
+ governor = find_devfreq_governor(name, true);
if (IS_ERR(governor)) {
if (!strncmp(name, DEVFREQ_GOV_SIMPLE_ONDEMAND,
DEVFREQ_NAME_LEN))
@@ -307,7 +317,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
if (err)
return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL);
- governor = find_devfreq_governor(name);
+ governor = find_devfreq_governor(name, true);
}
return governor;
@@ -1007,6 +1017,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
if (err)
goto err_devfreq;
+ module_put(governor->owner);
+
list_add(&devfreq->node, &devfreq_list);
mutex_unlock(&devfreq_list_lock);
@@ -1312,7 +1324,7 @@ int __devfreq_add_governor(struct devfreq_governor *governor,
return -EINVAL;
}
- g = find_devfreq_governor(governor->name);
+ g = find_devfreq_governor(governor->name, false);
if (!IS_ERR(g)) {
pr_err("%s: governor %s already registered\n", __func__,
g->name);
@@ -1361,7 +1373,7 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
return -EINVAL;
}
- g = find_devfreq_governor(governor->name);
+ g = find_devfreq_governor(governor->name, false);
if (IS_ERR(g)) {
pr_err("%s: governor %s not registered\n", __func__,
governor->name);
@@ -1436,6 +1448,8 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
ret = devfreq_set_governor(df, governor);
+ module_put(governor->owner);
+
return ret ? ret : count;
}
static DEVICE_ATTR_RW(governor);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2 0/2] mmc: hisilicon: Convert dw-mshc bindings and fix dtbs
From: Ulf Hansson @ 2026-03-26 12:39 UTC (permalink / raw)
To: Wei Xu
Cc: Bhargav Joshi, devicetree, linux-arm-kernel, robh, krzk+dt,
conor+dt, zhangfei.gao, linux-mmc, daniel.baluta, simona.toaca,
d-gole, m-chawdhry, linux-kernel
In-Reply-To: <69C51640.8070408@hisilicon.com>
On Thu, 26 Mar 2026 at 12:19, Wei Xu <xuwei5@hisilicon.com> wrote:
>
> Hi Bhargav,
>
> On 2026/3/26 6:54, Bhargav Joshi wrote:
> > This series converts the Hisilicon dw-mshc text bindings to DT schema
> > format and cleans up legacy node names in Hisilicon board files.
> >
> > While testing the new YAML schema, dtbs_check flagged the hi3660,
> > hi3670, and hi6220 SoC files for using the non-standard 'dwmmc' node
> > name prefix. resulting in warnings.
> >
> > Patch 1 Convert to DT schema
> > Patch 2 updates the Hisilicon dtsi files to use standard 'mmc'
> > node name.
> >
> > Changes in v2:
> > - Patch 1:
> > - Grouped compatible strings into an enum.
> > - Replaced raw numbers with proper flags.
> > - Fixed property order and removed invalid hex values.
> > - Added explanation for clock order change in commit message.
> > - Collected Acked-by tag.
> > - Patch 2:
> > - No code changes.
> > - Collected Acked-by and Reviewed-by tags.
> >
> > Signed-off-by: Bhargav Joshi <rougueprince47@gmail.com>
> > ---
> > Note: this patch is part of the process for applying to GSoC device
> > tree bindings conversion project #
> > https://github.com/LinuxFoundationGSoC/ProjectIdeas/wiki/GSoC-2026-Device-Tree-Bindings
> >
> > - The file is enabled by arm64 defconfig (CONFIG_MMC_DW_K3=y)
> > - It is used in following
> > /arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> > -included by /arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
> > /arch/arm64/boot/dts/hisilicon/hi3670.dtsi
> > -included by /arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
> >
> > Bhargav Joshi (2):
> > dt-bindings: mmc: hisilicon,hi3660-dw-mshc: Convert to DT schema
> > arm64: dts: hisilicon: Rename dwmmc nodes to mmc
> >
> > .../mmc/hisilicon,hi3660-dw-mshc.yaml | 117 ++++++++++++++++++
> > .../devicetree/bindings/mmc/k3-dw-mshc.txt | 73 -----------
> > arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 4 +-
> > arch/arm64/boot/dts/hisilicon/hi3670.dtsi | 4 +-
> > arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 6 +-
> > 5 files changed, 124 insertions(+), 80 deletions(-)
> > create mode 100644 Documentation/devicetree/bindings/mmc/hisilicon,hi3660-dw-mshc.yaml
> > delete mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> >
>
> Series applied to the HiSilicon arm64 dt tree.
> Thanks!
>
> Best Regards,
> Wei
Usually I pick DT bindings (patch1/2) for mmc via my mmc tree and I
also just did. Would it be possible for you to drop patch1/2 from your
tree?
Kind regards
Uffe
^ permalink raw reply
* [PATCH v1 07/10] devfreq: Get and put module refcount when switching governor
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
When compiled as a kernel module, the governor module can be dynamically
inserted or removed. 'devfreq->governor' would become NULL if the
governor module is removed when it's in use.
To prevent the governor module from being removed (except for force
unload) when it's in use, get and put a refcount of the governor module
when starting and stopping the governor.
Now, unloading a governor module that is set for a devfreq device
returns an error, for example:
# cat governor
performance
# rmmod governor_performance
rmmod: ERROR: Module governor_performance is in use
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 9b078458d129..ba09948915ba 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -338,22 +338,31 @@ static int devfreq_set_governor_locked(struct devfreq *df,
__func__, df->governor->name, ret);
return ret;
}
+ module_put(old_gov->owner);
}
/* Start the new governor */
+ if (!try_module_get(new_gov->owner))
+ return -EINVAL;
+
df->governor = new_gov;
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
if (ret) {
dev_warn(dev, "%s: Governor %s not started(%d)\n",
__func__, df->governor->name, ret);
+ module_put(new_gov->owner);
if (!old_gov)
return ret;
/* Restore previous governor */
+ if (!try_module_get(old_gov->owner))
+ return -EINVAL;
+
df->governor = old_gov;
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
if (ret) {
+ module_put(old_gov->owner);
dev_err(dev, "%s: restore Governor %s failed (%d)\n",
__func__, old_gov->name, ret);
df->governor = NULL;
--
2.43.0
^ permalink raw reply related
* [PATCH v1 06/10] devfreq: Add module owner to devfreq governor
From: Jie Zhan @ 2026-03-26 12:34 UTC (permalink / raw)
To: cw00.choi, myungjoo.ham, kyungmin.park, tianyaxiong
Cc: linux-pm, linux-arm-kernel, linuxarm, zhanjie9, jonathan.cameron,
zhenglifeng1, zhangpengjie2, lihuisong, prime.zeng
In-Reply-To: <20260326123428.800407-1-zhanjie9@hisilicon.com>
Add an 'owner' member to struct devfreq_governor, such that we can find
the module that holds the governor code when it's compiled as a kernel
module. This allows the devfreq core to properly manage the lifecycle
of governors.
Update devfreq_add_governor() and devm_devfreq_add_governor() to
automatically set 'owner' to THIS_MODULE via helper macros.
This is a prerequisite for implementing governor reference counting
to prevent module unloading while a governor is in use.
Signed-off-by: Jie Zhan <zhanjie9@hisilicon.com>
---
drivers/devfreq/devfreq.c | 26 +++++++++-----------------
include/linux/devfreq-governor.h | 26 +++++++++++++++++++++++---
2 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 7e71e8c76303..9b078458d129 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1293,11 +1293,8 @@ void devfreq_resume(void)
mutex_unlock(&devfreq_list_lock);
}
-/**
- * devfreq_add_governor() - Add devfreq governor
- * @governor: the devfreq governor to be added
- */
-int devfreq_add_governor(struct devfreq_governor *governor)
+int __devfreq_add_governor(struct devfreq_governor *governor,
+ struct module *mod)
{
struct devfreq_governor *g;
@@ -1313,38 +1310,33 @@ int devfreq_add_governor(struct devfreq_governor *governor)
return -EINVAL;
}
+ governor->owner = mod;
scoped_guard(mutex, &devfreq_gov_lock)
list_add(&governor->node, &devfreq_governor_list);
return 0;
}
-EXPORT_SYMBOL(devfreq_add_governor);
+EXPORT_SYMBOL(__devfreq_add_governor);
static void devm_devfreq_remove_governor(void *governor)
{
WARN_ON(devfreq_remove_governor(governor));
}
-/**
- * devm_devfreq_add_governor() - Add devfreq governor
- * @dev: device which adds devfreq governor
- * @governor: the devfreq governor to be added
- *
- * This is a resource-managed variant of devfreq_add_governor().
- */
-int devm_devfreq_add_governor(struct device *dev,
- struct devfreq_governor *governor)
+int __devm_devfreq_add_governor(struct device *dev,
+ struct devfreq_governor *governor,
+ struct module *mod)
{
int err;
- err = devfreq_add_governor(governor);
+ err = __devfreq_add_governor(governor, mod);
if (err)
return err;
return devm_add_action_or_reset(dev, devm_devfreq_remove_governor,
governor);
}
-EXPORT_SYMBOL(devm_devfreq_add_governor);
+EXPORT_SYMBOL(__devm_devfreq_add_governor);
/**
* devfreq_remove_governor() - Remove devfreq feature from a device.
diff --git a/include/linux/devfreq-governor.h b/include/linux/devfreq-governor.h
index dfdd0160a29f..1c4ff57e24de 100644
--- a/include/linux/devfreq-governor.h
+++ b/include/linux/devfreq-governor.h
@@ -12,6 +12,7 @@
#define __LINUX_DEVFREQ_DEVFREQ_H__
#include <linux/devfreq.h>
+struct module;
#define DEVFREQ_NAME_LEN 16
@@ -50,6 +51,7 @@
/**
* struct devfreq_governor - Devfreq policy governor
* @node: list node - contains registered devfreq governors
+ * @owner: Module that this governor belongs to
* @name: Governor's name
* @attrs: Governor's sysfs attribute flags
* @flags: Governor's feature flags
@@ -67,6 +69,7 @@
struct devfreq_governor {
struct list_head node;
+ struct module *owner;
const char name[DEVFREQ_NAME_LEN];
const u64 attrs;
const u64 flags;
@@ -81,11 +84,28 @@ void devfreq_monitor_suspend(struct devfreq *devfreq);
void devfreq_monitor_resume(struct devfreq *devfreq);
void devfreq_update_interval(struct devfreq *devfreq, unsigned int *delay);
-int devfreq_add_governor(struct devfreq_governor *governor);
+/**
+ * devfreq_add_governor() - Add devfreq governor
+ * @governor: The devfreq governor to be added
+ */
+#define devfreq_add_governor(governor) \
+ __devfreq_add_governor((governor), THIS_MODULE)
+int __devfreq_add_governor(struct devfreq_governor *governor,
+ struct module *mod);
int devfreq_remove_governor(struct devfreq_governor *governor);
-int devm_devfreq_add_governor(struct device *dev,
- struct devfreq_governor *governor);
+/**
+ * devm_devfreq_add_governor() - Add devfreq governor
+ * @dev: device which adds devfreq governor
+ * @governor: the devfreq governor to be added
+ *
+ * This is a resource-managed variant of devfreq_add_governor().
+ */
+#define devm_devfreq_add_governor(dev, governor) \
+ __devm_devfreq_add_governor((dev), (governor), THIS_MODULE)
+int __devm_devfreq_add_governor(struct device *dev,
+ struct devfreq_governor *governor,
+ struct module *mod);
int devfreq_update_status(struct devfreq *devfreq, unsigned long freq);
int devfreq_update_target(struct devfreq *devfreq, unsigned long freq);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2 2/4] mm: replace exec_folio_order() with generic preferred_exec_order()
From: Usama Arif @ 2026-03-26 12:40 UTC (permalink / raw)
To: Jan Kara, david, ryan.roberts
Cc: Andrew Morton, willy, linux-mm, r, ajd, apopple, baohua,
baolin.wang, brauner, catalin.marinas, dev.jain, kees,
kevin.brodsky, lance.yang, Liam.Howlett, linux-arm-kernel,
linux-fsdevel, linux-kernel, lorenzo.stoakes, mhocko, npache,
pasha.tatashin, rmclure, rppt, surenb, vbabka, Al Viro,
wilts.infradead.org, ziy, hannes, kas, shakeel.butt, kernel-team
In-Reply-To: <k45xs6btmt62uerbglqe665jozrtkeoklu4rek6odgxjdj63ni@ftw6ef3ug33x>
On 20/03/2026 17:42, Jan Kara wrote:
> On Fri 20-03-26 06:58:52, Usama Arif wrote:
>> Replace the arch-specific exec_folio_order() hook with a generic
>> preferred_exec_order() that dynamically computes the readahead folio
>> order for executable memory. It targets min(PMD_ORDER, 2M) as the
>> maximum, which optimally gives the right answer for contpte (arm64),
>> PMD mapping (x86, arm64 4K), and architectures with smaller PMDs
>> (s390 1M). It adapts at runtime based on:
>>
>> - VMA size: caps the order so folios fit within the mapping
>> - Memory pressure: steps down the order when the local node's free
>> memory is below the high watermark for the requested order
>>
>> This avoids over-allocating on memory-constrained systems while still
>> requesting the optimal order when memory is plentiful.
>>
>> Since exec_folio_order() is no longer needed, remove the arm64
>> definition and the generic default from pgtable.h.
>>
>> Signed-off-by: Usama Arif <usama.arif@linux.dev>
> ...
>> +static unsigned int preferred_exec_order(struct vm_area_struct *vma)
>> +{
>> + int order;
>> + unsigned long vma_len = vma_pages(vma);
>> + struct zone *zone;
>> + gfp_t gfp;
>> +
>> + if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
>> + return 0;
>> +
>> + /* Cap at min(PMD_ORDER, 2M) */
>> + order = min(HPAGE_PMD_ORDER, ilog2(SZ_2M >> PAGE_SHIFT));
>> +
>> + /* Don't request folios larger than the VMA */
>> + order = min(order, ilog2(vma_len));
>
Hi Jan,
Thanks for the feedback and sorry for the late reply! I was travelling
during the week.
> Hum, as far as I'm checking page_cache_ra_order() used in
> do_sync_mmap_readahead(), ra->order is the preferred order but it will be
> trimmed down to fit both within the file and within ra->size. And ra->size
> is set for the readahead to fit within the vma so I don't think any order
> trimming based on vma length is needed in this place?
Ack, yes makes sense.
>
>> + /* Step down under memory pressure */
>> + gfp = mapping_gfp_mask(vma->vm_file->f_mapping);
>> + zone = first_zones_zonelist(node_zonelist(numa_node_id(), gfp),
>> + gfp_zone(gfp), NULL)->zone;
>> + if (zone) {
>> + while (order > 0 &&
>> + !zone_watermark_ok(zone, order,
>> + high_wmark_pages(zone), 0, 0))
>> + order--;
>> + }
>
> It looks wrong for this logic to be here. Trimming order based on memory
> pressure makes sense (and we've already got reports that on memory limited
> devices large order folios in the page cache have too big memory overhead
> so we'll likely need to handle that for page cache allocations in general)
> but IMHO it belongs to page_cache_ra_order() or some other common place
> like that.
>
> Honza
So I have been thinking about this. readahead_gfp_mask() already sets
__GFP_NORETRY, so we wont try aggressive reclaim/compaction to satisfy
the allocation. page_cache_ra_order() falls through to the fallback path
faulting in order 0 page when allocation is not satsified.
So the allocator already naturally steps down under memory pressure,
the explicit zone_watermark_ok() loop might be redundant?
What are your thoughts on just setting
ra->order = min(HPAGE_PMD_ORDER, ilog2(SZ_2M >> PAGE_SHIFT))?
We can do the higher orlder allocation with gfp &= ~__GFP_RECLAIM
for the VM_EXEC case.
^ permalink raw reply
* Re: [PATCH v11 03/22] drm: Add new general DRM property "color format"
From: Nicolas Frattaroli @ 2026-03-26 12:44 UTC (permalink / raw)
To: Maxime Ripard, Ville Syrjälä
Cc: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, David Airlie, Simona Vetter,
Maarten Lankhorst, Thomas Zimmermann, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Sandy Huang, Heiko Stübner, Andy Yan,
Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
Dmitry Baryshkov, Sascha Hauer, Rob Herring, Jonathan Corbet,
Shuah Khan, kernel, amd-gfx, dri-devel, linux-kernel,
linux-arm-kernel, linux-rockchip, intel-gfx, intel-xe, linux-doc,
Werner Sembach, Andri Yngvason, Marius Vlad
In-Reply-To: <acPA60Ci3n_t__xF@intel.com>
On Wednesday, 25 March 2026 12:03:07 Central European Standard Time Ville Syrjälä wrote:
> On Wed, Mar 25, 2026 at 09:24:27AM +0100, Maxime Ripard wrote:
> > On Tue, Mar 24, 2026 at 09:53:35PM +0200, Ville Syrjälä wrote:
> > > On Tue, Mar 24, 2026 at 08:10:11PM +0100, Nicolas Frattaroli wrote:
> > > > On Tuesday, 24 March 2026 18:00:45 Central European Standard Time Ville Syrjälä wrote:
> > > > > On Tue, Mar 24, 2026 at 05:01:07PM +0100, Nicolas Frattaroli wrote:
> > > > > > +enum drm_connector_color_format {
> > > > > > + /**
> > > > > > + * @DRM_CONNECTOR_COLOR_FORMAT_AUTO: The driver or display protocol
> > > > > > + * helpers should pick a suitable color format. All implementations of a
> > > > > > + * specific display protocol must behave the same way with "AUTO", but
> > > > > > + * different display protocols do not necessarily have the same "AUTO"
> > > > > > + * semantics.
> > > > > > + *
> > > > > > + * For HDMI, "AUTO" picks RGB, but falls back to YCbCr 4:2:0 if the
> > > > > > + * bandwidth required for full-scale RGB is not available, or the mode
> > > > > > + * is YCbCr 4:2:0-only, as long as the mode and output both support
> > > > > > + * YCbCr 4:2:0.
> > > > > > + *
> > > > > > + * For display protocols other than HDMI, the recursive bridge chain
> > > > > > + * format selection picks the first chain of bridge formats that works,
> > > > > > + * as has already been the case before the introduction of the "color
> > > > > > + * format" property. Non-HDMI bridges should therefore either sort their
> > > > > > + * bus output formats by preference, or agree on a unified auto format
> > > > > > + * selection logic that's implemented in a common state helper (like
> > > > > > + * how HDMI does it).
> > > > > > + */
> > > > > > + DRM_CONNECTOR_COLOR_FORMAT_AUTO = 0,
> > > > > > +
> > > > > > + /**
> > > > > > + * @DRM_CONNECTOR_COLOR_FORMAT_RGB444: RGB output format
> > > > > > + */
> > > > > > + DRM_CONNECTOR_COLOR_FORMAT_RGB444,
> > > > > > +
> > > > > > + /**
> > > > > > + * @DRM_CONNECTOR_COLOR_FORMAT_YCBCR444: YCbCr 4:4:4 output format (ie.
> > > > > > + * not subsampled)
> > > > > > + */
> > > > > > + DRM_CONNECTOR_COLOR_FORMAT_YCBCR444,
> > > > > > +
> > > > > > + /**
> > > > > > + * @DRM_CONNECTOR_COLOR_FORMAT_YCBCR422: YCbCr 4:2:2 output format (ie.
> > > > > > + * with horizontal subsampling)
> > > > > > + */
> > > > > > + DRM_CONNECTOR_COLOR_FORMAT_YCBCR422,
> > > > > > +
> > > > > > + /**
> > > > > > + * @DRM_CONNECTOR_COLOR_FORMAT_YCBCR420: YCbCr 4:2:0 output format (ie.
> > > > > > + * with horizontal and vertical subsampling)
> > > > > > + */
> > > > > > + DRM_CONNECTOR_COLOR_FORMAT_YCBCR420,
> > > > >
> > > > > Seems like this should document what the quantization range
> > > > > should be for each format.
> > > > >
> > > >
> > > > I don't think so? If you want per-component bit depth values,
> > > > DRM_FORMAT_* defines would be the appropriate values to use. This
> > > > enum is more abstract than that, and is there to communicate
> > > > YUV vs. RGB and chroma subsampling, with bit depth being handled
> > > > by other properties.
> > > >
> > > > If you mean the factor used for subsampling, then that'd only be
> > > > relevant if YCBCR410 was supported where one chroma plane isn't
> > > > halved but quartered in resolution. I suspect 4:1:0 will never
> > > > be added; no digital display protocol standard supports it to my
> > > > knowledge, and hopefully none ever will.
> > >
> > > No, I mean the quantization range (16-235 vs. 0-255 etc).
> > >
> > > The i915 behaviour is that YCbCr is always limited range,
> > > RGB can either be full or limited range depending on the
> > > "Broadcast RGB" property and other related factors.
> >
> > So far the HDMI state has both the format and quantization range as
> > different fields. I'm not sure we need to document the range in the
> > format field, maybe only mention it's not part of the format but has a
> > field of its own?
>
> I think we only have it for RGB (on some drivers only?). For YCbCr
> I think the assumption is limited range everywhere.
>
> But I'm not really concerned about documenting struct members.
> What I'm talking about is the *uapi* docs. Surely userspace
> will want to know what the new property actually does so the
> uapi needs to be documented properly. And down the line some
> new driver might also implement the wrong behaviour if there
> is no clear specification.
>
> So I'm thinking (or perhaps hoping) the rule might be something like:
> - YCbCr limited range
> - RGB full range if "Broadcast RGB" property is not present
> - RGB full or limited range based on the "Broadcast RGB" property
> if it's present
>
> I think the "Broadcast RGB" property itself might also be lacking
> proper uapi docs, so that may need to be remedied as well.
>
>
Alright, so in v12 I'll do the following:
- Add a line to all YCBCR connector formats that specifies they're
limited range as long as Broadcast RGB is limited. Whether it's limited
range when Broadcast RGB is full is purposefully left undefined.
In the future, we can expand this to state they're limited range by
default unless some other property is set. If we're not re-using
Broadcast RGB for that, this will work out fine, because users who
don't know about the eventual new property won't have this behaviour
changed. If we do re-use "Broadcast RGB" for that, then only users
relying on things we explicitly left undefined will get surprise
full range YCBCR.
- Add a line to the RGB connector format that specifies its range
depends on the "Broadcast RGB" property
This is a bit of a mess, because it's entirely reasonable that a
future YCBCR range property would want to default to full range
so that users get the most color out of their monitors. But with
this description of the connector color formats, we can't do that.
If there are alternate suggestions, I'm open for them. We can't
really rename "Broadcast RGB" but if I had a time machine, that'd
be my first choice.
Kind regards,
Nicolas Frattaroli
^ permalink raw reply
* Re: [PATCH net-next v2 4/4] net: phy: Introduce Airoha AN8801/R Gigabit Ethernet PHY driver
From: Andrew Lunn @ 2026-03-26 12:47 UTC (permalink / raw)
To: Louis-Alexis Eyraud
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
AngeloGioacchino Del Regno, Heiner Kallweit, Russell King,
kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
devicetree, linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <20260326-add-airoha-an8801-support-v2-4-1a42d6b6050f@collabora.com>
> +static int an8801r_led_blink_set(struct phy_device *phydev, u8 index,
> + unsigned long *delay_on,
> + unsigned long *delay_off)
> +{
...
> + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
> + LED_ON_EN, blink ? LED_ON_EN : 0);
> + if (ret)
> + return ret;
> +
> + return 0;
Just
return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(index),
LED_ON_EN, blink ? LED_ON_EN : 0);
> + if (!led_trigger)
> + continue;
> +
> + ret = an8801r_led_hw_control_set(phydev, led_id, led_trigger);
> + if (ret)
> + return ret;
> + }
> + return 0;
> +}
Please take a look at all your functions. Can the last error check be
removed and just use return ret, etc.
> +static int an8801r_of_init_leds(struct phy_device *phydev, u8 *led_cfg)
> +{
> + struct device *dev = &phydev->mdio.dev;
> + struct device_node *np = dev->of_node;
> + struct device_node *leds;
> + u32 function_enum_idx;
> + int ret;
> +
> + if (!np)
> + return 0;
> +
> + /* If devicetree is present, leds configuration is required */
> + leds = of_get_child_by_name(np, "leds");
> + if (!leds)
> + return 0;
> +
> + for_each_available_child_of_node_scoped(leds, led) {
> + u32 led_idx;
> +
> + ret = of_property_read_u32(led, "reg", &led_idx);
> + if (ret)
> + goto out;
> +
> + if (led_idx >= AN8801R_NUM_LEDS) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + ret = of_property_read_u32(led, "function-enumerator",
> + &function_enum_idx);
> + if (ret)
> + function_enum_idx = AN8801R_LED_FN_NONE;
> +
What is this doing? Is this documented in the binding?
> + if (function_enum_idx >= AN8801R_LED_FN_MAX) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + led_cfg[led_idx] = function_enum_idx;
> + }
> +out:
> + of_node_put(leds);
> + return ret;
> +}
> +static int an8801r_read_status(struct phy_device *phydev)
> +{
> + int prev_speed, ret;
> + u32 val;
> +
> + prev_speed = phydev->speed;
> +
> + ret = genphy_read_status(phydev);
> + if (ret)
> + return ret;
> +
> + if (phydev->link && prev_speed != phydev->speed) {
> + val = phydev->speed == SPEED_1000 ?
> + AN8801_BPBUS_LINK_MODE_1000 : 0;
> +
> + return an8801_buckpbus_reg_rmw(phydev,
> + AN8801_BPBUS_REG_LINK_MODE,
> + AN8801_BPBUS_LINK_MODE_1000,
> + val);
> + };
This is unusual. What is it doing? Please add a comment.
Andrew
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox