* Re: [PATCH] media: nxp: imx8-isi: fix memory leaks in probe error paths and remove
From: Laurent Pinchart @ 2026-03-30 15:41 UTC (permalink / raw)
To: Frank Li
Cc: David Carlier, mchehab, s.hauer, festevam, jacopo, aisheng.dong,
guoniu.zhou, linux-media, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <acqM06YySijL1VpU@lizhi-Precision-Tower-5810>
On Mon, Mar 30, 2026 at 10:46:43AM -0400, Frank Li wrote:
> On Fri, Mar 27, 2026 at 10:27:11PM +0000, David Carlier wrote:
> > mxc_isi_probe() allocates isi->pipes with kzalloc_objs() but never
> > frees it on any probe failure path or in mxc_isi_remove(), leaking the
> > allocation on every failed probe and every normal unbind.
> >
> > Additionally, when mxc_isi_pipe_init() fails partway through the
> > channel loop or when mxc_isi_v4l2_init() fails, the already initialized
> > pipes are not cleaned up — their media entities and mutexes are leaked.
> >
> > Fix both by adding kfree(isi->pipes) to all probe error paths and to
> > mxc_isi_remove(), and cleaning up already-initialized pipes in the
> > err_xbar error path.
> >
> > Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISP Channel driver")
> > Signed-off-by: David Carlier <devnexen@gmail.com>
> > ---
>
> I think provide a helper function, devm_kzalloc_objs(), or using old
> devm_kzalloc is better fix method.
I quite agree. Kees said he's planning to introduce devm_kzalloc_objs().
I assume this will come in the next kernel version. I think we can wait
for that to fix this leak as it's a really minor issue.
> > .../platform/nxp/imx8-isi/imx8-isi-core.c | 24 +++++++++++++++----
> > 1 file changed, 19 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
> > index 4bf8570e1b9e..ab32c5b6ac9c 100644
> > --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
> > +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
> > @@ -490,33 +490,43 @@ static int mxc_isi_probe(struct platform_device *pdev)
> > return -ENOMEM;
> >
> > isi->num_clks = devm_clk_bulk_get_all(dev, &isi->clks);
> > - if (isi->num_clks < 0)
> > + if (isi->num_clks < 0) {
> > + kfree(isi->pipes);
> > return dev_err_probe(dev, isi->num_clks, "Failed to get clocks\n");
> > + }
> >
> >
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: [PATCH V2 1/5] dmaengine: xilinx_dma: Fix MCDMA descriptor fields for MM2S vs S2MM
From: Frank Li @ 2026-03-30 15:46 UTC (permalink / raw)
To: Srinivas Neeli
Cc: Vinod Koul, git, Frank Li, Michal Simek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Suraj Gupta,
Radhey Shyam Pandey, Thomas Gessler, Folker Schwesinger,
Tomi Valkeinen, Kees Cook, Abin Joseph, dmaengine, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260313062533.421249-2-srinivas.neeli@amd.com>
On Fri, Mar 13, 2026 at 11:55:29AM +0530, Srinivas Neeli wrote:
> The MCDMA BD format differs between MM2S and S2MM directions, but the
Can you use DMA_DEV_TO_MEM and DMA_MEM_TO_DEV instead of MM2S and S2MM?
or memory to slave, at least first place need extend term MM2S(memory to
slave).
> driver was using generic 'status' and 'sideband_status' fields for both.
> This could lead to incorrect residue calculations when the hardware
> updates direction-specific fields.
driver was using generic 'status' and 'sideband_status' fields for both,
which lead ... (use Affirmative Tone)
>
> Refactor the descriptor structure to use unions with direction-specific
> field names (mm2s_status/s2mm_status, etc.). This ensures the driver
Ensure .. (needn't this)
Frank
> accesses the correct hardware fields based on channel direction and
> matches the hardware documentation.
>
> Fixes: 6ccd692bfb7f ("dmaengine: xilinx_dma: Add Xilinx AXI MCDMA Engine driver support")
> Signed-off-by: Srinivas Neeli <srinivas.neeli@amd.com>
> ---
> drivers/dma/xilinx/xilinx_dma.c | 29 ++++++++++++++++++++++-------
> 1 file changed, 22 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index b53292e02448..4a83492f2435 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -275,8 +275,10 @@ struct xilinx_axidma_desc_hw {
> * @buf_addr_msb: MSB of Buffer address @0x0C
> * @rsvd: Reserved field @0x10
> * @control: Control Information field @0x14
> - * @status: Status field @0x18
> - * @sideband_status: Status of sideband signals @0x1C
> + * @mm2s_ctrl_sideband: Sideband control info for mm2s @0x18
> + * @s2mm_status: Status field for s2mm @0x18
> + * @mm2s_status: Status field for mm2s @0x1C
> + * @s2mm_sideband_status: Sideband status for s2mm @0x1C
> * @app: APP Fields @0x20 - 0x30
> */
> struct xilinx_aximcdma_desc_hw {
> @@ -286,8 +288,14 @@ struct xilinx_aximcdma_desc_hw {
> u32 buf_addr_msb;
> u32 rsvd;
> u32 control;
> - u32 status;
> - u32 sideband_status;
> + union {
> + u32 mm2s_ctrl_sideband;
> + u32 s2mm_status;
> + };
> + union {
> + u32 mm2s_status;
> + u32 s2mm_sideband_status;
> + };
> u32 app[XILINX_DMA_NUM_APP_WORDS];
> } __aligned(64);
>
> @@ -1013,9 +1021,16 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
> struct xilinx_aximcdma_tx_segment,
> node);
> aximcdma_hw = &aximcdma_seg->hw;
> - residue +=
> - (aximcdma_hw->control - aximcdma_hw->status) &
> - chan->xdev->max_buffer_len;
> + if (chan->direction == DMA_DEV_TO_MEM)
> + residue +=
> + (aximcdma_hw->control -
> + aximcdma_hw->s2mm_status) &
> + chan->xdev->max_buffer_len;
> + else
> + residue +=
> + (aximcdma_hw->control -
> + aximcdma_hw->mm2s_status) &
> + chan->xdev->max_buffer_len;
> }
> }
>
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH] media: cedrus: skip invalid H.264 reference list entries
From: Nicolas Dufresne @ 2026-03-30 15:54 UTC (permalink / raw)
To: Pengpeng Hou, mripard
Cc: paulk, mchehab, gregkh, wens, jernej.skrabec, samuel, linux-media,
linux-staging, linux-arm-kernel, linux-sunxi, linux-kernel
In-Reply-To: <20260324080856.56787-1-pengpeng@iscas.ac.cn>
[-- Attachment #1: Type: text/plain, Size: 1919 bytes --]
Le mardi 24 mars 2026 à 16:08 +0800, Pengpeng Hou a écrit :
> Cedrus consumes H.264 ref_pic_list0/ref_pic_list1 entries from the
> stateless slice control and later uses their indices to look up
> decode->dpb[] in _cedrus_write_ref_list().
>
> Rejecting such controls in cedrus_try_ctrl() would break existing
> userspace, since stateless H.264 reference lists may legitimately carry
> out-of-range indices for missing references. Instead, guard the actual
> DPB lookup in Cedrus and skip entries whose indices do not fit the fixed
> V4L2_H264_NUM_DPB_ENTRIES array.
>
> This keeps the fix local to the driver use site and avoids out-of-bounds
> reads from malformed or unsupported reference list entries.
>
> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> ---
> drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
> b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
> --- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
> +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
> @@ -210,6 +210,9 @@ static void _cedrus_write_ref_list(struct cedrus_ctx *ctx,
> u8 dpb_idx;
>
> dpb_idx = ref_list[i].index;
> + if (dpb_idx >= V4L2_H264_NUM_DPB_ENTRIES)
> + continue;
Matches how we skip inactive references (in this diff, though most userspace
just don't pass them). Now, if I looked lower, we set a position for each
references. My understanding is that if no bits are set, it means "no position".
How much testing have you done to confirm the HW behaves properly ?
Despite this question, I think this is going to work better then doing memory
overrun:
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Nicolas
> +
> dpb = &decode->dpb[dpb_idx];
>
> if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH V2 2/5] dmaengine: xilinx_dma: Move descriptors to done list based on completion bit
From: Frank Li @ 2026-03-30 15:54 UTC (permalink / raw)
To: Srinivas Neeli
Cc: Vinod Koul, git, Frank Li, Michal Simek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Suraj Gupta,
Radhey Shyam Pandey, Thomas Gessler, Folker Schwesinger,
Tomi Valkeinen, Kees Cook, Abin Joseph, dmaengine, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260313062533.421249-3-srinivas.neeli@amd.com>
On Fri, Mar 13, 2026 at 11:55:30AM +0530, Srinivas Neeli wrote:
> In AXIMCDMA scatter-gather mode, the hardware sets the completion bit when
> a transfer finishes. The driver now checks this bit to free descriptors
> from the active list and move them to the done list.
Add check complete bit because irq may be triggered before a configured
threshold is reached when interrupt delay timeout Dly_IrqEn is enabled.
Frank
> This is required when interrupt delay timeout Dly_IrqEn is enabled,
> as interrupts may be triggered before the configured threshold is reached,
> even if not all descriptors have completed.
>
> Signed-off-by: Srinivas Neeli <srinivas.neeli@amd.com>
> ---
> drivers/dma/xilinx/xilinx_dma.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index 4a83492f2435..00200b4c2372 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -1762,6 +1762,18 @@ static void xilinx_dma_complete_descriptor(struct xilinx_dma_chan *chan)
> struct xilinx_axidma_tx_segment, node);
> if (!(seg->hw.status & XILINX_DMA_BD_COMP_MASK) && chan->has_sg)
> break;
> + } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
> + struct xilinx_aximcdma_tx_segment *seg;
> + bool completed;
> +
> + seg = list_last_entry(&desc->segments,
> + struct xilinx_aximcdma_tx_segment,
> + node);
> + completed = (chan->direction == DMA_DEV_TO_MEM) ?
> + (seg->hw.s2mm_status & XILINX_DMA_BD_COMP_MASK) :
> + (seg->hw.mm2s_status & XILINX_DMA_BD_COMP_MASK);
> + if (!completed)
> + break;
> }
> if (chan->has_sg && chan->xdev->dma_config->dmatype !=
> XDMA_TYPE_VDMA)
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH] media: cedrus: skip invalid H.264 reference list entries
From: Nicolas Dufresne @ 2026-03-30 15:55 UTC (permalink / raw)
To: wens, Jernej Škrabec
Cc: mripard, Pengpeng Hou, paulk, mchehab, gregkh, samuel,
linux-media, linux-staging, linux-arm-kernel, linux-sunxi,
linux-kernel
In-Reply-To: <CAGb2v674Ei2uFh6O0LoFoJrPcqGKGr_v+hfvE7TSfwztxDfTAA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1415 bytes --]
Le dimanche 29 mars 2026 à 20:44 +0800, Chen-Yu Tsai a écrit :
> On Sun, Mar 29, 2026 at 5:21 PM Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
> >
> > Dne torek, 24. marec 2026 ob 09:08:56 Srednjeevropski poletni čas je Pengpeng Hou napisal(a):
> > > Cedrus consumes H.264 ref_pic_list0/ref_pic_list1 entries from the
> > > stateless slice control and later uses their indices to look up
> > > decode->dpb[] in _cedrus_write_ref_list().
> > >
> > > Rejecting such controls in cedrus_try_ctrl() would break existing
> > > userspace, since stateless H.264 reference lists may legitimately carry
> > > out-of-range indices for missing references. Instead, guard the actual
> > > DPB lookup in Cedrus and skip entries whose indices do not fit the fixed
> > > V4L2_H264_NUM_DPB_ENTRIES array.
> > >
> > > This keeps the fix local to the driver use site and avoids out-of-bounds
> > > reads from malformed or unsupported reference list entries.
> > >
> > > Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> >
> > Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
>
> Tested-by: Chen-Yu Tsai <wens@kernel.org>
>
> This fixes a KASAN slab-use-after-free warning when running fluster H.264
> tests.
Ah, very good, can you cite which test caused that ? I didn't expect fluster to
cover cases with missing references. I think it will be handy for future
testing.
Nicolas
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH V2 3/5] dmaengine: xilinx_dma: Extend metadata handling for AXI MCDMA
From: Frank Li @ 2026-03-30 15:58 UTC (permalink / raw)
To: Srinivas Neeli
Cc: Vinod Koul, git, Frank Li, Michal Simek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Suraj Gupta,
Radhey Shyam Pandey, Thomas Gessler, Folker Schwesinger,
Tomi Valkeinen, Kees Cook, Abin Joseph, dmaengine, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260313062533.421249-4-srinivas.neeli@amd.com>
On Fri, Mar 13, 2026 at 11:55:31AM +0530, Srinivas Neeli wrote:
> From: Suraj Gupta <suraj.gupta2@amd.com>
>
> Extend probe logic to detect AXI Stream connections for MCDMA. When
> an AXI Stream interface is present, metadata operations are enabled for
> the MCDMA channel. The xilinx_dma_get_metadata_ptr() is enhanced to
> retrieve metadata directly from MCDMA descriptors.
Need extra empty line between paragraph
> Add corresponding channel reference in struct xilinx_dma_tx_descriptor to
> retrieve associated channel.
> These changes ensure proper metadata handling and accurate transfer
> size reporting for MCDMA transfers.
>
> Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
> Co-developed-by: Srinivas Neeli <srinivas.neeli@amd.com>
> Signed-off-by: Srinivas Neeli <srinivas.neeli@amd.com>
> ---
> drivers/dma/xilinx/xilinx_dma.c | 30 +++++++++++++++++++++++++-----
> 1 file changed, 25 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index 00200b4c2372..52203d44e7a4 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -222,6 +222,8 @@
> #define XILINX_MCDMA_BD_EOP BIT(30)
> #define XILINX_MCDMA_BD_SOP BIT(31)
>
> +struct xilinx_dma_chan;
> +
> /**
> * struct xilinx_vdma_desc_hw - Hardware Descriptor
> * @next_desc: Next Descriptor Pointer @0x00
> @@ -371,6 +373,7 @@ struct xilinx_cdma_tx_segment {
>
> /**
> * struct xilinx_dma_tx_descriptor - Per Transaction structure
> + * @chan: DMA channel for which this descriptor is allocated
> * @async_tx: Async transaction descriptor
> * @segments: TX segments list
> * @node: Node in the channel descriptors list
> @@ -379,6 +382,7 @@ struct xilinx_cdma_tx_segment {
> * @residue: Residue of the completed descriptor
> */
> struct xilinx_dma_tx_descriptor {
> + struct xilinx_dma_chan *chan;
async_tx already include dma_chan's information.
Frank
^ permalink raw reply
* Re: [PATCH 0/2] arm64: dts: qcom: enable UARTs for robot expansion board
From: Bjorn Andersson @ 2026-03-30 16:01 UTC (permalink / raw)
To: konradybcio, Canfeng Zhuang
Cc: robh, krzk+dt, conor+dt, linux-arm-msm, devicetree,
linux-arm-kernel
In-Reply-To: <20260327083101.1343613-1-canfeng.zhuang@oss.qualcomm.com>
On Fri, 27 Mar 2026 16:30:59 +0800, Canfeng Zhuang wrote:
> The Qualcomm Lemans EVK and Monaco EVK boards expose a mezzanine
> connector used by a motor control expansion board.
>
> This expansion board hosts an MCU running NuttX and communicates with
> Linux over UART, with all protocol handling done in userspace.
>
> This series enables the required UARTs and assigns stable serial aliases
> to ensure consistent device enumeration across platforms.
>
> [...]
Applied, thanks!
[1/2] arm64: dts: qcom: lemans-evk: enable UART0 for robot expansion board
commit: 0be638f326c2015ae9406f4238d9bc54b5b7a584
[2/2] arm64: dts: qcom: monaco-evk: enable UART6 for robot expansion board
commit: 74620bf0c3c6091ecd7972075f5ddeba29994407
Best regards,
--
Bjorn Andersson <andersson@kernel.org>
^ permalink raw reply
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
From: Paul Kocialkowski @ 2026-03-30 16:09 UTC (permalink / raw)
To: Krzysztof Hałasa
Cc: Liu Ying, Maxime Ripard, Marco Felsch, Marek Vasut, Stefan Agner,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel,
Lucas Stach
In-Reply-To: <m3se9onkv0.fsf@t19.piap.pl>
[-- Attachment #1: Type: text/plain, Size: 3498 bytes --]
Hi folks,
On Wed 25 Mar 26, 13:40, Krzysztof Hałasa wrote:
> Why did the first (boot) sequence result in success and this second one
> in failure? This is somehow reproducible.
I've been seeing the same issue that is described in this thread when driving
a regular 1080p@60 monitor, which shows a solid color background with a pixel
from the previous frame when reconfiguring the mode from time to time.
When that happens, I see the lcdif fifo underrun/empty status until a new mode
is applied, which often resolves the situation. This situation never happens
with the downstream nxp bsp driver.
After weeks of investigation I finally narrowed it down to a part of the nxp
original code that is missing in the upstream driver:
https://github.com/phytec/linux-phytec-imx/blob/v6.6.23-2.0.0-phy/drivers/gpu/imx/lcdifv3/lcdifv3-common.c#L492
A big old sleep that waits for the DMA engine to finish handling the current
frame before it is disabled. When this delay is not respected, there seems to
be "unlucky" times when disabling the DMA engine too early will confuse the
unit and make it unable to resume proper operation later.
It is a bit surprising that the issue is not actually related to configuring
the display engine but to disabling it. This is why the first mode set always
works but subsequentil ones might fail. The crtc is essentially disabled and
re-enabled each time a new mode is applied.
Adding the sleep solves the issue on my side and all mode sets now work
reliably. It does add a delay before returning to userspace when configuring
a new mode, but it seems legitimate to me if the underlying hardware is still
in-flight. I'm also unsure if it would apply to an async atomic commit.
I will send a patch adding the delay and the undocumented fifo clear
bit that was discovered in this thread too.
All the best,
Paul
Perhaps there is a more elegant way to handle this
> Interestingly, Weston usually starts fine in subsequent launches.
>
> How is this first (actually second - after the first VSYNC) frame
> different from all the others? Maybe we're programming UPDATE_SHADOW
> after the actual start of blanking period, but before DE, so it has no
> chance to reload registers, yet the DMA is somehow not ready?
>
> The manual (LCDIF display control Register (CTRL)) suggests that the DMA
> (with present settings) starts to fetch FB data at the end of the
> previous active video pixel time (DE and pixel data going inactive):
> fetch_start_option (bits 9-8): Indicates when to start fetching for new
> frame. This signals also decide the shadow load, fifo clear time
> 00b - fetch start as soon as FPV begins(as the end of the data_enable).
>
> This should leave a lot of time to fill the FIFO (before the next DE),
> shouldn't it?
>
> 297 MHz pixclk, 3840x2160, 30 Hz, H back porch 296 pixclks, Vfp 176,
> V back porch 72 lines, Hfp 8 lines, VSYNC 10 lines, HSYNC 88 pixclks.
> HTotal = 4400 pixels which makes Vactive time = 4400 * 2160/297e6 =
> 32 ms, with the remaining 1.3333 ms for all the V sync stuff.
> --
> Krzysztof "Chris" Hałasa
>
> Sieć Badawcza Łukasiewicz
> Przemysłowy Instytut Automatyki i Pomiarów PIAP
> Al. Jerozolimskie 202, 02-486 Warszawa
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH v2 0/3] Fix bugs for realm guest plus BBML2_NOABORT
From: Ryan Roberts @ 2026-03-30 16:17 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, David Hildenbrand (Arm), Dev Jain,
Yang Shi, Suzuki K Poulose, Jinjiang Tu, Kevin Brodsky
Cc: Ryan Roberts, linux-arm-kernel, linux-kernel
Hi All,
This fixes a couple of bugs in the "large block mappings for linear map when we
have BBML2_NOABORT" feature when used in conjunction with a CCA realm guest.
While investigating I found and fixed some more general issues too. See commit
logs for full explanations.
Applies on top of v7.0-rc4.
Changes since v1 [1]
====================
Patch 1:
- Moved page_alloc_available declaration to asm/mmu.c (per Kevin)
- Added PTE_PRESENT_VALID_KERNEL macro to hide VALID|NG confusion (per Kevin)
- Improved logic in split_kernel_leaf_mapping() to avoid warning for
DEBUG_PAGEALLOC (per Sashiko)
Patch 2:
- Fixed transitional pgtables to handle present-invalid large leaves (per
Sashiko)
- Hardened split_pXd() for present-invalid leaves (per Sashiko)
Patch 3:
- Converted pXd_leaf() to function to avoid multi-eval of READ_ONCE() (per
Sashiko)
[1] https://lore.kernel.org/all/20260323130317.1737522-1-ryan.roberts@arm.com/
Thanks,
Ryan
Ryan Roberts (3):
arm64: mm: Fix rodata=full block mapping support for realm guests
arm64: mm: Handle invalid large leaf mappings correctly
arm64: mm: Remove pmd_sect() and pud_sect()
arch/arm64/include/asm/mmu.h | 2 +
arch/arm64/include/asm/pgtable-prot.h | 2 +
arch/arm64/include/asm/pgtable.h | 28 +++++++----
arch/arm64/mm/init.c | 9 +++-
arch/arm64/mm/mmu.c | 67 ++++++++++++++++++---------
arch/arm64/mm/pageattr.c | 50 +++++++++++---------
arch/arm64/mm/trans_pgd.c | 42 +++--------------
7 files changed, 111 insertions(+), 89 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH v2 1/3] arm64: mm: Fix rodata=full block mapping support for realm guests
From: Ryan Roberts @ 2026-03-30 16:17 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, David Hildenbrand (Arm), Dev Jain,
Yang Shi, Suzuki K Poulose, Jinjiang Tu, Kevin Brodsky
Cc: Ryan Roberts, linux-arm-kernel, linux-kernel, stable
In-Reply-To: <20260330161705.3349825-1-ryan.roberts@arm.com>
Commit a166563e7ec37 ("arm64: mm: support large block mapping when
rodata=full") enabled the linear map to be mapped by block/cont while
still allowing granular permission changes on BBML2_NOABORT systems by
lazily splitting the live mappings. This mechanism was intended to be
usable by realm guests since they need to dynamically share dma buffers
with the host by "decrypting" them - which for Arm CCA, means marking
them as shared in the page tables.
However, it turns out that the mechanism was failing for realm guests
because realms need to share their dma buffers (via
__set_memory_enc_dec()) much earlier during boot than
split_kernel_leaf_mapping() was able to handle. The report linked below
showed that GIC's ITS was one such user. But during the investigation I
found other callsites that could not meet the
split_kernel_leaf_mapping() constraints.
The problem is that we block map the linear map based on the boot CPU
supporting BBML2_NOABORT, then check that all the other CPUs support it
too when finalizing the caps. If they don't, then we stop_machine() and
split to ptes. For safety, split_kernel_leaf_mapping() previously
wouldn't permit splitting until after the caps were finalized. That
ensured that if any secondary cpus were running that didn't support
BBML2_NOABORT, we wouldn't risk breaking them.
I've fix this problem by reducing the black-out window where we refuse
to split; there are now 2 windows. The first is from T0 until the page
allocator is inititialized. Splitting allocates memory for the page
allocator so it must be in use. The second covers the period between
starting to online the secondary cpus until the system caps are
finalized (this is a very small window).
All of the problematic callers are calling __set_memory_enc_dec() before
the secondary cpus come online, so this solves the problem. However, one
of these callers, swiotlb_update_mem_attributes(), was trying to split
before the page allocator was initialized. So I have moved this call
from arch_mm_preinit() to mem_init(), which solves the ordering issue.
I've added warnings and return an error if any attempt is made to split
in the black-out windows.
Note there are other issues which prevent booting all the way to user
space, which will be fixed in subsequent patches.
Reported-by: Jinjiang Tu <tujinjiang@huawei.com>
Closes: https://lore.kernel.org/all/0b2a4ae5-fc51-4d77-b177-b2e9db74f11d@huawei.com/
Fixes: a166563e7ec37 ("arm64: mm: support large block mapping when rodata=full")
Cc: stable@vger.kernel.org
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
---
arch/arm64/include/asm/mmu.h | 2 ++
arch/arm64/mm/init.c | 9 +++++++-
arch/arm64/mm/mmu.c | 45 +++++++++++++++++++++++++-----------
3 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 137a173df1ff8..472610433aaea 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -112,5 +112,7 @@ void kpti_install_ng_mappings(void);
static inline void kpti_install_ng_mappings(void) {}
#endif
+extern bool page_alloc_available;
+
#endif /* !__ASSEMBLER__ */
#endif
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 96711b8578fd0..b9b248d24fd10 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -350,7 +350,6 @@ void __init arch_mm_preinit(void)
}
swiotlb_init(swiotlb, flags);
- swiotlb_update_mem_attributes();
/*
* Check boundaries twice: Some fundamental inconsistencies can be
@@ -377,6 +376,14 @@ void __init arch_mm_preinit(void)
}
}
+bool page_alloc_available __ro_after_init;
+
+void __init mem_init(void)
+{
+ page_alloc_available = true;
+ swiotlb_update_mem_attributes();
+}
+
void free_initmem(void)
{
void *lm_init_begin = lm_alias(__init_begin);
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index a6a00accf4f93..223947487a223 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -768,30 +768,51 @@ static inline bool force_pte_mapping(void)
}
static DEFINE_MUTEX(pgtable_split_lock);
+static bool linear_map_requires_bbml2;
int split_kernel_leaf_mapping(unsigned long start, unsigned long end)
{
int ret;
- /*
- * !BBML2_NOABORT systems should not be trying to change permissions on
- * anything that is not pte-mapped in the first place. Just return early
- * and let the permission change code raise a warning if not already
- * pte-mapped.
- */
- if (!system_supports_bbml2_noabort())
- return 0;
-
/*
* If the region is within a pte-mapped area, there is no need to try to
* split. Additionally, CONFIG_DEBUG_PAGEALLOC and CONFIG_KFENCE may
* change permissions from atomic context so for those cases (which are
* always pte-mapped), we must not go any further because taking the
- * mutex below may sleep.
+ * mutex below may sleep. Do not call force_pte_mapping() here because
+ * it could return a confusing result if called from a secondary cpu
+ * prior to finalizing caps. Instead, linear_map_requires_bbml2 gives us
+ * what we need.
*/
- if (force_pte_mapping() || is_kfence_address((void *)start))
+ if (!linear_map_requires_bbml2 || is_kfence_address((void *)start))
return 0;
+ if (!system_supports_bbml2_noabort()) {
+ /*
+ * !BBML2_NOABORT systems should not be trying to change
+ * permissions on anything that is not pte-mapped in the first
+ * place. Just return early and let the permission change code
+ * raise a warning if not already pte-mapped.
+ */
+ if (system_capabilities_finalized())
+ return 0;
+
+ /*
+ * Boot-time: split_kernel_leaf_mapping_locked() allocates from
+ * page allocator. Can't split until it's available.
+ */
+ if (WARN_ON(!page_alloc_available))
+ return -EBUSY;
+
+ /*
+ * Boot-time: Started secondary cpus but don't know if they
+ * support BBML2_NOABORT yet. Can't allow splitting in this
+ * window in case they don't.
+ */
+ if (WARN_ON(num_online_cpus() > 1))
+ return -EBUSY;
+ }
+
/*
* Ensure start and end are at least page-aligned since this is the
* finest granularity we can split to.
@@ -891,8 +912,6 @@ static int range_split_to_ptes(unsigned long start, unsigned long end, gfp_t gfp
return ret;
}
-static bool linear_map_requires_bbml2 __initdata;
-
u32 idmap_kpti_bbml2_flag;
static void __init init_idmap_kpti_bbml2_flag(void)
--
2.43.0
^ permalink raw reply related
* [PATCH v2 3/3] arm64: mm: Remove pmd_sect() and pud_sect()
From: Ryan Roberts @ 2026-03-30 16:17 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, David Hildenbrand (Arm), Dev Jain,
Yang Shi, Suzuki K Poulose, Jinjiang Tu, Kevin Brodsky
Cc: Ryan Roberts, linux-arm-kernel, linux-kernel
In-Reply-To: <20260330161705.3349825-1-ryan.roberts@arm.com>
The semantics of pXd_leaf() are very similar to pXd_sect(). The only
difference is that pXd_sect() only considers it a section if PTE_VALID
is set, whereas pXd_leaf() permits both "valid" and "present-invalid"
types.
Using pXd_sect() has caused issues now that large leaf entries can be
present-invalid since commit a166563e7ec37 ("arm64: mm: support large
block mapping when rodata=full"), so let's just remove the API and
standardize on pXd_leaf().
There are a few callsites of the form pXd_leaf(READ_ONCE(*pXdp)). This
was previously fine for the pXd_sect() macro because it only evaluated
its argument once. But pXd_leaf() evaluates its argument multiple times.
So let's avoid unintended side effects by reimplementing pXd_leaf() as
an inline function.
Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
---
arch/arm64/include/asm/pgtable.h | 19 ++++++++++++-------
arch/arm64/mm/mmu.c | 18 +++++++++---------
2 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index dd062179b9b66..5bc42b85acfc0 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -784,9 +784,13 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
#define pmd_table(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \
PMD_TYPE_TABLE)
-#define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \
- PMD_TYPE_SECT)
-#define pmd_leaf(pmd) (pmd_present(pmd) && !pmd_table(pmd))
+
+#define pmd_leaf pmd_leaf
+static inline bool pmd_leaf(pmd_t pmd)
+{
+ return pmd_present(pmd) && !pmd_table(pmd);
+}
+
#define pmd_bad(pmd) (!pmd_table(pmd))
#define pmd_leaf_size(pmd) (pmd_cont(pmd) ? CONT_PMD_SIZE : PMD_SIZE)
@@ -804,11 +808,8 @@ static inline int pmd_trans_huge(pmd_t pmd)
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3
-static inline bool pud_sect(pud_t pud) { return false; }
static inline bool pud_table(pud_t pud) { return true; }
#else
-#define pud_sect(pud) ((pud_val(pud) & PUD_TYPE_MASK) == \
- PUD_TYPE_SECT)
#define pud_table(pud) ((pud_val(pud) & PUD_TYPE_MASK) == \
PUD_TYPE_TABLE)
#endif
@@ -878,7 +879,11 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
PUD_TYPE_TABLE)
#define pud_present(pud) pte_present(pud_pte(pud))
#ifndef __PAGETABLE_PMD_FOLDED
-#define pud_leaf(pud) (pud_present(pud) && !pud_table(pud))
+#define pud_leaf pud_leaf
+static inline bool pud_leaf(pud_t pud)
+{
+ return pud_present(pud) && !pud_table(pud);
+}
#else
#define pud_leaf(pud) false
#endif
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 1575680675d8d..dcee56bb622ad 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -204,7 +204,7 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
pmd_t pmd = READ_ONCE(*pmdp);
pte_t *ptep;
- BUG_ON(pmd_sect(pmd));
+ BUG_ON(pmd_leaf(pmd));
if (pmd_none(pmd)) {
pmdval_t pmdval = PMD_TYPE_TABLE | PMD_TABLE_UXN | PMD_TABLE_AF;
phys_addr_t pte_phys;
@@ -303,7 +303,7 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
/*
* Check for initial section mappings in the pgd/pud.
*/
- BUG_ON(pud_sect(pud));
+ BUG_ON(pud_leaf(pud));
if (pud_none(pud)) {
pudval_t pudval = PUD_TYPE_TABLE | PUD_TABLE_UXN | PUD_TABLE_AF;
phys_addr_t pmd_phys;
@@ -1503,7 +1503,7 @@ static void unmap_hotplug_pmd_range(pud_t *pudp, unsigned long addr,
continue;
WARN_ON(!pmd_present(pmd));
- if (pmd_sect(pmd)) {
+ if (pmd_leaf(pmd)) {
pmd_clear(pmdp);
/*
@@ -1536,7 +1536,7 @@ static void unmap_hotplug_pud_range(p4d_t *p4dp, unsigned long addr,
continue;
WARN_ON(!pud_present(pud));
- if (pud_sect(pud)) {
+ if (pud_leaf(pud)) {
pud_clear(pudp);
/*
@@ -1650,7 +1650,7 @@ static void free_empty_pmd_table(pud_t *pudp, unsigned long addr,
if (pmd_none(pmd))
continue;
- WARN_ON(!pmd_present(pmd) || !pmd_table(pmd) || pmd_sect(pmd));
+ WARN_ON(!pmd_present(pmd) || !pmd_table(pmd));
free_empty_pte_table(pmdp, addr, next, floor, ceiling);
} while (addr = next, addr < end);
@@ -1690,7 +1690,7 @@ static void free_empty_pud_table(p4d_t *p4dp, unsigned long addr,
if (pud_none(pud))
continue;
- WARN_ON(!pud_present(pud) || !pud_table(pud) || pud_sect(pud));
+ WARN_ON(!pud_present(pud) || !pud_table(pud));
free_empty_pmd_table(pudp, addr, next, floor, ceiling);
} while (addr = next, addr < end);
@@ -1786,7 +1786,7 @@ int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
{
vmemmap_verify((pte_t *)pmdp, node, addr, next);
- return pmd_sect(READ_ONCE(*pmdp));
+ return pmd_leaf(READ_ONCE(*pmdp));
}
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
@@ -1850,7 +1850,7 @@ void p4d_clear_huge(p4d_t *p4dp)
int pud_clear_huge(pud_t *pudp)
{
- if (!pud_sect(READ_ONCE(*pudp)))
+ if (!pud_leaf(READ_ONCE(*pudp)))
return 0;
pud_clear(pudp);
return 1;
@@ -1858,7 +1858,7 @@ int pud_clear_huge(pud_t *pudp)
int pmd_clear_huge(pmd_t *pmdp)
{
- if (!pmd_sect(READ_ONCE(*pmdp)))
+ if (!pmd_leaf(READ_ONCE(*pmdp)))
return 0;
pmd_clear(pmdp);
return 1;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 2/3] arm64: mm: Handle invalid large leaf mappings correctly
From: Ryan Roberts @ 2026-03-30 16:17 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, David Hildenbrand (Arm), Dev Jain,
Yang Shi, Suzuki K Poulose, Jinjiang Tu, Kevin Brodsky
Cc: Ryan Roberts, linux-arm-kernel, linux-kernel, stable
In-Reply-To: <20260330161705.3349825-1-ryan.roberts@arm.com>
It has been possible for a long time to mark ptes in the linear map as
invalid. This is done for secretmem, kfence, realm dma memory un/share,
and others, by simply clearing the PTE_VALID bit. But until commit
a166563e7ec37 ("arm64: mm: support large block mapping when
rodata=full") large leaf mappings were never made invalid in this way.
It turns out various parts of the code base are not equipped to handle
invalid large leaf mappings (in the way they are currently encoded) and
I've observed a kernel panic while booting a realm guest on a
BBML2_NOABORT system as a result:
[ 15.432706] software IO TLB: Memory encryption is active and system is using DMA bounce buffers
[ 15.476896] Unable to handle kernel paging request at virtual address ffff000019600000
[ 15.513762] Mem abort info:
[ 15.527245] ESR = 0x0000000096000046
[ 15.548553] EC = 0x25: DABT (current EL), IL = 32 bits
[ 15.572146] SET = 0, FnV = 0
[ 15.592141] EA = 0, S1PTW = 0
[ 15.612694] FSC = 0x06: level 2 translation fault
[ 15.640644] Data abort info:
[ 15.661983] ISV = 0, ISS = 0x00000046, ISS2 = 0x00000000
[ 15.694875] CM = 0, WnR = 1, TnD = 0, TagAccess = 0
[ 15.723740] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 15.755776] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000081f3f000
[ 15.800410] [ffff000019600000] pgd=0000000000000000, p4d=180000009ffff403, pud=180000009fffe403, pmd=00e8000199600704
[ 15.855046] Internal error: Oops: 0000000096000046 [#1] SMP
[ 15.886394] Modules linked in:
[ 15.900029] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.0.0-rc4-dirty #4 PREEMPT
[ 15.935258] Hardware name: linux,dummy-virt (DT)
[ 15.955612] pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[ 15.986009] pc : __pi_memcpy_generic+0x128/0x22c
[ 16.006163] lr : swiotlb_bounce+0xf4/0x158
[ 16.024145] sp : ffff80008000b8f0
[ 16.038896] x29: ffff80008000b8f0 x28: 0000000000000000 x27: 0000000000000000
[ 16.069953] x26: ffffb3976d261ba8 x25: 0000000000000000 x24: ffff000019600000
[ 16.100876] x23: 0000000000000001 x22: ffff0000043430d0 x21: 0000000000007ff0
[ 16.131946] x20: 0000000084570010 x19: 0000000000000000 x18: ffff00001ffe3fcc
[ 16.163073] x17: 0000000000000000 x16: 00000000003fffff x15: 646e612065766974
[ 16.194131] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
[ 16.225059] x11: 0000000000000000 x10: 0000000000000010 x9 : 0000000000000018
[ 16.256113] x8 : 0000000000000018 x7 : 0000000000000000 x6 : 0000000000000000
[ 16.287203] x5 : ffff000019607ff0 x4 : ffff000004578000 x3 : ffff000019600000
[ 16.318145] x2 : 0000000000007ff0 x1 : ffff000004570010 x0 : ffff000019600000
[ 16.349071] Call trace:
[ 16.360143] __pi_memcpy_generic+0x128/0x22c (P)
[ 16.380310] swiotlb_tbl_map_single+0x154/0x2b4
[ 16.400282] swiotlb_map+0x5c/0x228
[ 16.415984] dma_map_phys+0x244/0x2b8
[ 16.432199] dma_map_page_attrs+0x44/0x58
[ 16.449782] virtqueue_map_page_attrs+0x38/0x44
[ 16.469596] virtqueue_map_single_attrs+0xc0/0x130
[ 16.490509] virtnet_rq_alloc.isra.0+0xa4/0x1fc
[ 16.510355] try_fill_recv+0x2a4/0x584
[ 16.526989] virtnet_open+0xd4/0x238
[ 16.542775] __dev_open+0x110/0x24c
[ 16.558280] __dev_change_flags+0x194/0x20c
[ 16.576879] netif_change_flags+0x24/0x6c
[ 16.594489] dev_change_flags+0x48/0x7c
[ 16.611462] ip_auto_config+0x258/0x1114
[ 16.628727] do_one_initcall+0x80/0x1c8
[ 16.645590] kernel_init_freeable+0x208/0x2f0
[ 16.664917] kernel_init+0x24/0x1e0
[ 16.680295] ret_from_fork+0x10/0x20
[ 16.696369] Code: 927cec03 cb0e0021 8b0e0042 a9411c26 (a900340c)
[ 16.723106] ---[ end trace 0000000000000000 ]---
[ 16.752866] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[ 16.792556] Kernel Offset: 0x3396ea200000 from 0xffff800080000000
[ 16.818966] PHYS_OFFSET: 0xfff1000080000000
[ 16.837237] CPU features: 0x0000000,00060005,13e38581,957e772f
[ 16.862904] Memory Limit: none
[ 16.876526] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---
This panic occurs because the swiotlb memory was previously shared to
the host (__set_memory_enc_dec()), which involves transitioning the
(large) leaf mappings to invalid, sharing to the host, then marking the
mappings valid again. But pageattr_p[mu]d_entry() would only update the
entry if it is a section mapping, since otherwise it concluded it must
be a table entry so shouldn't be modified. But p[mu]d_sect() only
returns true if the entry is valid. So the result was that the large
leaf entry was made invalid in the first pass then ignored in the second
pass. It remains invalid until the above code tries to access it and
blows up.
The simple fix would be to update pageattr_pmd_entry() to use
!pmd_table() instead of pmd_sect(). That would solve this problem.
But the ptdump code also suffers from a similar issue. It checks
pmd_leaf() and doesn't call into the arch-specific note_page() machinery
if it returns false. As a result of this, ptdump wasn't even able to
show the invalid large leaf mappings; it looked like they were valid
which made this super fun to debug. the ptdump code is core-mm and
pmd_table() is arm64-specific so we can't use the same trick to solve
that.
But we already support the concept of "present-invalid" for user space
entries. And even better, pmd_leaf() will return true for a leaf mapping
that is marked present-invalid. So let's just use that encoding for
present-invalid kernel mappings too. Then we can use pmd_leaf() where we
previously used pmd_sect() and everything is magically fixed.
Additionally, from inspection kernel_page_present() was broken in a
similar way, so I'm also updating that to use pmd_leaf().
The transitional page tables component was also similarly broken; it
creates a copy of the kernel page tables, making RO leaf mappings RW in
the process. It also makes invalid (but-not-none) pte mappings valid.
But it was not doing this for large leaf mappings. This could have
resulted in crashes at kexec- or hibernate-time. This code is fixed to
flip "present-invalid" mappings back to "present-valid" at all levels.
Finally, I have hardened split_pmd()/split_pud() so that if it is passed
a "present-invalid" leaf, it will maintain that property in the split
leaves, since I wasn't able to convince myself that it would only ever
be called for "present-valid" leaves.
Fixes: a166563e7ec37 ("arm64: mm: support large block mapping when rodata=full")
Cc: stable@vger.kernel.org
Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
---
arch/arm64/include/asm/pgtable-prot.h | 2 ++
arch/arm64/include/asm/pgtable.h | 9 +++--
arch/arm64/mm/mmu.c | 4 +++
arch/arm64/mm/pageattr.c | 50 +++++++++++++++------------
arch/arm64/mm/trans_pgd.c | 42 ++++------------------
5 files changed, 48 insertions(+), 59 deletions(-)
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index f560e64202674..212ce1b02e15e 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -25,6 +25,8 @@
*/
#define PTE_PRESENT_INVALID (PTE_NG) /* only when !PTE_VALID */
+#define PTE_PRESENT_VALID_KERNEL (PTE_VALID | PTE_MAYBE_NG)
+
#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP
#define PTE_UFFD_WP (_AT(pteval_t, 1) << 58) /* uffd-wp tracking */
#define PTE_SWP_UFFD_WP (_AT(pteval_t, 1) << 3) /* only for swp ptes */
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index b3e58735c49bd..dd062179b9b66 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -322,9 +322,11 @@ static inline pte_t pte_mknoncont(pte_t pte)
return clear_pte_bit(pte, __pgprot(PTE_CONT));
}
-static inline pte_t pte_mkvalid(pte_t pte)
+static inline pte_t pte_mkvalid_k(pte_t pte)
{
- return set_pte_bit(pte, __pgprot(PTE_VALID));
+ pte = clear_pte_bit(pte, __pgprot(PTE_PRESENT_INVALID));
+ pte = set_pte_bit(pte, __pgprot(PTE_PRESENT_VALID_KERNEL));
+ return pte;
}
static inline pte_t pte_mkinvalid(pte_t pte)
@@ -594,6 +596,7 @@ static inline int pmd_protnone(pmd_t pmd)
#define pmd_mkclean(pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))
#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd)))
#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
+#define pmd_mkvalid_k(pmd) pte_pmd(pte_mkvalid_k(pmd_pte(pmd)))
#define pmd_mkinvalid(pmd) pte_pmd(pte_mkinvalid(pmd_pte(pmd)))
#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP
#define pmd_uffd_wp(pmd) pte_uffd_wp(pmd_pte(pmd))
@@ -635,6 +638,8 @@ static inline pmd_t pmd_mkspecial(pmd_t pmd)
#define pud_young(pud) pte_young(pud_pte(pud))
#define pud_mkyoung(pud) pte_pud(pte_mkyoung(pud_pte(pud)))
+#define pud_mkwrite_novma(pud) pte_pud(pte_mkwrite_novma(pud_pte(pud)))
+#define pud_mkvalid_k(pud) pte_pud(pte_mkvalid_k(pud_pte(pud)))
#define pud_write(pud) pte_write(pud_pte(pud))
static inline pud_t pud_mkhuge(pud_t pud)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 223947487a223..1575680675d8d 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -602,6 +602,8 @@ static int split_pmd(pmd_t *pmdp, pmd_t pmd, gfp_t gfp, bool to_cont)
tableprot |= PMD_TABLE_PXN;
prot = __pgprot((pgprot_val(prot) & ~PTE_TYPE_MASK) | PTE_TYPE_PAGE);
+ if (!pmd_valid(pmd))
+ prot = pte_pgprot(pte_mkinvalid(pfn_pte(0, prot)));
prot = __pgprot(pgprot_val(prot) & ~PTE_CONT);
if (to_cont)
prot = __pgprot(pgprot_val(prot) | PTE_CONT);
@@ -647,6 +649,8 @@ static int split_pud(pud_t *pudp, pud_t pud, gfp_t gfp, bool to_cont)
tableprot |= PUD_TABLE_PXN;
prot = __pgprot((pgprot_val(prot) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT);
+ if (!pud_valid(pud))
+ prot = pmd_pgprot(pmd_mkinvalid(pfn_pmd(0, prot)));
prot = __pgprot(pgprot_val(prot) & ~PTE_CONT);
if (to_cont)
prot = __pgprot(pgprot_val(prot) | PTE_CONT);
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 358d1dc9a576f..ce035e1b4eaf6 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -25,6 +25,11 @@ static ptdesc_t set_pageattr_masks(ptdesc_t val, struct mm_walk *walk)
{
struct page_change_data *masks = walk->private;
+ /*
+ * Some users clear and set bits which alias each other (e.g. PTE_NG and
+ * PTE_PRESENT_INVALID). It is therefore important that we always clear
+ * first then set.
+ */
val &= ~(pgprot_val(masks->clear_mask));
val |= (pgprot_val(masks->set_mask));
@@ -36,7 +41,7 @@ static int pageattr_pud_entry(pud_t *pud, unsigned long addr,
{
pud_t val = pudp_get(pud);
- if (pud_sect(val)) {
+ if (pud_leaf(val)) {
if (WARN_ON_ONCE((next - addr) != PUD_SIZE))
return -EINVAL;
val = __pud(set_pageattr_masks(pud_val(val), walk));
@@ -52,7 +57,7 @@ static int pageattr_pmd_entry(pmd_t *pmd, unsigned long addr,
{
pmd_t val = pmdp_get(pmd);
- if (pmd_sect(val)) {
+ if (pmd_leaf(val)) {
if (WARN_ON_ONCE((next - addr) != PMD_SIZE))
return -EINVAL;
val = __pmd(set_pageattr_masks(pmd_val(val), walk));
@@ -132,11 +137,12 @@ static int __change_memory_common(unsigned long start, unsigned long size,
ret = update_range_prot(start, size, set_mask, clear_mask);
/*
- * If the memory is being made valid without changing any other bits
- * then a TLBI isn't required as a non-valid entry cannot be cached in
- * the TLB.
+ * If the memory is being switched from present-invalid to valid without
+ * changing any other bits then a TLBI isn't required as a non-valid
+ * entry cannot be cached in the TLB.
*/
- if (pgprot_val(set_mask) != PTE_VALID || pgprot_val(clear_mask))
+ if (pgprot_val(set_mask) != PTE_PRESENT_VALID_KERNEL ||
+ pgprot_val(clear_mask) != PTE_PRESENT_INVALID)
flush_tlb_kernel_range(start, start + size);
return ret;
}
@@ -237,18 +243,18 @@ int set_memory_valid(unsigned long addr, int numpages, int enable)
{
if (enable)
return __change_memory_common(addr, PAGE_SIZE * numpages,
- __pgprot(PTE_VALID),
- __pgprot(0));
+ __pgprot(PTE_PRESENT_VALID_KERNEL),
+ __pgprot(PTE_PRESENT_INVALID));
else
return __change_memory_common(addr, PAGE_SIZE * numpages,
- __pgprot(0),
- __pgprot(PTE_VALID));
+ __pgprot(PTE_PRESENT_INVALID),
+ __pgprot(PTE_PRESENT_VALID_KERNEL));
}
int set_direct_map_invalid_noflush(struct page *page)
{
- pgprot_t clear_mask = __pgprot(PTE_VALID);
- pgprot_t set_mask = __pgprot(0);
+ pgprot_t clear_mask = __pgprot(PTE_PRESENT_VALID_KERNEL);
+ pgprot_t set_mask = __pgprot(PTE_PRESENT_INVALID);
if (!can_set_direct_map())
return 0;
@@ -259,8 +265,8 @@ int set_direct_map_invalid_noflush(struct page *page)
int set_direct_map_default_noflush(struct page *page)
{
- pgprot_t set_mask = __pgprot(PTE_VALID | PTE_WRITE);
- pgprot_t clear_mask = __pgprot(PTE_RDONLY);
+ pgprot_t set_mask = __pgprot(PTE_PRESENT_VALID_KERNEL | PTE_WRITE);
+ pgprot_t clear_mask = __pgprot(PTE_PRESENT_INVALID | PTE_RDONLY);
if (!can_set_direct_map())
return 0;
@@ -296,8 +302,8 @@ static int __set_memory_enc_dec(unsigned long addr,
* entries or Synchronous External Aborts caused by RIPAS_EMPTY
*/
ret = __change_memory_common(addr, PAGE_SIZE * numpages,
- __pgprot(set_prot),
- __pgprot(clear_prot | PTE_VALID));
+ __pgprot(set_prot | PTE_PRESENT_INVALID),
+ __pgprot(clear_prot | PTE_PRESENT_VALID_KERNEL));
if (ret)
return ret;
@@ -311,8 +317,8 @@ static int __set_memory_enc_dec(unsigned long addr,
return ret;
return __change_memory_common(addr, PAGE_SIZE * numpages,
- __pgprot(PTE_VALID),
- __pgprot(0));
+ __pgprot(PTE_PRESENT_VALID_KERNEL),
+ __pgprot(PTE_PRESENT_INVALID));
}
static int realm_set_memory_encrypted(unsigned long addr, int numpages)
@@ -404,15 +410,15 @@ bool kernel_page_present(struct page *page)
pud = READ_ONCE(*pudp);
if (pud_none(pud))
return false;
- if (pud_sect(pud))
- return true;
+ if (pud_leaf(pud))
+ return pud_valid(pud);
pmdp = pmd_offset(pudp, addr);
pmd = READ_ONCE(*pmdp);
if (pmd_none(pmd))
return false;
- if (pmd_sect(pmd))
- return true;
+ if (pmd_leaf(pmd))
+ return pmd_valid(pmd);
ptep = pte_offset_kernel(pmdp, addr);
return pte_valid(__ptep_get(ptep));
diff --git a/arch/arm64/mm/trans_pgd.c b/arch/arm64/mm/trans_pgd.c
index 18543b603c77b..cca9706a875c3 100644
--- a/arch/arm64/mm/trans_pgd.c
+++ b/arch/arm64/mm/trans_pgd.c
@@ -31,36 +31,6 @@ static void *trans_alloc(struct trans_pgd_info *info)
return info->trans_alloc_page(info->trans_alloc_arg);
}
-static void _copy_pte(pte_t *dst_ptep, pte_t *src_ptep, unsigned long addr)
-{
- pte_t pte = __ptep_get(src_ptep);
-
- if (pte_valid(pte)) {
- /*
- * Resume will overwrite areas that may be marked
- * read only (code, rodata). Clear the RDONLY bit from
- * the temporary mappings we use during restore.
- */
- __set_pte(dst_ptep, pte_mkwrite_novma(pte));
- } else if (!pte_none(pte)) {
- /*
- * debug_pagealloc will removed the PTE_VALID bit if
- * the page isn't in use by the resume kernel. It may have
- * been in use by the original kernel, in which case we need
- * to put it back in our copy to do the restore.
- *
- * Other cases include kfence / vmalloc / memfd_secret which
- * may call `set_direct_map_invalid_noflush()`.
- *
- * Before marking this entry valid, check the pfn should
- * be mapped.
- */
- BUG_ON(!pfn_valid(pte_pfn(pte)));
-
- __set_pte(dst_ptep, pte_mkvalid(pte_mkwrite_novma(pte)));
- }
-}
-
static int copy_pte(struct trans_pgd_info *info, pmd_t *dst_pmdp,
pmd_t *src_pmdp, unsigned long start, unsigned long end)
{
@@ -76,7 +46,11 @@ static int copy_pte(struct trans_pgd_info *info, pmd_t *dst_pmdp,
src_ptep = pte_offset_kernel(src_pmdp, start);
do {
- _copy_pte(dst_ptep, src_ptep, addr);
+ pte_t pte = __ptep_get(src_ptep);
+
+ if (pte_none(pte))
+ continue;
+ __set_pte(dst_ptep, pte_mkvalid_k(pte_mkwrite_novma(pte)));
} while (dst_ptep++, src_ptep++, addr += PAGE_SIZE, addr != end);
return 0;
@@ -109,8 +83,7 @@ static int copy_pmd(struct trans_pgd_info *info, pud_t *dst_pudp,
if (copy_pte(info, dst_pmdp, src_pmdp, addr, next))
return -ENOMEM;
} else {
- set_pmd(dst_pmdp,
- __pmd(pmd_val(pmd) & ~PMD_SECT_RDONLY));
+ set_pmd(dst_pmdp, pmd_mkvalid_k(pmd_mkwrite_novma(pmd)));
}
} while (dst_pmdp++, src_pmdp++, addr = next, addr != end);
@@ -145,8 +118,7 @@ static int copy_pud(struct trans_pgd_info *info, p4d_t *dst_p4dp,
if (copy_pmd(info, dst_pudp, src_pudp, addr, next))
return -ENOMEM;
} else {
- set_pud(dst_pudp,
- __pud(pud_val(pud) & ~PUD_SECT_RDONLY));
+ set_pud(dst_pudp, pud_mkvalid_k(pud_mkwrite_novma(pud)));
}
} while (dst_pudp++, src_pudp++, addr = next, addr != end);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH V2 5/5] dmaengine: xilinx_dma: Add support for reporting transfer size to AXI DMA / MCDMA client when app fields are unavailable
From: Frank Li @ 2026-03-30 16:04 UTC (permalink / raw)
To: Srinivas Neeli
Cc: Vinod Koul, git, Frank Li, Michal Simek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Suraj Gupta,
Radhey Shyam Pandey, Thomas Gessler, Folker Schwesinger,
Tomi Valkeinen, Kees Cook, Abin Joseph, dmaengine, devicetree,
linux-arm-kernel, linux-kernel
In-Reply-To: <20260313062533.421249-6-srinivas.neeli@amd.com>
On Fri, Mar 13, 2026 at 11:55:33AM +0530, Srinivas Neeli wrote:
> From: Suraj Gupta <suraj.gupta2@amd.com>
>
> The AXI4-stream status and control interface is optional in the AXI DMA /
> MCDMA IP design; when it is not present, app fields are not available in
> DMA descriptor. In such cases, the transferred byte count can be
> communicated to the client using the status field (bits 0-25) of
> AXI DMA / MCDMA descriptor.
>
> Add a xferred_bytes field to struct xilinx_dma_tx_descriptor to record the
> number of bytes transferred for each transaction. The value is calculated
> using the existing xilinx_dma_get_residue() function, which traverses all
> hardware descriptors associated with the async transaction descriptor,
> avoiding redundant traversal.
Can you split this change to new patch?
Frank
>
> The driver uses the xlnx,include-stscntrl-strm device tree property to
> determine if the status/control stream interface is present and selects the
> appropriate metadata source accordingly.
>
> Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
> ---
> drivers/dma/xilinx/xilinx_dma.c | 28 ++++++++++++++++++++++++----
> 1 file changed, 24 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index 52203d44e7a4..f5ef03a1297c 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -380,6 +380,8 @@ struct xilinx_cdma_tx_segment {
> * @cyclic: Check for cyclic transfers.
> * @err: Whether the descriptor has an error.
> * @residue: Residue of the completed descriptor
> + * @xferred_bytes: Number of bytes transferred by this transaction
> + * descriptor.
> */
> struct xilinx_dma_tx_descriptor {
> struct xilinx_dma_chan *chan;
> @@ -389,6 +391,7 @@ struct xilinx_dma_tx_descriptor {
> bool cyclic;
> bool err;
> u32 residue;
> + u32 xferred_bytes;
> };
>
> /**
> @@ -515,6 +518,7 @@ struct xilinx_dma_config {
> * @mm2s_chan_id: DMA mm2s channel identifier
> * @max_buffer_len: Max buffer length
> * @has_axistream_connected: AXI DMA connected to AXI Stream IP
> + * @has_stsctrl_stream: AXI4-stream status and control interface is enabled
> */
> struct xilinx_dma_device {
> void __iomem *regs;
> @@ -534,6 +538,7 @@ struct xilinx_dma_device {
> u32 mm2s_chan_id;
> u32 max_buffer_len;
> bool has_axistream_connected;
> + bool has_stsctrl_stream;
> };
>
> /* Macros */
> @@ -672,8 +677,12 @@ static void *xilinx_dma_get_metadata_ptr(struct dma_async_tx_descriptor *tx,
> struct xilinx_axidma_tx_segment, node);
> metadata_ptr = seg->hw.app;
> }
> - *max_len = *payload_len = sizeof(u32) * XILINX_DMA_NUM_APP_WORDS;
> - return metadata_ptr;
> + if (desc->chan->xdev->has_stsctrl_stream) {
> + *max_len = *payload_len = sizeof(u32) * XILINX_DMA_NUM_APP_WORDS;
> + return metadata_ptr;
> + }
> + *max_len = *payload_len = sizeof(desc->xferred_bytes);
> + return (void *)&desc->xferred_bytes;
> }
>
> static struct dma_descriptor_metadata_ops xilinx_dma_metadata_ops = {
> @@ -864,6 +873,7 @@ xilinx_dma_alloc_tx_descriptor(struct xilinx_dma_chan *chan)
> return NULL;
>
> desc->chan = chan;
> + desc->xferred_bytes = 0;
> INIT_LIST_HEAD(&desc->segments);
>
> return desc;
> @@ -1014,6 +1024,7 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
> struct xilinx_aximcdma_desc_hw *aximcdma_hw;
> struct list_head *entry;
> u32 residue = 0;
> + u32 xferred = 0;
>
> list_for_each(entry, &desc->segments) {
> if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
> @@ -1031,25 +1042,32 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
> axidma_hw = &axidma_seg->hw;
> residue += (axidma_hw->control - axidma_hw->status) &
> chan->xdev->max_buffer_len;
> + xferred += axidma_hw->status & chan->xdev->max_buffer_len;
> } else {
> aximcdma_seg =
> list_entry(entry,
> struct xilinx_aximcdma_tx_segment,
> node);
> aximcdma_hw = &aximcdma_seg->hw;
> - if (chan->direction == DMA_DEV_TO_MEM)
> + if (chan->direction == DMA_DEV_TO_MEM) {
> residue +=
> (aximcdma_hw->control -
> aximcdma_hw->s2mm_status) &
> chan->xdev->max_buffer_len;
> - else
> + xferred += aximcdma_hw->s2mm_status &
> + chan->xdev->max_buffer_len;
> + } else {
> residue +=
> (aximcdma_hw->control -
> aximcdma_hw->mm2s_status) &
> chan->xdev->max_buffer_len;
> + xferred += aximcdma_hw->mm2s_status &
> + chan->xdev->max_buffer_len;
> + }
> }
> }
>
> + desc->xferred_bytes = xferred;
> return residue;
> }
>
> @@ -3284,6 +3302,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
> xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
> xdev->has_axistream_connected =
> of_property_read_bool(node, "xlnx,axistream-connected");
> + xdev->has_stsctrl_stream =
> + of_property_read_bool(node, "xlnx,include-stscntrl-strm");
> }
>
> if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
> --
> 2.43.0
>
^ permalink raw reply
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
From: Paul Kocialkowski @ 2026-03-30 16:20 UTC (permalink / raw)
To: Krzysztof Hałasa
Cc: Liu Ying, Maxime Ripard, Marco Felsch, Marek Vasut, Stefan Agner,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel,
Lucas Stach
In-Reply-To: <m35x6mpuya.fsf@t19.piap.pl>
[-- Attachment #1: Type: text/plain, Size: 3187 bytes --]
Hi,
On Mon 23 Mar 26, 13:54, Krzysztof Hałasa wrote:
> Liu Ying <victor.liu@nxp.com> writes:
> > If you may use a display mode with low resolution, say 640x480p60, and
> > the issue still happens, then I bet it's not related to the panic
> > threshold settings, but more likely related to KMS detail control seqeunce.
I've also seen the same behavior. The NoC panic thresholds are meant to
temporarily increase the NoC master priority if the FIFOs are not able to
fetch data in time because too much data is moving on the NoC interconnect
and the display engine may be starved and fail to fetch data in time for
scanout.
The fact that our issue also happens with low sizes means that NoC access is
probably not the bottleneck that causes the FIFO errors and that tweaking the
thresholds probably has no effect. I've also made my experiments with pretty
much nothing running on the system, so the NoC has no reason to be busy.
One issue I had with this issue is that it sometimes feels like certain changes
make the issue less frequent, but it is often just variability due to the small
numbers of tries.
It's true however that the nxp bsp does use different thereshold values for
lcdif3, which are probably tweaked for specific use cases with high load on
the interconnect. But I'm not sure it's very important to have them in mainline
for now.
All the best,
Paul
> > This reminds me that Lucas had a patch series[1] to try to fix the
> > sequence, but it seems that it didn't fix i.MX93 LCDIF according to [2]
> > hence no landing.
>
> It seems it depends on resolution: at 1080p60 with the DIV_ROUND_UP
> (thresholds increased by 1) it seems to work fine. At 2160p30 (twice the
> clock) there are frequent underruns. Now with thresholds increased to
> 2/4 and 3/4, weston started fine 10/10, while shutdowns were 8/10.
> 4/6 and 5/6 made it worse, though.
>
> I don't know now. I will try to investigate a bit more tomorrow.
> Perhaps the sequence of register writes could be better, indeed.
>
> The following doesn't fix it for me either:
> --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> @@ -358,34 +358,27 @@ static void lcdif_enable_controller(struct lcdif_drm_private *lcdif)
> writel(INT_ENABLE_D1_PLANE_PANIC_EN,
> lcdif->base + LCDC_V8_INT_ENABLE_D1);
>
> - reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
> - reg |= DISP_PARA_DISP_ON;
> - writel(reg, lcdif->base + LCDC_V8_DISP_PARA);
> -
> reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5);
> reg |= CTRLDESCL0_5_EN;
> writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5);
> +
> + reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
> + reg |= DISP_PARA_DISP_ON;
> + writel(reg, lcdif->base + LCDC_V8_DISP_PARA);
> }
>
>
> --
> Krzysztof "Chris" Hałasa
>
> Sieć Badawcza Łukasiewicz
> Przemysłowy Instytut Automatyki i Pomiarów PIAP
> Al. Jerozolimskie 202, 02-486 Warszawa
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/3] remoteproc: imx_rproc: Pass bootaddr to SM CPU/LMM reset vector
From: Mathieu Poirier @ 2026-03-30 16:22 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Bjorn Andersson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Daniel Baluta, linux-remoteproc, devicetree, imx,
linux-arm-kernel, linux-kernel, Peng Fan
In-Reply-To: <20260327-imx943-rproc-v2-2-a547a3588730@nxp.com>
On Fri, Mar 27, 2026 at 10:42:03AM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Cortex-M[7,33] processors use a fixed reset vector table format:
>
> 0x00 Initial SP value
> 0x04 Reset vector
> 0x08 NMI
> 0x0C ...
> ...
> IRQ[n]
>
> In ELF images, the corresponding layout is:
>
> reset_vectors: --> hardware reset address
> .word __stack_end__
> .word Reset_Handler
> .word NMI_Handler
> .word HardFault_Handler
> ...
> .word UART_IRQHandler
> .word SPI_IRQHandler
> ...
>
> Reset_Handler: --> ELF entry point address
> ...
>
> The hardware fetches the first two words from reset_vectors and populates
> SP with __stack_end__ and PC with Reset_Handler. Execution proceeds from
> Reset_Handler.
>
> However, the ELF entry point does not always match the hardware reset
> address. For example, on i.MX94 CM33S:
>
> ELF entry point: 0x0ffc211d
> hardware reset base: 0x0ffc0000 (default reset value, sw programmable)
>
But why? Why can't the ELF image be set to the right reset base?
> To derive the correct hardware reset address, the unused lower bits must
> be masked off. The boot code should apply a SoC-specific mask before
> programming the reset address registers, e.g.:
>
> reset_address = entry & reset_vector_mask
>
> Current driver always programs the reset vector as 0. But i.MX94 CM33S's
> default reset base is 0x0ffc0000, so the correct reset vector must be
> passed to the SM API; otherwise the M33 Sync core cannot boot successfully.
>
> rproc_elf_get_boot_addr() returns the ELF entry point, which is not the
> hardware reset vector address. To derive the proper reset vector, this
> patch introduces imx_rproc_get_boot_addr(), which masks the ELF entry
> point using the SoC‑specific 'reset_vector_mask'. The resulting reset
> vector address is then passed to the SM CPU/LMM reset vector API calls.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> drivers/remoteproc/imx_rproc.c | 17 ++++++++++++++---
> drivers/remoteproc/imx_rproc.h | 2 ++
> 2 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 0dd80e688b0ea3df4c66e5726884dc86c8a5a881..d8ead42640881bd523d605fa7002935ef6e98077 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -345,7 +345,7 @@ static int imx_rproc_sm_cpu_start(struct rproc *rproc)
> const struct imx_rproc_dcfg *dcfg = priv->dcfg;
> int ret;
>
> - ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, 0, true, false, false);
> + ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, rproc->bootaddr, true, false, false);
> if (ret) {
> dev_err(priv->dev, "Failed to set reset vector cpuid(%u): %d\n", dcfg->cpuid, ret);
> return ret;
> @@ -365,7 +365,7 @@ static int imx_rproc_sm_lmm_start(struct rproc *rproc)
> * If the remoteproc core can't start the M7, it will already be
> * handled in imx_rproc_sm_lmm_prepare().
> */
> - ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, 0);
> + ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, rproc->bootaddr);
> if (ret) {
> dev_err(dev, "Failed to set reset vector lmid(%u), cpuid(%u): %d\n",
> dcfg->lmid, dcfg->cpuid, ret);
> @@ -739,6 +739,17 @@ imx_rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *
> return rproc_elf_find_loaded_rsc_table(rproc, fw);
> }
>
> +static u64 imx_rproc_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
> +{
> + struct imx_rproc *priv = rproc->priv;
> + u32 reset_vector_mask = GENMASK_U32(31, 0);
> +
> + if (priv->dcfg->reset_vector_mask)
> + reset_vector_mask = priv->dcfg->reset_vector_mask;
> +
> + return rproc_elf_get_boot_addr(rproc, fw) & reset_vector_mask;
> +}
> +
> static const struct rproc_ops imx_rproc_ops = {
> .prepare = imx_rproc_prepare,
> .attach = imx_rproc_attach,
> @@ -752,7 +763,7 @@ static const struct rproc_ops imx_rproc_ops = {
> .find_loaded_rsc_table = imx_rproc_elf_find_loaded_rsc_table,
> .get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
> .sanity_check = rproc_elf_sanity_check,
> - .get_boot_addr = rproc_elf_get_boot_addr,
> + .get_boot_addr = imx_rproc_get_boot_addr,
> };
>
> static int imx_rproc_addr_init(struct imx_rproc *priv,
> diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h
> index d37e6f90548cec727b4aeb874680b42af85bdbb4..0d7d48352a1091ad24e8e083172ce6da6d26ae10 100644
> --- a/drivers/remoteproc/imx_rproc.h
> +++ b/drivers/remoteproc/imx_rproc.h
> @@ -41,6 +41,8 @@ struct imx_rproc_dcfg {
> /* For System Manager(SM) based SoCs */
> u32 cpuid; /* ID of the remote core */
> u32 lmid; /* ID of the Logcial Machine */
> + /* reset_vector = elf_entry_addr & reset_vector_mask */
> + u32 reset_vector_mask;
> };
>
> #endif /* _IMX_RPROC_H */
>
> --
> 2.37.1
>
^ permalink raw reply
* Re: [PATCH v2] raid6: arm64: add SVE optimized implementation for syndrome generation
From: Ard Biesheuvel @ 2026-03-30 16:39 UTC (permalink / raw)
To: Demian Shulhan, Mark Rutland
Cc: Christoph Hellwig, Song Liu, Yu Kuai, Will Deacon,
Catalin Marinas, Mark Brown, linux-arm-kernel, robin.murphy,
Li Nan, linux-raid, linux-kernel
In-Reply-To: <CAOLeWCsxhzdxQviizJ4X4VOp_28LCtO-RjWoCcZG29rQw86NVg@mail.gmail.com>
Hi Demian,
On Sun, 29 Mar 2026, at 15:01, Demian Shulhan wrote:
> I want to address the comment about the marginal 0.3% speedup on the
> 8-disk benchmark. While the pure memory bandwidth on a small array is
> indeed bottlenecked, it doesn't reveal the whole picture. I extracted
> the SVE and NEON implementations into a user-space benchmark to
> measure the actual hardware efficiency using perf stat, running on the
> same AWS Graviton3 (Neoverse-V1) instance.The results show a massive
> difference in CPU efficiency. For the same 8-disk workload, the svex4
> implementation requires about 35% fewer instructions and 46% fewer CPU
> cycles compared to neonx4 (7.58 billion instructions vs 11.62
> billion). This translates directly into significant energy savings and
> reduced pressure on the CPU frontend, which would leave more compute
> resources available for network and NVMe queues during an array
> rebuild.
>
I think the results are impressive, but I'd like to better understand
its implications on a real-world scenario. Is this code only a
bottleneck when rebuilding an array? Is it really that much more power
efficient, given that the registers (and ALU paths) are twice the size?
And given the I/O load of rebuilding a 24+ disk array, how much CPU
throughput can we make use of meaningfully in such a scenario?
Supporting SVE in the kernel primarily impacts the size of the per-task
buffers that we need to preserve/restore the context. Fortunately,
these are no longer allocated for the lifetime of the task, but
dynamically (by scoped_ksimd()), and so the main impediment has been
recently removed. But as Mark pointed out, there are other things to
take into account. Nonetheless, our position has always been that a
compelling use case could convince us that the additional complexity
of in-kernel SVE is justified.
> Furthermore, as Christoph suggested, I tested scalability on wider
> arrays since the default kernel benchmark is hardcoded to 8 disks,
> which doesn't give the unrolled SVE loop enough data to shine. On a
> 16-disk array, svex4 hits 15.1 GB/s compared to 8.0 GB/s for neonx4.
> On a 24-disk array, while neonx4 chokes and drops to 7.8 GB/s, svex4
> maintains a stable 15.0 GB/s — effectively doubling the throughput.
Does this mean the kernel benchmark is no longer fit for purpose? If
it cannot distinguish between implementations that differ in performance
by a factor of 2, I don't think we can rely on it to pick the optimal one.
> I agree this patch should be put on hold for now. My intention is to
> leave these numbers here as evidence that implementing SVE context
> preservation in the kernel (the "good use case") is highly justifiable
> from both a power-efficiency and a wide-array throughput perspective
> for modern ARM64 hardware.
>
Could you please summarize the results? The output below seems to have
become mangled a bit. Please also include the command line, a link to
the test source, and the vector length of the implementation.
> Thanks again for your time and time and review!
>
> ---------------------------------------------------
> User space test results:
> ==================================================
> RAID6 SVE Benchmark Results (AWS Graviton3)
> ==================================================
> Instance Details:
> Linux ip-172-31-87-234 6.8.0-1047-aws #50~22.04.1-Ubuntu SMP Thu Feb
> 19 20:49:25 UTC 2026 aarch64 aarch64 aarch64 GNU/Linux
> --------------------------------------------------
>
> [Test 1: Energy Efficiency / Instruction Count (8 disks)]
> Running baseline (neonx4)...
> algo=neonx4 ndisks=8 iterations=1000000 time=2.681s MB/s=8741.36
>
> Running SVE (svex1)...
>
> Performance counter stats for './raid6_bench neonx4 8 1000000':
>
> 11626717224 instructions # 1.67
> insn per cycle
> 6946699489 cycles
> 257013219 L1-dcache-load-misses
>
> 2.681213149 seconds time elapsed
>
> 2.676771000 seconds user
> 0.002000000 seconds sys
>
>
> algo=svex1 ndisks=8 iterations=1000000 time=1.688s MB/s=13885.23
>
> Performance counter stats for './raid6_bench svex1 8 1000000':
>
> 10527277490
> Running SVE unrolled x4 (svex4)...
> instructions # 2.40 insn per cycle
> 4379539835 cycles
> 175695656 L1-dcache-load-misses
>
> 1.688852006 seconds time elapsed
>
> 1.687298000 seconds user
> 0.000999000 seconds sys
>
>
> algo=svex4 ndisks=8 iterations=1000000 time=1.445s MB/s=16215.04
>
> Performance counter stats for './raid6_bench svex4 8 1000000':
>
> 7587813392 instructions
> ==================================================
> [Test 2: Scalability on Wide RAID Arrays (MB/s)]
> --- 16 Disks ---
> # 2.02 insn per cycle
> 3748486131 cycles
> 213816184 L1-dcache-load-misses
>
> 1.446032415 seconds time elapsed
>
> 1.442412000 seconds user
> 0.002996000 seconds sys
>
>
> algo=neonx4 ndisks=16 iterations=1000000 time=6.783s MB/s=8062.33
> algo=svex1 ndisks=16 iterations=1000000 time=4.912s MB/s=11132.90
> algo=svex4 ndisks=16 iterations=1000000 time=3.601s MB/s=15188.85
>
> --- 24 Disks ---
> algo=neonx4 ndisks=24 iterations=1000000 time=11.011s MB/s=7805.02
> algo=svex1 ndisks=24 iterations=1000000 time=8.843s MB/s=9718.26
> algo=svex4 ndisks=24 iterations=1000000 time=5.719s MB/s=15026.92
>
> Extra tests:
> --- 48 Disks ---
> algo=neonx4 ndisks=48 iterations=500000 time=11.826s MB/s=7597.25
> algo=svex4 ndisks=48 iterations=500000 time=5.808s MB/s=15468.10
> --- 96 Disks ---
> algo=neonx4 ndisks=96 iterations=200000 time=9.783s MB/s=7507.01
> algo=svex4 ndisks=96 iterations=200000 time=4.701s MB/s=15621.17
> ==================================================
>
^ permalink raw reply
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
From: Lucas Stach @ 2026-03-30 16:44 UTC (permalink / raw)
To: Paul Kocialkowski, Krzysztof Hałasa
Cc: Liu Ying, Maxime Ripard, Marco Felsch, Marek Vasut, Stefan Agner,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel
In-Reply-To: <acqgO5b8_1fL9t_U@shepard>
Hi Paul,
Am Montag, dem 30.03.2026 um 18:09 +0200 schrieb Paul Kocialkowski:
> Hi folks,
>
> On Wed 25 Mar 26, 13:40, Krzysztof Hałasa wrote:
> > Why did the first (boot) sequence result in success and this second one
> > in failure? This is somehow reproducible.
>
> I've been seeing the same issue that is described in this thread when driving
> a regular 1080p@60 monitor, which shows a solid color background with a pixel
> from the previous frame when reconfiguring the mode from time to time.
>
> When that happens, I see the lcdif fifo underrun/empty status until a new mode
> is applied, which often resolves the situation. This situation never happens
> with the downstream nxp bsp driver.
>
> After weeks of investigation I finally narrowed it down to a part of the nxp
> original code that is missing in the upstream driver:
> https://github.com/phytec/linux-phytec-imx/blob/v6.6.23-2.0.0-phy/drivers/gpu/imx/lcdifv3/lcdifv3-common.c#L492
>
Thanks for tracking this down! It was also on my list of things to look
at.
> A big old sleep that waits for the DMA engine to finish handling the current
> frame before it is disabled. When this delay is not respected, there seems to
> be "unlucky" times when disabling the DMA engine too early will confuse the
> unit and make it unable to resume proper operation later.
>
I think we can be a bit more clever than a indiscriminate sleep. If we
set the shadow load enable bit in the disable sequence, we should be
able to wait for this bit to be cleared by the hardware. All the DMA
parameters (presumably including the enable state) should be applied by
the hardware when this bit is cleared.
I guess the read_poll_timeout in lcdif_disable_controller() was
supposed to do exactly that wait, but as it was actually copied from
the mxsfb driver, it's not working as intended. It's my understanding
that the old lcdif HW only cleared the enable bit once it is actually
done, but on the lcdifv3 on i.MX8MP those states are double buffered,
so the bit in the register would be cleared instantaneously, rendering
the wait in the current code a no-op. The only reliable indicator to
see if the HW has updated it's internal state is to set the shadow load
enable bit and wait for it to be cleared.
> It is a bit surprising that the issue is not actually related to configuring
> the display engine but to disabling it. This is why the first mode set always
> works but subsequentil ones might fail. The crtc is essentially disabled and
> re-enabled each time a new mode is applied.
>
> Adding the sleep solves the issue on my side and all mode sets now work
> reliably. It does add a delay before returning to userspace when configuring
> a new mode, but it seems legitimate to me if the underlying hardware is still
> in-flight. I'm also unsure if it would apply to an async atomic commit.
>
This hardware doesn't support async commits. All DMA state changes are
applied during vblank when the shadow load enable bit is set.
Regards,
Lucas
> I will send a patch adding the delay and the undocumented fifo clear
> bit that was discovered in this thread too.
>
> All the best,
>
> Paul
>
> Perhaps there is a more elegant way to handle this
>
>
> > Interestingly, Weston usually starts fine in subsequent launches.
> >
> > How is this first (actually second - after the first VSYNC) frame
> > different from all the others? Maybe we're programming UPDATE_SHADOW
> > after the actual start of blanking period, but before DE, so it has no
> > chance to reload registers, yet the DMA is somehow not ready?
> >
> > The manual (LCDIF display control Register (CTRL)) suggests that the DMA
> > (with present settings) starts to fetch FB data at the end of the
> > previous active video pixel time (DE and pixel data going inactive):
> > fetch_start_option (bits 9-8): Indicates when to start fetching for new
> > frame. This signals also decide the shadow load, fifo clear time
> > 00b - fetch start as soon as FPV begins(as the end of the data_enable).
> >
> > This should leave a lot of time to fill the FIFO (before the next DE),
> > shouldn't it?
> >
> > 297 MHz pixclk, 3840x2160, 30 Hz, H back porch 296 pixclks, Vfp 176,
> > V back porch 72 lines, Hfp 8 lines, VSYNC 10 lines, HSYNC 88 pixclks.
> > HTotal = 4400 pixels which makes Vactive time = 4400 * 2160/297e6 =
> > 32 ms, with the remaining 1.3333 ms for all the V sync stuff.
> > --
> > Krzysztof "Chris" Hałasa
> >
> > Sieć Badawcza Łukasiewicz
> > Przemysłowy Instytut Automatyki i Pomiarów PIAP
> > Al. Jerozolimskie 202, 02-486 Warszawa
>
^ permalink raw reply
* Re: [PATCH] media: cedrus: skip invalid H.264 reference list entries
From: Chen-Yu Tsai @ 2026-03-30 16:45 UTC (permalink / raw)
To: Nicolas Dufresne
Cc: Jernej Škrabec, mripard, Pengpeng Hou, paulk, mchehab,
gregkh, samuel, linux-media, linux-staging, linux-arm-kernel,
linux-sunxi, linux-kernel
In-Reply-To: <603785eb48d69bc50c0296fc696eb0985c2a3ac5.camel@collabora.com>
On Mon, Mar 30, 2026 at 11:55 PM Nicolas Dufresne
<nicolas.dufresne@collabora.com> wrote:
>
> Le dimanche 29 mars 2026 à 20:44 +0800, Chen-Yu Tsai a écrit :
> > On Sun, Mar 29, 2026 at 5:21 PM Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
> > >
> > > Dne torek, 24. marec 2026 ob 09:08:56 Srednjeevropski poletni čas je Pengpeng Hou napisal(a):
> > > > Cedrus consumes H.264 ref_pic_list0/ref_pic_list1 entries from the
> > > > stateless slice control and later uses their indices to look up
> > > > decode->dpb[] in _cedrus_write_ref_list().
> > > >
> > > > Rejecting such controls in cedrus_try_ctrl() would break existing
> > > > userspace, since stateless H.264 reference lists may legitimately carry
> > > > out-of-range indices for missing references. Instead, guard the actual
> > > > DPB lookup in Cedrus and skip entries whose indices do not fit the fixed
> > > > V4L2_H264_NUM_DPB_ENTRIES array.
> > > >
> > > > This keeps the fix local to the driver use site and avoids out-of-bounds
> > > > reads from malformed or unsupported reference list entries.
> > > >
> > > > Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> > >
> > > Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> >
> > Tested-by: Chen-Yu Tsai <wens@kernel.org>
> >
> > This fixes a KASAN slab-use-after-free warning when running fluster H.264
> > tests.
>
> Ah, very good, can you cite which test caused that ? I didn't expect fluster to
> cover cases with missing references. I think it will be handy for future
> testing.
Looks like it is FM1_BT_B. And it only happens on the first run after reboot,
or KASAN just only reports it once.
BTW, this would be a lot easier to figure out if we could get fluster to
output a system timestamp for each decode run (at least in single job mode).
I had to hack in delays between each decode rune, and then look at `dmesg -w`
and switching back to the window that has fluster running once the warning
triggers.
ChenYu
^ permalink raw reply
* Re: [PATCH RESEND v4 4/4] drm/rockchip: dw_hdmi_qp: Do not send HPD events for all connectors
From: Heiko Stuebner @ 2026-03-30 16:56 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Sandy Huang,
Andy Yan, Cristian Ciocaltea
Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip,
Diederik de Haas, Maud Spierings
In-Reply-To: <20260323-dw-hdmi-qp-scramb-v4-4-1d99df84883e@collabora.com>
Am Montag, 23. März 2026, 18:45:30 Mitteleuropäische Sommerzeit schrieb Cristian Ciocaltea:
> In order to optimize the HPD event handling and run the detect cycle on
> the affected connector only, make use of
> drm_connector_helper_hpd_irq_event() instead of
> drm_helper_hpd_irq_event().
>
> Additionally, move devm_request_threaded_irq() after bridge connector
> initialization.
nit: Using "and", "additionally", etc in commit messages, is a strong
indicator, things should be separate commits.
Especially as the sentence above just explains the "what" but not the
why (interrupt firing, before the device is actually there probably).
If there are no other changes requested, they can stay together though,
the "why" is somewhat obvious here.
Both changes themself look fine, so
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
> Tested-by: Diederik de Haas <diederik@cknow-tech.com>
> Tested-by: Maud Spierings <maud_spierings@hotmail.com>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
> ---
> drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 44 ++++++++++++--------------
> 1 file changed, 20 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
> index 1a09bcc96c3e..65dfaee15178 100644
> --- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
> @@ -92,6 +92,7 @@ struct rockchip_hdmi_qp {
> struct regmap *regmap;
> struct regmap *vo_regmap;
> struct rockchip_encoder encoder;
> + struct drm_connector *connector;
> struct dw_hdmi_qp *hdmi;
> struct phy *phy;
> struct gpio_desc *frl_enable_gpio;
> @@ -251,14 +252,10 @@ static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work)
> struct rockchip_hdmi_qp *hdmi = container_of(work,
> struct rockchip_hdmi_qp,
> hpd_work.work);
> - struct drm_device *drm = hdmi->encoder.encoder.dev;
> - bool changed;
> + bool changed = drm_connector_helper_hpd_irq_event(hdmi->connector);
>
> - if (drm) {
> - changed = drm_helper_hpd_irq_event(drm);
> - if (changed)
> - dev_dbg(hdmi->dev, "connector status changed\n");
> - }
> + if (changed)
> + dev_dbg(hdmi->dev, "connector status changed\n");
> }
>
> static irqreturn_t dw_hdmi_qp_rk3576_hardirq(int irq, void *dev_id)
> @@ -466,13 +463,12 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
> struct dw_hdmi_qp_plat_data plat_data = {};
> const struct rockchip_hdmi_qp_cfg *cfg;
> struct drm_device *drm = data;
> - struct drm_connector *connector;
> struct drm_encoder *encoder;
> struct rockchip_hdmi_qp *hdmi;
> struct resource *res;
> struct clk_bulk_data *clks;
> struct clk *ref_clk;
> - int ret, irq, i;
> + int ret, hpd_irq, i;
>
> if (!pdev->dev.of_node)
> return -ENODEV;
> @@ -573,17 +569,9 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
> if (plat_data.cec_irq < 0)
> return plat_data.cec_irq;
>
> - irq = platform_get_irq_byname(pdev, "hpd");
> - if (irq < 0)
> - return irq;
> -
> - ret = devm_request_threaded_irq(hdmi->dev, irq,
> - cfg->ctrl_ops->hardirq_callback,
> - cfg->ctrl_ops->irq_callback,
> - IRQF_SHARED, "dw-hdmi-qp-hpd",
> - hdmi);
> - if (ret)
> - return ret;
> + hpd_irq = platform_get_irq_byname(pdev, "hpd");
> + if (hpd_irq < 0)
> + return hpd_irq;
>
> drm_encoder_helper_add(encoder, &dw_hdmi_qp_rockchip_encoder_helper_funcs);
> drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
> @@ -597,12 +585,20 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
> "Failed to bind dw-hdmi-qp");
> }
>
> - connector = drm_bridge_connector_init(drm, encoder);
> - if (IS_ERR(connector))
> - return dev_err_probe(hdmi->dev, PTR_ERR(connector),
> + hdmi->connector = drm_bridge_connector_init(drm, encoder);
> + if (IS_ERR(hdmi->connector))
> + return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->connector),
> "Failed to init bridge connector\n");
>
> - return drm_connector_attach_encoder(connector, encoder);
> + ret = drm_connector_attach_encoder(hdmi->connector, encoder);
> + if (ret)
> + return ret;
> +
> + return devm_request_threaded_irq(hdmi->dev, hpd_irq,
> + cfg->ctrl_ops->hardirq_callback,
> + cfg->ctrl_ops->irq_callback,
> + IRQF_SHARED, "dw-hdmi-qp-hpd",
> + hdmi);
> }
>
> static void dw_hdmi_qp_rockchip_unbind(struct device *dev,
>
>
^ permalink raw reply
* Re: [GIT PULL] arm64: dts: socfpga: updates for v7.1
From: Krzysztof Kozlowski @ 2026-03-30 16:57 UTC (permalink / raw)
To: Dinh Nguyen, linux-arm-kernel, soc
In-Reply-To: <20260330112844.240664-1-dinguyen@kernel.org>
On 30/03/2026 13:28, Dinh Nguyen wrote:
> The following changes since commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f:
>
> Linux 7.0-rc1 (2026-02-22 13:18:59 -0800)
>
> are available in the Git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git tags/socfpga_updates_for_v7.1
>
> for you to fetch changes up to 9d29bcefcdbec4498fe0539e6d8a4e7962d92489:
>
> arm64: dts: intel: agilex5: Drop CPU masks from GICv3 PPI interrupts (2026-03-10 21:10:05 -0500)
>
> ----------------------------------------------------------------
> SoCFPGA DTS updates for v7.1
> - dt-bindings updates:
> - Document fallback compatible for Stratix10 SoCDK eMMC board
> - Document compatible for the Agilex5 SoCFPGA modular board
>
> - Add emmc support for the Stratix10
> - Drop CPU masks from the GICv3 PPI interrupts for Agilex5
>
> ----------------------------------------------------------------
> Dinh Nguyen (1):
> dt-bindings: intel: Add Agilex5 SoCFPGA modular board
Your commit does not end with SoB. Intentional changelog in the patch
commit is fine if it follows standard commit rules, but here it does not
and also --- separator means changelog was not intentional.
Please use b4 to apply patches.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 00/15] KVM: arm64: First batch of vgic-v5 related fixes
From: Mark Brown @ 2026-03-30 17:05 UTC (permalink / raw)
To: Marc Zyngier
Cc: kvmarm, kvm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Oliver Upton, Zenghui Yu, Sascha Bischoff
In-Reply-To: <20260326153530.3981879-1-maz@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 464 bytes --]
On Thu, Mar 26, 2026 at 03:35:15PM +0000, Marc Zyngier wrote:
> Well, merging the first batch of vgic-v5 patches didn't go smoothly at
> all. We initially found a couple of regressions, but most of the crap
> was actually uncovered by everyone's new best friend (enemy?), the AI
> bot sitting behind sashiko.dev [1].
I threw this at my CI, nothing blew up though that's not testing any
GICv5 stuff particuarly. FWIW:
Tested-by: Mark Brown <broonie@kernel..org>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH] media: cedrus: skip invalid H.264 reference list entries
From: Nicolas Dufresne @ 2026-03-30 17:25 UTC (permalink / raw)
To: wens
Cc: Jernej Škrabec, mripard, Pengpeng Hou, paulk, mchehab,
gregkh, samuel, linux-media, linux-staging, linux-arm-kernel,
linux-sunxi, linux-kernel
In-Reply-To: <CAGb2v65EM1rZwePR2B8Y-ipz4iEJPLnd4jsfu140N9vq4GYL2Q@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2861 bytes --]
Le mardi 31 mars 2026 à 00:45 +0800, Chen-Yu Tsai a écrit :
> On Mon, Mar 30, 2026 at 11:55 PM Nicolas Dufresne
> <nicolas.dufresne@collabora.com> wrote:
> >
> > Le dimanche 29 mars 2026 à 20:44 +0800, Chen-Yu Tsai a écrit :
> > > On Sun, Mar 29, 2026 at 5:21 PM Jernej Škrabec <jernej.skrabec@gmail.com> wrote:
> > > >
> > > > Dne torek, 24. marec 2026 ob 09:08:56 Srednjeevropski poletni čas je Pengpeng Hou napisal(a):
> > > > > Cedrus consumes H.264 ref_pic_list0/ref_pic_list1 entries from the
> > > > > stateless slice control and later uses their indices to look up
> > > > > decode->dpb[] in _cedrus_write_ref_list().
> > > > >
> > > > > Rejecting such controls in cedrus_try_ctrl() would break existing
> > > > > userspace, since stateless H.264 reference lists may legitimately carry
> > > > > out-of-range indices for missing references. Instead, guard the actual
> > > > > DPB lookup in Cedrus and skip entries whose indices do not fit the fixed
> > > > > V4L2_H264_NUM_DPB_ENTRIES array.
> > > > >
> > > > > This keeps the fix local to the driver use site and avoids out-of-bounds
> > > > > reads from malformed or unsupported reference list entries.
> > > > >
> > > > > Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> > > >
> > > > Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> > >
> > > Tested-by: Chen-Yu Tsai <wens@kernel.org>
> > >
> > > This fixes a KASAN slab-use-after-free warning when running fluster H.264
> > > tests.
> >
> > Ah, very good, can you cite which test caused that ? I didn't expect fluster to
> > cover cases with missing references. I think it will be handy for future
> > testing.
>
> Looks like it is FM1_BT_B. And it only happens on the first run after reboot,
> or KASAN just only reports it once.
Thanks, its one of the unsupported stream that we didn't find how to detect
ahead of time, and so we try to decode it.
>
> BTW, this would be a lot easier to figure out if we could get fluster to
> output a system timestamp for each decode run (at least in single job mode).
Well, that's not magical, they have to trace the same timestamp. An example, the
kernel and gstreamer both uses their own uptime, which is of course not helping
it at all.
>
> I had to hack in delays between each decode rune, and then look at `dmesg -w`
> and switching back to the window that has fluster running once the warning
> triggers.
If all you care is which streams caused what kernel trace, I think the least
amount of effort is to propose a patch against fluster to syslog the start of
tests. Your logger will aggregate. Note that its only going to work for single
job run since the kernel error trace don't give enough context to trace back the
error into the V4L2 FD and back to the owning process.
Nicolas
>
>
> ChenYu
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v8 1/3] drm/v3d: Use devm_reset_control_get_optional_exclusive()
From: Florian Fainelli @ 2026-03-30 18:43 UTC (permalink / raw)
To: Maíra Canal, Stefan Wahren, Maxime Ripard, Melissa Wen,
Iago Toral Quiroga, Dave Stevenson
Cc: dri-devel, linux-rpi-kernel, linux-arm-kernel,
Broadcom internal kernel review list, kernel-dev, Philipp Zabel
In-Reply-To: <20260328-v3d-power-management-v8-1-94336830df5f@igalia.com>
On 3/28/26 11:52, Maíra Canal wrote:
> Simplify optional reset handling by using the function
> devm_reset_control_get_optional_exclusive().
>
> Reviewed-by: Melissa Wen <mwen@igalia.com>
> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
--
Florian
^ permalink raw reply
* Re: [PATCH v8 2/3] drm/v3d: Allocate all resources before enabling the clock
From: Florian Fainelli @ 2026-03-30 18:44 UTC (permalink / raw)
To: Maíra Canal, Stefan Wahren, Maxime Ripard, Melissa Wen,
Iago Toral Quiroga, Dave Stevenson
Cc: dri-devel, linux-rpi-kernel, linux-arm-kernel,
Broadcom internal kernel review list, kernel-dev
In-Reply-To: <20260328-v3d-power-management-v8-2-94336830df5f@igalia.com>
On 3/28/26 11:52, Maíra Canal wrote:
> Move all resource allocation operations before actually enabling the
> clock, as those operations don't require the GPU to be powered on.
>
> This is a preparation for runtime PM support. The next commit will
> move all code related to powering on and initiating the GPU into the
> runtime PM resume callback and all resource allocation will happen
> before resume().
>
> Reviewed-by: Melissa Wen <mwen@igalia.com>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
--
Florian
^ permalink raw reply
* Re: [PATCH v8 3/3] drm/v3d: Introduce Runtime Power Management
From: Florian Fainelli @ 2026-03-30 18:46 UTC (permalink / raw)
To: Maíra Canal, Stefan Wahren, Maxime Ripard, Melissa Wen,
Iago Toral Quiroga, Dave Stevenson
Cc: dri-devel, linux-rpi-kernel, linux-arm-kernel,
Broadcom internal kernel review list, kernel-dev
In-Reply-To: <20260328-v3d-power-management-v8-3-94336830df5f@igalia.com>
On 3/28/26 11:52, Maíra Canal wrote:
> Commit 90a64adb0876 ("drm/v3d: Get rid of pm code") removed the last
> bits of power management code that V3D had, which were actually never
> hooked. Therefore, currently, the GPU clock is enabled during probe
> and only disabled when removing the driver.
>
> Implement proper power management using the kernel's Runtime PM
> framework.
>
> Reviewed-by: Melissa Wen <mwen@igalia.com>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
> ---
[snip]
> +static void
> +v3d_suspend_sms(struct v3d_dev *v3d)
> +{
> + if (v3d->ver < V3D_GEN_71)
> + return;
> +
> + V3D_SMS_WRITE(V3D_SMS_TEE_CS, V3D_SMS_POWER_OFF);
> +
> + if (wait_for((V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_TEE_CS),
> + V3D_SMS_STATE) == V3D_SMS_POWER_OFF_STATE), 100)) {
> + drm_err(&v3d->drm, "Failed to power off SMS\n");
> + }
We would certainly want to propagate any errors from wait_for() here to
ensure that we built appropriately timeout and get a chance at debugging.
Same for v3d_resume_sms().
--
Florian
^ 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