* Re: [PATCH v7 18/28] media: rockchip: rga: use card type to specify rga type
From: Michael Tretter @ 2026-05-21 14:28 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-18-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:23 +0200, Sven Püschel wrote:
> In preparation of the RGA3 support add a filed to the rga_hw struct
*field
> to specify the desired card type value. This allows the user to
> differentiate the RGA2 and RGA3 video device nodes.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga-hw.c | 1 +
> drivers/media/platform/rockchip/rga/rga.c | 4 +++-
> drivers/media/platform/rockchip/rga/rga.h | 1 +
> 3 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
> index f2900812ba76f..43fd023b7571c 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -577,6 +577,7 @@ static struct rga_fmt formats[] = {
> };
>
> const struct rga_hw rga2_hw = {
> + .card_type = "rga2",
This changes the card type from "rockchip-rga" to "rga2", which is a
user space visible change and may break user space. Is this acceptable
or even intentional?
Michael
> .formats = formats,
> .num_formats = ARRAY_SIZE(formats),
> .cmdbuf_size = RGA_CMDBUF_SIZE,
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index 22954bbae55fc..91775b43ff617 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -354,8 +354,10 @@ static const struct v4l2_file_operations rga_fops = {
> static int
> vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
> {
> + struct rockchip_rga *rga = video_drvdata(file);
> +
> strscpy(cap->driver, RGA_NAME, sizeof(cap->driver));
> - strscpy(cap->card, "rockchip-rga", sizeof(cap->card));
> + strscpy(cap->card, rga->hw->card_type, sizeof(cap->card));
> strscpy(cap->bus_info, "platform:rga", sizeof(cap->bus_info));
>
> return 0;
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index df525c6aea8b6..cee2e75ea89f1 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -149,6 +149,7 @@ static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
> };
>
> struct rga_hw {
> + const char *card_type;
> struct rga_fmt *formats;
> u32 num_formats;
> size_t cmdbuf_size;
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH v14 08/44] arm64: RMI: Ensure that the RMM has GPT entries for memory
From: Marc Zyngier @ 2026-05-21 14:24 UTC (permalink / raw)
To: Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <868q9cx4ac.wl-maz@kernel.org>
On Thu, 21 May 2026 14:47:55 +0100,
Marc Zyngier <maz@kernel.org> wrote:
>
> On Wed, 13 May 2026 14:17:16 +0100,
> Steven Price <steven.price@arm.com> wrote:
> >
> > +/*
> > + * For now we set the tracking_region_size to 0 for RMI_RMM_CONFIG_SET().
> > + * TODO: Support other tracking sizes (via Kconfig option).
> > + */
> > +#ifdef CONFIG_PAGE_SIZE_4KB
> > +#define RMM_GRANULE_TRACKING_SIZE SZ_1G
> > +#elif defined(CONFIG_PAGE_SIZE_16KB)
> > +#define RMM_GRANULE_TRACKING_SIZE SZ_32M
> > +#elif defined(CONFIG_PAGE_SIZE_64KB)
> > +#define RMM_GRANULE_TRACKING_SIZE SZ_512M
> > +#endif
>
> Basically, a level 2 mapping. Which means this whole block really is:
>
> #define RMM_GRANULE_TRAKING_SIZE (2 * PAGE_SHIFT - 3)
Obviously wrong:
#define RMM_GRANULE_TRAKING_SIZE BIT(2 * PAGE_SHIFT - 3)
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH 18/43] KVM: arm64: gic-v5: Define remaining IRS MMIO registers
From: Sascha Bischoff @ 2026-05-21 14:22 UTC (permalink / raw)
To: maz@kernel.org
Cc: yuzenghui@huawei.com, Timothy Hayes, Suzuki Poulose, nd,
peter.maydell@linaro.org, kvmarm@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org,
Joey Gouly, lpieralisi@kernel.org, oliver.upton@linux.dev
In-Reply-To: <86pl37xnl8.wl-maz@kernel.org>
On Thu, 2026-05-07 at 16:10 +0100, Marc Zyngier wrote:
> On Mon, 27 Apr 2026 17:12:11 +0100,
> Sascha Bischoff <Sascha.Bischoff@arm.com> wrote:
> >
> > Complete the set of defined IRS MMIO registers in the GICv5 header
> > file. Up until now, the set of defined IRS MMIO registers has been
> > driven by code requirements. However, in order to properly emulate
> > the
> > IRS MMIO interface in KVM, the complete set of IRS MMIO registers
> > needs to be added.
>
> I really think you need to pick a register update "style". Either you
> add all the definitions in one go, or you add them with the patch
> that
> start making use of it.
>
> My preference goes with the former.
I've gone with the former. In my new series, this is one of the first
changes, and I've consolidated the addition of GICv5 register
definitions there.
>
> >
> > Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> > ---
> > include/linux/irqchip/arm-gic-v5.h | 105
> > ++++++++++++++++++++++++++---
> > 1 file changed, 96 insertions(+), 9 deletions(-)
> >
> > diff --git a/include/linux/irqchip/arm-gic-v5.h
> > b/include/linux/irqchip/arm-gic-v5.h
> > index 54b573783cd75..9ea3674a6613b 100644
> > --- a/include/linux/irqchip/arm-gic-v5.h
> > +++ b/include/linux/irqchip/arm-gic-v5.h
> > @@ -62,6 +62,14 @@
> > #define GICV5_OUTER_SHARE 0b10
> > #define GICV5_INNER_SHARE 0b11
> >
> > +#define GICV5_AIDR_COMPONENT_IRS 0b00
> > +#define GICV5_AIDR_COMPONENT_ITS 0b01
> > +#define GICV5_AIDR_COMPONENT_IWB 0b10
> > +
> > +#define GICV5_AIDR_ARCH_MAJ_REV_V5 0
> > +#define GICV5_AIDR_ARCH_MIN_REV_V0 0
> > +#define GICV5_IIDR_IMPLEMENTER_ARM 0x43b
> > +
>
> I'm in two minds about this. We used the same hack (advertising this
> as an ARM implementation) for GICv2/v3, but that's really not one.
>
> And in any case, the ARM encoding should not leave in this file -- it
> is only used for the KVM implementation, and everything else should
> be
> implementation agnostic (until we need to implement a workaround, of
> course...).
This was actually stale - the IRS MMIO code used KVM's existing
definition, and I'd just failed to drop this from the header. Aside
from that, I've left things as they are for the time being.
Thanks,
Sascha
>
> Thanks,
>
> M.
>
^ permalink raw reply
* Re: [PATCH v7 15/28] media: rockchip: rga: align stride to 4 bytes
From: Michael Tretter @ 2026-05-21 14:22 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-15-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:20 +0200, Sven Püschel wrote:
> Add an alignment setting to rga_hw to set the desired stride alignment.
> As the RGA2 register for the stride counts in word units, the code
> already divides the bytesperline value by 4 when writing it into the
> register. Therefore fix the alignment to a multiple of 4 to avoid
> potential off by one errors due from the division.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
Reviewed-by: Michael Tretter <m.tretter@pengutronix.de>
>
> ---
> Changed in v6:
> - Drop unintended change from fmt->fourcc to pix_fmt->pixelformat
> Flagged by Sashiko:
> https://sashiko.dev/#/patchset/20260428-spu-rga3-v5-0-eb7f5d019d86%40pengutronix.de?part=15
> ---
> drivers/media/platform/rockchip/rga/rga-hw.c | 1 +
> drivers/media/platform/rockchip/rga/rga.c | 11 ++++++-----
> drivers/media/platform/rockchip/rga/rga.h | 1 +
> 3 files changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
> index 9881c14f908d5..dac3cb6aa17d3 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -580,6 +580,7 @@ const struct rga_hw rga2_hw = {
> .max_width = MAX_WIDTH,
> .min_height = MIN_HEIGHT,
> .max_height = MAX_HEIGHT,
> + .stride_alignment = 4,
>
> .start = rga_hw_start,
> .handle_irq = rga_handle_irq,
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index bf6bbcbfc869b..d080cb672740b 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -234,10 +234,10 @@ static int rga_open(struct file *file)
> ctx->in = def_frame;
> ctx->out = def_frame;
>
> - v4l2_fill_pixfmt_mp(&ctx->in.pix,
> - ctx->in.fmt->fourcc, def_width, def_height);
> - v4l2_fill_pixfmt_mp(&ctx->out.pix,
> - ctx->out.fmt->fourcc, def_width, def_height);
> + v4l2_fill_pixfmt_mp_aligned(&ctx->in.pix, ctx->in.fmt->fourcc,
> + def_width, def_height, rga->hw->stride_alignment);
> + v4l2_fill_pixfmt_mp_aligned(&ctx->out.pix, ctx->out.fmt->fourcc,
> + def_width, def_height, rga->hw->stride_alignment);
>
> if (mutex_lock_interruptible(&rga->mutex)) {
> ret = -ERESTARTSYS;
> @@ -393,7 +393,8 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
> fmt = &hw->formats[0];
>
> v4l2_apply_frmsize_constraints(&pix_fmt->width, &pix_fmt->height, &frmsize);
> - v4l2_fill_pixfmt_mp(pix_fmt, fmt->fourcc, pix_fmt->width, pix_fmt->height);
> + v4l2_fill_pixfmt_mp_aligned(pix_fmt, fmt->fourcc,
> + pix_fmt->width, pix_fmt->height, hw->stride_alignment);
> pix_fmt->field = V4L2_FIELD_NONE;
>
> return 0;
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index 04aeb7b429523..38518146910a6 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -150,6 +150,7 @@ struct rga_hw {
> size_t cmdbuf_size;
> u32 min_width, min_height;
> u32 max_width, max_height;
> + u8 stride_alignment;
>
> void (*start)(struct rockchip_rga *rga,
> struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
>
> --
> 2.54.0
>
>
--
Pengutronix e.K. | Michael Tretter |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* Re: [PATCH v7 14/28] media: rockchip: rga: move cmdbuf to rga_ctx
From: Michael Tretter @ 2026-05-21 14:20 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-14-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:19 +0200, Sven Püschel wrote:
> Move the command buffer to the rga_ctx struct in preparation to reuse
> an already prepared command buffer. This allows to split the command
> buffer setup in a further commit to setup a template for the command
> buffer at streamon and only update the buffer addresses in device_run
> and trigger the command stream. No sync point is added, as one command
> buffer should only be used for one conversion at a time.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
Reviewed-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga-hw.c | 28 +++++++---------
> drivers/media/platform/rockchip/rga/rga.c | 48 ++++++++++++++++------------
> drivers/media/platform/rockchip/rga/rga.h | 5 +--
> 3 files changed, 41 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
> index 17f7a67c0b4bb..9881c14f908d5 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -122,8 +122,7 @@ static struct rga_addr_offset *rga_lookup_draw_pos(struct
>
> static void rga_cmd_set_src_addr(struct rga_ctx *ctx, dma_addr_t dma_addr)
> {
> - struct rockchip_rga *rga = ctx->rga;
> - u32 *dest = rga->cmdbuf_virt;
> + u32 *dest = ctx->cmdbuf_virt;
> unsigned int reg;
>
> reg = RGA_MMU_SRC_BASE - RGA_MODE_BASE_REG;
> @@ -135,8 +134,7 @@ static void rga_cmd_set_src_addr(struct rga_ctx *ctx, dma_addr_t dma_addr)
>
> static void rga_cmd_set_src1_addr(struct rga_ctx *ctx, dma_addr_t dma_addr)
> {
> - struct rockchip_rga *rga = ctx->rga;
> - u32 *dest = rga->cmdbuf_virt;
> + u32 *dest = ctx->cmdbuf_virt;
> unsigned int reg;
>
> reg = RGA_MMU_SRC1_BASE - RGA_MODE_BASE_REG;
> @@ -148,8 +146,7 @@ static void rga_cmd_set_src1_addr(struct rga_ctx *ctx, dma_addr_t dma_addr)
>
> static void rga_cmd_set_dst_addr(struct rga_ctx *ctx, dma_addr_t dma_addr)
> {
> - struct rockchip_rga *rga = ctx->rga;
> - u32 *dest = rga->cmdbuf_virt;
> + u32 *dest = ctx->cmdbuf_virt;
> unsigned int reg;
>
> reg = RGA_MMU_DST_BASE - RGA_MODE_BASE_REG;
> @@ -162,7 +159,7 @@ static void rga_cmd_set_dst_addr(struct rga_ctx *ctx, dma_addr_t dma_addr)
> static void rga_cmd_set_trans_info(struct rga_ctx *ctx)
> {
> struct rockchip_rga *rga = ctx->rga;
> - u32 *dest = rga->cmdbuf_virt;
> + u32 *dest = ctx->cmdbuf_virt;
> unsigned int scale_dst_w, scale_dst_h;
> unsigned int src_h, src_w, dst_h, dst_w;
> union rga_src_info src_info;
> @@ -322,8 +319,7 @@ static void rga_cmd_set_src_info(struct rga_ctx *ctx,
> struct rga_addr_offset *offset)
> {
> struct rga_corners_addr_offset src_offsets;
> - struct rockchip_rga *rga = ctx->rga;
> - u32 *dest = rga->cmdbuf_virt;
> + u32 *dest = ctx->cmdbuf_virt;
> unsigned int src_h, src_w, src_x, src_y;
>
> src_h = ctx->in.crop.height;
> @@ -350,8 +346,7 @@ static void rga_cmd_set_dst_info(struct rga_ctx *ctx,
> {
> struct rga_addr_offset *dst_offset;
> struct rga_corners_addr_offset offsets;
> - struct rockchip_rga *rga = ctx->rga;
> - u32 *dest = rga->cmdbuf_virt;
> + u32 *dest = ctx->cmdbuf_virt;
> unsigned int dst_h, dst_w, dst_x, dst_y;
> unsigned int mir_mode = 0;
> unsigned int rot_mode = 0;
> @@ -397,8 +392,7 @@ static void rga_cmd_set_dst_info(struct rga_ctx *ctx,
>
> static void rga_cmd_set_mode(struct rga_ctx *ctx)
> {
> - struct rockchip_rga *rga = ctx->rga;
> - u32 *dest = rga->cmdbuf_virt;
> + u32 *dest = ctx->cmdbuf_virt;
> union rga_mode_ctrl mode;
> union rga_alpha_ctrl0 alpha_ctrl0;
> union rga_alpha_ctrl1 alpha_ctrl1;
> @@ -423,7 +417,7 @@ static void rga_cmd_set(struct rga_ctx *ctx,
> {
> struct rockchip_rga *rga = ctx->rga;
>
> - memset(rga->cmdbuf_virt, 0, RGA_CMDBUF_SIZE);
> + memset(ctx->cmdbuf_virt, 0, RGA_CMDBUF_SIZE);
>
> rga_cmd_set_src_addr(ctx, src->dma_desc_pa);
> /*
> @@ -439,11 +433,11 @@ static void rga_cmd_set(struct rga_ctx *ctx,
> rga_cmd_set_dst_info(ctx, &dst->offset);
> rga_cmd_set_trans_info(ctx);
>
> - rga_write(rga, RGA_CMD_BASE, rga->cmdbuf_phy);
> + rga_write(rga, RGA_CMD_BASE, ctx->cmdbuf_phy);
>
> /* sync CMD buf for RGA */
> - dma_sync_single_for_device(rga->dev, rga->cmdbuf_phy,
> - PAGE_SIZE, DMA_BIDIRECTIONAL);
> + dma_sync_single_for_device(rga->dev, ctx->cmdbuf_phy,
> + PAGE_SIZE, DMA_BIDIRECTIONAL);
> }
>
> static void rga_hw_start(struct rockchip_rga *rga,
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index 77b8c7ab74274..bf6bbcbfc869b 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -219,6 +219,16 @@ static int rga_open(struct file *file)
> ctx = kzalloc_obj(*ctx);
> if (!ctx)
> return -ENOMEM;
> +
> + /* Create CMD buffer */
> + ctx->cmdbuf_virt = dma_alloc_attrs(rga->dev, rga->hw->cmdbuf_size,
> + &ctx->cmdbuf_phy, GFP_KERNEL,
> + DMA_ATTR_WRITE_COMBINE);
> + if (!ctx->cmdbuf_virt) {
> + ret = -ENOMEM;
> + goto rel_ctx;
> + }
> +
> ctx->rga = rga;
> /* Set default formats */
> ctx->in = def_frame;
> @@ -230,15 +240,13 @@ static int rga_open(struct file *file)
> ctx->out.fmt->fourcc, def_width, def_height);
>
> if (mutex_lock_interruptible(&rga->mutex)) {
> - kfree(ctx);
> - return -ERESTARTSYS;
> + ret = -ERESTARTSYS;
> + goto rel_cmdbuf;
> }
> ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(rga->m2m_dev, ctx, &queue_init);
> if (IS_ERR(ctx->fh.m2m_ctx)) {
> ret = PTR_ERR(ctx->fh.m2m_ctx);
> - mutex_unlock(&rga->mutex);
> - kfree(ctx);
> - return ret;
> + goto unlock_mutex;
> }
> v4l2_fh_init(&ctx->fh, video_devdata(file));
> v4l2_fh_add(&ctx->fh, file);
> @@ -252,6 +260,15 @@ static int rga_open(struct file *file)
> mutex_unlock(&rga->mutex);
>
> return 0;
> +
> +unlock_mutex:
> + mutex_unlock(&rga->mutex);
> +rel_cmdbuf:
> + dma_free_attrs(rga->dev, rga->hw->cmdbuf_size, ctx->cmdbuf_virt,
> + ctx->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
> +rel_ctx:
> + kfree(ctx);
> + return ret;
> }
>
> static int rga_release(struct file *file)
> @@ -266,6 +283,10 @@ static int rga_release(struct file *file)
> v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> v4l2_fh_del(&ctx->fh, file);
> v4l2_fh_exit(&ctx->fh);
> +
> + dma_free_attrs(rga->dev, rga->hw->cmdbuf_size, ctx->cmdbuf_virt,
> + ctx->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
> +
> kfree(ctx);
>
> mutex_unlock(&rga->mutex);
> @@ -720,19 +741,10 @@ static int rga_probe(struct platform_device *pdev)
>
> pm_runtime_put(rga->dev);
>
> - /* Create CMD buffer */
> - rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, rga->hw->cmdbuf_size,
> - &rga->cmdbuf_phy, GFP_KERNEL,
> - DMA_ATTR_WRITE_COMBINE);
> - if (!rga->cmdbuf_virt) {
> - ret = -ENOMEM;
> - goto rel_m2m;
> - }
> -
> ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
> if (ret) {
> v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
> - goto free_dma;
> + goto rel_m2m;
> }
>
> v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n",
> @@ -740,9 +752,6 @@ static int rga_probe(struct platform_device *pdev)
>
> return 0;
>
> -free_dma:
> - dma_free_attrs(rga->dev, rga->hw->cmdbuf_size, rga->cmdbuf_virt,
> - rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
> rel_m2m:
> v4l2_m2m_release(rga->m2m_dev);
> rel_vdev:
> @@ -759,9 +768,6 @@ static void rga_remove(struct platform_device *pdev)
> {
> struct rockchip_rga *rga = platform_get_drvdata(pdev);
>
> - dma_free_attrs(rga->dev, rga->hw->cmdbuf_size, rga->cmdbuf_virt,
> - rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
> -
> v4l2_info(&rga->v4l2_dev, "Removing\n");
>
> v4l2_m2m_release(rga->m2m_dev);
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index 27b3c9b4f220c..04aeb7b429523 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -53,6 +53,9 @@ struct rga_ctx {
> struct rga_frame out;
> struct v4l2_ctrl_handler ctrl_handler;
>
> + void *cmdbuf_virt;
> + dma_addr_t cmdbuf_phy;
> +
> int osequence;
> int csequence;
>
> @@ -89,8 +92,6 @@ struct rockchip_rga {
> spinlock_t ctrl_lock;
>
> struct rga_ctx *curr;
> - dma_addr_t cmdbuf_phy;
> - void *cmdbuf_virt;
>
> const struct rga_hw *hw;
> };
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH 17/43] KVM: arm64: gic-v5: Enable VPE DBs on VPE reset and disable on teardown
From: Sascha Bischoff @ 2026-05-21 14:17 UTC (permalink / raw)
To: maz@kernel.org
Cc: yuzenghui@huawei.com, Timothy Hayes, Suzuki Poulose, nd,
peter.maydell@linaro.org, kvmarm@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org,
Joey Gouly, lpieralisi@kernel.org, oliver.upton@linux.dev
In-Reply-To: <861pfozijq.wl-maz@kernel.org>
On Wed, 2026-05-06 at 16:03 +0100, Marc Zyngier wrote:
> On Mon, 27 Apr 2026 17:11:50 +0100,
> Sascha Bischoff <Sascha.Bischoff@arm.com> wrote:
> >
> > Ensure that each VPE doorbell is enabled on the host prior to
> > running
> > the guest by enabling it as part of vgic_v5_reset(). Add a function
> > to
> > disable it again as part of VM teardown, vgic_v5_disable_vcpu(),
> > which
> > also frees the IRQ again.
> >
> > Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> > ---
> > arch/arm64/kvm/vgic/vgic-v5.c | 29 +++++++++++++++++++++++++++++
> > 1 file changed, 29 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/vgic/vgic-v5.c
> > b/arch/arm64/kvm/vgic/vgic-v5.c
> > index 9347bc6895223..48ffcb2494db3 100644
> > --- a/arch/arm64/kvm/vgic/vgic-v5.c
> > +++ b/arch/arm64/kvm/vgic/vgic-v5.c
> > @@ -736,6 +736,31 @@ void vgic_v5_reset(struct kvm_vcpu *vcpu)
> > kvm_vm_dead(vcpu->kvm);
> > return;
> > }
> > +
> > + enable_irq(vgic_v5_vpe_db(vcpu));
>
> Odd. Why do you need to manage the enabling of the doorbell? I see
> from the previous patch that you set it as IRQ_NOAUTOEN, but this
> seems to be cargo-culted from GICv4 (which really needs it).
>
> My expectations that since the doorbell is controlled from KVM and is
> only one-shot, we should be OK. This is the flow that v4.1 adopts,
> without a need to baby-sit the interrupt state.
I've reworked this to make most of it go away. We didn't need the
IRQ_NOAUTOEN (it was just copied from GICv4), and that means that much
of this can go away. In general, I've rolled these changes into the
ones that init and tear down GICv5 VMs in general given how tightly
coupled they are in the first place.
>
> > +}
> > +
> > +static void vgic_v5_disable_vcpu(struct kvm_vcpu *vcpu)
> > +{
> > + int virq = vgic_v5_vpe_db(vcpu);
> > +
> > + if (!vcpu->kvm->arch.vgic.gicv5_vm.domain)
> > + return;
> > +
> > + if (!virq)
> > + return;
> > +
> > + /*
> > + * We are called in the vgic_v5_teardown path. We no
> > longer need the
> > + * doorbell virqs.
> > + */
> > + disable_irq(virq);
>
> And then this can go as well.
Yup, gone.
>
> > +
> > + /* Free the doorbell irq (counter-part to request_irq)*/
> > + free_irq(virq, vcpu);
> > +
> > + /* Remove the irq from the domain too */
> > + irq_domain_free_irqs(virq, 1);
>
> Surely you remove the domain at some point. That should cover the
> freeing of all the doorbells.
Again, I've reworked and consolidated this.
>
> > }
> >
> > int vgic_v5_map_resources(struct kvm *kvm)
> > @@ -875,6 +900,10 @@ void vgic_v5_teardown(struct kvm *kvm)
> > kvm_err("Failed to release VM 0x%x\n",
> > dist->gicv5_vm.vm_id);
> > }
> >
> > + /* Goodbye doorbells */
> > + kvm_for_each_vcpu(i, vcpu, kvm)
> > + vgic_v5_disable_vcpu(vcpu);
> > +
> > vgic_v5_teardown_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> >
> > vgic_v5_release_vm_id(kvm);
>
> I reckon this patch would be better folded into the previous one, so
> that we can see both the requesting and freeing of the doorbell
> interrupt in the same patch.
Agreed, and that's what I've done now.
Thanks,
Sascha
>
> Thanks,
>
> M.
>
^ permalink raw reply
* Re: [PATCH] firmware: smccc: Fix Arm SMCCC SOC_ID name call
From: Sudeep Holla @ 2026-05-21 14:18 UTC (permalink / raw)
To: Mark Rutland, Lorenzo Pieralisi, Sudeep Holla, Andre Przywara
Cc: Paul Benoit, linux-arm-kernel, linux-kernel
In-Reply-To: <20250902172053.304911-1-andre.przywara@arm.com>
On Tue, 02 Sep 2025 18:20:53 +0100, Andre Przywara wrote:
> Commit 5f9c23abc477 ("firmware: smccc: Support optional Arm SMCCC SOC_ID
> name") introduced the SOC_ID name string call, which reports a human
> readable string describing the SoC, as returned by firmware.
> The SMCCC spec v1.6 describes this feature as AArch64 only, since we rely
> on 8 characters to be transmitted per register. Consequently the SMCCC
> call must use the AArch64 calling convention, which requires bit 30 of
> the FID to be set. The spec is a bit confusing here, since it mentions
> that in the parameter description ("2: SoC name (optionally implemented for
> SMC64 calls, ..."), but still prints the FID explicitly as 0x80000002.
> But as this FID is using the SMC32 calling convention (correct for the
> other two calls), it will not match what mainline TF-A is expecting, so
> any call would return NOT_SUPPORTED.
>
> [...]
Applied to sudeep.holla/linux (for-next/ffa/updates), thanks!
[1/1] firmware: smccc: Fix Arm SMCCC SOC_ID name call
https://git.kernel.org/sudeep.holla/c/70492cfce2a4
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v7 13/28] media: rockchip: rga: calculate x_div/y_div using v4l2_format_info
From: Michael Tretter @ 2026-05-21 14:17 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-13-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:18 +0200, Sven Püschel wrote:
> Calculate the x_div and y_div variables with the information from
> v4l2_format_info instead of storing these in the rga_fmt struct.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
Reviewed-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga-hw.c | 45 +++++++---------------------
> drivers/media/platform/rockchip/rga/rga.h | 2 --
> 2 files changed, 11 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
> index 40498796507e0..17f7a67c0b4bb 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -42,6 +42,7 @@ rga_get_addr_offset(struct rga_frame *frm, struct rga_addr_offset *offset,
> {
> struct rga_corners_addr_offset offsets;
> struct rga_addr_offset *lt, *lb, *rt, *rb;
> + const struct v4l2_format_info *format_info;
> unsigned int x_div = 0,
> y_div = 0, uv_stride = 0, pixel_width = 0;
>
> @@ -50,8 +51,16 @@ rga_get_addr_offset(struct rga_frame *frm, struct rga_addr_offset *offset,
> rt = &offsets.right_top;
> rb = &offsets.right_bottom;
>
> - x_div = frm->fmt->x_div;
> - y_div = frm->fmt->y_div;
> + format_info = v4l2_format_info(frm->pix.pixelformat);
> + /* x_div is only used for the u/v planes.
> + * When the format doesn't have these, use 1 to avoid a division by zero.
> + */
> + if (format_info->bpp[1])
> + x_div = format_info->hdiv * format_info->bpp_div[1] /
> + format_info->bpp[1];
> + else
> + x_div = 1;
> + y_div = format_info->vdiv;
> uv_stride = frm->stride / x_div;
> pixel_width = frm->stride / frm->pix.width;
>
> @@ -476,128 +485,96 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_ALPHA_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR8888,
> .depth = 32,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_ABGR32,
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR8888,
> .depth = 32,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_XBGR32,
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_XBGR8888,
> .depth = 32,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_RGB24,
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_RGB888,
> .depth = 24,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_BGR24,
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_RGB888,
> .depth = 24,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_ARGB444,
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR4444,
> .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_ARGB555,
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR1555,
> .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_RGB565,
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_BGR565,
> .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_NV21,
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .y_div = 2,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_NV61,
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422SP,
> .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_NV12,
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .y_div = 2,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_NV12M,
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .y_div = 2,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_NV16,
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422SP,
> .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> },
> {
> .fourcc = V4L2_PIX_FMT_YUV420,
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420P,
> .depth = 12,
> - .y_div = 2,
> - .x_div = 2,
> },
> {
> .fourcc = V4L2_PIX_FMT_YUV422P,
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422P,
> .depth = 16,
> - .y_div = 1,
> - .x_div = 2,
> },
> {
> .fourcc = V4L2_PIX_FMT_YVU420,
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420P,
> .depth = 12,
> - .y_div = 2,
> - .x_div = 2,
> },
> };
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index 640e510285341..27b3c9b4f220c 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -20,8 +20,6 @@
> struct rga_fmt {
> u32 fourcc;
> int depth;
> - u8 y_div;
> - u8 x_div;
> u8 color_swap;
> u8 hw_format;
> };
>
> --
> 2.54.0
>
>
--
Pengutronix e.K. | Michael Tretter |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* Re: [PATCH v12 5/5] mfd: Add support for MediaTek SPMI PMICs and MT6363/73
From: Lee Jones @ 2026-05-21 14:13 UTC (permalink / raw)
To: AngeloGioacchino Del Regno
Cc: linux-mediatek, robh, krzk+dt, conor+dt, matthias.bgg, lgirdwood,
broonie, devicetree, linux-kernel, linux-arm-kernel, kernel,
wenst, Nícolas F. R. A. Prado
In-Reply-To: <20260511101355.122478-6-angelogioacchino.delregno@collabora.com>
On Mon, 11 May 2026, AngeloGioacchino Del Regno wrote:
> This driver adds support for the MediaTek SPMI PMICs and their
> interrupt controller (which is present in 95% of the cases).
>
> Other than probing all of the sub-devices of a SPMI PMIC, this
> sets up a regmap from the relevant SPMI bus and initializes an
> interrupt controller with its irq domain and irqchip to handle
> chained interrupts, with the SPMI bus itself being its parent
> irq controller, and the PMIC being the outmost device.
>
> This driver hence holds all of the information about a specific
> PMIC's interrupts and will properly handle them, calling the
> ISR for any subdevice that requested an interrupt.
>
> As for the interrupt spec, this driver wants either three or
> two interrupt cells, but in the case 3 were given it ignores
> the first one: this is because of how this first revision of
> of the MediaTek SPMI 2.0 Controller works, which doesn't hold
> hold irq number information in its register, but delegates
> that to the SPMI device - it's possible that this will change
> in the future with a newer revision of the controller IP, and
> this is the main reason for that.
>
> To make use of this implementation, this driver also adds the
> required bits to support MediaTek MT6363 and MT6373 SPMI PMICs.
>
> Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
> drivers/mfd/Kconfig | 16 +
> drivers/mfd/Makefile | 1 +
> drivers/mfd/mtk-spmi-pmic.c | 427 ++++++++++++++++++++++
> include/linux/mfd/mt63x3_spmi/registers.h | 34 ++
> 4 files changed, 478 insertions(+)
> create mode 100644 drivers/mfd/mtk-spmi-pmic.c
> create mode 100644 include/linux/mfd/mt63x3_spmi/registers.h
>
> diff --git "a/drivers/mfd/Kconfig" "b/drivers/mfd/Kconfig"
> index 7192c9d1d268..3e9acdf648b7 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1148,6 +1148,22 @@ config MFD_MT6397
> accessing the device; additional drivers must be enabled in order
> to use the functionality of the device.
>
> +config MFD_MTK_SPMI_PMIC
> + tristate "MediaTek SPMI PMICs"
> + depends on ARCH_MEDIATEK || COMPILE_TEST
> + depends on OF
> + depends on SPMI
> + select REGMAP_SPMI
> + help
> + Say yes here to enable support for MediaTek's SPMI PMICs.
> + These PMICs made their first appearance in board designs using the
> + MediaTek Dimensity 9400 series of SoCs.
> + Note that this will only be useful when paired with descriptions
> + of the independent functions as child nodes in the device tree.
> +
> + Say M here if you want to include support for the MediaTek SPMI
> + PMICs as a module. The module will be called "mtk-spmi-pmic".
> +
> config MFD_MENF21BMC
> tristate "MEN 14F021P00 Board Management Controller Support"
> depends on I2C
> diff --git "a/drivers/mfd/Makefile" "b/drivers/mfd/Makefile"
> index e75e8045c28a..e00d283450c6 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -190,6 +190,7 @@ obj-$(CONFIG_MFD_MT6360) += mt6360-core.o
> obj-$(CONFIG_MFD_MT6370) += mt6370.o
> mt6397-objs := mt6397-core.o mt6397-irq.o mt6358-irq.o
> obj-$(CONFIG_MFD_MT6397) += mt6397.o
> +obj-$(CONFIG_MFD_MTK_SPMI_PMIC) += mtk-spmi-pmic.o
>
> obj-$(CONFIG_RZ_MTU3) += rz-mtu3.o
> obj-$(CONFIG_ABX500_CORE) += abx500-core.o
> diff --git "a/drivers/mfd/mtk-spmi-pmic.c" "b/drivers/mfd/mtk-spmi-pmic.c
> new file mode 100644
> index 000000000000..d1fc8156e696
> --- /dev/null
> +++ b/drivers/mfd/mtk-spmi-pmic.c
> @@ -0,0 +1,427 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * MediaTek SPMI PMICs Driver
> + *
> + * Copyright (c) 2024 MediaTek Inc.
> + * Copyright (c) 2025 Collabora Ltd
> + *
> + * Authors:
> + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/gfp.h>
> +#include <linux/irq.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/mt63x3_spmi/registers.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <linux/regmap.h>
> +#include <linux/spmi.h>
> +#include <linux/types.h>
> +
> +#define MTK_SPMI_PMIC_VAL_BITS 8
> +#define MTK_SPMI_PMIC_REG_CHIP_ID 0xb
> +#define MTK_SPMI_PMIC_RCS_IRQ_DONE 0x41b
> +
> +/**
> + * struct mtk_spmi_pmic_irq_group - Group of interrupts in SPMI PMIC
> + * @num_int_regs: Number of registers for this group of interrupts
> + * @con_reg: PMIC Interrupt Group Control 0 register
> + * @sta_reg: PMIC Interrupt Group Status 0 register
> + * @group_num: PMIC Interrupt Group number - also corresponds to the
> + * status bit in the global IRQ Control register
> + */
> +struct mtk_spmi_pmic_irq_grp {
> + u8 hwirq_base;
> + u8 num_int_regs;
> + u16 con_reg;
> + u16 sta_reg;
> + u8 group_num;
> +};
> +
> +/**
> + * struct mtk_spmi_pmic_variant - SPMI PMIC variant-specific data
> + * @pmic_irq: Group of interrupts in SPMI PMIC
> + * @num_groups: Number of groups of interrupts
> + * @con_reg_len: Length in bytes of Control registers, depends on
> + * existence of SET and CLR registers in the layout
> + * @irq_grp_reg: Global interrupt status register, explains which
> + * group needs attention because of a group IRQ;
> + * if this is zero, it means that there is only one
> + * group and the device has no irqgroup register
> + * @chip_id_reg: Chip ID Register
> + */
> +struct mtk_spmi_pmic_variant {
> + const struct mtk_spmi_pmic_irq_grp *pmic_irq;
> + u8 num_groups;
> + u8 con_reg_len;
> + u8 irq_grp_reg;
> + u8 chip_id_reg;
> +};
Where is chip_id_reg used?
> +
> +/**
> + * struct mtk_spmi_pmic - Main driver structure
> + * @variant: SPMI PMIC variant-specific data
> + * @dev: Handle to SPMI Device
> + * @dom: IRQ Domain of the PMIC's interrupt controller
> + * @regmap: Handle to PMIC regmap
> + * @irq: PMIC chained interrupt
> + */
> +struct mtk_spmi_pmic {
> + const struct mtk_spmi_pmic_variant *variant;
> + struct device *dev;
> + struct irq_domain *dom;
> + struct regmap *regmap;
> + int irq;
> +};
> +
> +static void mtk_spmi_pmic_irq_set_unmasking(struct irq_data *d, bool unmask)
> +{
> + struct mtk_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
> + const struct mtk_spmi_pmic_variant *variant = pmic->variant;
> + struct regmap *regmap = pmic->regmap;
> + irq_hw_number_t hwirq = irqd_to_hwirq(d);
> + unsigned short i;
> +
> + for (i = 0; i < variant->num_groups; i++) {
for (ini i = 0; ...
Did I not bring this up last time?
> + const struct mtk_spmi_pmic_irq_grp *irq_grp = &variant->pmic_irq[i];
> + u32 con_reg;
> + u8 irq_en_bit;
> +
> + if (hwirq < irq_grp->hwirq_base)
> + continue;
> +
> + con_reg = irq_grp->con_reg + (variant->con_reg_len * i);
> + irq_en_bit = hwirq - irq_grp->hwirq_base;
> + regmap_assign_bits(regmap, con_reg, BIT(irq_en_bit), unmask);
> +
> + break;
> + }
> +}
> +
> +static void mtk_spmi_pmic_irq_mask(struct irq_data *d)
> +{
> + mtk_spmi_pmic_irq_set_unmasking(d, false);
> +}
> +
> +static void mtk_spmi_pmic_irq_unmask(struct irq_data *d)
> +{
> + mtk_spmi_pmic_irq_set_unmasking(d, true);
> +}
> +
> +static struct irq_chip mtk_spmi_pmic_irq_chip = {
> + .name = "mtk-spmi-pmic",
> + .irq_mask = mtk_spmi_pmic_irq_mask,
> + .irq_unmask = mtk_spmi_pmic_irq_unmask,
> + .flags = IRQCHIP_SKIP_SET_WAKE,
> +};
> +
> +static struct lock_class_key mtk_spmi_pmic_irq_lock_class, mtk_spmi_pmic_irq_request_class;
> +
> +static int mtk_spmi_pmic_irq_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
> + unsigned long *out_hwirq, unsigned int *out_type)
> +{
> + struct mtk_spmi_pmic *pmic = d->host_data;
> + u32 intsize = fwspec->param_count;
> + u32 *intspec = fwspec->param;
> + unsigned int irq_type_index;
> + unsigned int irq_num_index;
> +
> + /*
> + * Interrupt cell index - For interrupt size 3:
> + * [0] - SID Interrupt number
> + * [1] - SPMI PMIC (Sub-)Device Interrupt number
> + * [2] - Interrupt Type mask
> + *
> + * When only two cells are specified the SID Interrupt is not present.
> + */
> + if (intsize != 2 && intsize != 3) {
> + dev_err(pmic->dev, "Expected IRQ specifier of size 2 or 3, got %u\n", intsize);
> + return -EINVAL;
> + }
> +
> + /* irq_num_index refers to the SPMI (Sub-)Device Interrupt number */
> + irq_num_index = intsize - 2;
> + irq_type_index = irq_num_index + 1;
> +
> + /*
> + * For 3 cells, the IRQ number in intspec[0] is ignored on purpose here!
> + *
> + * This is because of how at least the first revision of the SPMI 2.0
> + * controller works in MediaTek SoCs: the controller will raise an
> + * interrupt for each SID (but doesn't know the details), and the
> + * specific IRQ number that got raised must be read from the PMIC or
> + * its sub-device driver.
> + * It's possible that this will change in the future with a newer
> + * revision of the SPMI controller, and this is why the device tree
> + * holds the full interrupt specifier.
> + *
> + * out_hwirq: SPMI PMIC (Sub-)Device Interrupt number
> + * out_type: Interrupt type sense mask
> + */
> + *out_hwirq = intspec[irq_num_index];
> + *out_type = intspec[irq_type_index] & IRQ_TYPE_SENSE_MASK;
> +
> + return 0;
> +}
> +
> +static int mtk_spmi_pmic_irq_alloc(struct irq_domain *d, unsigned int virq,
> + unsigned int nr_irqs, void *data)
> +{
> + struct mtk_spmi_pmic *pmic = d->host_data;
> + struct irq_fwspec *fwspec = data;
> + irq_hw_number_t hwirq;
> + unsigned int irqtype;
> + int i, ret;
> +
> + ret = mtk_spmi_pmic_irq_translate(d, fwspec, &hwirq, &irqtype);
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < nr_irqs; i++) {
As above.
> + irq_set_lockdep_class(virq, &mtk_spmi_pmic_irq_lock_class,
> + &mtk_spmi_pmic_irq_request_class);
> + irq_domain_set_info(d, virq, hwirq, &mtk_spmi_pmic_irq_chip,
> + pmic, handle_level_irq, NULL, NULL);
> + }
> +
> + return 0;
> +}
> +
> +
> +static const struct irq_domain_ops mtk_spmi_pmic_irq_domain_ops = {
> + .alloc = mtk_spmi_pmic_irq_alloc,
> + .free = irq_domain_free_irqs_common,
> + .translate = mtk_spmi_pmic_irq_translate,
> +};
> +
> +static int mtk_spmi_pmic_handle_group_irq(struct mtk_spmi_pmic *pmic, int group)
> +{
> + const struct mtk_spmi_pmic_irq_grp *irq_grp = &pmic->variant->pmic_irq[group];
> + struct regmap *regmap = pmic->regmap;
> + struct device *dev = pmic->dev;
> + int i, ret;
Etc.
> +
> + for (i = 0; i < irq_grp->num_int_regs; i++) {
> + u32 status, saved_status;
> +
> + ret = regmap_read(regmap, irq_grp->sta_reg + i, &status);
> + if (ret) {
> + dev_err(dev, "Could not read IRQ status register: %d", ret);
> + return ret;
> + }
> +
> + if (status == 0)
> + continue;
> +
> + saved_status = status;
> + do {
> + irq_hw_number_t hwirq;
> + u8 bit = __ffs(status);
> +
> + /* Each register has 8 bits: this is the first IRQ of this group */
> + hwirq = MTK_SPMI_PMIC_VAL_BITS * i;
> +
> + /* Offset by this group's start interrupt */
> + hwirq += irq_grp->hwirq_base;
> +
> + /* Finally, offset by the fired IRQ's bit number */
> + hwirq += bit;
> +
> + status &= ~BIT(bit);
> +
> + generic_handle_domain_irq_safe(pmic->dom, hwirq);
> + } while (status);
> +
> + /* Clear the interrupts by writing the previous status */
> + regmap_write(regmap, irq_grp->sta_reg + i, saved_status);
> + }
> +
> + return 0;
> +}
> +
> +static void mtk_spmi_pmic_handle_chained_irq(struct irq_desc *desc)
> +{
> + struct mtk_spmi_pmic *pmic = irq_desc_get_handler_data(desc);
> + const struct mtk_spmi_pmic_variant *variant = pmic->variant;
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + struct regmap *regmap = pmic->regmap;
> + bool irq_handled = false;
> + int i, ret;
> + u32 val;
> +
> + chained_irq_enter(chip, desc);
> +
> + /* If irq_grp_reg is present there are multiple IRQ groups */
> + if (variant->irq_grp_reg > 0) {
> + ret = regmap_read(regmap, variant->irq_grp_reg, &val);
> + if (ret)
> + handle_bad_irq(desc);
> +
> + /* This is very unlikely to happen */
> + if (val == 0) {
> + chained_irq_exit(chip, desc);
> + return;
> + }
> + } else {
> + val = BIT(0);
> + }
> +
> + for (i = 0; i < variant->num_groups; i++) {
> + const struct mtk_spmi_pmic_irq_grp *irq_grp = &variant->pmic_irq[i];
> + u8 group_bit = BIT(irq_grp[i].group_num);
Did you mean to index twice here?
irq_grp[i + i].group_num
> +
> + if (val & group_bit) {
> + ret = mtk_spmi_pmic_handle_group_irq(pmic, i);
> + if (ret == 0)
> + irq_handled = true;
> + }
> + }
> +
> + /* The RCS flag has to be cleared even if the IRQ was not handled. */
> + ret = regmap_write(regmap, MTK_SPMI_PMIC_RCS_IRQ_DONE, 1);
> + if (ret)
> + dev_warn(pmic->dev, "Could not clear RCS flag!\n");
> +
> + if (!irq_handled)
> + handle_bad_irq(desc);
> +
> + chained_irq_exit(chip, desc);
> +}
> +
> +static void mtk_spmi_pmic_irq_remove(void *data)
> +{
> + struct mtk_spmi_pmic *pmic = (struct mtk_spmi_pmic *)data;
You shouldn't need from a void.
> +
> + irq_set_chained_handler_and_data(pmic->irq, NULL, NULL);
> + irq_domain_remove(pmic->dom);
> +}
> +
> +static int mtk_spmi_pmic_irq_init(struct device *dev, struct regmap *regmap,
> + const struct mtk_spmi_pmic_variant *variant)
> +{
> + struct fwnode_handle *fwnode = of_fwnode_handle(dev->of_node);
> + struct mtk_spmi_pmic *pmic;
> + int ret;
> +
> + pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
> + if (!pmic)
> + return -ENOMEM;
> +
> + pmic->irq = of_irq_get(dev->of_node, 0);
> + if (pmic->irq < 0)
> + return dev_err_probe(dev, pmic->irq, "Cannot get IRQ\n");
> +
> + pmic->dev = dev;
> + pmic->regmap = regmap;
> + pmic->variant = variant;
> +
> + pmic->dom = irq_domain_create_tree(fwnode, &mtk_spmi_pmic_irq_domain_ops, pmic);
> + if (!pmic->dom)
> + return dev_err_probe(dev, -ENOMEM, "Cannot create IRQ domain\n");
> +
> + ret = devm_add_action_or_reset(dev, mtk_spmi_pmic_irq_remove, pmic);
> + if (ret) {
> + irq_domain_remove(pmic->dom);
You just double-freed.
> + return ret;
> + }
> +
> + irq_set_chained_handler_and_data(pmic->irq, mtk_spmi_pmic_handle_chained_irq, pmic);
> +
> + return 0;
> +}
> +
> +#define MTK_SPMI_PMIC_IRQ_GROUP(pmic, group_name, group_index, first_irq, last_irq) \
> +{ \
> + .hwirq_base = first_irq, \
> + .num_int_regs = ((last_irq - first_irq) / MTK_SPMI_PMIC_VAL_BITS) + 1, \
> + .con_reg = pmic##_REG_##group_name##_TOP_INT_CON0, \
> + .sta_reg = pmic##_REG_##group_name##_TOP_INT_STATUS0, \
> + .group_num = group_index, \
> +}
> +
> +static const struct mtk_spmi_pmic_irq_grp mt6363_irq_groups[] = {
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6363, BUCK, 0, 0, 9),
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6363, LDO, 1, 16, 40),
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6363, PSC, 2, 48, 57),
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6363, MISC, 3, 64, 79),
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6363, HK, 4, 80, 87),
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6363, BM, 6, 88, 107)
> +};
> +
> +static const struct mtk_spmi_pmic_irq_grp mt6373_irq_groups[] = {
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6373, BUCK, 0, 0, 9),
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6373, LDO, 1, 16, 39),
> + MTK_SPMI_PMIC_IRQ_GROUP(MT6373, MISC, 3, 56, 71),
> +};
> +
> +static const struct mtk_spmi_pmic_variant mt6363_variant = {
> + .pmic_irq = mt6363_irq_groups,
> + .num_groups = ARRAY_SIZE(mt6363_irq_groups),
> + .con_reg_len = 3,
> + .irq_grp_reg = MT6363_REG_TOP_INT_STATUS1,
> + .chip_id_reg = MTK_SPMI_PMIC_REG_CHIP_ID,
> +};
> +
> +static const struct mtk_spmi_pmic_variant mt6373_variant = {
> + .pmic_irq = mt6373_irq_groups,
> + .num_groups = ARRAY_SIZE(mt6373_irq_groups),
> + .con_reg_len = 3,
> + .irq_grp_reg = MT6373_REG_TOP_INT_STATUS1,
> + .chip_id_reg = MTK_SPMI_PMIC_REG_CHIP_ID,
> +};
> +
> +static const struct regmap_config mtk_spmi_regmap_config = {
> + .reg_bits = 16,
> + .val_bits = MTK_SPMI_PMIC_VAL_BITS,
> + .max_register = 0xffff,
> + .fast_io = true,
> +};
> +
> +static int mtk_spmi_pmic_probe(struct spmi_device *sdev)
> +{
> + const struct mtk_spmi_pmic_variant *variant;
> + struct device *dev = &sdev->dev;
> + struct regmap *regmap;
> + int ret;
> +
> + regmap = devm_regmap_init_spmi_ext(sdev, &mtk_spmi_regmap_config);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + variant = (const struct mtk_spmi_pmic_variant *)device_get_match_data(dev);
Again, no casting required.
> + if (variant && variant->num_groups) {
> + ret = mtk_spmi_pmic_irq_init(dev, regmap, variant);
> + if (ret)
> + return ret;
> + }
> +
> + return devm_of_platform_populate(dev);
> +}
> +
> +static const struct of_device_id mtk_pmic_spmi_id_table[] = {
> + { .compatible = "mediatek,mt6363", .data = &mt6363_variant },
> + { .compatible = "mediatek,mt6373", .data = &mt6373_variant },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, mtk_pmic_spmi_id_table);
> +
> +static struct spmi_driver mtk_spmi_pmic_driver = {
> + .probe = mtk_spmi_pmic_probe,
> + .driver = {
> + .name = "mtk-spmi-pmic",
> + .of_match_table = mtk_pmic_spmi_id_table,
> + },
> +};
> +module_spmi_driver(mtk_spmi_pmic_driver);
> +
> +MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
> +MODULE_DESCRIPTION("MediaTek SPMI PMIC driver");
> +MODULE_LICENSE("GPL");
> diff --git "a/include/linux/mfd/mt63x3_spmi/registers.h" "b/include/linux/mfd/mt63x3_spmi/registers.h
> new file mode 100644
> index 000000000000..808927280b40
> --- /dev/null
> +++ "b/include/linux/mfd/mt63x3_spmi/registers.h"
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2021 MediaTek Inc.
> + * Copyright (c) 2025 Collabora Ltd
> + */
> +
> +#ifndef __MFD_MT63X3_SPMI_REGISTERS_H__
> +#define __MFD_MT63X3_SPMI_REGISTERS_H__
> +
> +/* MT6363 PMIC Registers */
> +#define MT6363_REG_MISC_TOP_INT_CON0 0x37
> +#define MT6363_REG_MISC_TOP_INT_STATUS0 0x43
> +#define MT6363_REG_TOP_INT_STATUS1 0x4e
> +#define MT6363_REG_PSC_TOP_INT_CON0 0x90f
> +#define MT6363_REG_PSC_TOP_INT_STATUS0 0x91b
> +#define MT6363_REG_BM_TOP_INT_CON0 0xc24
> +#define MT6363_REG_BM_TOP_INT_STATUS0 0xc36
> +#define MT6363_REG_HK_TOP_INT_CON0 0xf92
> +#define MT6363_REG_HK_TOP_INT_STATUS0 0xf9e
> +#define MT6363_REG_BUCK_TOP_INT_CON0 0x1411
> +#define MT6363_REG_BUCK_TOP_INT_STATUS0 0x141d
> +#define MT6363_REG_LDO_TOP_INT_CON0 0x1b11
> +#define MT6363_REG_LDO_TOP_INT_STATUS0 0x1b29
> +
> +/* MT6373 PMIC Registers */
> +#define MT6373_REG_MISC_TOP_INT_CON0 0x3c
> +#define MT6373_REG_MISC_TOP_INT_STATUS0 0x48
> +#define MT6373_REG_TOP_INT_STATUS1 0x53
> +#define MT6373_REG_BUCK_TOP_INT_CON0 0x1411
> +#define MT6373_REG_BUCK_TOP_INT_STATUS0 0x141d
> +#define MT6373_REG_LDO_TOP_INT_CON0 0x1b10
> +#define MT6373_REG_LDO_TOP_INT_STATUS0 0x1b22
> +
> +#endif /* __MFD_MT63X3_SPMI_REGISTERS_H__ */
> --
> 2.53.0
>
--
Lee Jones
^ permalink raw reply
* Re: [PATCH 36/43] KVM: arm64: gic-v5: Implement save/restore mechanisms for ISTs
From: Sascha Bischoff @ 2026-05-21 14:12 UTC (permalink / raw)
To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org, Vladimir Murzin
Cc: yuzenghui@huawei.com, Timothy Hayes, Suzuki Poulose,
oliver.upton@linux.dev, peter.maydell@linaro.org, nd,
maz@kernel.org, Joey Gouly, lpieralisi@kernel.org
In-Reply-To: <187900ec-4585-42d9-946c-e6de3111552d@arm.com>
On Fri, 2026-05-01 at 19:54 +0100, Vladimir Murzin wrote:
> Hi Sascha,
Hi Vladimir,
>
> On 4/27/26 17:18, Sascha Bischoff wrote:
> > + tmp = le64_to_cpu(READ_ONCE(vmte->val[3]));
> > + host_id_bits = FIELD_GET(GICV5_VMTEL2E_IST_ID_BITS, tmp);
> > + host_istsz = FIELD_GET(GICV5_VMTEL2E_IST_ISTSZ, tmp);
> > + host_l2sz = FIELD_GET(GICV5_VMTEL2E_IST_L2SZ, tmp);
> > +
> > + /* We always use a Linear SPI IST on the host */
> > + for (int i = 0; i < BIT(host_id_bits); ++i) {
>
> IIUC here we iterate over host's SPIs and save them into buffer
> provided
> by the user. One thing I noticed is that if user set number of SPIs
> via
> KVM_DEV_ARM_VGIC_GRP_NR_IRQS bellow 16, say 1 (btw, it seems there is
> no
> way to set SPIs to 0...), it would be rounded up to 16 in
> kvm_vgic_v5_irs_init(). So from user perspective it needs to save
> just
> single SPI, thus it could provide buffer just for that single entry.
> With such
> setup we can end up corrupting user's memory. We can argue that it is
> user's
> problem... perhaps we need to spell explicitly requirements for the
> buffer or
> provide interface to the user to query required size or respect
> nr_spis set
> by user or some combinations of all :)
I've gone and have tightened the requirements for SPIs (and actually
match what GICv3 does here).
For GICv3, the default number of SPIs is 32, and the smallest number of
IRQs that can be specified via KVM_DEV_ARM_VGIC_GRP_NR_IRQS is 64 (16
SGIs, 16 PPIs, and 32 SPIs) - there's no way to specify 0 SPIs. The
number of SPIs must be a multiple of 32.
I've gone and mimicked this for GICv5. I've removed the ability to set
0 SPIs, making 32 the new minimum. The interface now also mandates that
we need a multiple of 32 SPIs.
Overall this means that the interface works just like the GICv3 one
(except that it doesn't also convey the private IRQs), and that we will
never be at risk of SPI IST alignment issues (which effectively mandate
at least 16 SPIs when no metadata is required). This does, of course,
mean that the SPI IST must ALWAYS be saved/restored, but if anything
that's clearer. Size-wise, it is always 32 if nothing was specified, or
it exactly matches what userspace (successfully) conveyed to KVM.
>
> Cheers
> Vladimir
Thank you for pointing that out. It was definitely not sane before.
Sascha
^ permalink raw reply
* Re: [PATCH v14 03/28] drm: Add new general DRM property "color format"
From: Daniel Stone @ 2026-05-21 14:12 UTC (permalink / raw)
To: Nicolas Frattaroli
Cc: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
Jonathan Corbet, Shuah Khan, kernel, amd-gfx, dri-devel,
linux-kernel, linux-arm-kernel, linux-rockchip, intel-gfx,
intel-xe, linux-doc, wayland-devel, Werner Sembach,
Andri Yngvason, Marius Vlad
In-Reply-To: <20260423-color-format-v14-3-449a419ccbd4@collabora.com>
Hi,
On Thu, 23 Apr 2026 at 20:04, Nicolas Frattaroli
<nicolas.frattaroli@collabora.com> wrote:
> + } else if (property == connector->color_format_property) {
> + if (val > INT_MAX || !drm_connector_color_format_valid(val)) {
> + drm_dbg_atomic(connector->dev,
> + "[CONNECTOR:%d:%s] unknown color format %llu\n",
> + connector->base.id, connector->name, val);
> + return -EINVAL;
> + }
Shouldn't this already be ensured by drm_property_change_valid_get()?
Cheers,
Daniel
^ permalink raw reply
* Re: [RFC PATCH 2/2] arm64: mm: add SMCCC-backed cache invalidate provider
From: Conor Dooley @ 2026-05-21 14:12 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Srirangan Madhavan, catalin.marinas, will, mark.rutland,
lpieralisi, sudeep.holla, linux-arm-kernel, linux-kernel, vsethi,
jevans, raghupathyk, srikars, nbenech, alwilliamson, Dan Williams
In-Reply-To: <20260521121812.2e4abd71@jic23-huawei>
[-- Attachment #1: Type: text/plain, Size: 2725 bytes --]
On Thu, May 21, 2026 at 12:18:12PM +0100, Jonathan Cameron wrote:
> On Thu, 21 May 2026 07:30:47 +0000
> Srirangan Madhavan <smadhavan@nvidia.com> wrote:
>
> > Add an arm64 cache maintenance backend that discovers SMCCC cache
> > clean+invalidate support, queries attributes, handles transient BUSY and
> > RATE_LIMITED responses with bounded retries, and registers with the generic
> > cache coherency framework.
> >
> > Signed-off-by: Srirangan Madhavan <smadhavan@nvidia.com>
> Hi Srirangan,
>
> Other than the file location and Kconfig option comments, everything else
> is really trivial. + some musings about maybe being worth more clever
> fusing of ops in the future if it turns out to be useful.
>
> > ---
> > MAINTAINERS | 1 +
> > arch/arm64/mm/Makefile | 1 +
> > arch/arm64/mm/cache_maint.c | 180 ++++++++++++++++++++++++++++++++++++
>
> File location wise, this is a driver for a subsystem, be it one closely
> coupled to arm. Arm maintainers, do you want it in there or in drivers/cache ?
> My personal preference is always to keep drivers with subsystems but I don't
> care that much.
At the risk of stepping on Will's/Catalin's toes, I'll butt in here..
If this was on riscv, using an ecall into sbi firmware, I'd be asking
for it to be put in drivers/cache. The mechanism for requesting the
ops is arch-specific, but the actual execution of it is not, right?
The actual execution is going to depend on the device-specific
firmware that the smc is made to. That puts it in the same boat as
clk-scmi to me, but I'm not really familiar with how these things break
down on arm64 to be sure.
> > 3 files changed, 182 insertions(+)
> > create mode 100644 arch/arm64/mm/cache_maint.c
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 2fb1c75afd16..33c35f8e6e40 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -25383,6 +25383,7 @@ M: Jonathan Cameron <jic23@kernel.org>
> > S: Maintained
> > T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
> > F: Documentation/devicetree/bindings/cache/
> > +F: arch/arm64/mm/cache_maint.c
>
> I wonder if this should just have a separate maintainers entry?
> We did that for the hisi driver.
>
> If not maybe add yourself as at least a Reviewer so that you get +CC'd
> on relevant changes.
>
> Conor, what do you think makes sense here.
I think it is very weird to have an arch/arm64/mm file in this entry,
implying that I would be applying patches for it, which I do not
consider to be appropriate. If it gets moved to drivers/cache, then it
I think a standalone maintainers entry for the driver is a good idea.
Cheers,
Conor.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v5 00/13] net: lan966x: add support for PCIe FDMA
From: Daniel Machon @ 2026-05-21 14:12 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Horatiu Vultur, Steen Hegelund, UNGLinuxDriver,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Herve Codina, Arnd Bergmann,
Greg Kroah-Hartman, Mohsin Bashir
Cc: netdev, linux-kernel, bpf, linux-arm-kernel
In-Reply-To: <20260520-lan966x-pci-fdma-v5-0-ca56197ae05b@microchip.com>
> This series adds FDMA (Frame DMA) support for the PCIe path. When
> operating as a PCIe endpoint, the internal FDMA engine on lan966x cannot
> directly access host memory, so DMA buffers are allocated as contiguous
> coherent memory and mapped through the PCIe Address Translation Unit
> (ATU). The ATU provides outbound windows that translate internal FDMA
> addresses to PCIe bus addresses, allowing the FDMA engine to read and
> write host memory. Because the ATU requires contiguous address regions,
> page_pool and normal per-page DMA mappings cannot be used. Instead,
> frames are transferred using memcpy between the ATU-mapped buffers and
> the network stack. With this, throughput increases from ~33 Mbps to
> ~620 Mbps for default MTU.
I went through the sashiko review for v5 (gemini and nipa). AFAICT no new
series-level issues were raised — the only Critical (XDP features exposed before
the xdp_setup() PCIe short-circuit lands) is a per-patch bisectability concern
that sashiko itself flags as "likely fixed by the subsequent patch", and indeed
patch [11/13] adds the guard. The NAPI bailout issue Paolo raised on v4 is
fixed in this version and not reflagged.
^ permalink raw reply
* Re: [PATCH v7 12/28] media: rockchip: rga: avoid odd frame sizes for YUV formats
From: Michael Tretter @ 2026-05-21 14:11 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-12-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:17 +0200, Sven Püschel wrote:
> Avoid odd frame sizes for YUV formats, as they may cause undefined
> behavior. This is done in preparation for the RGA3, which hangs when the
> output format is set to 129x129 pixel YUV420 SP (NV12).
>
> This requirement is documented explicitly for the RGA3 in section 5.6.3
> of the RK3588 TRM Part 2. For the RGA2 the RK3588 TRM Part 2
> (section 6.1.2) and RK3568 TRM Part 2 (section 14.2) only mentions the
> x/y offsets and stride aligning requirements. But the vendor driver for
> the RGA2 also contains checks for the width and height to be aligned to
> 2 bytes.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga.c | 19 ++++++++++++++-----
> 1 file changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index f599c992829dd..77b8c7ab74274 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -337,6 +337,19 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
> struct rga_ctx *ctx = file_to_rga_ctx(file);
> const struct rga_hw *hw = ctx->rga->hw;
> struct rga_fmt *fmt;
> + struct v4l2_frmsize_stepwise frmsize = {
> + .min_width = hw->min_width,
> + .max_width = hw->max_width,
> + .min_height = hw->min_height,
> + .max_height = hw->max_height,
> + .step_width = 1,
> + .step_height = 1,
> + };
> +
> + if (v4l2_is_format_yuv(v4l2_format_info(pix_fmt->pixelformat))) {
> + frmsize.step_width = 2;
> + frmsize.step_height = 2;
If I understand correctly, this limitation may be a result of 4:2:0
chroma subsampling. Thus, formats with 4:2:2 subsampling would also work
with step_height = 1.
As this may be some hardware limitation, a comment that points to the
TRM (in addition to the commit message) may be beneficial, too.
Michael
> + }
>
> if (V4L2_TYPE_IS_CAPTURE(f->type)) {
> const struct rga_frame *frm;
> @@ -358,11 +371,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
> if (!fmt)
> fmt = &hw->formats[0];
>
> - pix_fmt->width = clamp(pix_fmt->width,
> - hw->min_width, hw->max_width);
> - pix_fmt->height = clamp(pix_fmt->height,
> - hw->min_height, hw->max_height);
> -
> + v4l2_apply_frmsize_constraints(&pix_fmt->width, &pix_fmt->height, &frmsize);
> v4l2_fill_pixfmt_mp(pix_fmt, fmt->fourcc, pix_fmt->width, pix_fmt->height);
> pix_fmt->field = V4L2_FIELD_NONE;
>
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH 0/4] firmware: arm_scmi: Fix protocol parsing and validation
From: Sudeep Holla @ 2026-05-21 14:09 UTC (permalink / raw)
To: Cristian Marussi, arm-scmi, linux-arm-kernel, Sudeep Holla
In-Reply-To: <20260517-scmi_fixes-v1-0-d86daec4defd@kernel.org>
On Sun, 17 May 2026 20:02:39 +0100, Sudeep Holla wrote:
> This series fixes a few SCMI protocol parsing and validation issues found
> while checking the driver message layouts against the SCMI specification.
>
> The first patch fixes a clear response width mismatch in SENSOR_CONFIG_GET,
> where the driver requested a 4-byte response but read it as a 64-bit value.
>
> The next two patches harden notification parsing for variable-sized payloads.
> BASE_ERROR_EVENT and SENSOR_UPDATE both carry counted trailing arrays, so the
> received payload size must be validated before copying or parsing those
> entries.
>
> [...]
Applied to sudeep.holla/linux (for-next/scmi/updates), thanks!
[1/4] firmware: arm_scmi: Read sensor config as 32-bit value
https://git.kernel.org/sudeep.holla/c/f6fe7c3c007d
[2/4] firmware: arm_scmi: Validate BASE_ERROR_EVENT payload size
https://git.kernel.org/sudeep.holla/c/56e7e64cdd0e
[3/4] firmware: arm_scmi: Validate SENSOR_UPDATE payload size
https://git.kernel.org/sudeep.holla/c/32bc5496b481
[4/4] firmware: arm_scmi: Validate Powercap domains before state access
https://git.kernel.org/sudeep.holla/c/fcca603c6a09
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH 16/43] KVM: arm64: gic-v5: Initialise and teardown VMTEs & doorbells
From: Sascha Bischoff @ 2026-05-21 14:07 UTC (permalink / raw)
To: maz@kernel.org
Cc: yuzenghui@huawei.com, Timothy Hayes, Suzuki Poulose, nd,
peter.maydell@linaro.org, kvmarm@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org,
Joey Gouly, lpieralisi@kernel.org, oliver.upton@linux.dev
In-Reply-To: <86cxzgzlff.wl-maz@kernel.org>
On Thu, 2026-04-30 at 13:23 +0100, Marc Zyngier wrote:
> On Mon, 27 Apr 2026 17:11:30 +0100,
> Sascha Bischoff <Sascha.Bischoff@arm.com> wrote:
> >
> > Each GICv5 VM requires a valid VM Table Entry (VMTE). The VM Table
> > itself is allocated during probe time, but a VM needs to provision
> > a
> > VMTE before it is able to properly run (PPIs will work, but nothing
> > else will - and PPIs only are not useful!).
> >
> > The correct time for setting up the VMTE is during VM
> > initialisation. For GICv5, this is vgic_v5_init(). Each VM needs a
> > VM
> > ID - this is actually the index into the VM Table so it is how a
> > specific VMTE is selected too. As part of vgic_v5_init get a VM ID
> > via
> > vgic_v5_allocate_vm_id(), which internally uses an IDA to select an
> > unused VM ID (and hence VMTE) within the range of allowed VM IDs.
> >
> > Once the VM ID has been allocated, the doorbell domain for the VM
> > is
> > allocated, and each of the doorbells itself is allocated and
> > assigned
> > to a vcpu.
> >
> > Assuming everything up until this point has succeeded, initialise
> > the
> > VMTE. Internally this allocates the additional data structures
> > required by the hardware - the VM Descriptor, VPE Table, etc. This
> > VMTE is then made valid via the IRS's MMIO interface. Finally, all
> > VPEs are allocated within the VPET.
> >
> > On teardown, this process is reversed again. The VMTE is made
> > invalid,
> > the VPEs are freed, the doorbells are released and the domain torn
> > down, and finally the VM ID is released. The latter allows the VM
> > ID
> > and VMTE to be reused for a future VM.
> >
> > Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> > ---
> > arch/arm64/kvm/vgic/vgic-v5.c | 146 +++++++++++++++++++++++++++++-
> > ----
> > 1 file changed, 128 insertions(+), 18 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/vgic/vgic-v5.c
> > b/arch/arm64/kvm/vgic/vgic-v5.c
> > index 2fc6fa4df034f..9347bc6895223 100644
> > --- a/arch/arm64/kvm/vgic/vgic-v5.c
> > +++ b/arch/arm64/kvm/vgic/vgic-v5.c
> > @@ -518,6 +518,18 @@ static int vgic_v5_irs_vpe_cr0_update(int
> > vm_id, int vpe_id, u32 cr0)
> > return 0;
> > }
> >
> > +static irqreturn_t db_handler(int irq, void *data)
> > +{
> > + struct kvm_vcpu *vcpu = data;
> > +
> > + WRITE_ONCE(vcpu->arch.vgic_cpu.vgic_v5.gicv5_vpe.db_fired, true);
> > +
> > + kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
> > + kvm_vcpu_kick(vcpu);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
>
> I think it'd make more sense if the doorbell
> handling/requesting/freeing was one patch, or at least a set of
> consecutive patches in the series.
>
> As it is now, it is very hard to keep track of things. You have part
> of it in the previous patch, the requesting and handling here, and
> probably the freeing in some other patch I haven't seen.
>
> > static int vgic_v5_send_command(struct kvm_vcpu *vcpu,
> > enum gicv5_vcpu_info_cmd_type type)
> > {
> > @@ -726,26 +738,46 @@ void vgic_v5_reset(struct kvm_vcpu *vcpu)
> > }
> > }
> >
> > -int vgic_v5_init(struct kvm *kvm)
> > +int vgic_v5_map_resources(struct kvm *kvm)
> > {
> > - struct kvm_vcpu *vcpu;
> > - unsigned long idx;
> > - int ret;
> > + if (!vgic_initialized(kvm))
> > + return -EBUSY;
> >
> > - if (vgic_initialized(kvm))
> > - return 0;
> > + return 0;
> > +}
>
> Pointless code movement?
Very pointless. Removed that.
>
> >
> > - ret = vgic_v5_create_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> > - if (ret)
> > - return ret;
> > +/*
> > + * Claim and populate a VMTE (optionally making a new L2 VMT
> > valid), create VPE
> > + * doorbells, allocate VPET and populate for each VPE. Finally, we
> > also init the
> > + * vIRS, which means allocating and making the virtual SPI IST
> > valid.
> > + *
> > + * Note: We do need to put the cart before the horse here. The VPE
> > doorbells are
> > + * our conduit for communication with the IRS, which means we need
> > to have those
> > + * before making the VMTE valid.
> > + *
> > + * On failure, we clean up in the teardown path
> > (vgic_v5_teardown()).
> > + */
> > +int vgic_v5_init(struct kvm *kvm)
> > +{
> > + int nr_vcpus, ret = 0;
> > + struct kvm_vcpu *vcpu, *vcpu0;
> > + unsigned long i;
> > + struct irq_data *d;
> > + unsigned int db_virq;
> > +
> > + nr_vcpus = atomic_read(&kvm->online_vcpus);
> > + if (nr_vcpus == 0)
> > + return -ENODEV;
> >
> > - kvm_for_each_vcpu(idx, vcpu, kvm) {
> > + kvm_for_each_vcpu(i, vcpu, kvm) {
> > if (vcpu_has_nv(vcpu)) {
> > kvm_err("Nested GICv5 VMs are currently unsupported\n");
> > return -EINVAL;
> > }
> > }
> >
> > + kvm->arch.vgic.gicv5_vm.nr_vpes = nr_vcpus;
>
> Why do we need to track the number of vcpus separately from what KVM
> already does? GICv4 does it because a lot of the state is managed by
> the irqchip driver, but that's not the case here. I hope we can come
> up with a slightly simpler model with GICv5.
Right, it isn't needed. I've removed it from here (and from the earlier
commits that introduced it/used it).
>
> > +
> > /* We only allow userspace to drive the SW_PPI, if it is
> > implemented. */
> > bitmap_zero(kvm->arch.vgic.gicv5_vm.userspace_ppis,
> > VGIC_V5_NR_PRIVATE_IRQS);
> > @@ -754,20 +786,98 @@ int vgic_v5_init(struct kvm *kvm)
> > kvm->arch.vgic.gicv5_vm.userspace_ppis,
> > ppi_caps.impl_ppi_mask, VGIC_V5_NR_PRIVATE_IRQS);
> >
> > - return 0;
> > + ret = vgic_v5_allocate_vm_id(kvm);
> > + if (ret) {
> > + kvm_err("Maximum number of GICv5 VMs reached!\n");
> > + return ret;
> > + }
>
> I'd rather we don't scream on the console when running out of
> VMIDs. If we're at capacity, so be it. That's not an error worth
> spamming the console over.
Alright. Have removed the printing here.
>
> > +
> > + ret = vgic_v5_create_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> > + if (ret)
> > + return ret;
>
> Who is freeing the VMID?
We are in the vgic_v5_teardown() path.
>
> > +
> > + /*
> > + * Allocate VPE doorbells first - these are our conduit for
> > + * communicating with the host irqchip driver.
> > + */
> > + db_virq = irq_domain_alloc_irqs(kvm->arch.vgic.gicv5_vm.domain,
> > + nr_vcpus, NUMA_NO_NODE,
> > + &kvm->arch.vgic.gicv5_vm);
> > + if (db_virq < 0) {
> > + /* Simplify teardown by doing this early! */
> > + vgic_v5_teardown_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> > + return db_virq;
> > + }
> > +
> > + kvm->arch.vgic.gicv5_vm.vpe_db_base = db_virq;
> > +
> > + kvm_for_each_vcpu(i, vcpu, kvm) {
> > + d = irq_domain_get_irq_data(kvm->arch.vgic.gicv5_vm.domain,
> > + db_virq + i);
> > + irq_set_status_flags(db_virq + i, IRQ_NOAUTOEN);
> > +
> > + ret = request_irq(db_virq + i, db_handler, 0, "vcpu", vcpu);
> > + if (ret)
> > + return ret;
> > +
> > + /* Stash it with the VCPU for easy retrieval */
> > + vcpu->arch.vgic_cpu.vgic_v5.gicv5_vpe.db = db_virq + i;
> > + }
> > +
> > + /* Populate VMTE (with VPET and VM descriptor) */
> > + ret = vgic_v5_vmte_init(kvm);
> > + if (ret)
> > + return ret;
> > +
> > + /* We pick the first vcpu to make the VMTE valid - any would do
> > */
> > + vcpu0 = kvm_get_vcpu(kvm, 0);
> > + ret = vgic_v5_send_command(vcpu0, VMTE_MAKE_VALID);
> > + if (ret)
> > + return ret;
> > +
> > + /* Loop over all VPEs, allocate/populate their data structures */
> > + kvm_for_each_vcpu(i, vcpu, kvm) {
> > + ret = vgic_v5_vmte_alloc_vpe(vcpu);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > + return ret;
>
> I'm very worried about the error handling of that function. Who is
> responsible for cleaning up the mess when this fails?
I'd been working on the flawed assumption that vgic_v5_teardown() will
be called in response to an init failure. I've now reworked this to
explicitly roll back everything on a failure by proactively calling
vgic_v5_teardown(), which has also been made safe to call again in the
teardown path.
Thanks,
Sascha
>
> > }
> >
> > void vgic_v5_teardown(struct kvm *kvm)
> > {
> > - vgic_v5_teardown_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> > -}
> > + struct kvm_vcpu *vcpu, *vcpu0;
> > + struct vgic_dist *dist = &kvm->arch.vgic;
> > + unsigned long i;
> > + int rc;
> >
> > -int vgic_v5_map_resources(struct kvm *kvm)
> > -{
> > - if (!vgic_initialized(kvm))
> > - return -EBUSY;
> > + /*
> > + * If the VM's ID isn't valid, then we failed init very early.
> > Nothing
> > + * to do here.
> > + */
> > + if (!kvm->arch.vgic.gicv5_vm.vm_id_valid)
> > + return;
> >
> > - return 0;
> > + if (kvm->arch.vgic.gicv5_vm.vmte_allocated) {
> > + /* Make the VM invalid */
> > + vcpu0 = kvm_get_vcpu(kvm, 0);
> > + rc = vgic_v5_send_command(vcpu0, VMTE_MAKE_INVALID);
> > + if (rc)
> > + kvm_err("could not make VMTE invalid\n");
> > +
> > + kvm_for_each_vcpu(i, vcpu, kvm) {
> > + if (vgic_v5_vmte_free_vpe(vcpu))
> > + kvm_err("Failed to free VPE\n");
> > + }
> > +
> > + if (vgic_v5_vmte_release(kvm))
> > + kvm_err("Failed to release VM 0x%x\n", dist->gicv5_vm.vm_id);
> > + }
> > +
> > + vgic_v5_teardown_per_vm_domain(&kvm->arch.vgic.gicv5_vm);
> > +
> > + vgic_v5_release_vm_id(kvm);
> > }
> >
> > int vgic_v5_finalize_ppi_state(struct kvm *kvm)
>
> Thanks,
>
> M.
>
^ permalink raw reply
* Re: [PATCH 14/43] KVM: arm64: gic-v5: Request VPE doorbells when going non-resident
From: Sascha Bischoff @ 2026-05-21 14:06 UTC (permalink / raw)
To: maz@kernel.org
Cc: yuzenghui@huawei.com, Timothy Hayes, Suzuki Poulose, nd,
peter.maydell@linaro.org, kvmarm@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org,
Joey Gouly, lpieralisi@kernel.org, oliver.upton@linux.dev
In-Reply-To: <86ecjwzqcr.wl-maz@kernel.org>
On Thu, 2026-04-30 at 11:37 +0100, Marc Zyngier wrote:
> On Mon, 27 Apr 2026 17:10:49 +0100,
> Sascha Bischoff <Sascha.Bischoff@arm.com> wrote:
> >
> > When a VPE is made non-resident and is entering WFI, a doorbell
> > should
> > be requested for the VPE. This allows the VPE to be easily woken
> > once
> > an SPI/LPI interrupt is pending for it. This is tracked by the IRS,
> > which will signal the specific VPE doorbell for the VPE once such
> > an
> > interrupt arrives.
> >
> > Requesting a doorbell involves calculating the DBPM - DoorBell
> > Priority Mask - which ensures that the DB is only signalled by the
> > hardware if the pending interrupt is of sufficient priority. This
> > avoids waking a VPE that can't process the incoming interrupt.
> >
> > Doorbells are NOT requested if a VPE is not entering WFI as we
> > expect
> > to enter again imminently.
> >
> > Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> > ---
> > arch/arm64/kvm/vgic/vgic-v5.c | 28 ++++++++++++++++++++++++++++
> > 1 file changed, 28 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/vgic/vgic-v5.c
> > b/arch/arm64/kvm/vgic/vgic-v5.c
> > index 11a1a491b7e0a..2fc6fa4df034f 100644
> > --- a/arch/arm64/kvm/vgic/vgic-v5.c
> > +++ b/arch/arm64/kvm/vgic/vgic-v5.c
> > @@ -1077,6 +1077,9 @@ void vgic_v5_load(struct kvm_vcpu *vcpu)
> > void vgic_v5_put(struct kvm_vcpu *vcpu)
> > {
> > struct vgic_v5_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v5;
> > + bool req_db = !!vcpu_get_flag(vcpu, IN_WFI);
>
> Drop the spurious variable and move the check in the if () statement.
> This is way more readable than declaring a variable.
Done.
>
> > + u32 priority_mask;
> > + int dbpm;
>
> Move these in the inner block.
Done.
>
> >
> > /*
> > * Do nothing if we're not resident. This can happen in the WFI
> > path
> > @@ -1090,6 +1093,31 @@ void vgic_v5_put(struct kvm_vcpu *vcpu)
> > kvm_call_hyp(__vgic_v5_save_apr, cpu_if);
> >
> > cpu_if->vgic_contextr = 0;
> > + if (req_db) {
> > + /*
> > + * Find the virtual running priority and use this to calculate
> > + * the doorbell priority mask. We combine the highest active
> > + * priority and the CPU's priority mask. The guest can't handle
> > + * interrupts with priorities less than or equal to the virtual
> > + * running priority, so there's literally no point in waking the
> > + * guest for these.
> > + *
> > + * The priority needs to be higher than the mask to signal, so
> > + * pick the next higher priority (subtract 1).
> > + */
> > + priority_mask = vgic_v5_get_effective_priority_mask(vcpu);
> > +
> > + /* Don't request a doorbell if the max priority is masked */
>
> This comment reads badly. I'd suggest something like "Request a
> doorbell *unless* the priority is 0, indicating that no interrupt can
> wake the vcpu up".
Done.
>
> > + if (priority_mask) {
> > + dbpm = priority_mask - 1;
> > + cpu_if->vgic_contextr = FIELD_PREP(ICH_CONTEXTR_EL2_DB, 1) |
> > + FIELD_PREP(ICH_CONTEXTR_EL2_DBPM, dbpm);
> > + }
> > +
> > + /* Make the doorbell affine to this CPU */
> > + WARN_ON(irq_set_affinity(vgic_v5_vpe_db(vcpu),
> > + cpumask_of(smp_processor_id())));
>
> Repeatedly setting the affinity is likely to be costly. It may be
> worth comparing with the current affinity somehow.
I've changed this to check the affinity first, and then only change it
if the CPU has changed since it was last set.
>
> > + }
> >
> > kvm_call_hyp(__vgic_v5_make_non_resident, cpu_if);
> >
>
> Thanks,
>
> M.
>
Thanks,
Sascha
^ permalink raw reply
* Re: [PATCH v14 09/44] arm64: RMI: Provide functions to delegate/undelegate ranges of memory
From: Marc Zyngier @ 2026-05-21 13:59 UTC (permalink / raw)
To: Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <20260513131757.116630-10-steven.price@arm.com>
On Wed, 13 May 2026 14:17:17 +0100,
Steven Price <steven.price@arm.com> wrote:
>
> The RMM requires memory is 'delegated' to it so that it can be used
> either for a realm guest or for various tracking purposes within the RMM
> (e.g. for metadata or page tables). Memory that has been delegated
> cannot be accessed by the host (it will result in a Granule Protection
> Fault).
>
> Undelegation may fail if the memory is still in use by the RMM. This
> shouldn't happen (Linux should ensure it has destroyed the RMM objects
> before attempting to undelegate). In the event that it does happen this
> points to a programming bug and the only reasonable approach is for the
> physical pages to be leaked - it is up to the caller of
> rmi_undelegate_range() to handle this.
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> v14:
> * Split into separate patch and moved out of KVM
> ---
> arch/arm64/include/asm/rmi_cmds.h | 13 +++++++++++
> arch/arm64/kernel/rmi.c | 36 +++++++++++++++++++++++++++++++
> 2 files changed, 49 insertions(+)
>
> diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
> index 9078a2920a7c..eb213c8e6f26 100644
> --- a/arch/arm64/include/asm/rmi_cmds.h
> +++ b/arch/arm64/include/asm/rmi_cmds.h
> @@ -33,6 +33,19 @@ struct rmi_sro_state {
> } while (RMI_RETURN_STATUS(res.a0) == RMI_BUSY || \
> RMI_RETURN_STATUS(res.a0) == RMI_BLOCKED)
>
> +int rmi_delegate_range(phys_addr_t phys, unsigned long size);
> +int rmi_undelegate_range(phys_addr_t phys, unsigned long size);
> +
> +static inline int rmi_delegate_page(phys_addr_t phys)
> +{
> + return rmi_delegate_range(phys, PAGE_SIZE);
> +}
> +
> +static inline int rmi_undelegate_page(phys_addr_t phys)
> +{
> + return rmi_undelegate_range(phys, PAGE_SIZE);
> +}
> +
> bool rmi_is_available(void);
>
> unsigned long rmi_sro_execute(struct rmi_sro_state *sro, gfp_t gfp);
> diff --git a/arch/arm64/kernel/rmi.c b/arch/arm64/kernel/rmi.c
> index 52a415e99500..08cef54acadb 100644
> --- a/arch/arm64/kernel/rmi.c
> +++ b/arch/arm64/kernel/rmi.c
> @@ -12,6 +12,42 @@ static bool arm64_rmi_is_available;
> unsigned long rmm_feat_reg0;
> unsigned long rmm_feat_reg1;
>
> +int rmi_delegate_range(phys_addr_t phys, unsigned long size)
> +{
> + unsigned long ret = 0;
> + unsigned long top = phys + size;
> + unsigned long out_top;
> +
> + while (phys < top) {
> + ret = rmi_granule_range_delegate(phys, top, &out_top);
> + if (ret == RMI_SUCCESS)
> + phys = out_top;
> + else if (ret != RMI_BUSY && ret != RMI_BLOCKED)
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> +int rmi_undelegate_range(phys_addr_t phys, unsigned long size)
> +{
> + unsigned long ret = 0;
> + unsigned long top = phys + size;
> + unsigned long out_top;
> +
> + WARN_ON(size == 0);
I find it odd to warn on size = 0. After all, free(NULL) is not an
error. But even then, you continue feeding this to the RMM.
You also don't seem to be bothered with that on the delegation side...
> +
> + while (phys < top) {
> + ret = rmi_granule_range_undelegate(phys, top, &out_top);
> + if (ret == RMI_SUCCESS)
> + phys = out_top;
and size==0 doesn't violate any of the failure conditions listed in
B4.5.18.2 (beta2). Will you end-up looping around forever?
Same questions for the delegation, obviously.
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: (subset) [PATCH 0/4] power: sys-off: fix Pixel C shutdown via MAX77620
From: Diogo Ivo @ 2026-05-21 13:59 UTC (permalink / raw)
To: Lee Jones
Cc: Mark Rutland, Lorenzo Pieralisi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Thierry Reding, Jonathan Hunter, linux-arm-kernel,
linux-kernel, devicetree, linux-tegra
In-Reply-To: <20260521104136.GA2921053@google.com>
On 5/21/26 12:41, Lee Jones wrote:
> On Thu, 21 May 2026, Diogo Ivo wrote:
>
>> Hi Lee,
>>
>> On 5/20/26 18:25, Lee Jones wrote:
>>> On Thu, 14 May 2026 16:47:18 +0200, Diogo Ivo wrote:
>>>> This series migrates PSCI and MAX77620 poweroff handling to the
>>>> sys-off framework and fixes shutdown on the Pixel C (Smaug).
>>>>
>>>> The first two patches replace legacy pm_power_off usage in the PSCI
>>>> and MAX77620 drivers with sys-off handlers. Besides aligning both
>>>> drivers with the modern poweroff infrastructure, this removes the
>>>> global callback dependency and allows multiple handlers to coexist
>>>> with explicit priorities.
>>>>
>>>> [...]
>>>
>>> Applied, thanks!
>>
>> Thanks for applying the patches! Just a question and an observation:
>>
>> - I'm assuming you were ok with merging [2/4] despite the possible
>> deadlock since this risk is already present in mainline in the same
>> form so we're not actually making things worse, is that so?
>
> Did you see the text below?
Yes, but patch 3 is not addressing the possible deadlock hence my
question.
> Both patches 2 and 3 are applied.
>
>> - The observation is that the comment about overriding PSCI is only
>> true after (and if) a reworked [1/4] is actually merged.
>> If it isn't then patch [3/4] is actually working around another handler
>> in soc/tegra/pmc.c where a handler that only does work for the Nexus
>> 7 is actually registered at FIRMWARE level for all platforms that
>> probe that driver (I will send out a patch shortly to only register
>> the handler on the Nexus 7).
>
> I assume the other patches will be applied soon.
>
> If this causes some kind of issue - let me know later on in the cycle
> and I'll remove whatever patches you ask me to.
The PSCI patch [1/4] has a fundamental issue and needs a respin to be
applied.
In connection with this it might then become easier to quirk the PSCI
driver rather than the PMIC driver, so for the moment I'll ask you to
drop [3/4] until I propose the changes to the PSCI maintainers and see
the feedback and at that point we can either completely drop [3/4] or
reapply it; sorry for the noise.
Best regards,
Diogo
^ permalink raw reply
* Re: [PATCH v7 11/28] media: rockchip: rga: move hw specific parts to a dedicated struct
From: Michael Tretter @ 2026-05-21 13:56 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-11-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:16 +0200, Sven Püschel wrote:
> In preparation for the RGA3 unit, move RGA2 specific parts from rga.c
> to rga-hw.c and create a struct to reference the RGA2 specific functions
> and formats. This also allows to remove the rga-hw.h reference from the
> include list of the rga driver.
>
> Also document the command finish interrupt with a dedicated define.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
A few nits below, but
Reviewed-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga-hw.c | 166 ++++++++++++++++++++-
> drivers/media/platform/rockchip/rga/rga-hw.h | 5 +-
> drivers/media/platform/rockchip/rga/rga.c | 211 +++++----------------------
> drivers/media/platform/rockchip/rga/rga.h | 23 ++-
> 4 files changed, 227 insertions(+), 178 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
> index ec6c17504ca15..40498796507e0 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -437,8 +437,8 @@ static void rga_cmd_set(struct rga_ctx *ctx,
> PAGE_SIZE, DMA_BIDIRECTIONAL);
> }
>
> -void rga_hw_start(struct rockchip_rga *rga,
> - struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
> +static void rga_hw_start(struct rockchip_rga *rga,
> + struct rga_vb_buffer *src, struct rga_vb_buffer *dst)
> {
> struct rga_ctx *ctx = rga->curr;
>
> @@ -452,3 +452,165 @@ void rga_hw_start(struct rockchip_rga *rga,
>
> rga_write(rga, RGA_CMD_CTRL, 0x1);
> }
> +
> +static bool rga_handle_irq(struct rockchip_rga *rga)
Returning a bool for success prevents to report any error interrupts to
the core. I guess that's fine and can be changed later, if it may be
necessary.
> +{
> + int intr;
> +
> + intr = rga_read(rga, RGA_INT) & 0xf;
> +
> + rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
> +
> + return intr & RGA_INT_COMMAND_FINISHED;
> +}
> +
> +static void rga_get_version(struct rockchip_rga *rga)
> +{
> + rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
> + rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
> +}
> +
> +static struct rga_fmt formats[] = {
> + {
> + .fourcc = V4L2_PIX_FMT_ARGB32,
> + .color_swap = RGA_COLOR_ALPHA_SWAP,
> + .hw_format = RGA_COLOR_FMT_ABGR8888,
> + .depth = 32,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_ABGR32,
> + .color_swap = RGA_COLOR_RB_SWAP,
> + .hw_format = RGA_COLOR_FMT_ABGR8888,
> + .depth = 32,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_XBGR32,
> + .color_swap = RGA_COLOR_RB_SWAP,
> + .hw_format = RGA_COLOR_FMT_XBGR8888,
> + .depth = 32,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_RGB24,
> + .color_swap = RGA_COLOR_NONE_SWAP,
> + .hw_format = RGA_COLOR_FMT_RGB888,
> + .depth = 24,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_BGR24,
> + .color_swap = RGA_COLOR_RB_SWAP,
> + .hw_format = RGA_COLOR_FMT_RGB888,
> + .depth = 24,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_ARGB444,
> + .color_swap = RGA_COLOR_RB_SWAP,
> + .hw_format = RGA_COLOR_FMT_ABGR4444,
> + .depth = 16,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_ARGB555,
> + .color_swap = RGA_COLOR_RB_SWAP,
> + .hw_format = RGA_COLOR_FMT_ABGR1555,
> + .depth = 16,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_RGB565,
> + .color_swap = RGA_COLOR_RB_SWAP,
> + .hw_format = RGA_COLOR_FMT_BGR565,
> + .depth = 16,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV21,
> + .color_swap = RGA_COLOR_UV_SWAP,
> + .hw_format = RGA_COLOR_FMT_YUV420SP,
> + .depth = 12,
> + .y_div = 2,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV61,
> + .color_swap = RGA_COLOR_UV_SWAP,
> + .hw_format = RGA_COLOR_FMT_YUV422SP,
> + .depth = 16,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV12,
> + .color_swap = RGA_COLOR_NONE_SWAP,
> + .hw_format = RGA_COLOR_FMT_YUV420SP,
> + .depth = 12,
> + .y_div = 2,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV12M,
> + .color_swap = RGA_COLOR_NONE_SWAP,
> + .hw_format = RGA_COLOR_FMT_YUV420SP,
> + .depth = 12,
> + .y_div = 2,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_NV16,
> + .color_swap = RGA_COLOR_NONE_SWAP,
> + .hw_format = RGA_COLOR_FMT_YUV422SP,
> + .depth = 16,
> + .y_div = 1,
> + .x_div = 1,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_YUV420,
> + .color_swap = RGA_COLOR_NONE_SWAP,
> + .hw_format = RGA_COLOR_FMT_YUV420P,
> + .depth = 12,
> + .y_div = 2,
> + .x_div = 2,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_YUV422P,
> + .color_swap = RGA_COLOR_NONE_SWAP,
> + .hw_format = RGA_COLOR_FMT_YUV422P,
> + .depth = 16,
> + .y_div = 1,
> + .x_div = 2,
> + },
> + {
> + .fourcc = V4L2_PIX_FMT_YVU420,
> + .color_swap = RGA_COLOR_UV_SWAP,
> + .hw_format = RGA_COLOR_FMT_YUV420P,
> + .depth = 12,
> + .y_div = 2,
> + .x_div = 2,
> + },
> +};
> +
> +const struct rga_hw rga2_hw = {
> + .formats = formats,
> + .num_formats = ARRAY_SIZE(formats),
> + .cmdbuf_size = RGA_CMDBUF_SIZE,
> + .min_width = MIN_WIDTH,
> + .max_width = MAX_WIDTH,
> + .min_height = MIN_HEIGHT,
> + .max_height = MAX_HEIGHT,
> +
> + .start = rga_hw_start,
> + .handle_irq = rga_handle_irq,
> + .get_version = rga_get_version,
> +};
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.h b/drivers/media/platform/rockchip/rga/rga-hw.h
> index 2b8537a5fd0d7..c2e34be751939 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.h
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.h
> @@ -15,9 +15,6 @@
> #define MIN_WIDTH 34
> #define MIN_HEIGHT 34
>
> -#define DEFAULT_WIDTH 100
> -#define DEFAULT_HEIGHT 100
> -
> #define RGA_TIMEOUT 500
>
> /* Registers address */
> @@ -178,6 +175,8 @@
> #define RGA_ALPHA_COLOR_NORMAL 0
> #define RGA_ALPHA_COLOR_MULTIPLY_CAL 1
>
> +#define RGA_INT_COMMAND_FINISHED 4
This is probably a bitfield in the interrupt register:
#define RGA_INT_COMMAND_FINISHED 0x4
or
#define RGA_INT_COMMAND_FINISHED BIT(2)
> +
> /* Registers union */
> union rga_mode_ctrl {
> unsigned int val;
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index 8c34f73d69764..f599c992829dd 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -25,7 +25,6 @@
> #include <media/videobuf2-dma-sg.h>
> #include <media/videobuf2-v4l2.h>
>
> -#include "rga-hw.h"
> #include "rga.h"
>
> static int debug;
> @@ -47,7 +46,7 @@ static void device_run(void *prv)
>
> dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
>
> - rga_hw_start(rga, vb_to_rga(src), vb_to_rga(dst));
> + rga->hw->start(rga, vb_to_rga(src), vb_to_rga(dst));
>
> spin_unlock_irqrestore(&rga->ctrl_lock, flags);
> }
> @@ -55,13 +54,8 @@ static void device_run(void *prv)
> static irqreturn_t rga_isr(int irq, void *prv)
> {
> struct rockchip_rga *rga = prv;
> - int intr;
>
> - intr = rga_read(rga, RGA_INT) & 0xf;
> -
> - rga_mod(rga, RGA_INT, intr << 4, 0xf << 4);
> -
> - if (intr & 0x04) {
> + if (rga->hw->handle_irq(rga)) {
> struct vb2_v4l2_buffer *src, *dst;
> struct rga_ctx *ctx = rga->curr;
>
> @@ -184,158 +178,17 @@ static int rga_setup_ctrls(struct rga_ctx *ctx)
> return 0;
> }
>
> -static struct rga_fmt formats[] = {
> - {
> - .fourcc = V4L2_PIX_FMT_ARGB32,
> - .color_swap = RGA_COLOR_ALPHA_SWAP,
> - .hw_format = RGA_COLOR_FMT_ABGR8888,
> - .depth = 32,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_ABGR32,
> - .color_swap = RGA_COLOR_RB_SWAP,
> - .hw_format = RGA_COLOR_FMT_ABGR8888,
> - .depth = 32,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_XBGR32,
> - .color_swap = RGA_COLOR_RB_SWAP,
> - .hw_format = RGA_COLOR_FMT_XBGR8888,
> - .depth = 32,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_RGB24,
> - .color_swap = RGA_COLOR_NONE_SWAP,
> - .hw_format = RGA_COLOR_FMT_RGB888,
> - .depth = 24,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_BGR24,
> - .color_swap = RGA_COLOR_RB_SWAP,
> - .hw_format = RGA_COLOR_FMT_RGB888,
> - .depth = 24,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_ARGB444,
> - .color_swap = RGA_COLOR_RB_SWAP,
> - .hw_format = RGA_COLOR_FMT_ABGR4444,
> - .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_ARGB555,
> - .color_swap = RGA_COLOR_RB_SWAP,
> - .hw_format = RGA_COLOR_FMT_ABGR1555,
> - .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_RGB565,
> - .color_swap = RGA_COLOR_RB_SWAP,
> - .hw_format = RGA_COLOR_FMT_BGR565,
> - .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_NV21,
> - .color_swap = RGA_COLOR_UV_SWAP,
> - .hw_format = RGA_COLOR_FMT_YUV420SP,
> - .depth = 12,
> - .y_div = 2,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_NV61,
> - .color_swap = RGA_COLOR_UV_SWAP,
> - .hw_format = RGA_COLOR_FMT_YUV422SP,
> - .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_NV12,
> - .color_swap = RGA_COLOR_NONE_SWAP,
> - .hw_format = RGA_COLOR_FMT_YUV420SP,
> - .depth = 12,
> - .y_div = 2,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_NV12M,
> - .color_swap = RGA_COLOR_NONE_SWAP,
> - .hw_format = RGA_COLOR_FMT_YUV420SP,
> - .depth = 12,
> - .y_div = 2,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_NV16,
> - .color_swap = RGA_COLOR_NONE_SWAP,
> - .hw_format = RGA_COLOR_FMT_YUV422SP,
> - .depth = 16,
> - .y_div = 1,
> - .x_div = 1,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_YUV420,
> - .color_swap = RGA_COLOR_NONE_SWAP,
> - .hw_format = RGA_COLOR_FMT_YUV420P,
> - .depth = 12,
> - .y_div = 2,
> - .x_div = 2,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_YUV422P,
> - .color_swap = RGA_COLOR_NONE_SWAP,
> - .hw_format = RGA_COLOR_FMT_YUV422P,
> - .depth = 16,
> - .y_div = 1,
> - .x_div = 2,
> - },
> - {
> - .fourcc = V4L2_PIX_FMT_YVU420,
> - .color_swap = RGA_COLOR_UV_SWAP,
> - .hw_format = RGA_COLOR_FMT_YUV420P,
> - .depth = 12,
> - .y_div = 2,
> - .x_div = 2,
> - },
> -};
> -
> -#define NUM_FORMATS ARRAY_SIZE(formats)
> -
> -static struct rga_fmt *rga_fmt_find(u32 pixelformat)
> +static struct rga_fmt *rga_fmt_find(struct rockchip_rga *rga, u32 pixelformat)
> {
> unsigned int i;
>
> - for (i = 0; i < NUM_FORMATS; i++) {
> - if (formats[i].fourcc == pixelformat)
> - return &formats[i];
> + for (i = 0; i < rga->hw->num_formats; i++) {
> + if (rga->hw->formats[i].fourcc == pixelformat)
> + return &rga->hw->formats[i];
> }
> return NULL;
> }
>
> -static struct rga_frame def_frame = {
> - .crop.left = 0,
> - .crop.top = 0,
> - .crop.width = DEFAULT_WIDTH,
> - .crop.height = DEFAULT_HEIGHT,
> - .fmt = &formats[0],
> -};
> -
> struct rga_frame *rga_get_frame(struct rga_ctx *ctx, enum v4l2_buf_type type)
> {
> if (V4L2_TYPE_IS_OUTPUT(type))
> @@ -350,6 +203,18 @@ static int rga_open(struct file *file)
> struct rockchip_rga *rga = video_drvdata(file);
> struct rga_ctx *ctx = NULL;
> int ret = 0;
> + u32 def_width = clamp(DEFAULT_WIDTH, rga->hw->min_width, rga->hw->max_width);
> + u32 def_height = clamp(DEFAULT_HEIGHT, rga->hw->min_height, rga->hw->max_height);
> + struct rga_frame def_frame = {
> + .crop.left = 0,
> + .crop.top = 0,
> + .crop.width = def_width,
> + .crop.height = def_height,
> + .fmt = &rga->hw->formats[0],
> + };
> +
> + def_frame.stride = (def_width * def_frame.fmt->depth) >> 3;
> + def_frame.size = def_frame.stride * def_height;
>
> ctx = kzalloc_obj(*ctx);
> if (!ctx)
> @@ -360,9 +225,9 @@ static int rga_open(struct file *file)
> ctx->out = def_frame;
>
> v4l2_fill_pixfmt_mp(&ctx->in.pix,
> - ctx->in.fmt->fourcc, DEFAULT_WIDTH, DEFAULT_HEIGHT);
> + ctx->in.fmt->fourcc, def_width, def_height);
> v4l2_fill_pixfmt_mp(&ctx->out.pix,
> - ctx->out.fmt->fourcc, DEFAULT_WIDTH, DEFAULT_HEIGHT);
> + ctx->out.fmt->fourcc, def_width, def_height);
>
> if (mutex_lock_interruptible(&rga->mutex)) {
> kfree(ctx);
> @@ -429,12 +294,13 @@ vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
>
> static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
> {
> + struct rockchip_rga *rga = video_drvdata(file);
> struct rga_fmt *fmt;
>
> - if (f->index >= NUM_FORMATS)
> + if (f->index >= rga->hw->num_formats)
> return -EINVAL;
>
> - fmt = &formats[f->index];
> + fmt = &rga->hw->formats[f->index];
> f->pixelformat = fmt->fourcc;
>
> if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
> @@ -469,6 +335,7 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
> {
> struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp;
> struct rga_ctx *ctx = file_to_rga_ctx(file);
> + const struct rga_hw *hw = ctx->rga->hw;
> struct rga_fmt *fmt;
>
> if (V4L2_TYPE_IS_CAPTURE(f->type)) {
> @@ -487,14 +354,14 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
> pix_fmt->xfer_func = frm->pix.xfer_func;
> }
>
> - fmt = rga_fmt_find(pix_fmt->pixelformat);
> + fmt = rga_fmt_find(ctx->rga, pix_fmt->pixelformat);
> if (!fmt)
> - fmt = &formats[0];
> + fmt = &hw->formats[0];
>
> pix_fmt->width = clamp(pix_fmt->width,
> - (u32)MIN_WIDTH, (u32)MAX_WIDTH);
> + hw->min_width, hw->max_width);
> pix_fmt->height = clamp(pix_fmt->height,
> - (u32)MIN_HEIGHT, (u32)MAX_HEIGHT);
> + hw->min_height, hw->max_height);
>
> v4l2_fill_pixfmt_mp(pix_fmt, fmt->fourcc, pix_fmt->width, pix_fmt->height);
> pix_fmt->field = V4L2_FIELD_NONE;
> @@ -529,7 +396,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
> frm->size = 0;
> for (i = 0; i < pix_fmt->num_planes; i++)
> frm->size += pix_fmt->plane_fmt[i].sizeimage;
> - frm->fmt = rga_fmt_find(pix_fmt->pixelformat);
> + frm->fmt = rga_fmt_find(rga, pix_fmt->pixelformat);
> frm->stride = pix_fmt->plane_fmt[0].bytesperline;
>
> /*
> @@ -660,7 +527,7 @@ static int vidioc_s_selection(struct file *file, void *priv,
>
> if (s->r.left + s->r.width > f->pix.width ||
> s->r.top + s->r.height > f->pix.height ||
> - s->r.width < MIN_WIDTH || s->r.height < MIN_HEIGHT) {
> + s->r.width < rga->hw->min_width || s->r.height < rga->hw->min_height) {
> v4l2_dbg(debug, 1, &rga->v4l2_dev, "unsupported crop value.\n");
> return -EINVAL;
> }
> @@ -770,6 +637,10 @@ static int rga_probe(struct platform_device *pdev)
> if (!rga)
> return -ENOMEM;
>
> + rga->hw = of_device_get_match_data(&pdev->dev);
> + if (!rga->hw)
> + return dev_err_probe(&pdev->dev, -ENODEV, "failed to get match data\n");
> +
> rga->dev = &pdev->dev;
> spin_lock_init(&rga->ctrl_lock);
> mutex_init(&rga->mutex);
> @@ -833,8 +704,7 @@ static int rga_probe(struct platform_device *pdev)
> if (ret < 0)
> goto rel_m2m;
>
> - rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
> - rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
> + rga->hw->get_version(rga);
>
> v4l2_info(&rga->v4l2_dev, "HW Version: 0x%02x.%02x\n",
> rga->version.major, rga->version.minor);
> @@ -842,7 +712,7 @@ static int rga_probe(struct platform_device *pdev)
> pm_runtime_put(rga->dev);
>
> /* Create CMD buffer */
> - rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE,
> + rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, rga->hw->cmdbuf_size,
> &rga->cmdbuf_phy, GFP_KERNEL,
> DMA_ATTR_WRITE_COMBINE);
> if (!rga->cmdbuf_virt) {
> @@ -850,9 +720,6 @@ static int rga_probe(struct platform_device *pdev)
> goto rel_m2m;
> }
>
> - def_frame.stride = (DEFAULT_WIDTH * def_frame.fmt->depth) >> 3;
> - def_frame.size = def_frame.stride * DEFAULT_HEIGHT;
> -
> ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
> if (ret) {
> v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
> @@ -865,7 +732,7 @@ static int rga_probe(struct platform_device *pdev)
> return 0;
>
> free_dma:
> - dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
> + dma_free_attrs(rga->dev, rga->hw->cmdbuf_size, rga->cmdbuf_virt,
> rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
> rel_m2m:
> v4l2_m2m_release(rga->m2m_dev);
> @@ -883,7 +750,7 @@ static void rga_remove(struct platform_device *pdev)
> {
> struct rockchip_rga *rga = platform_get_drvdata(pdev);
>
> - dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
> + dma_free_attrs(rga->dev, rga->hw->cmdbuf_size, rga->cmdbuf_virt,
> rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
>
> v4l2_info(&rga->v4l2_dev, "Removing\n");
> @@ -919,9 +786,11 @@ static const struct dev_pm_ops rga_pm = {
> static const struct of_device_id rockchip_rga_match[] = {
> {
> .compatible = "rockchip,rk3288-rga",
> + .data = &rga2_hw,
> },
> {
> .compatible = "rockchip,rk3399-rga",
> + .data = &rga2_hw,
> },
> {},
> };
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index c4a3905a48f0d..640e510285341 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -14,6 +14,9 @@
>
> #define RGA_NAME "rockchip-rga"
>
> +#define DEFAULT_WIDTH 100
> +#define DEFAULT_HEIGHT 100
> +
> struct rga_fmt {
> u32 fourcc;
> int depth;
> @@ -68,6 +71,8 @@ static inline struct rga_ctx *file_to_rga_ctx(struct file *filp)
> return container_of(file_to_v4l2_fh(filp), struct rga_ctx, fh);
> }
>
> +struct rga_hw;
> +
> struct rockchip_rga {
> struct v4l2_device v4l2_dev;
> struct v4l2_m2m_dev *m2m_dev;
> @@ -88,6 +93,8 @@ struct rockchip_rga {
> struct rga_ctx *curr;
> dma_addr_t cmdbuf_phy;
> void *cmdbuf_virt;
> +
> + const struct rga_hw *hw;
> };
>
> struct rga_addr_offset {
> @@ -138,7 +145,19 @@ static inline void rga_mod(struct rockchip_rga *rga, u32 reg, u32 val, u32 mask)
> rga_write(rga, reg, temp);
> };
>
> -void rga_hw_start(struct rockchip_rga *rga,
> - struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
> +struct rga_hw {
> + struct rga_fmt *formats;
> + u32 num_formats;
> + size_t cmdbuf_size;
> + u32 min_width, min_height;
> + u32 max_width, max_height;
> +
> + void (*start)(struct rockchip_rga *rga,
> + struct rga_vb_buffer *src, struct rga_vb_buffer *dst);
> + bool (*handle_irq)(struct rockchip_rga *rga);
> + void (*get_version)(struct rockchip_rga *rga);
> +};
> +
> +extern const struct rga_hw rga2_hw;
>
> #endif
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH AUTOSEL 7.0-5.10] arm64: cputype: Add C1-Pro definitions
From: Sasha Levin @ 2026-05-21 13:50 UTC (permalink / raw)
To: Mark Rutland
Cc: patches, stable, Catalin Marinas, Will Deacon, James Morse,
linux-arm-kernel, linux-kernel
In-Reply-To: <afCWPTqKxIqGPe1r@J2N7QTR9R3>
On Tue, Apr 28, 2026 at 12:13:01PM +0100, Mark Rutland wrote:
>On Tue, Apr 28, 2026 at 06:41:02AM -0400, Sasha Levin wrote:
>> From: Catalin Marinas <catalin.marinas@arm.com>
>>
>> [ Upstream commit 2c99561016c591f4c3d5ad7d22a61b8726e79735 ]
>>
>> Add cputype definitions for C1-Pro. These will be used for errata
>> detection in subsequent patches.
>
>This definition is only needed for a workaround which is only applicable
>to v6.18+ (and the downstream android16-6.12 tree).
>
>We needn't backport this patch to v5.1.0.y unless there's something that
>depends upon it.
I'll drop it, thanks.
--
Thanks,
Sasha
^ permalink raw reply
* Re: [PATCH v14 08/44] arm64: RMI: Ensure that the RMM has GPT entries for memory
From: Marc Zyngier @ 2026-05-21 13:47 UTC (permalink / raw)
To: Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve, WeiLin.Chang, Lorenzo.Pieralisi2
In-Reply-To: <20260513131757.116630-9-steven.price@arm.com>
On Wed, 13 May 2026 14:17:16 +0100,
Steven Price <steven.price@arm.com> wrote:
>
> The RMM maintains the state of all the granules in the system to make
> sure that the host is abiding by the rules. This state can be maintained
> at different granularity, per page (TRACKING_FINE) or per region
> (TRACKING_COARSE). The region size depends on the underlying
> "RMI_GRANULE_SIZE". For a "coarse" region all pages in the region must
> be of the same state, this implies we need to have "fine" tracking for
> DRAM, so that we can delegated individual pages.
>
> For now we only support a statically carved out memory for tracking
> granules for the "fine" regions. This can be extended in the future to
> allow modifying the tracking granularity and remove the need for a
> static allocation.
>
> Similarly, the firmware may create L0 GPT entries describing the total
> address space. But if we change the "PAS" (Physical Address Space) of a
> granule then the firmware may need to create L1 tables to track the PAS
> at a finer granularity.
>
> Note: support is currently missing for SROs which means that if the RMM
> needs memory donating this will fail (and render CCA unusable in Linux).
> This effectively means that the L1 GPT tables must be created before
> Linux starts.
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> Changes since v13:
> * Moved out of KVM
> ---
> arch/arm64/include/asm/rmi_cmds.h | 2 +
> arch/arm64/kernel/rmi.c | 103 ++++++++++++++++++++++++++++++
> 2 files changed, 105 insertions(+)
>
> diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
> index 9179934925c5..9078a2920a7c 100644
> --- a/arch/arm64/include/asm/rmi_cmds.h
> +++ b/arch/arm64/include/asm/rmi_cmds.h
> @@ -33,6 +33,8 @@ struct rmi_sro_state {
> } while (RMI_RETURN_STATUS(res.a0) == RMI_BUSY || \
> RMI_RETURN_STATUS(res.a0) == RMI_BLOCKED)
>
> +bool rmi_is_available(void);
> +
> unsigned long rmi_sro_execute(struct rmi_sro_state *sro, gfp_t gfp);
> void rmi_sro_free(struct rmi_sro_state *sro);
>
> diff --git a/arch/arm64/kernel/rmi.c b/arch/arm64/kernel/rmi.c
> index a14ead5dedda..52a415e99500 100644
> --- a/arch/arm64/kernel/rmi.c
> +++ b/arch/arm64/kernel/rmi.c
> @@ -7,6 +7,8 @@
>
> #include <asm/rmi_cmds.h>
>
> +static bool arm64_rmi_is_available;
> +
> unsigned long rmm_feat_reg0;
> unsigned long rmm_feat_reg1;
>
> @@ -88,6 +90,102 @@ static int rmi_configure(void)
> return 0;
> }
>
> +/*
> + * For now we set the tracking_region_size to 0 for RMI_RMM_CONFIG_SET().
> + * TODO: Support other tracking sizes (via Kconfig option).
> + */
> +#ifdef CONFIG_PAGE_SIZE_4KB
> +#define RMM_GRANULE_TRACKING_SIZE SZ_1G
> +#elif defined(CONFIG_PAGE_SIZE_16KB)
> +#define RMM_GRANULE_TRACKING_SIZE SZ_32M
> +#elif defined(CONFIG_PAGE_SIZE_64KB)
> +#define RMM_GRANULE_TRACKING_SIZE SZ_512M
> +#endif
Basically, a level 2 mapping. Which means this whole block really is:
#define RMM_GRANULE_TRAKING_SIZE (2 * PAGE_SHIFT - 3)
(adjust for D128 as needed).
> +
> +/*
> + * Make sure the area is tracked by RMM at FINE granularity.
> + * We do not support changing the tracking yet.
> + */
> +static int rmi_verify_memory_tracking(phys_addr_t start, phys_addr_t end)
> +{
> + while (start < end) {
> + unsigned long ret, category, state, next;
> +
> + ret = rmi_granule_tracking_get(start, end, &category, &state, &next);
> + if (ret != RMI_SUCCESS ||
> + state != RMI_TRACKING_FINE ||
> + category != RMI_MEM_CATEGORY_CONVENTIONAL) {
> + /* TODO: Set granule tracking in this case */
> + pr_err("Granule tracking for region isn't fine/conventional: %llx",
> + start);
> + return -ENODEV;
How is this triggered? Do we really need to spam the console with
this? A PA doesn't mean much, and there is no context (stack trace).
If that's not expected, turn this into a WARN_ONCE().
> + }
> + start = next;
> + }
> +
> + return 0;
> +}
> +
> +static unsigned long rmi_l0gpt_size(void)
> +{
> + return 1UL << (30 + FIELD_GET(RMI_FEATURE_REGISTER_1_L0GPTSZ,
> + rmm_feat_reg1));
> +}
> +
> +static int rmi_create_gpts(phys_addr_t start, phys_addr_t end)
> +{
> + unsigned long l0gpt_sz = rmi_l0gpt_size();
> +
> + start = ALIGN_DOWN(start, l0gpt_sz);
> + end = ALIGN(end, l0gpt_sz);
> +
> + while (start < end) {
> + int ret = rmi_gpt_l1_create(start);
> +
> + /*
> + * Make sure the L1 GPT tables are created for the region.
> + * RMI_ERROR_GPT indicates the L1 table already exists.
> + */
> + if (ret && ret != RMI_ERROR_GPT) {
> + /*
> + * FIXME: Handle SRO so that memory can be donated for
> + * the tables.
> + */
> + pr_err("GPT Level1 table missing for %llx\n", start);
> + return -ENOMEM;
If any of this fails, where is the cleanup done? Is that part of the
missing SRO support that's indicated in the commit message?
> + }
> + start += l0gpt_sz;
> + }
> +
> + return 0;
> +}
> +
> +static int rmi_init_metadata(void)
> +{
> + phys_addr_t start, end;
> + const struct memblock_region *r;
> +
> + for_each_mem_region(r) {
> + int ret;
> +
> + start = memblock_region_memory_base_pfn(r) << PAGE_SHIFT;
> + end = memblock_region_memory_end_pfn(r) << PAGE_SHIFT;
> + ret = rmi_verify_memory_tracking(start, end);
> + if (ret)
> + return ret;
> + ret = rmi_create_gpts(start, end);
> + if (ret)
> + return ret;
> + }
How does this work with, say, memory hotplug?
> +
> + return 0;
> +}
> +
> +bool rmi_is_available(void)
> +{
> + return arm64_rmi_is_available;
> +}
> +
> static int __init arm64_init_rmi(void)
> {
> /* Continue without realm support if we can't agree on a version */
> @@ -101,6 +199,11 @@ static int __init arm64_init_rmi(void)
>
> if (rmi_configure())
> return 0;
> + if (rmi_init_metadata())
> + return 0;
> +
> + arm64_rmi_is_available = true;
> + pr_info("RMI configured");
>
> return 0;
> }
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v5 3/3] iommu/arm-smmu-v3: Allow ATS to be always on
From: Jason Gunthorpe @ 2026-05-21 13:44 UTC (permalink / raw)
To: Nicolin Chen
Cc: will, joro, bhelgaas, robin.murphy, praan, baolu.lu, kevin.tian,
miko.lenczewski, linux-arm-kernel, iommu, linux-kernel, linux-pci,
dan.j.williams, jonathan.cameron, vsethi, linux-cxl, nirmoyd
In-Reply-To: <ag43NP4UiS7Z9T6q@Asurada-Nvidia>
On Wed, May 20, 2026 at 03:35:32PM -0700, Nicolin Chen wrote:
> @ -3870,13 +3870,15 @@ static int arm_smmu_blocking_set_dev_pasid(struct iommu_domain *new_domain,
> * When the last user of the CD table goes away downgrade the STE back
> * to a non-cd_table one, by re-attaching its sid_domain.
> */
> - if (!master->ats_always_on &&
> - !arm_smmu_ssids_in_use(&master->cd_table)) {
> + if (!arm_smmu_ssids_in_use(&master->cd_table)) {
> struct iommu_domain *sid_domain =
> iommu_driver_get_domain_for_dev(master->dev);
> + bool ats_always_on = master->ats_always_on &&
> + sid_domain->type != IOMMU_DOMAIN_BLOCKED;
> + bool downgrade = sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
> + sid_domain->type == IOMMU_DOMAIN_BLOCKED;
>
> - if (sid_domain->type == IOMMU_DOMAIN_IDENTITY ||
> - sid_domain->type == IOMMU_DOMAIN_BLOCKED)
> + if (!ats_always_on && downgrade)
> sid_domain->ops->attach_dev(sid_domain, dev,
> sid_domain);
Only identity should remain with the CD S1DSS STE, BLOCKED should
attach the normal blocking domain still
Jason
^ permalink raw reply
* Re: [PATCH v7 10/28] media: rockchip: rga: announce and sync colorimetry
From: Michael Tretter @ 2026-05-21 13:44 UTC (permalink / raw)
To: Sven Püschel
Cc: Jacob Chen, Ezequiel Garcia, Mauro Carvalho Chehab,
Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hans Verkuil, linux-media, linux-rockchip, linux-arm-kernel,
linux-kernel, devicetree, kernel, nicolas, sebastian.reichel,
p.zabel, Nicolas Dufresne
In-Reply-To: <20260521-spu-rga3-v7-10-3f33e8c7145f@pengutronix.de>
"announce colorimetry" in the subject is a bit strange. Maybe rephrase
the subject to
media: rockchip: rga: announce CSC and sync colorimetry
On Thu, 21 May 2026 00:44:15 +0200, Sven Püschel wrote:
> Announce the capability to adjust the quantization and ycbcr_enc on the
> capture side and check if the SET_CSC flag is set when the colorimetry
> is changed. Furthermore copy the colorimetry from the output to the
> capture side to fix the currently failing v4l2-compliance tests, which
> expect exactly this behavior.
>
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
> ---
> drivers/media/platform/rockchip/rga/rga.c | 37 +++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index ca8d8a53dc251..8c34f73d69764 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -437,6 +437,15 @@ static int vidioc_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f
> fmt = &formats[f->index];
> f->pixelformat = fmt->fourcc;
>
> + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
> + f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
Is there a reason for not using V4L2_TYPE_IS_CAPTURE(f->type)? I'd also
invert the condition, set the flags in the branch and have a single exit
point of this function.
> + return 0;
> +
> + /* allow changing the quantization and xfer func for YUV formats */
> + if (v4l2_is_format_yuv(v4l2_format_info(f->pixelformat)))
> + f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION |
> + V4L2_FMT_FLAG_CSC_YCBCR_ENC;
> +
> return 0;
> }
>
> @@ -459,8 +468,25 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
> static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
> {
> struct v4l2_pix_format_mplane *pix_fmt = &f->fmt.pix_mp;
> + struct rga_ctx *ctx = file_to_rga_ctx(file);
> struct rga_fmt *fmt;
>
> + if (V4L2_TYPE_IS_CAPTURE(f->type)) {
> + const struct rga_frame *frm;
> +
> + frm = rga_get_frame(ctx, f->type);
> + if (IS_ERR(frm))
> + return PTR_ERR(frm);
> +
> + if (!(pix_fmt->flags & V4L2_PIX_FMT_FLAG_SET_CSC)) {
> + pix_fmt->quantization = frm->pix.quantization;
> + pix_fmt->ycbcr_enc = frm->pix.ycbcr_enc;
> + }
Are there any limits on the colorspace conversion that the RGA can do?
If I understand correctly, user space may set an arbitrary
v4l2_ycbcr_encoding (for example V4L2_YCBCR_ENC_BT2020) and the driver
will happily accept it.
> + /* disallow values not announced in vidioc_enum_fmt */
"disallow values" sounds strange. Maybe:
/* The RGA cannot convert colorspace and xfer_func */
> + pix_fmt->colorspace = frm->pix.colorspace;
> + pix_fmt->xfer_func = frm->pix.xfer_func;
> + }
> +
> fmt = rga_fmt_find(pix_fmt->pixelformat);
> if (!fmt)
> fmt = &formats[0];
> @@ -506,6 +532,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
> frm->fmt = rga_fmt_find(pix_fmt->pixelformat);
> frm->stride = pix_fmt->plane_fmt[0].bytesperline;
>
> + /*
> + * Copy colorimetry from output to capture as required by the
> + * v4l2-compliance tests
> + */
> + if (V4L2_TYPE_IS_OUTPUT(f->type)) {
> + ctx->out.pix.colorspace = pix_fmt->colorspace;
> + ctx->out.pix.ycbcr_enc = pix_fmt->ycbcr_enc;
> + ctx->out.pix.quantization = pix_fmt->quantization;
> + ctx->out.pix.xfer_func = pix_fmt->xfer_func;
I was very confused, because ctx->out is actually the format for
CAPTURE. The comment kind of helps to mark this trap. Not sure, if there
is anything that can be done about this.
Michael
> + }
> +
> /* Reset crop settings */
> frm->crop.left = 0;
> frm->crop.top = 0;
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH 5/6] firmware: samsung: acpm: Add TMU protocol support
From: Alexey Klimov @ 2026-05-21 13:37 UTC (permalink / raw)
To: Peter Griffin
Cc: Tudor Ambarus, Krzysztof Kozlowski, Michael Turquette,
Stephen Boyd, Lee Jones, Alim Akhtar, Sylwester Nawrocki,
Chanwoo Choi, André Draszik, linux-kernel, linux-samsung-soc,
linux-arm-kernel, linux-clk, jyescas, kernel-team,
Krzysztof Kozlowski
In-Reply-To: <CADrjBPqiooFC9o56bOAg-j7908ssPtrzff1reNe6eXmu7hcA=w@mail.gmail.com>
On Thu May 21, 2026 at 9:25 AM BST, Peter Griffin wrote:
> Hi Alexey,
>
> On Wed, 20 May 2026 at 22:01, Alexey Klimov <alexey.klimov@linaro.org> wrote:
>>
>> Hi Tudor,
>>
>> On Tue May 19, 2026 at 4:46 PM BST, Tudor Ambarus wrote:
>> > Hi, Alexey,
>> >
>> > On 5/18/26 2:24 PM, Alexey Klimov wrote:
>> >> Thinking further about this I'd humbly suggest that even
>> >>
>> >> if (fw_err >= 0)
>> >> return 0;
>> >>
>> >> pr_debug_ratelimited("ACPM tmu call returned: %x\n", fw_err);
>> >> or pr_debug(...);
>> >>
>> >> if (fw_err == -1)
>> >> return -EACCES;
>> >>
>> >> some debug message would do.
>> >> Perhaps we need some convertation, for instance as it is done in scmi
>> >> code (scmi_to_linux_errno(), scmi_linux_errmap[]). But I don't have any
>> >> data for mapping acpm errors to some human meanings.
>> >
>> > I did that for the pmic helpers. I don't need any debug prints for
>> > gs101 TMU as I have clear instructions from firmware: 0 for success,
>> > -1 for error.
>>
>> This doesn't look like a right approach for upstreaming a ACPM TMU
>> framework.
>>
>> You are trying to submit a gs101-specific implementation masquerading
>> it as a generic ACPM TMU framework, while explicitly pushing the
>> refactoring work onto the next developer to add support for other
>> SoCs in this generic ACPM code.
>>
>> The ACPM TMU protocol implementation on Exynos850 is different: it uses
>> different error codes, and half of the calls in this 'generic' driver
>> are not even implemented in the Exynos850 firmware. Relying on a
>> hardcoded if (fw_err == -1) in a driver named generic ACPM is broken
>> by design and may silently swallow critical firmware errors on other
>> SoCs.
>>
>> What about such options below?
>> - rename the driver to reflect reality: rename this specifically to
>> gs101-acpm-tmu-something to reflect that it is tailored for gs101-s;
>>
>> or
>> - abstract the firmware error handling paths through driver_data or
>> a dedicated ops structure now, so that other SoCs can cleanly hook into
>> it without having to rewrite the logic later.
>
> AFAIK it's pretty normal not to add new hooks before they are
> required. I think the approach taken in this series makes sense, as
> it's the developer adding support for SoC #2 who best knows what the
> differences are on their platform versus what exists upstream.
> Similarly, the developer adding support for SoC #3 may have different
> requirements to e850 and gs101 and that developer is best placed to
> refactor and add hooks or quirks that are required for that platform.
>
> Let's not try to boil the ocean with this series, it's targeting GS101
> support. We can evolve it for future SoCs as those requirements and
> differences become clear.
Peter, I agree we shouldn't bother about hypothetical SoCs. However,
Exynos850 is not hypothetical (I guess SoC #2 in this text). It is
possible to take set of patches from maillist, copy acpm DT node from
gs101 (minimal compatible rename) and it will be Exynos SoC with enabled
ACPM. I am also actively working on it. Hooks or whatever other way of
handling firmware error codes are required now.
We actually already know the differences: different error codes and
only 4 ACPM TMU calls are implemented on e850: TMU init, TMU read
temperature, TMU suspend/resume.
Extra TMU calls are fine since we can just do not use them from thermal
driver but hiding correct error codes, well, that's another story.
We already know this way of handling firmware codes is not ACPM TMU
generic.
The ACPM TMU part of gs101 ACPM firmware might be a vendor-specific fork.
We shouldn't assume it strictly adheres to the reference Samsung ACPM TMU
design.
Alexey
^ 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