* Re: [PATCH 09/49] mm: panic on memory allocation failure in sparse_init_nid()
From: Muchun Song @ 2026-04-29 3:14 UTC (permalink / raw)
To: Mike Rapoport
Cc: Muchun Song, Andrew Morton, David Hildenbrand, Oscar Salvador,
Michael Ellerman, Madhavan Srinivasan, Lorenzo Stoakes,
Liam R . Howlett, Vlastimil Babka, Suren Baghdasaryan,
Michal Hocko, Nicholas Piggin, Christophe Leroy, aneesh.kumar,
joao.m.martins, linux-mm, linuxppc-dev, linux-kernel
In-Reply-To: <afCxZ5vYDeAlzTK2@kernel.org>
> On Apr 28, 2026, at 21:08, Mike Rapoport <rppt@kernel.org> wrote:
>
> Hi Muchun,
>
> On Tue, Apr 28, 2026 at 08:13:05PM +0800, Muchun Song wrote:
>>
>>> On Apr 28, 2026, at 14:56, Mike Rapoport <rppt@kernel.org> wrote:
>>>
>>> On Sun, Apr 05, 2026 at 08:52:00PM +0800, Muchun Song wrote:
>>>> When vmemmap pages allocation or usemap allocation fails, sparse_init_nid()
>>>> currently only marks the corresponding section as non-present. However,
>>>> subsequent code like memmap_init() iterating over PFNs does not check for
>>>> non-present sections, leading to invalid memory access (additional,
>>>> subsection_map_init() accessing the unallocated usemap as well).
>>>>
>>>> It is complex to audit and fix all boot-time PFN iterators to handle these
>>>> partially initialized sections correctly. Since vmemmap and usemap allocation
>>>> failures are extremely rare during early boot, the more appropriate approach
>>>> is to expose the problem as early as possible.
>>>>
>>>> Therefore, use BUG_ON() to panic immediately if allocation fails, instead of
>>>> attempting a partial recovery that leads to obscure crashes later.
>>>>
>>>> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
>>>
>>> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
>>>
>>>> ---
>>>> mm/sparse.c | 37 ++++++++-----------------------------
>>>> 1 file changed, 8 insertions(+), 29 deletions(-)
>>>>
>>>> diff --git a/mm/sparse.c b/mm/sparse.c
>>>> index effdac6b0ab1..5c12b979a618 100644
>>>> --- a/mm/sparse.c
>>>> +++ b/mm/sparse.c
>>>> @@ -354,19 +354,15 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
>>>> unsigned long map_count)
>>>> {
>>>> unsigned long pnum;
>>>> - struct page *map;
>>>> - struct mem_section *ms;
>>>> -
>>>> - if (sparse_usage_init(nid, map_count)) {
>>>> - pr_err("%s: node[%d] usemap allocation failed", __func__, nid);
>>>> - goto failed;
>>>> - }
>>>>
>>>> + if (sparse_usage_init(nid, map_count))
>>>> + panic("The node[%d] usemap allocation failed\n", nid);
>>>
>>> Please consider using memblock_alloc_or_panic() in sparse_usage_init(), it
>>> would simplify the code even more.
>>
>> Hi Mike,
>>
>> Should we add a new function like memblock_alloc_node_or_panic? Because
>> we want to allocate vmemmap pages on the same node.
>
> Heh, I missed the nid part :)
> There are a few _node_ or _nid_ allocation helpers in memblock, starting to
> add _nopanic for them would be overkill. Let's keep panic()s at call sites.
We can add a panic inside memmap_alloc() because it is used specifically for
memmap allocation. To some extent, this also reduces the number of places where
callers need to add a panic. What do you think?
Thanks.
>
>> Thanks.
>>
>>
>
> --
> Sincerely yours,
> Mike.
^ permalink raw reply
* Re: [PATCH V15 7/7] powerpc: Enable Rust for ppc64le
From: Mukesh Kumar Chaurasiya @ 2026-04-29 5:17 UTC (permalink / raw)
To: maddy, mpe, npiggin, chleroy, peterz, jpoimboe, jbaron, aliceryhl,
rostedt, ardb, ojeda, boqun, gary, bjorn3_gh, lossin, a.hindborg,
tmgross, dakr, nathan, nick.desaulniers+lkml, morbo, justinstitt,
daniel.almeida, fujita.tomonori, viresh.kumar, prafulrai522,
gregkh, arnd, tamird, mark.rutland, lyude, lina+kernel,
linuxppc-dev, linux-kernel, rust-for-linux, llvm
Cc: Link Mauve, Venkat Rao Bagalkote
In-Reply-To: <20260426105932.2270364-8-mkchauras@gmail.com>
On Sun, Apr 26, 2026 at 04:29:32PM +0530, Mukesh Kumar Chaurasiya (IBM) wrote:
> Enabling rust support for ppc64le.
>
> Tested on pseries Power11:
> ╰─❯ dmesg | grep rust
> [ 0.225728] Initialise system trusted keyrings
> [ 0.270961] rust_minimal: Rust minimal sample (init)
> [ 0.270968] rust_minimal: Am I built-in? true
> [ 0.270974] rust_minimal: test_parameter: 1
> [ 0.270983] rust_misc_device: Initialising Rust Misc Device Sample
> [ 0.271012] rust_print: Rust printing macros sample (init)
> [ 0.271019] rust_print: Emergency message (level 0) without args
> [ 0.271023] rust_print: Alert message (level 1) without args
> [ 0.271026] rust_print: Critical message (level 2) without args
> [ 0.271030] rust_print: Error message (level 3) without args
> [ 0.271033] rust_print: Warning message (level 4) without args
> [ 0.271037] rust_print: Notice message (level 5) without args
> [ 0.271040] rust_print: Info message (level 6) without args
> [ 0.271043] rust_print: A line that is continued without args
> [ 0.271054] rust_print: Emergency message (level 0) with args
> [ 0.271064] rust_print: Alert message (level 1) with args
> [ 0.271072] rust_print: Critical message (level 2) with args
> [ 0.271077] rust_print: Error message (level 3) with args
> [ 0.271083] rust_print: Warning message (level 4) with args
> [ 0.271091] rust_print: Notice message (level 5) with args
> [ 0.271097] rust_print: Info message (level 6) with args
> [ 0.271102] rust_print: A line that is continued with args
> [ 0.271110] rust_print: 1
> [ 0.271113] rust_print: "hello, world"
> [ 0.271121] rust_print: [samples/rust/rust_print_main.rs:35:5] c = "hello, world"
> [ 0.271129] rust_print: Arc<dyn Display> says 42
> [ 0.271130] rust_print: Arc<dyn Display> says hello, world
> [ 0.271136] rust_print: "hello, world"
> [ 0.271198] usbcore: registered new interface driver rust_driver_usb
> [ 0.271207] rust_faux_driver: Initialising Rust Faux Device Sample
> [ 0.271227] faux_driver rust-faux-sample-device: Hello from faux device!
> [ 0.271297] rust_configfs: Rust configfs sample (init)
>
> Reviewed-by: Link Mauve <linkmauve@linkmauve.fr>
> Tested-by: Link Mauve <linkmauve@linkmauve.fr>
> Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
> Link: https://github.com/Rust-for-Linux/linux/issues/105
> Link: https://github.com/linuxppc/issues/issues/451
> Acked-by: Gary Guo <gary@garyguo.net>
> Signed-off-by: Mukesh Kumar Chaurasiya (IBM) <mkchauras@gmail.com>
> ---
Upstream issue for powerpc64 and powerpc64le target.
Link: https://github.com/rust-lang/compiler-team/issues/987
Link: https://github.com/rust-lang/compiler-team/issues/988
Regards,
Mukesh
> arch/powerpc/Kconfig | 1 +
> arch/powerpc/Makefile | 7 ++++++-
> rust/Makefile | 6 ++++++
> 3 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 4ac897b650d4..2e3065bce9cd 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -286,6 +286,7 @@ config PPC
> select HAVE_RELIABLE_STACKTRACE
> select HAVE_RSEQ
> select HAVE_RUST if PPC32
> + select HAVE_RUST if PPC64 && CPU_LITTLE_ENDIAN
> select HAVE_SAMPLE_FTRACE_DIRECT if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
> select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
> select HAVE_SETUP_PER_CPU_AREA if PPC64
> diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
> index 589613eaa5dc..9385db478c59 100644
> --- a/arch/powerpc/Makefile
> +++ b/arch/powerpc/Makefile
> @@ -61,7 +61,12 @@ else
> KBUILD_LDFLAGS_MODULE += $(objtree)/arch/powerpc/lib/crtsavres.o
> endif
>
> -KBUILD_RUSTFLAGS += --target=powerpc-unknown-linux-gnu
> +ifdef CONFIG_PPC64
> +KBUILD_RUSTFLAGS += --target=powerpc64le-unknown-linux-gnu
> +KBUILD_RUSTFLAGS += -Ctarget-feature=-mma,-vsx,-hard-float,-altivec
> +else
> +KBUILD_RUSTFLAGS += --target=powerpc-unknown-linux-gnu
> +endif
>
> ifdef CONFIG_CPU_LITTLE_ENDIAN
> KBUILD_CPPFLAGS += -mlittle-endian
> diff --git a/rust/Makefile b/rust/Makefile
> index 54096ce8a675..068b6fc3e0aa 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -408,7 +408,13 @@ BINDGEN_TARGET_x86 := x86_64-linux-gnu
> BINDGEN_TARGET_arm64 := aarch64-linux-gnu
> BINDGEN_TARGET_arm := arm-linux-gnueabi
> BINDGEN_TARGET_loongarch := loongarch64-linux-gnusf
> +
> +ifdef CONFIG_PPC64
> +BINDGEN_TARGET_powerpc := powerpc64le-linux-gnu
> +else
> BINDGEN_TARGET_powerpc := powerpc-linux-gnu
> +endif
> +
> BINDGEN_TARGET_um := $(BINDGEN_TARGET_$(SUBARCH))
> BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH))
>
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH V15 6/7] rust: Add PowerPC support
From: Mukesh Kumar Chaurasiya @ 2026-04-29 5:18 UTC (permalink / raw)
To: maddy, mpe, npiggin, chleroy, peterz, jpoimboe, jbaron, aliceryhl,
rostedt, ardb, ojeda, boqun, gary, bjorn3_gh, lossin, a.hindborg,
tmgross, dakr, nathan, nick.desaulniers+lkml, morbo, justinstitt,
daniel.almeida, fujita.tomonori, viresh.kumar, prafulrai522,
gregkh, arnd, tamird, mark.rutland, lyude, lina+kernel,
linuxppc-dev, linux-kernel, rust-for-linux, llvm
Cc: Link Mauve
In-Reply-To: <20260426105932.2270364-7-mkchauras@gmail.com>
On Sun, Apr 26, 2026 at 04:29:31PM +0530, Mukesh Kumar Chaurasiya (IBM) wrote:
> From: Link Mauve <linkmauve@linkmauve.fr>
>
> For now only Big Endian 32-bit PowerPC is supported, as that is the only
> hardware I have. This has been tested on the Nintendo Wii so far, but I
> plan on also using it on the GameCube, Wii U and Apple G4.
>
> These changes aren’t the only ones required to get the kernel to compile
> and link on PowerPC, libcore will also have to be changed to not use
> integer division to format u64, u128 and core::time::Duration, otherwise
> __udivdi3() and __umoddi3() will have to be added. I have tested this
> change by replacing the three implementations with unimplemented!() and
> it linked just fine.
>
> Signed-off-by: Link Mauve <linkmauve@linkmauve.fr>
> Link: https://github.com/Rust-for-Linux/linux/issues/105
> Link: https://github.com/linuxppc/issues/issues/451
> Acked-by: Gary Guo <gary@garyguo.net>
> Signed-off-by: Mukesh Kumar Chaurasiya (IBM) <mkchauras@gmail.com>
Upstream Issue for powerpc target.
Link: https://github.com/rust-lang/compiler-team/issues/986
Regards,
Mukesh
> ---
> arch/powerpc/Kconfig | 1 +
> arch/powerpc/Makefile | 2 ++
> rust/Makefile | 4 +++-
> 3 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index e93df95b79e7..4ac897b650d4 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -285,6 +285,7 @@ config PPC
> select HAVE_REGS_AND_STACK_ACCESS_API
> select HAVE_RELIABLE_STACKTRACE
> select HAVE_RSEQ
> + select HAVE_RUST if PPC32
> select HAVE_SAMPLE_FTRACE_DIRECT if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
> select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
> select HAVE_SETUP_PER_CPU_AREA if PPC64
> diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
> index a58b1029592c..589613eaa5dc 100644
> --- a/arch/powerpc/Makefile
> +++ b/arch/powerpc/Makefile
> @@ -61,6 +61,8 @@ else
> KBUILD_LDFLAGS_MODULE += $(objtree)/arch/powerpc/lib/crtsavres.o
> endif
>
> +KBUILD_RUSTFLAGS += --target=powerpc-unknown-linux-gnu
> +
> ifdef CONFIG_CPU_LITTLE_ENDIAN
> KBUILD_CPPFLAGS += -mlittle-endian
> KBUILD_LDFLAGS += -EL
> diff --git a/rust/Makefile b/rust/Makefile
> index d70fb186cae9..54096ce8a675 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -400,13 +400,15 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \
> -fstrict-flex-arrays=% -fmin-function-alignment=% \
> -fzero-init-padding-bits=% -mno-fdpic \
> -fdiagnostics-show-context -fdiagnostics-show-context=% \
> - --param=% --param asan-% -fno-isolate-erroneous-paths-dereference
> + --param=% --param asan-% -fno-isolate-erroneous-paths-dereference \
> + -ffixed-r2 -mmultiple -mno-readonly-in-sdata
>
> # Derived from `scripts/Makefile.clang`.
> BINDGEN_TARGET_x86 := x86_64-linux-gnu
> BINDGEN_TARGET_arm64 := aarch64-linux-gnu
> BINDGEN_TARGET_arm := arm-linux-gnueabi
> BINDGEN_TARGET_loongarch := loongarch64-linux-gnusf
> +BINDGEN_TARGET_powerpc := powerpc-linux-gnu
> BINDGEN_TARGET_um := $(BINDGEN_TARGET_$(SUBARCH))
> BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH))
>
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH RESEND 1/2] powerpc/ps3: Drop redundant result assignment
From: Michael Ellerman @ 2026-04-29 6:03 UTC (permalink / raw)
To: Krzysztof Kozlowski, Madhavan Srinivasan, Nicholas Piggin,
Christophe Leroy (CS GROUP), Geoff Levand, Nathan Chancellor,
Nick Desaulniers, Bill Wendling, Justin Stitt, linuxppc-dev,
linux-kernel, llvm
In-Reply-To: <90c122bc-3067-4e3d-8083-dd94844c31f2@oss.qualcomm.com>
On 28/4/2026 23:22, Krzysztof Kozlowski wrote:
> On 17/03/2026 14:08, Krzysztof Kozlowski wrote:
>> Return value of ps3_start_probe_thread() is not used, so code can be
>> simplified to fix W=1 clang warnings:
>>
>> arch/powerpc/platforms/ps3/device-init.c:953:6: error: variable 'result' set but not used [-Werror,-Wunused-but-set-variable]
>>
>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>> ---
>>
>> Resend after ~2.5 months
>>
>> arch/powerpc/platforms/ps3/device-init.c | 4 +---
>> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> Ping. This also got a review.
>
> I do not plan to resend second time... And I also understand if this is
> somehow legacy and fixing warnings is not desired, but then it would be
> great if you just responded "don't send such patches" and I would not
> waste my time.
Thanks for the patch, sorry it hasn't been picked up.
I have been AWOL, and I suspect Maddy is not sure about taking PS3
patches directly without hearing from Geoff.
Maddy this is fine to pick up for next.
cheers
^ permalink raw reply
* Re: [PATCH 09/49] mm: panic on memory allocation failure in sparse_init_nid()
From: Mike Rapoport @ 2026-04-29 6:53 UTC (permalink / raw)
To: Muchun Song
Cc: Muchun Song, Andrew Morton, David Hildenbrand, Oscar Salvador,
Michael Ellerman, Madhavan Srinivasan, Lorenzo Stoakes,
Liam R . Howlett, Vlastimil Babka, Suren Baghdasaryan,
Michal Hocko, Nicholas Piggin, Christophe Leroy, aneesh.kumar,
joao.m.martins, linux-mm, linuxppc-dev, linux-kernel
In-Reply-To: <408EDCB4-7F65-4595-BE44-E23300FBD397@linux.dev>
On Wed, Apr 29, 2026 at 11:14:14AM +0800, Muchun Song wrote:
> > On Apr 28, 2026, at 21:08, Mike Rapoport <rppt@kernel.org> wrote:
> >>>>
> >>>> + if (sparse_usage_init(nid, map_count))
> >>>> + panic("The node[%d] usemap allocation failed\n", nid);
> >>>
> >>> Please consider using memblock_alloc_or_panic() in sparse_usage_init(), it
> >>> would simplify the code even more.
> >>
> >> Hi Mike,
> >>
> >> Should we add a new function like memblock_alloc_node_or_panic? Because
> >> we want to allocate vmemmap pages on the same node.
> >
> > Heh, I missed the nid part :)
> > There are a few _node_ or _nid_ allocation helpers in memblock, starting to
> > add _nopanic for them would be overkill. Let's keep panic()s at call sites.
>
> We can add a panic inside memmap_alloc() because it is used specifically for
> memmap allocation. To some extent, this also reduces the number of places where
> callers need to add a panic. What do you think?
Right, with sparse_buffer_alloc() and with this change memmap_alloc() can
panic(). I like the idea.
> Thanks.
--
Sincerely yours,
Mike.
^ permalink raw reply
* Re: [PATCH 10/49] mm: move subsection_map_init() into sparse_init()
From: Mike Rapoport @ 2026-04-29 6:54 UTC (permalink / raw)
To: Muchun Song
Cc: Muchun Song, Andrew Morton, David Hildenbrand, Oscar Salvador,
Michael Ellerman, Madhavan Srinivasan, Lorenzo Stoakes,
Liam R . Howlett, Vlastimil Babka, Suren Baghdasaryan,
Michal Hocko, Nicholas Piggin, Christophe Leroy, aneesh.kumar,
joao.m.martins, linux-mm, linuxppc-dev, linux-kernel
In-Reply-To: <DFB372BA-A262-4507-9280-7C0072280CC4@linux.dev>
On Wed, Apr 29, 2026 at 11:06:15AM +0800, Muchun Song wrote:
>
>
> > On Apr 28, 2026, at 15:06, Mike Rapoport <rppt@kernel.org> wrote:
> >
> > On Sun, Apr 05, 2026 at 08:52:01PM +0800, Muchun Song wrote:
> >> Move the initialization of the subsection map from free_area_init()
> >> into sparse_init(). This encapsulates the logic within the sparse
> >> memory initialization code.
> >>
> >> Signed-off-by: Muchun Song <songmuchun@bytedance.com>
> >
> > Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
>
> Thanks.
>
> >
> >> ---
> >> mm/internal.h | 5 ++---
> >> mm/mm_init.c | 10 ++--------
> >> mm/sparse-vmemmap.c | 11 ++++++++++-
> >> mm/sparse.c | 1 +
> >> 4 files changed, 15 insertions(+), 12 deletions(-)
> >>
> >> diff --git a/mm/internal.h b/mm/internal.h
> >> index edb1c04d0617..d70075d0e788 100644
> >> --- a/mm/internal.h
> >> +++ b/mm/internal.h
> >> @@ -1004,10 +1004,9 @@ static inline void sparse_init(void) {}
> >> * mm/sparse-vmemmap.c
> >> */
> >> #ifdef CONFIG_SPARSEMEM_VMEMMAP
> >> -void sparse_init_subsection_map(unsigned long pfn, unsigned long nr_pages);
> >> +void sparse_init_subsection_map(void);
> >> #else
> >> -static inline void sparse_init_subsection_map(unsigned long pfn,
> >> - unsigned long nr_pages)
> >> +static inline void sparse_init_subsection_map(void)
> >> {
> >> }
> >> #endif /* CONFIG_SPARSEMEM_VMEMMAP */
> >
> > I side note: we might want to split out mm/sparse.h and also move some
> > declarations from include/linux/mmzone.h there.
>
> I think we can do that in a separate series for cleanup only.
Sure, that's what I meant too.
> Thanks.
>
>
--
Sincerely yours,
Mike.
^ permalink raw reply
* [PATCH v2 0/5] ASoC: fsl-asoc-card: Add some improvements
From: Shengjiu Wang @ 2026-04-29 10:00 UTC (permalink / raw)
To: shengjiu.wang, Xiubo.Lee, festevam, nicoleotsuka, lgirdwood,
broonie, perex, tiwai, linux-sound, linuxppc-dev, linux-kernel
This patch series addresses several issues in the Freescale Generic ASoC
Sound Card driver related to hardware limitations, DPCM path switching,
and codec-specific constraints.
The fsl-asoc-card driver provides a generic machine driver for i.MX SoCs,
supporting various codecs and optional ASRC (Asynchronous Sample Rate
Converter) for sample rate conversion. During testing several issues were
identified:
1. Missing channel constraint propagation in DPCM mode
2. DPCM path switching causing audio dropouts
3. Hardware channel alignment requirements
4. Clock generation limitations preventing certain audio formats
5. Codec-specific PLL frequency violations
changes in v2:
- Patch 3/5: remove the static constraint_rates and constraint_channels
variable in fsl_asoc_card_startup(), move them to
struct fsl_asoc_card_priv, to avoid conflict with other instance
- Patch 4/5: make exclude S20_3LE format specific to WM8960/WM8962 + SAI
case, to avoid impact to other users.
Shengjiu Wang (5):
ASoC: fsl-asoc-card: enable dpcm_merged_chan flag for ASRC frontend
ASoC: fsl-asoc-card: enable ignore_pmdown_time for ASRC case
ASoC: fsl-asoc-card: add channel and rate constraints for CS42888
ASoC: fsl-asoc-card: exclude S20_3LE format for WM8960/WM8962 + SAI
ASoC: fsl-asoc-card: reduce WM8904 PLL ratio to meet frequency limit
sound/soc/fsl/fsl-asoc-card.c | 111 +++++++++++++++++++++++++++++++++-
1 file changed, 110 insertions(+), 1 deletion(-)
--
2.34.1
^ permalink raw reply
* [PATCH v2 1/5] ASoC: fsl-asoc-card: enable dpcm_merged_chan flag for ASRC frontend
From: Shengjiu Wang @ 2026-04-29 10:00 UTC (permalink / raw)
To: shengjiu.wang, Xiubo.Lee, festevam, nicoleotsuka, lgirdwood,
broonie, perex, tiwai, linux-sound, linuxppc-dev, linux-kernel
In-Reply-To: <20260429100028.2739711-1-shengjiu.wang@nxp.com>
When using ASRC in DPCM mode, the backend DAI (codec) may have channel
constraints that differ from the frontend. For example, the ASRC can
support 1-8 channels, but the codec might only support stereo (2 channels).
Without dpcm_merged_chan, userspace can open the frontend with unsupported
channel counts, leading to errors when the backend is configured.
Enable dpcm_merged_chan to merge backend channel constraints to the
frontend, ensuring userspace only sees valid channel configurations.
This fixes issues where applications attempt to use channel counts
that the backend codec doesn't support.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl-asoc-card.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 70a6159430ed..41cd2fc2ea56 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -989,6 +989,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
if (asrc_pdev) {
/* DPCM DAI Links only if ASRC exists */
+ priv->dai_link[1].dpcm_merged_chan = 1;
priv->dai_link[1].cpus->of_node = asrc_np;
priv->dai_link[1].platforms->of_node = asrc_np;
for_each_link_codecs((&(priv->dai_link[2])), codec_idx, codec_comp) {
--
2.34.1
^ permalink raw reply related
* [PATCH v2 2/5] ASoC: fsl-asoc-card: enable ignore_pmdown_time for ASRC case
From: Shengjiu Wang @ 2026-04-29 10:00 UTC (permalink / raw)
To: shengjiu.wang, Xiubo.Lee, festevam, nicoleotsuka, lgirdwood,
broonie, perex, tiwai, linux-sound, linuxppc-dev, linux-kernel
In-Reply-To: <20260429100028.2739711-1-shengjiu.wang@nxp.com>
Problem:
When switching from ASRC path (hw:0,1) to direct path (hw:0,0),
audio stops after 5 seconds due to DAPM powering down shared widgets.
Scenario:
1. Play on hw:0,1 (ASRC): ASRC-Playback → CPU-Playback → Codec
2. Stop playback
3. Play on hw:0,0 (Direct): CPU-Playback → Codec
4. After 5s: No sound (DAPM powered down CPU-Playback)
Root Cause:
DAPM sees ASRC-Playback disconnected and powers down the entire
path including CPU-Playback, even though CPU-Playback is still
needed for the direct path.
Solution:
Enable ignore_pmdown_time for DPCM links to prevent premature
widget power-down when switching between paths.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl-asoc-card.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 41cd2fc2ea56..e08e135886f7 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -990,6 +990,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
if (asrc_pdev) {
/* DPCM DAI Links only if ASRC exists */
priv->dai_link[1].dpcm_merged_chan = 1;
+ priv->dai_link[1].ignore_pmdown_time = 1;
priv->dai_link[1].cpus->of_node = asrc_np;
priv->dai_link[1].platforms->of_node = asrc_np;
for_each_link_codecs((&(priv->dai_link[2])), codec_idx, codec_comp) {
@@ -999,6 +1000,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
}
priv->dai_link[2].cpus->of_node = cpu_np;
priv->dai_link[2].dai_fmt = priv->dai_fmt;
+ priv->dai_link[2].ignore_pmdown_time = 1;
priv->card.num_links = 3;
ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
--
2.34.1
^ permalink raw reply related
* [PATCH v2 3/5] ASoC: fsl-asoc-card: add channel and rate constraints for CS42888
From: Shengjiu Wang @ 2026-04-29 10:00 UTC (permalink / raw)
To: shengjiu.wang, Xiubo.Lee, festevam, nicoleotsuka, lgirdwood,
broonie, perex, tiwai, linux-sound, linuxppc-dev, linux-kernel
In-Reply-To: <20260429100028.2739711-1-shengjiu.wang@nxp.com>
The CS42888 codec has 4 I2S lanes with 2 channels per lane. Using odd
channel counts (3, 5, 7) causes data misalignment in the I2S frame,
resulting in incorrect channel mapping. Only mono and even channel
counts (1, 2, 4, 6, 8) work correctly.
Additionally, the fixed system clock on i.MX platforms limits supported
sample rates. With 12.288 MHz MCLK, only 48kHz family rates (48k, 96k,
192k) achieve valid MCLK:LRCK ratios. With 11.2896 MHz MCLK, only 44k
family rates are supported.
Add a startup callback to apply PCM constraints for both channels and
rates, preventing userspace from requesting unsupported configurations.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl-asoc-card.c | 71 +++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index e08e135886f7..90414ac10032 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -40,6 +40,33 @@
/* Default DAI format without Master and Slave flag */
#define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF)
+static const u32 cs42888_rates_48k[] = {
+ 48000, 96000, 192000,
+};
+
+static const u32 cs42888_rates_44k[] = {
+ 44100, 88200, 176400,
+};
+
+static const u32 cs42888_channels[] = {
+ 1, 2, 4, 6, 8,
+};
+
+static const struct snd_pcm_hw_constraint_list cs42888_rate_48k_constraints = {
+ .list = cs42888_rates_48k,
+ .count = ARRAY_SIZE(cs42888_rates_48k),
+};
+
+static const struct snd_pcm_hw_constraint_list cs42888_rate_44k_constraints = {
+ .list = cs42888_rates_44k,
+ .count = ARRAY_SIZE(cs42888_rates_44k),
+};
+
+static const struct snd_pcm_hw_constraint_list cs42888_channel_constraints = {
+ .list = cs42888_channels,
+ .count = ARRAY_SIZE(cs42888_channels),
+};
+
/**
* struct codec_priv - CODEC private data
* @mclk: Main clock of the CODEC
@@ -87,6 +114,8 @@ struct cpu_priv {
* @codec_priv: CODEC private data
* @cpu_priv: CPU private data
* @card: ASoC card structure
+ * @constraint_rates: array of supported rates
+ * @constraint_channels: array of supported channels
* @streams: Mask of current active streams
* @sample_rate: Current sample rate
* @sample_format: Current sample format
@@ -104,6 +133,8 @@ struct fsl_asoc_card_priv {
struct codec_priv codec_priv[2];
struct cpu_priv cpu_priv;
struct snd_soc_card card;
+ const struct snd_pcm_hw_constraint_list *constraint_rates;
+ const struct snd_pcm_hw_constraint_list *constraint_channels;
u8 streams;
u32 sample_rate;
snd_pcm_format_t sample_format;
@@ -291,7 +322,39 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream)
return 0;
}
+static int fsl_asoc_card_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ if (priv->constraint_channels) {
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ priv->constraint_channels);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Apply rate constraints only to frontend DAI links (no_pcm = 0).
+ * Skip DPCM backend (no_pcm = 1) as rate is fixed by be_hw_params_fixup()
+ * and ASRC frontend handles rate conversion.
+ */
+ if (priv->constraint_rates && !rtd->dai_link->no_pcm) {
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ priv->constraint_rates);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct snd_soc_ops fsl_asoc_card_ops = {
+ .startup = fsl_asoc_card_startup,
.hw_params = fsl_asoc_card_hw_params,
.hw_free = fsl_asoc_card_hw_free,
};
@@ -753,6 +816,14 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
priv->cpu_priv.slot_width = 32;
priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
+ priv->constraint_channels = &cs42888_channel_constraints;
+ if (priv->codec_priv[0].mclk_freq % 12288000 == 0)
+ priv->constraint_rates = &cs42888_rate_48k_constraints;
+ else if (priv->codec_priv[0].mclk_freq % 11289600 == 0)
+ priv->constraint_rates = &cs42888_rate_44k_constraints;
+ else
+ dev_warn(&pdev->dev, "Unknown MCLK frequency %lu, no rate constraints\n",
+ priv->codec_priv[0].mclk_freq);
} else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) {
codec_dai_name[0] = "cs4271-hifi";
priv->codec_priv[0].mclk_id = CS427x_SYSCLK_MCLK;
--
2.34.1
^ permalink raw reply related
* [PATCH v2 4/5] ASoC: fsl-asoc-card: exclude S20_3LE format for WM8960/WM8962 + SAI
From: Shengjiu Wang @ 2026-04-29 10:00 UTC (permalink / raw)
To: shengjiu.wang, Xiubo.Lee, festevam, nicoleotsuka, lgirdwood,
broonie, perex, tiwai, linux-sound, linuxppc-dev, linux-kernel
In-Reply-To: <20260429100028.2739711-1-shengjiu.wang@nxp.com>
S20_3LE format cannot be used with WM8960/WM8962 codecs when paired
with SAI, due to two distinct BCLK generation limitations:
1. Codec Master Mode:
When WM8960/WM8962 generates BCLK, it cannot produce the exact
1.92 MHz required for S20_3LE at 48kHz stereo (48000 × 2 × 20).
The codec uses fixed dividers from SYSCLK (12.288 MHz), and the
required divider (6.4) is not available. The closest divider is 6,
producing 2.048 MHz, which causes right channel corruption.
2. SAI Master Mode:
SAI derive BCLK from MCLK using integer dividers only. S20_3LE
requires non-integer divider ratios with standard MCLK frequencies.
For example, 48kHz stereo needs 1.920 MHz BCLK, which requires a
divider of 6.4 from 12.288 MHz MCLK (not an integer).
Exclude S20_3LE format for WM8960/WM8962 when used with SAI to prevent
these issues. Users should use S16_LE, S24_LE, or S32_LE instead.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl-asoc-card.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 90414ac10032..44083d15f6e5 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -122,6 +122,7 @@ struct cpu_priv {
* @asrc_rate: ASRC sample rate used by Back-Ends
* @asrc_format: ASRC sample format used by Back-Ends
* @dai_fmt: DAI format between CPU and CODEC
+ * @exclude_format: excluded format;
* @name: Card name
*/
@@ -141,6 +142,7 @@ struct fsl_asoc_card_priv {
u32 asrc_rate;
snd_pcm_format_t asrc_format;
u32 dai_fmt;
+ u64 exclude_format;
char name[32];
};
@@ -329,6 +331,14 @@ static int fsl_asoc_card_startup(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
+ if (priv->exclude_format && !rtd->dai_link->no_pcm) {
+ ret = snd_pcm_hw_constraint_mask64(runtime,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ ~priv->exclude_format);
+ if (ret)
+ return ret;
+ }
+
if (priv->constraint_channels) {
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
@@ -850,11 +860,30 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->codec_priv[0].fll_id = WM8962_SYSCLK_FLL;
priv->codec_priv[0].pll_id = WM8962_FLL;
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
+ /*
+ * WM8962 has same BCLK generation limitations as WM8960.
+ * See WM8960 section for detailed explanation.
+ */
+ if (of_node_name_eq(cpu_np, "sai"))
+ priv->exclude_format = SNDRV_PCM_FMTBIT_S20_3LE;
} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) {
codec_dai_name[0] = "wm8960-hifi";
priv->codec_priv[0].fll_id = WM8960_SYSCLK_AUTO;
priv->codec_priv[0].pll_id = WM8960_SYSCLK_AUTO;
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
+ /*
+ * WM8960 in master mode cannot generate exact 1.92 MHz BCLK
+ * required for S20_3LE (48kHz × 2ch × 20bit). Closest available
+ * is 2.048 MHz (SYSCLK/6), which causes right channel corruption.
+ *
+ * In SAI master mode, SAI derive BCLK from MCLK using integer
+ * dividers only. S20_3LE requires non-integer divider ratios
+ * with standard MCLK frequencies. For example, 48kHz stereo
+ * needs 1.920 MHz BCLK, which requires a divider of 6.4 from
+ * 12.288 MHz MCLK (not an integer).
+ */
+ if (of_node_name_eq(cpu_np, "sai"))
+ priv->exclude_format = SNDRV_PCM_FMTBIT_S20_3LE;
} else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) {
codec_dai_name[0] = "ac97-hifi";
priv->dai_fmt = SND_SOC_DAIFMT_AC97;
--
2.34.1
^ permalink raw reply related
* [PATCH v2 5/5] ASoC: fsl-asoc-card: reduce WM8904 PLL ratio to meet frequency limit
From: Shengjiu Wang @ 2026-04-29 10:00 UTC (permalink / raw)
To: shengjiu.wang, Xiubo.Lee, festevam, nicoleotsuka, lgirdwood,
broonie, perex, tiwai, linux-sound, linuxppc-dev, linux-kernel
In-Reply-To: <20260429100028.2739711-1-shengjiu.wang@nxp.com>
WM8904 has a 27 MHz PLL frequency limit. The current S24_LE PLL ratio
of 384 exceeds this at high sample rates (96 kHz × 384 = 36.864 MHz).
Reduce the ratio to 192 for WM8904, keeping PLL within limits at all
supported rates (96 kHz × 192 = 18.432 MHz).
Add codec-specific pll_ratio_s24 field, default 384, override to 192
for WM8904.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl-asoc-card.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 44083d15f6e5..709543308fe9 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -75,6 +75,9 @@ static const struct snd_pcm_hw_constraint_list cs42888_channel_constraints = {
* @mclk_id: MCLK (or main clock) id for set_sysclk()
* @fll_id: FLL (or secordary clock) id for set_sysclk()
* @pll_id: PLL id for set_pll()
+ * @pll_ratio_s24: PLL output ratio for S24_LE format (PLL_freq = sample_rate × ratio)
+ * Default is 384, but some codecs (e.g., WM8904) require lower values
+ * to stay within PLL frequency limits
*/
struct codec_priv {
struct clk *mclk;
@@ -83,6 +86,7 @@ struct codec_priv {
u32 mclk_id;
int fll_id;
int pll_id;
+ int pll_ratio_s24;
};
/**
@@ -255,7 +259,7 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) {
if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
- pll_out = priv->sample_rate * 384;
+ pll_out = priv->sample_rate * codec_priv->pll_ratio_s24;
else
pll_out = priv->sample_rate * 256;
@@ -815,6 +819,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
for (codec_idx = 0; codec_idx < 2; codec_idx++) {
priv->codec_priv[codec_idx].fll_id = -1;
priv->codec_priv[codec_idx].pll_id = -1;
+ priv->codec_priv[codec_idx].pll_ratio_s24 = 384;
}
/* Diversify the card configurations */
@@ -935,6 +940,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->codec_priv[0].mclk_id = WM8904_FLL_MCLK;
priv->codec_priv[0].fll_id = WM8904_CLK_FLL;
priv->codec_priv[0].pll_id = WM8904_FLL_MCLK;
+ priv->codec_priv[0].pll_ratio_s24 = 192;
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
} else if (of_device_is_compatible(np, "fsl,imx-audio-spdif")) {
ret = fsl_asoc_card_spdif_init(codec_np, cpu_np, codec_dai_name, priv);
--
2.34.1
^ permalink raw reply related
* Re: [mainline][BUG] Observed Workqueue lockups on offline CPUs.
From: Samir M @ 2026-04-29 10:16 UTC (permalink / raw)
To: Boqun Feng
Cc: Paul E . McKenney, Boqun Feng, LKML, Tejun Heo, RCU, linuxppc-dev,
Shrikanth Hegde
In-Reply-To: <ae-EP1BpXgnEWCt4@tardis.local>
On 27/04/26 9:13 pm, Boqun Feng wrote:
> On Mon, Apr 27, 2026 at 05:00:10PM +0530, Samir M wrote:
> Hi Samir,
>
>> On 27/04/26 3:32 pm, Samir M wrote:
>>> Hi Paul,
>>>
>>> I've been testing the latest upstream kernel on a PowerPC system and
>>> encountered workqueue lockup issues that I've bisected to commit
>>> 61bbcfb50514 ("srcu: Push srcu_node allocation to GP when
>>> non-preemptible").
>>> After booting, I'm seeing workqueue lockup warnings for CPUs 81-96,
>>> which are offline on my system. The workqueues remain stuck for over 237
>>> seconds:
>>>
>>> [ 243.309302][ C0] BUG: workqueue lockup - pool cpus=81 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309311][ C0] BUG: workqueue lockup - pool cpus=82 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309318][ C0] BUG: workqueue lockup - pool cpus=83 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309326][ C0] BUG: workqueue lockup - pool cpus=84 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309333][ C0] BUG: workqueue lockup - pool cpus=85 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309341][ C0] BUG: workqueue lockup - pool cpus=86 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309348][ C0] BUG: workqueue lockup - pool cpus=87 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309355][ C0] BUG: workqueue lockup - pool cpus=88 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309363][ C0] BUG: workqueue lockup - pool cpus=89 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309370][ C0] BUG: workqueue lockup - pool cpus=90 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309377][ C0] BUG: workqueue lockup - pool cpus=91 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309384][ C0] BUG: workqueue lockup - pool cpus=92 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309392][ C0] BUG: workqueue lockup - pool cpus=93 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309399][ C0] BUG: workqueue lockup - pool cpus=94 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309406][ C0] BUG: workqueue lockup - pool cpus=95 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>> [ 243.309413][ C0] BUG: workqueue lockup - pool cpus=96 node=0
>>> flags=0x4 nice=0 stuck for 237s!
>>>
>>> Git bisect identified this as the first bad commit:
>>>
>>> commit 61bbcfb50514a8a94e035a7349697a3790ab4783
>>> Author: Paul E. McKenney <paulmck@kernel.org>
>>> Date: Fri Mar 20 20:29:20 2026 -0700
>>>
>>> srcu: Push srcu_node allocation to GP when non-preemptible
>>>
>>> When the srcutree.convert_to_big and srcutree.big_cpu_lim kernel boot
>>> parameters specify initialization-time allocation of the srcu_node
>>> tree for statically allocated srcu_struct structures (for example, in
>>> DEFINE_SRCU() at build time instead of init_srcu_struct() at
>>> runtime),
>>> init_srcu_struct_nodes() will attempt to dynamically allocate this
>>> tree
>>> at the first run-time update-side use of this srcu_struct structure,
>>> but while holding a raw spinlock. Because the memory allocator can
>>> acquire non-raw spinlocks, this can result in lockdep splats.
>>>
>>> This commit therefore uses the same SRCU_SIZE_ALLOC trick that is
>>> used
>>> when the first run-time update-side use of this srcu_struct structure
>>> happens before srcu_init() is called. The actual allocation then
>>> takes
>>> place from workqueue context at the ends of upcoming SRCU grace
>>> periods.
>>>
>>> [boqun: Adjust the sha1 of the Fixes tag]
>>>
>>> Fixes: 175b45ed343a ("srcu: Use raw spinlocks so call_srcu() can be
>>> used under preempt_disable()")
>>> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
>>> Signed-off-by: Boqun Feng <boqun@kernel.org>
>>>
>>> kernel/rcu/srcutree.c | 7 +++++--
>>> 1 file changed, 5 insertions(+), 2 deletions(-)
>>>
>>> Reverting this commit resolves the issue.
>>>
>>> The problem appears to be that the workqueue is attempting to execute on
>>> offline CPUs. The commit moves SRCU node allocation to workqueue context
>>> to avoid lockdep issues with memory allocation under raw spinlocks,
>>> which makes sense. However, it seems the workqueue scheduling doesn't
>>> properly account for CPU online/offline state in this code path.
>>>
>>> My test environment:
>>> - Architecture: PowerPC
>>> - Kernel version: Latest upstream (7.1-rc1)
>>> - CPUs 81-96 are offline at boot time
>>>
>>> I suspect the issue might be related to:
>>> 1. Workqueue not checking CPU online status before scheduling SRCU
>>> allocation work
>>> 2. Missing CPU hotplug awareness in the new workqueue-based allocation
>>> path
>>> 3. Possible race condition with CPU hotplug events
>>>
>>> Would it make sense to use queue_work_on() with explicit online CPU
>>> selection, or add CPU hotplug handlers for this workqueue? I'm not
>>> deeply familiar with the workqueue internals, so I might be missing
>>> something.
>>> Please let me know if you need any additional details or if you'd like
>>> me to test any patches.
>>>
>>> If you happen to fix the above issue, then please add below tag.
>>> Reported-by: Samir M <samir@linux.ibm.com>
>>>
>>>
>>> Thanks,
>>> Samir
>> Hi Paul,
>>
>>
>> I worked on fixing the issue and introduced the changes below. With these
>> updates, I no longer observe any workqueue lockup messages for offline CPUs.
>> Could you please review the changes and share your feedback?
>>
>> The commit 61bbcfb50514 ("srcu: Push srcu_node allocation to GP when
>> non-preemptible") introduced workqueue lockups on systems with offline
>> CPUs. The issue occurs because srcu_queue_delayed_work_on() calls
>> queue_work_on() with sdp->cpu, which may be offline, causing the
>> workqueue to spin indefinitely on that CPU.
>>
>> This patch fixes the issue by checking if the target CPU is online
>> before queuing work on it. If the CPU is offline, we fall back to
>> using queue_work() which will schedule the work on any available
>> online CPU.
>>
>> Fixes: 61bbcfb50514 ("srcu: Push srcu_node allocation to GP when
>> non-preemptible")
>>
>> Signed-off-by: Samir <samir@linux.ibm.com>
> Thanks for the patch, but I wonder: have you checked this email thread:
>
> https://lore.kernel.org/rcu/ttd89ul@ub.hpns/
>
> Paul had a fix [1], and TJ had a "fix" [2] on workqueue side.
>
> In general I think we discovered that as long as a CPU has been onlined
> once, it's OK to queue the work on that CPU (which may be offlined) even
> with our TJ's patch (whether we should do that is a different problem
> ;-)). Please do check whether Paul's fix works for your case, thanks!
>
> [1]: https://lore.kernel.org/rcu/ed1fa6cd-7343-4ca3-8b9d-d699ca496f83@paulmck-laptop/
> [2]: https://lore.kernel.org/rcu/adlHKowvhn8AGXCc@slm.duckdns.org/
>
> Regards,
> Boqun
>
>> ---
>> kernel/rcu/srcutree.c | 7 ++++++-
>> 1 file changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
>> index 0d01cd8c4b4a..55a90dd4a030 100644
>> --- a/kernel/rcu/srcutree.c
>> +++ b/kernel/rcu/srcutree.c
>> @@ -869,10 +869,15 @@ static void srcu_delay_timer(struct timer_list *t)
>> static void srcu_queue_delayed_work_on(struct srcu_data *sdp,
>> unsigned long delay)
>> {
>> - if (!delay) {
>> + if (!delay && cpu_online(sdp->cpu)) {
>> queue_work_on(sdp->cpu, rcu_gp_wq, &sdp->work);
>> return;
>> + } else if (!delay) {
>> + /* CPU is offline, queue on any available CPU */
>> + queue_work(rcu_gp_wq, &sdp->work);
>> + return;
>> + }
>>
>> timer_reduce(&sdp->delay_work, jiffies + delay);
>> }
>> --
>>
>>
>> Thanks,
>> Samir
Hi Boqun,
Thank you for pointing me to the existing patches. I have tested both
Paul's patch [1] and TJ's workqueue patch [2] on my PowerPC system (80
CPUs), and can confirm that the workqueue lockup issue is not observed.
Test Environment:
- System: PowerPC with 80 CPUs ( e.g. PowerPC LPARs with 80 online and
384 possible CPUs)
- Kernel version: Latest upstream (7.1-rc1)
Regression Testing Results:
All tests completed successfully with no issues observed:
- Hackbench
- Kernel selftests
- LTP scheduler tests
The workqueue lockup that was previously occurring is no longer present
with the patches applied.
References:
[1]:
https://lore.kernel.org/rcu/ed1fa6cd-7343-4ca3-8b9d-d699ca496f83@paulmck-laptop/
[2]: https://lore.kernel.org/rcu/adlHKowvhn8AGXCc@slm.duckdns.org/
Best regards,
Samir
^ permalink raw reply
* fortify_test_known_sizes: EXPECTATION FAILED at lib/tests/fortify_kunit.c:90 (v7.0.2, ppc)
From: Erhard Furtner @ 2026-04-29 10:17 UTC (permalink / raw)
To: linux-hardening; +Cc: linuxppc-dev
Greetings!
Getting this on my G4 DP on kernel v7.0.2 and v7.1-rc1 at running
fortify_kunit test:
[...]
KTAP version 1
1..1
KTAP version 1
# Subtest: fortify
# module: fortify_kunit
1..26
# fortify_test_known_sizes: EXPECTATION FAILED at
lib/tests/fortify_kunit.c:90
Expected ({ char *__p = (char *)(stack); size_t __ret =
(~(size_t)0); const size_t __p_size =
__builtin_dynamic_object_size(stack, 1); if (__p_size != (~(size_t)0) &&
__builtin_constant_p(*__p)) { size_t __p_len = __p_size - 1; if
(__builtin_constant_p(__p[__p_len]) && __p[__p_len] == '\0') __ret =
__builtin_strlen(__p); } __ret; }) == 5, but
({ char *__p = (char *)(stack); size_t __ret = (~(size_t)0);
const size_t __p_size = __builtin_dynamic_object_size(stack, 1); if
(__p_size != (~(size_t)0) && __builtin_constant_p(*__p)) { size_t
__p_len = __p_size - 1; if (__builtin_constant_p(__p[__p_len]) &&
__p[__p_len] == '\0') __ret = __builtin_strlen(__p); } __ret; }) ==
4294967295 (0xffffffff)
not ok 1 fortify_test_known_sizes
ok 2 fortify_test_control_flow_split
ok 3 fortify_test_alloc_size_kmalloc_const
ok 4 fortify_test_alloc_size_kmalloc_dynamic
ok 5 fortify_test_alloc_size_vmalloc_const
ok 6 fortify_test_alloc_size_vmalloc_dynamic
ok 7 fortify_test_alloc_size_kvmalloc_const
ok 8 fortify_test_alloc_size_kvmalloc_dynamic
ok 9 fortify_test_alloc_size_devm_kmalloc_const
ok 10 fortify_test_alloc_size_devm_kmalloc_dynamic
ok 11 fortify_test_realloc_size
ok 12 fortify_test_strlen
ok 13 fortify_test_strnlen
ok 14 fortify_test_strcpy
ok 15 fortify_test_strncpy
ok 16 fortify_test_strscpy
ok 17 fortify_test_strcat
ok 18 fortify_test_strncat
ok 19 fortify_test_strlcat
ok 20 fortify_test_memcpy
ok 21 fortify_test_memmove
ok 22 fortify_test_memscan
ok 23 fortify_test_memchr
ok 24 fortify_test_memchr_inv
ok 25 fortify_test_memcmp
ok 26 fortify_test_kmemdup
# fortify: pass:25 fail:1 skip:0 total:26
# Totals: pass:25 fail:1 skip:0 total:26
Suppose this may be a ppc/BE specific test failure as I don't get it on
my Thinkpad T60 (x86).
Full dmesg and kernel .config available on request.
Greetings,
Erhard
^ permalink raw reply
* Re: [RFC PATCH v1 7/9] x86: Add unsafe_copy_from_user()
From: Usama Arif @ 2026-04-29 10:25 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: Usama Arif, Yury Norov, Andrew Morton, Linus Torvalds,
David Laight, Thomas Gleixner, linux-alpha, linux-kernel,
linux-snps-arc, linux-arm-kernel, linux-mips, linuxppc-dev, kvm,
linux-riscv, linux-s390, sparclinux, linux-um, dmaengine,
linux-efi, linux-fsi, amd-gfx, dri-devel, intel-gfx, linux-wpan,
netdev, linux-wireless, linux-spi, linux-media, linux-staging,
linux-serial, linux-usb, xen-devel, linux-fsdevel, ocfs2-devel,
bpf, kasan-dev, linux-mm, linux-x25, rust-for-linux, linux-sound,
sound-open-firmware, linux-csky, linux-hexagon, loongarch,
linux-m68k, linux-openrisc, linux-parisc, linux-sh, linux-arch
In-Reply-To: <0ee46bb228d97163fbdc14f2a7c52b93d8bc34ce.1777306795.git.chleroy@kernel.org>
On Mon, 27 Apr 2026 19:13:48 +0200 "Christophe Leroy (CS GROUP)" <chleroy@kernel.org> wrote:
> At the time being, x86 and arm64 are missing unsafe_copy_from_user().
>
> Add it.
>
> Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> ---
> arch/x86/include/asm/uaccess.h | 29 ++++++++++++++++++++++++-----
> 1 file changed, 24 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
> index 3a0dd3c2b233..10c458ffa399 100644
> --- a/arch/x86/include/asm/uaccess.h
> +++ b/arch/x86/include/asm/uaccess.h
> @@ -598,7 +598,7 @@ _label: \
> * We want the unsafe accessors to always be inlined and use
> * the error labels - thus the macro games.
> */
> -#define unsafe_copy_loop(dst, src, len, type, label) \
> +#define unsafe_put_loop(dst, src, len, type, label) \
> while (len >= sizeof(type)) { \
> unsafe_put_user(*(type *)(src),(type __user *)(dst),label); \
> dst += sizeof(type); \
> @@ -611,10 +611,29 @@ do { \
> char __user *__ucu_dst = (_dst); \
> const char *__ucu_src = (_src); \
> size_t __ucu_len = (_len); \
> - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u64, label); \
> - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u32, label); \
> - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u16, label); \
> - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \
> + unsafe_put_loop(__ucu_dst, __ucu_src, __ucu_len, u64, label); \
> + unsafe_put_loop(__ucu_dst, __ucu_src, __ucu_len, u32, label); \
> + unsafe_put_loop(__ucu_dst, __ucu_src, __ucu_len, u16, label); \
> + unsafe_put_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \
> +} while (0)
> +
> +#define unsafe_get_loop(dst, src, len, type, label) \
> + while (len >= sizeof(type)) { \
> + unsafe_get_user(*(type __user *)(src),(type *)(dst),label); \
Hi,
Just wanted to check if src and dst need to be swapped? Same for arm64 patch.
> + dst += sizeof(type); \
> + src += sizeof(type); \
> + len -= sizeof(type); \
> + }
> +
> +#define unsafe_copy_from_user(_dst,_src,_len,label) \
> +do { \
> + char *__ucu_dst = (_dst); \
> + const char __user *__ucu_src = (_src); \
> + size_t __ucu_len = (_len); \
> + unsafe_get_loop(__ucu_dst, __ucu_src, __ucu_len, u64, label); \
> + unsafe_get_loop(__ucu_dst, __ucu_src, __ucu_len, u32, label); \
> + unsafe_get_loop(__ucu_dst, __ucu_src, __ucu_len, u16, label); \
> + unsafe_get_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \
> } while (0)
>
> #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
> --
> 2.49.0
>
>
^ permalink raw reply
* Re: [RFC PATCH v1 8/9] arm64: Add unsafe_copy_from_user()
From: Will Deacon @ 2026-04-29 11:26 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: Yury Norov, Andrew Morton, Linus Torvalds, David Laight,
Thomas Gleixner, linux-alpha, linux-kernel, linux-snps-arc,
linux-arm-kernel, linux-mips, linuxppc-dev, kvm, linux-riscv,
linux-s390, sparclinux, linux-um, dmaengine, linux-efi, linux-fsi,
amd-gfx, dri-devel, intel-gfx, linux-wpan, netdev, linux-wireless,
linux-spi, linux-media, linux-staging, linux-serial, linux-usb,
xen-devel, linux-fsdevel, ocfs2-devel, bpf, kasan-dev, linux-mm,
linux-x25, rust-for-linux, linux-sound, sound-open-firmware,
linux-csky, linux-hexagon, loongarch, linux-m68k, linux-openrisc,
linux-parisc, linux-sh, linux-arch, catalin.marinas
In-Reply-To: <5b09e58a84c9edcfe5724db5cd57e45d96a96bfa.1777306795.git.chleroy@kernel.org>
[+Catalin]
On Mon, Apr 27, 2026 at 07:13:49PM +0200, Christophe Leroy (CS GROUP) wrote:
> At the time being, x86 and arm64 are missing unsafe_copy_from_user().
>
> Add it.
>
> Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> ---
> arch/arm64/include/asm/uaccess.h | 29 ++++++++++++++++++++++++-----
> 1 file changed, 24 insertions(+), 5 deletions(-)
Why?
And please cc the arm64 maintainers on arm64 patches next time. You've
managed to cc most of the world apart from us.
Will
^ permalink raw reply
* iov_kunit_copy_to_kvec: ASSERTION FAILED at lib/tests/kunit_iov_iter.c:63, Expected got == npages, but, got == 1 (0x1), npages == 256 (0x100) (v7.0.2, ppc)
From: Erhard Furtner @ 2026-04-29 11:45 UTC (permalink / raw)
To: linux-hardening; +Cc: linuxppc-dev
Greetings!
Getting this on my G4 DP on kernel v7.0.2 and v7.1-rc1 via 'modprobe -v
kunit_iov_iter':
[...]
KTAP version 1
1..1
KTAP version 1
# Subtest: iov_iter
# module: kunit_iov_iter
1..12
# iov_kunit_copy_to_kvec: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 1 iov_kunit_copy_to_kvec
# iov_kunit_copy_from_kvec: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 2 iov_kunit_copy_from_kvec
# iov_kunit_copy_to_bvec: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 3 iov_kunit_copy_to_bvec
# iov_kunit_copy_from_bvec: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 4 iov_kunit_copy_from_bvec
# iov_kunit_copy_to_folioq: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 5 iov_kunit_copy_to_folioq
# iov_kunit_copy_from_folioq: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 6 iov_kunit_copy_from_folioq
# iov_kunit_copy_to_xarray: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 7 iov_kunit_copy_to_xarray
# iov_kunit_copy_from_xarray: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 8 iov_kunit_copy_from_xarray
# iov_kunit_extract_pages_kvec: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 9 iov_kunit_extract_pages_kvec
# iov_kunit_extract_pages_bvec: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 10 iov_kunit_extract_pages_bvec
# iov_kunit_extract_pages_folioq: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 11 iov_kunit_extract_pages_folioq
# iov_kunit_extract_pages_xarray: ASSERTION FAILED at
lib/tests/kunit_iov_iter.c:63
Expected got == npages, but
got == 1 (0x1)
npages == 256 (0x100)
not ok 12 iov_kunit_extract_pages_xarray
# iov_iter: pass:0 fail:12 skip:0 total:12
# Totals: pass:0 fail:12 skip:0 total:12
not ok 1 iov_iter
Suppose this may be a ppc/BE specific test failure as I don't get it on
my Thinkpad T60 (x86).
Full dmesg and kernel .config available on request.
Greetings,
Erhard
^ permalink raw reply
* [PATCH 2/2] net: wan: fsl_ucc_hdlc: fix ucc_hdlc_remove
From: Holger Brunck @ 2026-04-29 11:42 UTC (permalink / raw)
To: netdev, linuxppc-dev; +Cc: andrew+netdev, chleroy, qiang.zhao, Holger Brunck
In-Reply-To: <20260429114208.941011-1-holger.brunck@hitachienergy.com>
If the driver is used in a non tdm mode priv->utdm is a NULL pointer.
Therefore we need to check this pointer first before checking si_regs.
Signed-off-by: Holger Brunck <holger.brunck@hitachienergy.com>
---
drivers/net/wan/fsl_ucc_hdlc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
index 8155e92af14e..15bfb78381d4 100644
--- a/drivers/net/wan/fsl_ucc_hdlc.c
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -1250,12 +1250,12 @@ static void ucc_hdlc_remove(struct platform_device *pdev)
uhdlc_memclean(priv);
- if (priv->utdm->si_regs) {
+ if (priv->utdm && priv->utdm->si_regs) {
iounmap(priv->utdm->si_regs);
priv->utdm->si_regs = NULL;
}
- if (priv->utdm->siram) {
+ if (priv->utdm && priv->utdm->siram) {
iounmap(priv->utdm->siram);
priv->utdm->siram = NULL;
}
--
2.52.0.120.gb31ab939fe
^ permalink raw reply related
* [PATCH 1/2] net: wan: fsl_ucc_hdlc: fix uhdlc_memclean
From: Holger Brunck @ 2026-04-29 11:42 UTC (permalink / raw)
To: netdev, linuxppc-dev; +Cc: andrew+netdev, chleroy, qiang.zhao, Holger Brunck
Unmapping of uf_regs is done from ucc_fast_free and doesn't need to be
done explicitly. If already unmapped ucc_fast_free will crash.
Signed-off-by: Holger Brunck <holger.brunck@hitachienergy.com>
---
drivers/net/wan/fsl_ucc_hdlc.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
index 3bd57527b1be..8155e92af14e 100644
--- a/drivers/net/wan/fsl_ucc_hdlc.c
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -773,11 +773,6 @@ static void uhdlc_memclean(struct ucc_hdlc_private *priv)
kfree(priv->tx_skbuff);
priv->tx_skbuff = NULL;
- if (priv->uf_regs) {
- iounmap(priv->uf_regs);
- priv->uf_regs = NULL;
- }
-
if (priv->uccf) {
ucc_fast_free(priv->uccf);
priv->uccf = NULL;
--
2.52.0.120.gb31ab939fe
^ permalink raw reply related
* [PATCH 00/11] PCI: pci_resource_alignment() improvement + cleanups
From: Ilpo Järvinen @ 2026-04-29 12:26 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Shawn Jin, linuxppc-dev,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin
Cc: linux-kernel, Ilpo Järvinen
pci_resource_alignment() returns 0 when resource is already assigned
and in case of disabled bridge windows. This has caused problems to
calculations relying on pci_resource_alignment():
https://lore.kernel.org/linux-pci/LV8P221MB1472A24B9975F7C8E8D6BF929947A@LV8P221MB1472.NAMP221.PROD.OUTLOOK.COM/
This series reworks pci_resource_alignment() interface to return always
non-zero alignment if the resource exists. For assigned bridge windows,
the calculation is using heuristic based on size and start address
alignment as calculating the alignment again is costly (would require
sizing the entire sub-hierarchy).
As pci_resource_alignment() is becoming more complicated, it's also
moved to setup-res.c. While moving pci_resource_alignment()'s arguments
are converted into const to tell compiler it can rely on resource
remaining the same across the call.
This was intended to be part of a larger series that addresses some
shortcomings in pci=realloc. The pci=realloc changes will recalculate
bridge window sizes considering also assigned resources which required
making these changes to pci_resource_alignment().
As this also relates to the issue linked above, I'm sending it already
now without pci=realloc changes that are still incomplete. The first
patches originate from the large pci=realloc work but seem generally
useful even if independent of the alignment improvements so I've
included them here without reorganizing the series to contain only
alignment related changes.
Ilpo Järvinen (11):
PCI: Log all resource claims
PCI: Rename added to add_list
PCI: Consolidate add_list (aka realloc_head) empty sanity checks
PCI: Remove const removal cast
resource: Make resource_alignment() input const resource
powerpc/pseries: Make pseries_get_iov_fw_value() & pnv_iov_get()
pci_dev const
PCI: Make pci_sriov_resource_alignment() pci_dev const
PCI: Convert pci_resource_alignment() input parameters to const
PCI: Move pci_resource_alignment() to setup-res.c file
PCI: Lower bound bridge windown alignment
PCI: Return valid alignment for assigned resources
arch/powerpc/include/asm/machdep.h | 2 +-
arch/powerpc/kernel/pci-common.c | 2 +-
arch/powerpc/platforms/powernv/pci-sriov.c | 4 +-
arch/powerpc/platforms/powernv/pci.h | 5 ++-
arch/powerpc/platforms/pseries/setup.c | 5 ++-
drivers/pci/iov.c | 7 +--
drivers/pci/pci.h | 24 ++++-------
drivers/pci/setup-bus.c | 50 ++++++++++++----------
drivers/pci/setup-cardbus.c | 2 +-
drivers/pci/setup-res.c | 37 ++++++++++++++++
include/linux/ioport.h | 2 +-
include/linux/pci.h | 8 ++--
kernel/resource.c | 2 +-
13 files changed, 94 insertions(+), 56 deletions(-)
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
--
2.39.5
^ permalink raw reply
* [PATCH 01/11] PCI: Log all resource claims
From: Ilpo Järvinen @ 2026-04-29 12:26 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Shawn Jin, linuxppc-dev,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
linux-kernel
Cc: Ilpo Järvinen
In-Reply-To: <20260429122617.7324-1-ilpo.jarvinen@linux.intel.com>
There are two ways to graft resource into resource tree in PCI,
pci_assign_resource() and pci_claim_resource(). Only the former logs
the action which complicated troubleshooting the cases where resources
are assigned by pci_claim_resource() which mostly assigns the addresses
inherited from the FW.
Add logging into pci_claim_resource() to make troubleshooting easier.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/pci/setup-res.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index fbc05cda96ee..0d203325562b 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -167,6 +167,8 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
return -EBUSY;
}
+ pci_dbg(dev, "%s %pR: claiming\n", res_name, res);
+
return 0;
}
EXPORT_SYMBOL(pci_claim_resource);
--
2.39.5
^ permalink raw reply related
* [PATCH 02/11] PCI: Rename added to add_list
From: Ilpo Järvinen @ 2026-04-29 12:26 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Shawn Jin, linuxppc-dev,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
linux-kernel
Cc: Ilpo Järvinen
In-Reply-To: <20260429122617.7324-1-ilpo.jarvinen@linux.intel.com>
The resource fitting algorithm uses different names from the list
holding the optional sizes: added, add_head, add_list, and
realloc_head. 'add_list' sounds the most natural and some of the
related variables also use 'add' such as 'add_size'.
To reduce variation, rename 'added' and 'add_head' to 'add_list'.
Also rename some 'realloc_head' cases selectively to 'add_list'.
While it would be nice to rename every 'realloc_head' to 'add_list' for
consistency, it might create a backport headache with all to work going
into this algorithm that may need to be eventually backported. Thus,
it's better to leave 'realloc_head' as is for now.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/pci/pci.h | 2 +-
drivers/pci/setup-bus.c | 26 +++++++++++++-------------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4a14f88e543a..4fcf5a25ad9e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -515,7 +515,7 @@ int pci_dev_res_add_to_list(struct list_head *head, struct pci_dev *dev,
void __pci_bus_size_bridges(struct pci_bus *bus,
struct list_head *realloc_head);
void __pci_bus_assign_resources(const struct pci_bus *bus,
- struct list_head *realloc_head,
+ struct list_head *add_list,
struct list_head *fail_head);
bool pci_bus_clip_resource(struct pci_dev *dev, int idx);
void pci_walk_bus_locked(struct pci_bus *top,
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 4cf120ebe5ad..3765693e95f0 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -756,13 +756,13 @@ static void __assign_resources_sorted(struct list_head *head,
}
static void pdev_assign_resources_sorted(struct pci_dev *dev,
- struct list_head *add_head,
+ struct list_head *add_list,
struct list_head *fail_head)
{
LIST_HEAD(head);
pdev_sort_resources(dev, &head);
- __assign_resources_sorted(&head, add_head, fail_head);
+ __assign_resources_sorted(&head, add_list, fail_head);
}
@@ -1502,13 +1502,13 @@ static void pdev_assign_fixed_resources(struct pci_dev *dev)
}
void __pci_bus_assign_resources(const struct pci_bus *bus,
- struct list_head *realloc_head,
+ struct list_head *add_list,
struct list_head *fail_head)
{
struct pci_bus *b;
struct pci_dev *dev;
- pbus_assign_resources_sorted(bus, realloc_head, fail_head);
+ pbus_assign_resources_sorted(bus, add_list, fail_head);
list_for_each_entry(dev, &bus->devices, bus_list) {
pdev_assign_fixed_resources(dev);
@@ -1517,7 +1517,7 @@ void __pci_bus_assign_resources(const struct pci_bus *bus,
if (!b)
continue;
- __pci_bus_assign_resources(b, realloc_head, fail_head);
+ __pci_bus_assign_resources(b, add_list, fail_head);
switch (dev->hdr_type) {
case PCI_HEADER_TYPE_BRIDGE:
@@ -1613,19 +1613,19 @@ void pci_bus_claim_resources(struct pci_bus *b)
EXPORT_SYMBOL(pci_bus_claim_resources);
static void __pci_bridge_assign_resources(const struct pci_dev *bridge,
- struct list_head *add_head,
+ struct list_head *add_list,
struct list_head *fail_head)
{
struct pci_bus *b;
pdev_assign_resources_sorted((struct pci_dev *)bridge,
- add_head, fail_head);
+ add_list, fail_head);
b = bridge->subordinate;
if (!b)
return;
- __pci_bus_assign_resources(b, add_head, fail_head);
+ __pci_bus_assign_resources(b, add_list, fail_head);
switch (bridge->class >> 8) {
case PCI_CLASS_BRIDGE_PCI:
@@ -2303,7 +2303,7 @@ static int pbus_reassign_bridge_resources(struct pci_bus *bus, struct resource *
unsigned long type = res->flags;
struct pci_dev_resource *dev_res;
struct pci_dev *bridge = NULL;
- LIST_HEAD(added);
+ LIST_HEAD(add_list);
LIST_HEAD(failed);
unsigned int i;
int ret = 0;
@@ -2337,10 +2337,10 @@ static int pbus_reassign_bridge_resources(struct pci_bus *bus, struct resource *
if (!bridge)
return -ENOENT;
- __pci_bus_size_bridges(bridge->subordinate, &added);
- __pci_bridge_assign_resources(bridge, &added, &failed);
- if (WARN_ON_ONCE(!list_empty(&added)))
- pci_dev_res_free_list(&added);
+ __pci_bus_size_bridges(bridge->subordinate, &add_list);
+ __pci_bridge_assign_resources(bridge, &add_list, &failed);
+ if (WARN_ON_ONCE(!list_empty(&add_list)))
+ pci_dev_res_free_list(&add_list);
if (!list_empty(&failed)) {
if (pci_required_resource_failed(&failed, type))
--
2.39.5
^ permalink raw reply related
* [PATCH 03/11] PCI: Consolidate add_list (aka realloc_head) empty sanity checks
From: Ilpo Järvinen @ 2026-04-29 12:26 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Shawn Jin, linuxppc-dev,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
linux-kernel
Cc: Ilpo Järvinen
In-Reply-To: <20260429122617.7324-1-ilpo.jarvinen@linux.intel.com>
Callers of __pci_bridge_assign_resources() and
__pci_bus_assign_resources() perform
WARN_ON_ONCE(list_empty(add_list))) checks to sanity check that all
optional sizes were processed (and removed) from the list. The empty
list sanity check is duplicated code so the more appropriate place for
it would be inside the called function.
Placing the empty list check into __pci_bus_assign_resources() also
ensures all callsites do perform the sanity check which currently is
not the case when being called from enable_slot(). This inconsistency
was noted by Sashiko though only inside its in depth log but not
flagged as a real problem, possibly because this is only a sanity check
that should never fire. Nonetheless, this sanity check has been very
useful to catch problems early in the past so it's good to do it
consistenty everywhere.
As __pci_bus_assign_resources() is recursive function, it needs to be
renamed to __pci_bus_assign_resources_one() to only perform the empty
list check at the end of processing the entire hierarchy in
__pci_bus_assign_resources().
Suggested-by: sashiko.dev # Sanity check missing from enable_slot()
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/pci/setup-bus.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 3765693e95f0..1e0e28efe8b8 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1501,9 +1501,9 @@ static void pdev_assign_fixed_resources(struct pci_dev *dev)
}
}
-void __pci_bus_assign_resources(const struct pci_bus *bus,
- struct list_head *add_list,
- struct list_head *fail_head)
+static void __pci_bus_assign_resources_one(const struct pci_bus *bus,
+ struct list_head *add_list,
+ struct list_head *fail_head)
{
struct pci_bus *b;
struct pci_dev *dev;
@@ -1517,7 +1517,7 @@ void __pci_bus_assign_resources(const struct pci_bus *bus,
if (!b)
continue;
- __pci_bus_assign_resources(b, add_list, fail_head);
+ __pci_bus_assign_resources_one(b, add_list, fail_head);
switch (dev->hdr_type) {
case PCI_HEADER_TYPE_BRIDGE:
@@ -1537,6 +1537,16 @@ void __pci_bus_assign_resources(const struct pci_bus *bus,
}
}
+void __pci_bus_assign_resources(const struct pci_bus *bus,
+ struct list_head *add_list,
+ struct list_head *fail_head)
+{
+ __pci_bus_assign_resources_one(bus, add_list, fail_head);
+
+ if (WARN_ON_ONCE(add_list && !list_empty(add_list)))
+ pci_dev_res_free_list(add_list);
+}
+
void pci_bus_assign_resources(const struct pci_bus *bus)
{
__pci_bus_assign_resources(bus, NULL, NULL);
@@ -1641,6 +1651,9 @@ static void __pci_bridge_assign_resources(const struct pci_dev *bridge,
pci_domain_nr(b), b->number);
break;
}
+
+ if (WARN_ON_ONCE(add_list && !list_empty(add_list)))
+ pci_dev_res_free_list(add_list);
}
static void pci_bridge_release_resources(struct pci_bus *bus,
@@ -2205,8 +2218,6 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
/* Depth last, allocate resources and update the hardware. */
__pci_bus_assign_resources(bus, add_list, &fail_head);
- if (WARN_ON_ONCE(add_list && !list_empty(add_list)))
- pci_dev_res_free_list(add_list);
tried_times++;
/* Any device complain? */
@@ -2268,8 +2279,6 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
pci_bridge_distribute_available_resources(bridge, &add_list);
__pci_bridge_assign_resources(bridge, &add_list, &fail_head);
- if (WARN_ON_ONCE(!list_empty(&add_list)))
- pci_dev_res_free_list(&add_list);
tried_times++;
if (list_empty(&fail_head))
@@ -2339,8 +2348,6 @@ static int pbus_reassign_bridge_resources(struct pci_bus *bus, struct resource *
__pci_bus_size_bridges(bridge->subordinate, &add_list);
__pci_bridge_assign_resources(bridge, &add_list, &failed);
- if (WARN_ON_ONCE(!list_empty(&add_list)))
- pci_dev_res_free_list(&add_list);
if (!list_empty(&failed)) {
if (pci_required_resource_failed(&failed, type))
@@ -2473,7 +2480,5 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
__pci_bus_size_bridges(dev->subordinate, &add_list);
up_read(&pci_bus_sem);
__pci_bus_assign_resources(bus, &add_list, NULL);
- if (WARN_ON_ONCE(!list_empty(&add_list)))
- pci_dev_res_free_list(&add_list);
}
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bus_resources);
--
2.39.5
^ permalink raw reply related
* [PATCH 04/11] PCI: Remove const removal cast
From: Ilpo Järvinen @ 2026-04-29 12:26 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Shawn Jin, linuxppc-dev,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
linux-kernel
Cc: Ilpo Järvinen
In-Reply-To: <20260429122617.7324-1-ilpo.jarvinen@linux.intel.com>
__pci_bridge_assign_resources() inputs const pci_dev *bridge, but then
immediately casts const away to pass the bridge to
pdev_assign_resources_sorted().
As pdev_assign_resources_sorted() performs assignment of resources, it
is not possible to make its input parameter to const. Neither of the
__pci_bridge_assign_resources() callers requires the bridge parameter
to be const.
Thus, simply remove the out of place cast and convert the input
parameter to non-const.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
drivers/pci/setup-bus.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 1e0e28efe8b8..c0a949f2c995 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1622,14 +1622,13 @@ void pci_bus_claim_resources(struct pci_bus *b)
}
EXPORT_SYMBOL(pci_bus_claim_resources);
-static void __pci_bridge_assign_resources(const struct pci_dev *bridge,
+static void __pci_bridge_assign_resources(struct pci_dev *bridge,
struct list_head *add_list,
struct list_head *fail_head)
{
struct pci_bus *b;
- pdev_assign_resources_sorted((struct pci_dev *)bridge,
- add_list, fail_head);
+ pdev_assign_resources_sorted(bridge, add_list, fail_head);
b = bridge->subordinate;
if (!b)
--
2.39.5
^ permalink raw reply related
* [PATCH 05/11] resource: Make resource_alignment() input const resource
From: Ilpo Järvinen @ 2026-04-29 12:26 UTC (permalink / raw)
To: linux-pci, Bjorn Helgaas, Shawn Jin, linuxppc-dev,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
linux-kernel
Cc: Ilpo Järvinen
In-Reply-To: <20260429122617.7324-1-ilpo.jarvinen@linux.intel.com>
resource_alignment() does not need to change resource so it can be
made const.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
include/linux/ioport.h | 2 +-
kernel/resource.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 3c73c9c0d4f7..f7930b3dfd0a 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -261,7 +261,7 @@ extern int allocate_resource(struct resource *root, struct resource *new,
struct resource *lookup_resource(struct resource *root, resource_size_t start);
int adjust_resource(struct resource *res, resource_size_t start,
resource_size_t size);
-resource_size_t resource_alignment(struct resource *res);
+resource_size_t resource_alignment(const struct resource *res);
/**
* resource_set_size - Calculate resource end address from size and start
diff --git a/kernel/resource.c b/kernel/resource.c
index d02a53fb95d8..3d17e3196a3e 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -1238,7 +1238,7 @@ reserve_region_with_split(struct resource *root, resource_size_t start,
*
* Returns alignment on success, 0 (invalid alignment) on failure.
*/
-resource_size_t resource_alignment(struct resource *res)
+resource_size_t resource_alignment(const struct resource *res)
{
switch (res->flags & (IORESOURCE_SIZEALIGN | IORESOURCE_STARTALIGN)) {
case IORESOURCE_SIZEALIGN:
--
2.39.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox