* Re: [PATCH v4 3/5] firmware: arm_ffa: Fix Endpoint Memory Access Descriptor offset calculation
From: Sudeep Holla @ 2026-05-21 12:55 UTC (permalink / raw)
To: Mostafa Saleh
Cc: op-tee, linux-kernel, Sudeep Holla, kvmarm, linux-arm-kernel, maz,
oupton, joey.gouly, suzuki.poulose, catalin.marinas,
jens.wiklander, sumit.garg, sebastianene, vdonnefort
In-Reply-To: <20260520204948.2440882-4-smostafa@google.com>
On Wed, May 20, 2026 at 08:49:46PM +0000, Mostafa Saleh wrote:
> From: Sebastian Ene <sebastianene@google.com>
>
> Use the descriptor's `ep_mem_offset` to calculate the start of the endpoint
> memory access array and to comply with the FF-A spec instead of defaulting
> to `sizeof(struct ffa_mem_region)`.
> This requires moving `ffa_mem_region_additional_setup()` earlier in the setup
> flow.
> Also, add sanity checks to ensure the calculated descriptor offsets do not
> exceed `max_fragsize`.
>
Core change remains same as v3 except improved error checking, so my
review still applies.
Reviewed-by: Sudeep Holla <sudeep.holla@kernel.org>
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v7 08/28] media: rockchip: rga: use stride for offset calculation
From: Michael Tretter @ 2026-05-21 12:52 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-8-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:13 +0200, Sven Püschel wrote:
> Use the stride instead of the width for the offset calculation. This
> ensures that the bytesperline value doesn't need to match the width
> value of the image.
>
> Furthermore this patch removes the dependency on the uv_factor property
> and instead reuses the v4l2_format_info to determine the correct
> division factor.
>
> 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-buf.c | 14 +++++++++-----
> drivers/media/platform/rockchip/rga/rga.c | 16 ----------------
> drivers/media/platform/rockchip/rga/rga.h | 1 -
> 3 files changed, 9 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-buf.c b/drivers/media/platform/rockchip/rga/rga-buf.c
> index bb575873f2b24..65fc0d5b4aa10 100644
> --- a/drivers/media/platform/rockchip/rga/rga-buf.c
> +++ b/drivers/media/platform/rockchip/rga/rga-buf.c
> @@ -14,7 +14,6 @@
> #include <media/videobuf2-dma-sg.h>
> #include <media/videobuf2-v4l2.h>
>
> -#include "rga-hw.h"
> #include "rga.h"
>
> static ssize_t fill_descriptors(struct rga_dma_desc *desc, size_t max_desc,
> @@ -95,14 +94,19 @@ static int rga_buf_init(struct vb2_buffer *vb)
> return 0;
> }
>
> -static int get_plane_offset(struct rga_frame *f, int plane)
> +static int get_plane_offset(struct rga_frame *f,
> + const struct v4l2_format_info *info,
> + int plane)
> {
> + u32 stride = f->pix.plane_fmt[0].bytesperline;
> +
> if (plane == 0)
> return 0;
> if (plane == 1)
> - return f->width * f->height;
> + return stride * f->height;
> if (plane == 2)
> - return f->width * f->height + (f->width * f->height / f->fmt->uv_factor);
> + return stride * f->height +
> + (stride * f->height / info->hdiv / info->vdiv);
>
> return -EINVAL;
> }
> @@ -148,7 +152,7 @@ static int rga_buf_prepare(struct vb2_buffer *vb)
> /* Fill the remaining planes */
> info = v4l2_format_info(f->fmt->fourcc);
> for (i = info->mem_planes; i < info->comp_planes; i++)
> - offsets[i] = get_plane_offset(f, i);
> + offsets[i] = get_plane_offset(f, info, i);
>
> rbuf->offset.y_off = offsets[0];
> rbuf->offset.u_off = offsets[1];
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index 4e710a050cb7c..c07207edffdb6 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -190,7 +190,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_ALPHA_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR8888,
> .depth = 32,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -199,7 +198,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR8888,
> .depth = 32,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -208,7 +206,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_XBGR8888,
> .depth = 32,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -217,7 +214,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_RGB888,
> .depth = 24,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -226,7 +222,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_RGB888,
> .depth = 24,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -235,7 +230,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR4444,
> .depth = 16,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -244,7 +238,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_ABGR1555,
> .depth = 16,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -253,7 +246,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_RB_SWAP,
> .hw_format = RGA_COLOR_FMT_BGR565,
> .depth = 16,
> - .uv_factor = 1,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -262,7 +254,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 1,
> },
> @@ -271,7 +262,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422SP,
> .depth = 16,
> - .uv_factor = 2,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -280,7 +270,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 1,
> },
> @@ -289,7 +278,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420SP,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 1,
> },
> @@ -298,7 +286,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422SP,
> .depth = 16,
> - .uv_factor = 2,
> .y_div = 1,
> .x_div = 1,
> },
> @@ -307,7 +294,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420P,
> .depth = 12,
> - .uv_factor = 4,
> .y_div = 2,
> .x_div = 2,
> },
> @@ -316,7 +302,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_NONE_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV422P,
> .depth = 16,
> - .uv_factor = 2,
> .y_div = 1,
> .x_div = 2,
> },
> @@ -325,7 +310,6 @@ static struct rga_fmt formats[] = {
> .color_swap = RGA_COLOR_UV_SWAP,
> .hw_format = RGA_COLOR_FMT_YUV420P,
> .depth = 12,
> - .uv_factor = 4,
> .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 2db10acecb405..477cf5b62bbb2 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -17,7 +17,6 @@
> struct rga_fmt {
> u32 fourcc;
> int depth;
> - u8 uv_factor;
> u8 y_div;
> u8 x_div;
> u8 color_swap;
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH v4 2/5] firmware: arm_ffa: Fix out-of-bound writes in ffa_setup_and_transmit()
From: Sudeep Holla @ 2026-05-21 12:51 UTC (permalink / raw)
To: Mostafa Saleh
Cc: op-tee, linux-kernel, Sudeep Holla, kvmarm, linux-arm-kernel, maz,
oupton, joey.gouly, suzuki.poulose, catalin.marinas,
jens.wiklander, sumit.garg, sebastianene, vdonnefort
In-Reply-To: <20260520204948.2440882-3-smostafa@google.com>
On Wed, May 20, 2026 at 08:49:45PM +0000, Mostafa Saleh wrote:
> Sashiko (locally) reports multiple out-of-bound issues in
> ffa_setup_and_transmit:
> 1) Writing ep_mem_access->reserved can write out of bounds for FFA
> versions < 1.2 as ffa_emad_size_get() returns 16 bytes in that case
> while reserved has an offset of 24.
> Instead of zeroing fields, memset the struct to zero first based on
> the FFA version.
>
Neat, I clearly missed taking this approach when I added zero-ing of
member initially.
> 2) Make sure there is enough size to write constituents.
>
> While at it, convert the only sizeof() in the driver that uses a
> type instead of variable.
>
Reviewed-by: Sudeep Holla <sudeep.holla@kernel.org>
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v14 05/44] arm64: RMI: Add wrappers for RMI calls
From: Marc Zyngier @ 2026-05-21 12:49 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-6-steven.price@arm.com>
On Wed, 13 May 2026 14:17:13 +0100,
Steven Price <steven.price@arm.com> wrote:
>
> The wrappers make the call sites easier to read and deal with the
> boiler plate of handling the error codes from the RMM.
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> Changes from v13:
> * Update to RMM v2.0-bet1 spec including some SRO support (there still
> some FIXMEs where SRO support is incomplete).
> Changes from v12:
> * Update to RMM v2.0 specification
> Changes from v8:
> * Switch from arm_smccc_1_2_smc() to arm_smccc_1_2_invoke() in
> rmi_rtt_read_entry() for consistency.
> Changes from v7:
> * Minor renaming of parameters and updated comments
> Changes from v5:
> * Further improve comments
> Changes from v4:
> * Improve comments
> Changes from v2:
> * Make output arguments optional.
> * Mask RIPAS value rmi_rtt_read_entry()
> * Drop unused rmi_rtt_get_phys()
> ---
> arch/arm64/include/asm/rmi_cmds.h | 661 ++++++++++++++++++++++++++++++
> 1 file changed, 661 insertions(+)
> create mode 100644 arch/arm64/include/asm/rmi_cmds.h
>
> diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
> new file mode 100644
> index 000000000000..04f7066894e9
> --- /dev/null
> +++ b/arch/arm64/include/asm/rmi_cmds.h
> @@ -0,0 +1,661 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2023 ARM Ltd.
> + */
> +
> +#ifndef __ASM_RMI_CMDS_H
> +#define __ASM_RMI_CMDS_H
> +
> +#include <linux/arm-smccc.h>
> +
> +#include <asm/rmi_smc.h>
> +
> +struct rtt_entry {
> + unsigned long walk_level;
> + unsigned long desc;
> + int state;
> + int ripas;
> +};
> +
> +#define RMI_MAX_ADDR_LIST 256
> +
> +struct rmi_sro_state {
> + struct arm_smccc_1_2_regs regs;
> + unsigned long addr_count;
> + unsigned long addr_list[RMI_MAX_ADDR_LIST];
> +};
> +
> +#define rmi_smccc(...) do { \
> + arm_smccc_1_1_invoke(__VA_ARGS__); \
> +} while (RMI_RETURN_STATUS(res.a0) == RMI_BUSY || \
> + RMI_RETURN_STATUS(res.a0) == RMI_BLOCKED)
> +
> +unsigned long rmi_sro_execute(struct rmi_sro_state *sro, gfp_t gfp);
> +void rmi_sro_free(struct rmi_sro_state *sro);
> +
> +/**
> + * rmi_rmm_config_set() - Configure the RMM
> + * @cfg_ptr: PA of a struct rmm_config
> + *
> + * Sets configuration options on the RMM.
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_rmm_config_set(unsigned long cfg_ptr)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_RMM_CONFIG_SET, cfg_ptr, &res);
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_rmm_activate() - Activate the RMM
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_rmm_activate(void)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_RMM_ACTIVATE, &res);
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_granule_tracking_get() - Get configuration of a Granule tracking region
> + * @start: Base PA of the tracking region
> + * @end: End of the PA region
> + * @out_category: Memory category
> + * @out_state: Tracking region state
> + * @out_top: Top of the memory region
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_granule_tracking_get(unsigned long start,
> + unsigned long end,
> + unsigned long *out_category,
> + unsigned long *out_state,
> + unsigned long *out_top)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_GRANULE_TRACKING_GET, start, end, &res);
> +
> + if (out_category)
> + *out_category = res.a1;
> + if (out_state)
> + *out_state = res.a2;
> + if (out_top)
> + *out_top = res.a3;
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_gpt_l1_create() - Create a Level 1 GPT
> + * @addr: Base of physical address region described by the L1GPT
> + *
> + * Return: RMI return code
> + */
> +static inline int rmi_gpt_l1_create(unsigned long addr)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_GPT_L1_CREATE, addr, &res);
> +
> + if (RMI_RETURN_STATUS(res.a0) == RMI_INCOMPLETE) {
> + /* FIXME */
Is that part of the SRO stuff you're talking about in the notes?
What is the ETA for fixing all these FIXMEs?
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v7 07/28] media: rockchip: rga: use clk_bulk api
From: Michael Tretter @ 2026-05-21 12:48 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-7-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:12 +0200, Sven Püschel wrote:
> Use the clk_bulk API to avoid code duplication for each of the three
> clocks.
>
> 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 | 65 ++++---------------------------
> drivers/media/platform/rockchip/rga/rga.h | 6 +--
> 2 files changed, 11 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
> index fea63b94c5f3d..4e710a050cb7c 100644
> --- a/drivers/media/platform/rockchip/rga/rga.c
> +++ b/drivers/media/platform/rockchip/rga/rga.c
> @@ -698,48 +698,10 @@ static const struct video_device rga_videodev = {
> .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
> };
>
> -static int rga_enable_clocks(struct rockchip_rga *rga)
> -{
> - int ret;
> -
> - ret = clk_prepare_enable(rga->sclk);
> - if (ret) {
> - dev_err(rga->dev, "Cannot enable rga sclk: %d\n", ret);
> - return ret;
> - }
> -
> - ret = clk_prepare_enable(rga->aclk);
> - if (ret) {
> - dev_err(rga->dev, "Cannot enable rga aclk: %d\n", ret);
> - goto err_disable_sclk;
> - }
> -
> - ret = clk_prepare_enable(rga->hclk);
> - if (ret) {
> - dev_err(rga->dev, "Cannot enable rga hclk: %d\n", ret);
> - goto err_disable_aclk;
> - }
> -
> - return 0;
> -
> -err_disable_aclk:
> - clk_disable_unprepare(rga->aclk);
> -err_disable_sclk:
> - clk_disable_unprepare(rga->sclk);
> -
> - return ret;
> -}
> -
> -static void rga_disable_clocks(struct rockchip_rga *rga)
> -{
> - clk_disable_unprepare(rga->sclk);
> - clk_disable_unprepare(rga->hclk);
> - clk_disable_unprepare(rga->aclk);
> -}
> -
> static int rga_parse_dt(struct rockchip_rga *rga)
> {
> struct reset_control *core_rst, *axi_rst, *ahb_rst;
> + int ret;
>
> core_rst = devm_reset_control_get(rga->dev, "core");
> if (IS_ERR(core_rst)) {
> @@ -771,23 +733,12 @@ static int rga_parse_dt(struct rockchip_rga *rga)
> udelay(1);
> reset_control_deassert(ahb_rst);
>
> - rga->sclk = devm_clk_get(rga->dev, "sclk");
> - if (IS_ERR(rga->sclk)) {
> - dev_err(rga->dev, "failed to get sclk clock\n");
> - return PTR_ERR(rga->sclk);
> - }
> -
> - rga->aclk = devm_clk_get(rga->dev, "aclk");
> - if (IS_ERR(rga->aclk)) {
> - dev_err(rga->dev, "failed to get aclk clock\n");
> - return PTR_ERR(rga->aclk);
> - }
> -
> - rga->hclk = devm_clk_get(rga->dev, "hclk");
> - if (IS_ERR(rga->hclk)) {
> - dev_err(rga->dev, "failed to get hclk clock\n");
> - return PTR_ERR(rga->hclk);
> + ret = devm_clk_bulk_get_all(rga->dev, &rga->clks);
> + if (ret < 0) {
This changes the behavior since the call is now successful if there are
no clocks specified in the device tree. Is this an intended change?
Michael
> + dev_err(rga->dev, "failed to get clocks\n");
> + return ret;
> }
> + rga->num_clks = ret;
>
> return 0;
> }
> @@ -935,7 +886,7 @@ static int __maybe_unused rga_runtime_suspend(struct device *dev)
> {
> struct rockchip_rga *rga = dev_get_drvdata(dev);
>
> - rga_disable_clocks(rga);
> + clk_bulk_disable_unprepare(rga->num_clks, rga->clks);
>
> return 0;
> }
> @@ -944,7 +895,7 @@ static int __maybe_unused rga_runtime_resume(struct device *dev)
> {
> struct rockchip_rga *rga = dev_get_drvdata(dev);
>
> - return rga_enable_clocks(rga);
> + return clk_bulk_prepare_enable(rga->num_clks, rga->clks);
> }
>
> static const struct dev_pm_ops rga_pm = {
> diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h
> index 72a28b120fabf..2db10acecb405 100644
> --- a/drivers/media/platform/rockchip/rga/rga.h
> +++ b/drivers/media/platform/rockchip/rga/rga.h
> @@ -6,6 +6,7 @@
> #ifndef __RGA_H__
> #define __RGA_H__
>
> +#include <linux/clk.h>
> #include <linux/platform_device.h>
> #include <media/videobuf2-v4l2.h>
> #include <media/v4l2-ctrls.h>
> @@ -81,9 +82,8 @@ struct rockchip_rga {
> struct device *dev;
> struct regmap *grf;
> void __iomem *regs;
> - struct clk *sclk;
> - struct clk *aclk;
> - struct clk *hclk;
> + struct clk_bulk_data *clks;
> + int num_clks;
> struct rockchip_rga_version version;
>
> /* vfd lock */
>
> --
> 2.54.0
>
>
^ permalink raw reply
* [PATCH v2 3/3] KVM: arm64: Fix memory leak in hyp_trace_unload()
From: Vincent Donnefort @ 2026-05-21 12:46 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort, Sashiko
In-Reply-To: <20260521124613.911067-1-vdonnefort@google.com>
During trace remote loading, hyp_trace_load() allocates the descriptor
pages but fails to store the allocated size in trace_buffer->desc_size.
As a result, when unloading the trace buffer, hyp_trace_unload() calls
free_pages_exact() with a size of 0 which fails to free the memory.
Fix this by updating the descriptor size in trace_buffer->desc_size.
Fixes: 3aed038aac8d ("KVM: arm64: Add trace remote for the nVHE/pKVM hyp")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 8595f9bdb3dc..c4b3ee552131 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -249,6 +249,7 @@ static struct trace_buffer_desc *hyp_trace_load(unsigned long size, void *priv)
goto err_free_desc;
trace_buffer->desc = desc;
+ trace_buffer->desc_size = desc_size;
ret = hyp_trace_buffer_alloc_bpages_backing(trace_buffer, size);
if (ret)
@@ -298,6 +299,7 @@ static void hyp_trace_unload(struct trace_buffer_desc *desc, void *priv)
hyp_trace_buffer_free_bpages_backing(trace_buffer);
free_pages_exact(trace_buffer->desc, trace_buffer->desc_size);
trace_buffer->desc = NULL;
+ trace_buffer->desc_size = 0;
}
static int hyp_trace_enable_tracing(bool enable, void *priv)
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* [PATCH v2 2/3] KVM: arm64: Fix rollback in hyp_trace_buffer_share_hyp()
From: Vincent Donnefort @ 2026-05-21 12:46 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort, Sashiko
In-Reply-To: <20260521124613.911067-1-vdonnefort@google.com>
When sharing the trace buffer with the hypervisor, if sharing a page
fails, the rollback path in hyp_trace_buffer_share_hyp() misses
unsharing the metadata page (meta_va) which was successfully shared
before entering the page sharing loop.
Additionally, if a failure occurs, the cleanup calls
hyp_trace_buffer_unshare_hyp() with an incorrect CPU index. Since that
CPU's pages were already rolled back locally in the loop, this leads to
duplicate unsharing attempts.
Fix both issues affecting the rollback.
Fixes: 3aed038aac8d ("KVM: arm64: Add trace remote for the nVHE/pKVM hyp")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 06805b426101..8595f9bdb3dc 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -212,14 +212,15 @@ static int hyp_trace_buffer_share_hyp(struct hyp_trace_buffer *trace_buffer)
}
if (ret) {
- for (p--; p >= 0; p--)
+ while (--p >= 0)
__unshare_page(rb_desc->page_va[p]);
+ __unshare_page(rb_desc->meta_va);
break;
}
}
if (ret)
- hyp_trace_buffer_unshare_hyp(trace_buffer, cpu--);
+ hyp_trace_buffer_unshare_hyp(trace_buffer, --cpu);
return ret;
}
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* [PATCH v2 1/3] KVM: arm64: Fix meta-page unsharing in pKVM hyp tracing
From: Vincent Donnefort @ 2026-05-21 12:46 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort
In-Reply-To: <20260521124613.911067-1-vdonnefort@google.com>
As the hyp_trace_buffer_unshare_hyp() function name suggests we should
unshare all the previously shared pages, otherwise we leak hyp-shared
pages which won't be reusable for hyp memory.
Fix the typo by calling __unshare_page() on the meta-page, ensuring all
previously shared pages are correctly unshared.
Fixes: 3aed038aac8d ("KVM: arm64: Add trace remote for the nVHE/pKVM hyp")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 8b7f2bf2fba8..06805b426101 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -189,7 +189,7 @@ static void hyp_trace_buffer_unshare_hyp(struct hyp_trace_buffer *trace_buffer,
if (cpu > last_cpu)
break;
- __share_page(rb_desc->meta_va);
+ __unshare_page(rb_desc->meta_va);
for (p = 0; p < rb_desc->nr_page_va; p++)
__unshare_page(rb_desc->page_va[p]);
}
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* [PATCH v2 0/3] Fixes for hyp_trace.c
From: Vincent Donnefort @ 2026-05-21 12:46 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort
While reviewing my v1, Sashiko found a couple of issues with the error path and
more annoyingly a memory leak which I originally missed as the allocated
decriptor isn't tracked by kmemleak.
Changes since v2:
- Fix rollback in hyp_trace_buffer_share_hyp()
- Fix memory leak in hyp_trace_unload()
v1 (https://lore.kernel.org/all/20260521090939.735108-1-vdonnefort@google.com/)
Vincent Donnefort (3):
KVM: arm64: Fix meta-page unsharing in pKVM hyp tracing
KVM: arm64: Fix rollback in hyp_trace_buffer_share_hyp()
KVM: arm64: Fix memory leak in hyp_trace_unload()
arch/arm64/kvm/hyp_trace.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply
* Re: [PATCH v7 06/28] media: rockchip: rga: fix too small buffer size
From: Michael Tretter @ 2026-05-21 12: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-6-3f33e8c7145f@pengutronix.de>
On Thu, 21 May 2026 00:44:11 +0200, Sven Püschel wrote:
> Fix the command buffer size being only a quarter of the actual size.
> The RGA_CMDBUF_SIZE macro was potentially intended to specify the length
> of the cmdbuf u32 array pointer. But as it's used to specify the size of
> the allocation, which is counted in bytes. Therefore adjust the macro
> size to bytes as it better matches the variable name and adjust it's
> users accordingly.
>
> As the command buffer is relatively small, it probably didn't caused
> an issue due to being smaller than a single page.
>
> Fixes: f7e7b48e6d79 ("[media] rockchip/rga: v4l2 m2m support")
> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
>
> ---
>
> Flagged by Sashiko:
> https://sashiko.dev/#/patchset/20260325-spu-rga3-v4-0-e90ec1c61354%40pengutronix.de?part=10
> ---
> drivers/media/platform/rockchip/rga/rga-hw.c | 2 +-
> drivers/media/platform/rockchip/rga/rga-hw.h | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c
> index 43ed742a16492..d1618bb247501 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.c
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.c
> @@ -414,7 +414,7 @@ static void rga_cmd_set(struct rga_ctx *ctx,
> {
> struct rockchip_rga *rga = ctx->rga;
>
> - memset(rga->cmdbuf_virt, 0, RGA_CMDBUF_SIZE * 4);
> + memset(rga->cmdbuf_virt, 0, RGA_CMDBUF_SIZE);
Maybe use rga->hw->cmdbuf_size instead of RGA_CMDBUF_SIZE to really be
in sync with the allocation.
Anyway:
Reviewed-by: Michael Tretter <m.tretter@pengutronix.de>
>
> rga_cmd_set_src_addr(ctx, src->dma_desc_pa);
> /*
> diff --git a/drivers/media/platform/rockchip/rga/rga-hw.h b/drivers/media/platform/rockchip/rga/rga-hw.h
> index cc6bd7f5b0300..2b8537a5fd0d7 100644
> --- a/drivers/media/platform/rockchip/rga/rga-hw.h
> +++ b/drivers/media/platform/rockchip/rga/rga-hw.h
> @@ -6,7 +6,7 @@
> #ifndef __RGA_HW_H__
> #define __RGA_HW_H__
>
> -#define RGA_CMDBUF_SIZE 0x20
> +#define RGA_CMDBUF_SIZE 0x80
>
> /* Hardware limits */
> #define MAX_WIDTH 8192
>
> --
> 2.54.0
>
>
^ permalink raw reply
* Re: [PATCH v14 04/44] arm64: RMI: Add SMC definitions for calling the RMM
From: Marc Zyngier @ 2026-05-21 12:40 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-5-steven.price@arm.com>
On Wed, 13 May 2026 14:17:12 +0100,
Steven Price <steven.price@arm.com> wrote:
>
> The RMM (Realm Management Monitor) provides functionality that can be
> accessed by SMC calls from the host.
>
> The SMC definitions are based on DEN0137[1] version 2.0-bet1
>
> [1] https://developer.arm.com/documentation/den0137/2-0bet1/
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> Changes since v13:
> * Updated to RMM spec v2.0-bet1
> Changes since v12:
> * Updated to RMM spec v2.0-bet0
> Changes since v9:
> * Corrected size of 'ripas_value' in struct rec_exit. The spec states
> this is an 8-bit type with padding afterwards (rather than a u64).
> Changes since v8:
> * Added RMI_PERMITTED_GICV3_HCR_BITS to define which bits the RMM
> permits to be modified.
> Changes since v6:
> * Renamed REC_ENTER_xxx defines to include 'FLAG' to make it obvious
> these are flag values.
> Changes since v5:
> * Sorted the SMC #defines by value.
> * Renamed SMI_RxI_CALL to SMI_RMI_CALL since the macro is only used for
> RMI calls.
> * Renamed REC_GIC_NUM_LRS to REC_MAX_GIC_NUM_LRS since the actual
> number of available list registers could be lower.
> * Provided a define for the reserved fields of FeatureRegister0.
> * Fix inconsistent names for padding fields.
> Changes since v4:
> * Update to point to final released RMM spec.
> * Minor rearrangements.
> Changes since v3:
> * Update to match RMM spec v1.0-rel0-rc1.
> Changes since v2:
> * Fix specification link.
> * Rename rec_entry->rec_enter to match spec.
> * Fix size of pmu_ovf_status to match spec.
> ---
> arch/arm64/include/asm/rmi_smc.h | 448 +++++++++++++++++++++++++++++++
> 1 file changed, 448 insertions(+)
> create mode 100644 arch/arm64/include/asm/rmi_smc.h
>
> diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_smc.h
> new file mode 100644
> index 000000000000..a09b7a631fef
> --- /dev/null
> +++ b/arch/arm64/include/asm/rmi_smc.h
> @@ -0,0 +1,448 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2023-2026 ARM Ltd.
> + *
> + * The values and structures in this file are from the Realm Management Monitor
> + * specification (DEN0137) version 2.0-bet1:
> + * https://developer.arm.com/documentation/den0137/2-0bet1/
How long is this spec going to be available on the ARM web site, which
has a tendency of being reorganised every other week? And there is
already a beta2.
> + */
> +
> +#ifndef __ASM_RMI_SMC_H
> +#define __ASM_RMI_SMC_H
> +
> +#include <linux/arm-smccc.h>
> +
> +#define SMC_RMI_CALL(func) \
> + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
> + ARM_SMCCC_SMC_64, \
> + ARM_SMCCC_OWNER_STANDARD, \
> + (func))
> +
> +#define SMC_RMI_VERSION SMC_RMI_CALL(0x0150)
> +
> +#define SMC_RMI_RTT_DATA_MAP_INIT SMC_RMI_CALL(0x0153)
> +
> +#define SMC_RMI_REALM_ACTIVATE SMC_RMI_CALL(0x0157)
> +#define SMC_RMI_REALM_CREATE SMC_RMI_CALL(0x0158)
> +#define SMC_RMI_REALM_DESTROY SMC_RMI_CALL(0x0159)
> +#define SMC_RMI_REC_CREATE SMC_RMI_CALL(0x015a)
> +#define SMC_RMI_REC_DESTROY SMC_RMI_CALL(0x015b)
> +#define SMC_RMI_REC_ENTER SMC_RMI_CALL(0x015c)
> +#define SMC_RMI_RTT_CREATE SMC_RMI_CALL(0x015d)
> +#define SMC_RMI_RTT_DESTROY SMC_RMI_CALL(0x015e)
> +
> +#define SMC_RMI_RTT_READ_ENTRY SMC_RMI_CALL(0x0161)
> +
> +#define SMC_RMI_RTT_DEV_VALIDATE SMC_RMI_CALL(0x0163)
> +#define SMC_RMI_PSCI_COMPLETE SMC_RMI_CALL(0x0164)
> +#define SMC_RMI_FEATURES SMC_RMI_CALL(0x0165)
> +#define SMC_RMI_RTT_FOLD SMC_RMI_CALL(0x0166)
> +
> +#define SMC_RMI_RTT_INIT_RIPAS SMC_RMI_CALL(0x0168)
> +#define SMC_RMI_RTT_SET_RIPAS SMC_RMI_CALL(0x0169)
> +#define SMC_RMI_VSMMU_CREATE SMC_RMI_CALL(0x016a)
> +#define SMC_RMI_VSMMU_DESTROY SMC_RMI_CALL(0x016b)
> +#define SMC_RMI_RMM_CONFIG_SET SMC_RMI_CALL(0x016e)
> +#define SMC_RMI_PSMMU_IRQ_NOTIFY SMC_RMI_CALL(0x016f)
> +
> +#define SMC_RMI_PDEV_ABORT SMC_RMI_CALL(0x0174)
> +#define SMC_RMI_PDEV_COMMUNICATE SMC_RMI_CALL(0x0175)
> +#define SMC_RMI_PDEV_CREATE SMC_RMI_CALL(0x0176)
> +#define SMC_RMI_PDEV_DESTROY SMC_RMI_CALL(0x0177)
> +#define SMC_RMI_PDEV_GET_STATE SMC_RMI_CALL(0x0178)
> +
> +#define SMC_RMI_PDEV_STREAM_KEY_REFRESH SMC_RMI_CALL(0x017a)
> +#define SMC_RMI_PDEV_SET_PUBKEY SMC_RMI_CALL(0x017b)
> +#define SMC_RMI_PDEV_STOP SMC_RMI_CALL(0x017c)
> +#define SMC_RMI_RTT_AUX_CREATE SMC_RMI_CALL(0x017d)
> +#define SMC_RMI_RTT_AUX_DESTROY SMC_RMI_CALL(0x017e)
> +#define SMC_RMI_RTT_AUX_FOLD SMC_RMI_CALL(0x017f)
> +
> +#define SMC_RMI_VDEV_ABORT SMC_RMI_CALL(0x0185)
> +#define SMC_RMI_VDEV_COMMUNICATE SMC_RMI_CALL(0x0186)
> +#define SMC_RMI_VDEV_CREATE SMC_RMI_CALL(0x0187)
> +#define SMC_RMI_VDEV_DESTROY SMC_RMI_CALL(0x0188)
> +#define SMC_RMI_VDEV_GET_STATE SMC_RMI_CALL(0x0189)
> +#define SMC_RMI_VDEV_UNLOCK SMC_RMI_CALL(0x018a)
> +#define SMC_RMI_RTT_SET_S2AP SMC_RMI_CALL(0x018b)
> +#define SMC_RMI_VDEV_COMPLETE SMC_RMI_CALL(0x018e)
> +
> +#define SMC_RMI_VDEV_GET_INTERFACE_REPORT SMC_RMI_CALL(0x01d0)
> +#define SMC_RMI_VDEV_GET_MEASUREMENTS SMC_RMI_CALL(0x01d1)
> +#define SMC_RMI_VDEV_LOCK SMC_RMI_CALL(0x01d2)
> +#define SMC_RMI_VDEV_START SMC_RMI_CALL(0x01d3)
> +
> +#define SMC_RMI_VSMMU_EVENT_NOTIFY SMC_RMI_CALL(0x01d6)
> +#define SMC_RMI_PSMMU_ACTIVATE SMC_RMI_CALL(0x01d7)
> +#define SMC_RMI_PSMMU_DEACTIVATE SMC_RMI_CALL(0x01d8)
> +
> +#define SMC_RMI_PSMMU_ST_L2_CREATE SMC_RMI_CALL(0x01db)
> +#define SMC_RMI_PSMMU_ST_L2_DESTROY SMC_RMI_CALL(0x01dc)
> +#define SMC_RMI_DPT_L0_CREATE SMC_RMI_CALL(0x01dd)
> +#define SMC_RMI_DPT_L0_DESTROY SMC_RMI_CALL(0x01de)
> +#define SMC_RMI_DPT_L1_CREATE SMC_RMI_CALL(0x01df)
> +#define SMC_RMI_DPT_L1_DESTROY SMC_RMI_CALL(0x01e0)
> +#define SMC_RMI_GRANULE_TRACKING_GET SMC_RMI_CALL(0x01e1)
> +
> +#define SMC_RMI_GRANULE_TRACKING_SET SMC_RMI_CALL(0x01e3)
> +
> +#define SMC_RMI_RMM_CONFIG_GET SMC_RMI_CALL(0x01ec)
> +
> +#define SMC_RMI_RMM_STATE_GET SMC_RMI_CALL(0x01ee)
> +
> +#define SMC_RMI_PSMMU_EVENT_CONSUME SMC_RMI_CALL(0x01f0)
> +#define SMC_RMI_GRANULE_RANGE_DELEGATE SMC_RMI_CALL(0x01f1)
> +#define SMC_RMI_GRANULE_RANGE_UNDELEGATE SMC_RMI_CALL(0x01f2)
> +#define SMC_RMI_GPT_L1_CREATE SMC_RMI_CALL(0x01f3)
> +#define SMC_RMI_GPT_L1_DESTROY SMC_RMI_CALL(0x01f4)
> +#define SMC_RMI_RTT_DATA_MAP SMC_RMI_CALL(0x01f5)
> +#define SMC_RMI_RTT_DATA_UNMAP SMC_RMI_CALL(0x01f6)
> +#define SMC_RMI_RTT_DEV_MAP SMC_RMI_CALL(0x01f7)
> +#define SMC_RMI_RTT_DEV_UNMAP SMC_RMI_CALL(0x01f8)
> +#define SMC_RMI_RTT_ARCH_DEV_MAP SMC_RMI_CALL(0x01f9)
> +#define SMC_RMI_RTT_ARCH_DEV_UNMAP SMC_RMI_CALL(0x01fa)
> +#define SMC_RMI_RTT_UNPROT_MAP SMC_RMI_CALL(0x01fb)
> +#define SMC_RMI_RTT_UNPROT_UNMAP SMC_RMI_CALL(0x01fc)
> +#define SMC_RMI_RTT_AUX_PROT_MAP SMC_RMI_CALL(0x01fd)
> +#define SMC_RMI_RTT_AUX_PROT_UNMAP SMC_RMI_CALL(0x01fe)
> +#define SMC_RMI_RTT_AUX_UNPROT_MAP SMC_RMI_CALL(0x01ff)
> +#define SMC_RMI_RTT_AUX_UNPROT_UNMAP SMC_RMI_CALL(0x0200)
> +#define SMC_RMI_REALM_TERMINATE SMC_RMI_CALL(0x0201)
> +#define SMC_RMI_RMM_ACTIVATE SMC_RMI_CALL(0x0202)
> +#define SMC_RMI_OP_CONTINUE SMC_RMI_CALL(0x0203)
> +#define SMC_RMI_PDEV_STREAM_CONNECT SMC_RMI_CALL(0x0204)
> +#define SMC_RMI_PDEV_STREAM_DISCONNECT SMC_RMI_CALL(0x0205)
> +#define SMC_RMI_PDEV_STREAM_COMPLETE SMC_RMI_CALL(0x0206)
> +#define SMC_RMI_PDEV_STREAM_KEY_PURGE SMC_RMI_CALL(0x0207)
> +#define SMC_RMI_OP_MEM_DONATE SMC_RMI_CALL(0x0208)
> +#define SMC_RMI_OP_MEM_RECLAIM SMC_RMI_CALL(0x0209)
> +#define SMC_RMI_OP_CANCEL SMC_RMI_CALL(0x020a)
> +#define SMC_RMI_VSMMU_FEATURES SMC_RMI_CALL(0x020b)
> +#define SMC_RMI_VSMMU_CMD_GET SMC_RMI_CALL(0x020c)
> +#define SMC_RMI_VSMMU_CMD_COMPLETE SMC_RMI_CALL(0x020d)
> +#define SMC_RMI_PSMMU_INFO SMC_RMI_CALL(0x020e)
> +
> +#define RMI_ABI_MAJOR_VERSION 2
> +#define RMI_ABI_MINOR_VERSION 0
> +
> +#define RMI_ABI_VERSION_GET_MAJOR(version) ((version) >> 16)
> +#define RMI_ABI_VERSION_GET_MINOR(version) ((version) & 0xFFFF)
> +#define RMI_ABI_VERSION(major, minor) (((major) << 16) | (minor))
> +
> +#define RMI_UNASSIGNED 0
> +#define RMI_ASSIGNED 1
> +#define RMI_TABLE 2
> +
> +#define RMI_RETURN_STATUS(ret) ((ret) & 0xFF)
> +#define RMI_RETURN_INDEX(ret) (((ret) >> 8) & 0xFF)
> +#define RMI_RETURN_MEMREQ(ret) (((ret) >> 8) & 0x3)
> +#define RMI_RETURN_CAN_CANCEL(ret) (((ret) >> 10) & 0x1)
Use FIELD_GET() and specify masks that define the actual fields.
> +
> +#define RMI_SUCCESS 0
> +#define RMI_ERROR_INPUT 1
> +#define RMI_ERROR_REALM 2
> +#define RMI_ERROR_REC 3
> +#define RMI_ERROR_RTT 4
> +#define RMI_ERROR_NOT_SUPPORTED 5
> +#define RMI_ERROR_DEVICE 6
> +#define RMI_ERROR_RTT_AUX 7
> +#define RMI_ERROR_PSMMU_ST 8
> +#define RMI_ERROR_DPT 9
> +#define RMI_BUSY 10
> +#define RMI_ERROR_GLOBAL 11
> +#define RMI_ERROR_TRACKING 12
> +#define RMI_INCOMPLETE 13
> +#define RMI_BLOCKED 14
> +#define RMI_ERROR_GPT 15
> +#define RMI_ERROR_GRANULE 16
> +
> +#define RMI_OP_MEM_REQ_NONE 0
> +#define RMI_OP_MEM_REQ_DONATE 1
> +#define RMI_OP_MEM_REQ_RECLAIM 2
> +
> +#define RMI_DONATE_SIZE(req) ((req) & 0x3)
> +#define RMI_DONATE_COUNT_MASK GENMASK(15, 2)
> +#define RMI_DONATE_COUNT(req) (((req) & RMI_DONATE_COUNT_MASK) >> 2)
> +#define RMI_DONATE_CONTIG(req) (!!((req) & BIT(16)))
> +#define RMI_DONATE_STATE(req) (!!((req) & BIT(17)))
FIELD_GET().
> +
> +#define RMI_OP_MEM_DELEGATED 0
> +#define RMI_OP_MEM_UNDELEGATED 1
> +
> +#define RMI_ADDR_TYPE_NONE 0
> +#define RMI_ADDR_TYPE_SINGLE 1
> +#define RMI_ADDR_TYPE_LIST 2
> +
> +#define RMI_ADDR_RANGE_SIZE_MASK GENMASK(1, 0)
> +#define RMI_ADDR_RANGE_COUNT_MASK GENMASK(PAGE_SHIFT - 1, 2)
> +#define RMI_ADDR_RANGE_ADDR_MASK (PAGE_MASK & GENMASK(51, 0))
> +#define RMI_ADDR_RANGE_STATE_MASK BIT(63)
> +
> +#define RMI_ADDR_RANGE_SIZE(ar) (FIELD_GET(RMI_ADDR_RANGE_SIZE_MASK, \
> + (ar)))
> +#define RMI_ADDR_RANGE_COUNT(ar) (FIELD_GET(RMI_ADDR_RANGE_COUNT_MASK, \
> + (ar)))
> +#define RMI_ADDR_RANGE_ADDR(ar) ((ar) & RMI_ADDR_RANGE_ADDR_MASK)
> +#define RMI_ADDR_RANGE_STATE(ar) (FIELD_GET(RMI_ADDR_RANGE_STATE_MASK, \
> + (ar)))
> +
> +enum rmi_ripas {
> + RMI_EMPTY = 0,
> + RMI_RAM = 1,
> + RMI_DESTROYED = 2,
> + RMI_DEV = 3,
> +};
> +
> +#define RMI_NO_MEASURE_CONTENT 0
> +#define RMI_MEASURE_CONTENT 1
> +
> +#define RMI_FEATURE_REGISTER_0_S2SZ GENMASK(7, 0)
> +#define RMI_FEATURE_REGISTER_0_LPA2 BIT(8)
> +#define RMI_FEATURE_REGISTER_0_SVE BIT(9)
> +#define RMI_FEATURE_REGISTER_0_SVE_VL GENMASK(13, 10)
> +#define RMI_FEATURE_REGISTER_0_NUM_BPS GENMASK(19, 14)
> +#define RMI_FEATURE_REGISTER_0_NUM_WPS GENMASK(25, 20)
> +#define RMI_FEATURE_REGISTER_0_PMU BIT(26)
> +#define RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS GENMASK(31, 27)
> +
> +#define RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_4KB BIT(0)
> +#define RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_16KB BIT(1)
> +#define RMI_FEATURE_REGISTER_1_RMI_GRAN_SZ_64KB BIT(2)
> +#define RMI_FEATURE_REGISTER_1_HASH_SHA_256 BIT(3)
> +#define RMI_FEATURE_REGISTER_1_HASH_SHA_384 BIT(4)
> +#define RMI_FEATURE_REGISTER_1_HASH_SHA_512 BIT(5)
> +#define RMI_FEATURE_REGISTER_1_MAX_RECS_ORDER GENMASK(9, 6)
> +#define RMI_FEATURE_REGISTER_1_L0GPTSZ GENMASK(13, 10)
> +#define RMI_FEATURE_REGISTER_1_PPS GENMASK(16, 14)
> +
> +#define RMI_FEATURE_REGISTER_2_DA BIT(0)
> +#define RMI_FEATURE_REGISTER_2_DA_COH BIT(1)
> +#define RMI_FEATURE_REGISTER_2_VSMMU BIT(2)
> +#define RMI_FEATURE_REGISTER_2_ATS BIT(3)
> +#define RMI_FEATURE_REGISTER_2_MAX_VDEVS_ORDER GENMASK(7, 4)
> +#define RMI_FEATURE_REGISTER_2_VDEV_KROU BIT(8)
> +#define RMI_FEATURE_REGISTER_2_NON_TEE_STREAM BIT(9)
> +
> +#define RMI_FEATURE_REGISTER_3_MAX_NUM_AUX_PLANES GENMASK(3, 0)
> +#define RMI_FEATURE_REGISTER_3_RTT_PLAN GENMASK(5, 4)
> +#define RMI_FEATURE_REGISTER_3_RTT_S2AP_INDIRECT BIT(6)
> +
> +#define RMI_FEATURE_REGISTER_4_MEC_COUNT GENMASK(63, 0)
> +
> +#define RMI_MEM_CATEGORY_CONVENTIONAL 0
> +#define RMI_MEM_CATEGORY_DEV_NCOH 1
> +#define RMI_MEM_CATEGORY_DEV_COH 2
> +
> +#define RMI_TRACKING_RESERVED 0
> +#define RMI_TRACKING_NONE 1
> +#define RMI_TRACKING_FINE 2
> +#define RMI_TRACKING_COARSE 3
> +
> +#define RMI_GRANULE_SIZE_4KB 0
> +#define RMI_GRANULE_SIZE_16KB 1
> +#define RMI_GRANULE_SIZE_64KB 2
> +
> +/*
> + * Note many of these fields are smaller than u64 but all fields have u64
> + * alignment, so use u64 to ensure correct alignment.
> + */
> +struct rmm_config {
> + union { /* 0x0 */
> + struct {
> + u64 tracking_region_size;
> + u64 rmi_granule_size;
> + };
> + u8 sizer[0x1000];
SZ_4K?
> + };
> +};
> +
> +#define RMI_REALM_PARAM_FLAG_LPA2 BIT(0)
> +#define RMI_REALM_PARAM_FLAG_SVE BIT(1)
> +#define RMI_REALM_PARAM_FLAG_PMU BIT(2)
> +
> +struct realm_params {
> + union { /* 0x0 */
> + struct {
> + u64 flags;
> + u64 s2sz;
> + u64 sve_vl;
> + u64 num_bps;
> + u64 num_wps;
> + u64 pmu_num_ctrs;
> + u64 hash_algo;
> + u64 num_aux_planes;
> + };
> + u8 padding0[0x400];
SZ_1K? And similarly all over the shop?
I haven't checked the details of the encodings (life is too short),
but I wonder how much of this exists as an MRS and could be
automatically generated?
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v3] i2c: imx: mark I2C adapter when hardware is powered down
From: Mukesh Savaliya @ 2026-05-21 12:39 UTC (permalink / raw)
To: Carlos Song (OSS), Mukesh Savaliya, o.rempel@pengutronix.de,
kernel@pengutronix.de, andi.shyti@kernel.org, Frank Li,
s.hauer@pengutronix.de, festevam@gmail.com, Carlos Song,
Bough Chen
Cc: linux-i2c@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org
In-Reply-To: <AM0PR04MB68024A0FAF0637726C08B87BE80E2@AM0PR04MB6802.eurprd04.prod.outlook.com>
On 5/21/2026 5:32 PM, Carlos Song (OSS) wrote:
>
>
>> -----Original Message-----
>> From: Mukesh Savaliya <mukesh.savaliya@oss.qualcomm.com>
>> Sent: Thursday, May 21, 2026 7:14 PM
>> To: Carlos Song (OSS) <carlos.song@oss.nxp.com>; Mukesh Savaliya
>> <mukesh.savaliya@oss.qualcomm.com>; o.rempel@pengutronix.de;
>> kernel@pengutronix.de; andi.shyti@kernel.org; Frank Li <frank.li@nxp.com>;
>> s.hauer@pengutronix.de; festevam@gmail.com; Carlos Song
>> <carlos.song@nxp.com>; Bough Chen <haibo.chen@nxp.com>
>> Cc: linux-i2c@vger.kernel.org; imx@lists.linux.dev;
>> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
>> stable@vger.kernel.org
>> Subject: Re: [PATCH v3] i2c: imx: mark I2C adapter when hardware is powered
>> down
>>
>>
>> On 5/21/2026 4:21 PM, Carlos Song (OSS) wrote:
>>
>> [...]
>>
>>>>>> -----Original Message-----
>>>>>> From: Mukesh Savaliya <mukesh.savaliya@oss.qualcomm.com>
>>>>>> Sent: Thursday, May 21, 2026 3:40 PM
>>>>>> To: Carlos Song (OSS) <carlos.song@oss.nxp.com>;
>>>>>> o.rempel@pengutronix.de; kernel@pengutronix.de;
>>>>>> andi.shyti@kernel.org; Frank Li <frank.li@nxp.com>;
>>>>>> s.hauer@pengutronix.de; festevam@gmail.com; Carlos Song
>>>>>> <carlos.song@nxp.com>; Bough Chen <haibo.chen@nxp.com>
>>>>>> Cc: linux-i2c@vger.kernel.org; imx@lists.linux.dev;
>>>>>> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
>>>>>> stable@vger.kernel.org
>>>>>> Subject: Re: [PATCH v3] i2c: imx: mark I2C adapter when hardware is
>>>>>> powered down
>>>>>>
>>>>>> Hi Carlos,
>>>>>>
>>>>>> On 5/20/2026 3:45 PM, Carlos Song (OSS) wrote:
>>>>>>> From: Carlos Song <carlos.song@nxp.com>
>>>>>>>
>>>>>>> Mark the I2C adapter as suspended during system suspend to block
>>>>>>> further transfers, and resume it on system resume. This prevents
>>>>>>> potential hangs when the hardware is powered down but clients
>>>>>>> still attempt
>>>>>> I2C transfers.
>>>>>>>
>>>> what was the reason of this hang ? I was thinking you don't have
>>>> interrupts working when client requested transfer but adapter was
>>>> suspended. Please correct me if wrong.
>>>>
>>>> And it would be good to mention the actual problem and why/how it
>> occurred.
>>>>>> Code changes looks fine to me but have comment on commit log.
>>>>>>
>>>>>> It seems, you are adding support of _noirq() callbacks to allow
>>>>>> transfers during suspend/resume noirq phase of PM.
>>>>>>
>>>>>> Would it make sense if you can write "Replace system PM callbacks
>>>>>> with noirq PM callbacks" OR "Allow transfers during _noirq phase of
>>>>>> the PM ops" instead of "mark I2C adapter when hardware is powered
>>>> down" ?
>>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> Thank you for your comments!
>>>>>
>>>>> But this patch is added is not for support noirq PM callback or
>>>>> transfer in noirq
>>>> phase.
>>>>>
>>>> Okay, may be actual problem description can help me.
>>>>> In fact, this fix is to mark the I2C adapter as suspended during
>>>>> system noirq suspend to block further transfers, and resume it on
>>>>> system noirq resume. This is to prohibit I2C device calling the I2C
>>>>> controller after the system noirq suspend and before noirq resume,
>>>>> because at
>>>> this time the I2C instance is powered off or the clock is disabled
>>>> ... So I want to keep current commit. How do you think?
>>>> completely Makes sense. Please help add how this problem occurred and
>> why ?
>>>> So the change/fix will be good to understand against it.
>>>
>>> Hi,
>>>
>>> In some I.MX platform, some I2C devices will keep a work queue all
>>> time, the work queue will trigger I2C xfer every once in a while, but the work
>> queue shouldn't be free in system suspend.
>>>
>>
>> work queue has transfers queued even if system is suspended ? IMO, the client
>> i2c devices should not let system go to suspend.
>>
>
> Hi Mukesh,
>
> Thank you for the detailed discussion.
>
> Yes, I totally agree that I2C client drivers should ideally stop
> issuing transfers when the system is suspending.
>
> However, in practice there are many different I2C clients, and not all
> of them strictly adhere to this requirement. Some clients may still
> trigger transfers through workqueues or deferred contexts during the
> suspend/resume window.
>
> Therefore, adding this protection at the I2C controller side helps to
> avoid unexpected accesses when the hardware resources are unavailable,
> making the system more robust.
>
Agreed !
>>> Within a very short time window, possibly from noirq_suspend to the
>>> system actually being suspended, or possibly from the system starting
>>> to resume to before noirq_resume, this work queue will trigger an I2C
>>> transfer, and at this time the I2C controller's clk and pinctrl have
>>> not yet been restored, reading and
>>
>> Right, this kind of explains the problem to me. I think you are trying to serve
>> i2c transfers when your resources(clk, pinctrl) are not turned ON and also
>> interrupt remains disabled. And that's why you need to add
>> _noir() PM callbacks supports along with IRQF_NO_SUSPEND |
>> IRQF_EARLY_RESUME flags.
>>
>>> writing I2C registers causes the system to hang. This patch make all
>>> I2C operations are performed in a safe hardware state.
>>>
>>> Is it better if I add these comment to patch commit log?
>>>>>
>> if my latest comments makes sense against the issue, you may write
>> accordingly. if i am wrong, then your explanation makes sense. Cause of the
>> hang needs to be clearly mention int the commit log in your next patch.
>>
>
> Based on our discussion, I have updated the commit log as below:
>
> On some i.MX platforms, certain I2C client drivers keep a periodic
> workqueue which continues to trigger I2C transfers.
>
> During system suspend/resume, there exists a time window between:
> - noirq_suspend and full suspend
> - resume start and noirq_resume
- noirq_resume and resume start [Just opposite ?]
>
> In this window, the I2C controller resources such as clock and pinctrl
> may already be disabled or not yet restored.
>
> If a workqueue triggers an I2C transfer in this period, the driver
> attempts to access I2C registers while the hardware resources are
> unavailable, which may lead to system hang.
>
> Mark the I2C adapter as suspended during noirq suspend and block new
> transfers until resume, ensuring that I2C transfers are only issued
> when hardware resources are available.
>
> Does this look good to you?
>
Looks good, Thanks !
>>>>
>>>
>
^ permalink raw reply
* Re: [PATCH] irqchip/exynos-combiner: switch to raw_spinlock
From: Thomas Gleixner @ 2026-05-21 12:31 UTC (permalink / raw)
To: Marek Szyprowski, linux-arm-kernel, linux-samsung-soc,
linux-rt-devel
Cc: Krzysztof Kozlowski, Alim Akhtar, Sebastian Andrzej Siewior,
Clark Williams, Steven Rostedt
In-Reply-To: <97f33a9d-5fdd-4766-aaff-d10d5f5fdf28@samsung.com>
On Thu, May 21 2026 at 13:26, Marek Szyprowski wrote:
> On 21.05.2026 11:06, Thomas Gleixner wrote:
>> What is this lock actually protecting?
>>
>> Each combiner has it's own @base address, so there is no concurrency
>> problem between two cascade interrupts being handled at the same time.
>>
>> That means the only possible problem would be that the same cascade
>> interrupt is handled on two CPUs concurrently. Is that even possible?
> Frankly speaking I did this conversion mechanically, late in the evening to fix
> the bug warning I've spotted. Indeed this spinlock looks like a copy&paste or
> development leftover. The only side-effect of it I see is a memory barrier,
> which might affect how the register access happens, but this should not affect
> cascade operation imho. Do You want me to send a patch removing it completely?
I've applied the fixup for now. But, yes please send a removal against
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/urgent
Thanks,
tglx
^ permalink raw reply
* Re: [PATCH v22 08/13] mfd: core: Add firmware-node support to MFD cells
From: Bartosz Golaszewski @ 2026-05-21 12:29 UTC (permalink / raw)
To: Lee Jones
Cc: Shivendra Pratap, Sebastian Reichel, Mark Rutland,
Lorenzo Pieralisi, Rafael J. Wysocki, Daniel Lezcano,
Christian Loehle, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Arnd Bergmann,
Souvik Chakravarty, Andy Yan, Matthias Brugger, John Stultz,
Moritz Fischer, Sudeep Holla, linux-pm, linux-kernel,
linux-arm-msm, linux-arm-kernel, devicetree, Florian Fainelli,
Krzysztof Kozlowski, Dmitry Baryshkov, Mukesh Ojha, Andre Draszik,
Greg Kroah-Hartman, Kathiravan Thirumoorthy, Srinivas Kandagatla,
Bartosz Golaszewski
In-Reply-To: <20260521112638.GD2921053@google.com>
On Thu, May 21, 2026 at 1:26 PM Lee Jones <lee@kernel.org> wrote:
>
> On Thu, 14 May 2026, Shivendra Pratap wrote:
>
> > MFD core has no way to register a child device using an explicit firmware
> > node. This prevents drivers from registering child nodes when those nodes
> > do not define a compatible string. One such example is the PSCI
> > "reboot-mode" node, which omits a compatible string as it describes
> > boot-states provided by the underlying firmware.
> >
> > Extend struct mfd_cell with a callback that allows drivers to provide an
> > explicit firmware node. The node is added to the MFD child device during
> > registration when none is assigned by device tree, ACPI, or software
> > matching.
> >
> > Suggested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> > Signed-off-by: Shivendra Pratap <shivendra.pratap@oss.qualcomm.com>
> > ---
> > drivers/mfd/mfd-core.c | 30 ++++++++++++++++++++++++++++++
> > include/linux/mfd/core.h | 14 ++++++++++++++
> > 2 files changed, 44 insertions(+)
> >
> > diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> > index 7aa32b90cf1eb7fa0a05bf3dc506e60a262c9850..cc2a2a924d6d3044e29a9f864b536ee325ed797b 100644
> > --- a/drivers/mfd/mfd-core.c
> > +++ b/drivers/mfd/mfd-core.c
> > @@ -10,6 +10,7 @@
> > #include <linux/kernel.h>
> > #include <linux/platform_device.h>
> > #include <linux/acpi.h>
> > +#include <linux/fwnode.h>
> > #include <linux/list.h>
> > #include <linux/property.h>
> > #include <linux/mfd/core.h>
> > @@ -148,6 +149,11 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
> > return 0;
> > }
> >
> > +static void mfd_child_fwnode_put(void *data)
> > +{
> > + fwnode_handle_put(data);
> > +}
> > +
> > static int mfd_add_device(struct device *parent, int id,
> > const struct mfd_cell *cell,
> > struct resource *mem_base,
> > @@ -156,6 +162,7 @@ static int mfd_add_device(struct device *parent, int id,
> > struct resource *res;
> > struct platform_device *pdev;
> > struct mfd_of_node_entry *of_entry, *tmp;
> > + struct fwnode_handle *fwnode;
> > bool disabled = false;
> > int ret = -ENOMEM;
> > int platform_id;
> > @@ -224,6 +231,29 @@ static int mfd_add_device(struct device *parent, int id,
> >
> > mfd_acpi_add_device(cell, pdev);
> >
> > + if (!pdev->dev.fwnode && cell->get_child_fwnode) {
> > + fwnode = cell->get_child_fwnode(parent);
> > + if (fwnode) {
> > + device_set_node(&pdev->dev, fwnode);
> > +
> > + /*
> > + * platform_device_release() drops only of_node refs.
> > + * Track non-OF fwnodes explicitly so they are put on
> > + * all teardown paths.
> > + */
> > + if (!to_of_node(fwnode)) {
> > + ret = devm_add_action(&pdev->dev,
> > + mfd_child_fwnode_put,
> > + fwnode);
> > + if (ret) {
> > + device_set_node(&pdev->dev, NULL);
> > + fwnode_handle_put(fwnode);
> > + goto fail_of_entry;
> > + }
> > + }
> > + }
> > + }
>
> mfd_add_device() is getting very busy now with support for all of these
> different registration APIs. Suggest that we start breaking them out.
>
> > +
> > if (cell->pdata_size) {
> > ret = platform_device_add_data(pdev,
> > cell->platform_data, cell->pdata_size);
> > diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
> > index faeea7abd688f223fb0b31cde0a9b69dfe2a61ff..abfc26c057d6ee46947ba2b6f2e99f420e74b127 100644
> > --- a/include/linux/mfd/core.h
> > +++ b/include/linux/mfd/core.h
> > @@ -50,6 +50,7 @@
> > #define MFD_DEP_LEVEL_HIGH 1
> >
> > struct irq_domain;
> > +struct fwnode_handle;
> > struct software_node;
> >
> > /* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */
> > @@ -80,6 +81,19 @@ struct mfd_cell {
> >
> > /* Software node for the device. */
> > const struct software_node *swnode;
> > + /*
> > + * Callback to return an explicit firmware node.
> > + * @parent: MFD parent device passed to mfd_add_devices().
> > + *
> > + * Called only if OF/ACPI matching did not assign a fwnode.
> > + * Ownership of the returned reference is transferred to MFD core.
> > + *
> > + * Return a referenced fwnode or NULL if none is available.
> > + *
> > + * mfd_cell must be zero-initialized or get_child_fwnode must be NULL
> > + * when unused.
> > + */
> > + struct fwnode_handle *(*get_child_fwnode)(struct device *parent);
>
> I'm very much against pointers to functions if they can be avoided. Why
> does fwnode need this and none of the other APIs do?
>
I suggested it because of its flexibility. The alternative I had in
mind is something like a new field in mfd_cell:
const char *cell_node_name;
Which - if set - would tell MFD to look up an fwnode that's a child of
the parent device's node by name - as it may not have a compatible.
Bart
^ permalink raw reply
* [PATCH] arm: Implement _THIS_IP_ using inline asm
From: Marco Elver @ 2026-05-21 12:29 UTC (permalink / raw)
To: elver, Russell King; +Cc: linux-arm-kernel, linux-kernel, kasan-dev
Both GCC [1] and Clang [2] consider the generic version of _THIS_IP_ to
be broken:
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
In particular, the address of a label is only expected to be used with a
computed goto.
While the generic version more or less works today, it is known to be
brittle and may break with current and future optimizations. For
example, Clang -O2 always returns 1 when this function is inlined:
static inline unsigned long get_ip(void)
{ return ({ __label__ __here; __here: (unsigned long)&&__here; }); }
Fix it by overriding _THIS_IP_ in <asm/linkage.h> (which is included by
<linux/instruction_pointer.h>) using an architecture-specific inline asm
version. Additionally, avoiding taking the address of a label prevents
compilers from emitting spurious indirect branch targets (e.g. ENDBR or
BTI) under control-flow integrity schemes.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120071 [1]
Link: https://github.com/llvm/llvm-project/issues/138272 [2]
Signed-off-by: Marco Elver <elver@google.com>
---
arch/arm/include/asm/linkage.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/include/asm/linkage.h b/arch/arm/include/asm/linkage.h
index c4670694ada7..416e6a242dc4 100644
--- a/arch/arm/include/asm/linkage.h
+++ b/arch/arm/include/asm/linkage.h
@@ -9,4 +9,6 @@
.type name, %function; \
END(name)
+#define _THIS_IP_ ({ unsigned long __ip; asm volatile("1: adr %0, 1b" : "=r" (__ip)); __ip; })
+
#endif
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* Re: [PATCH v02] mailbox: pcc: report errors for PCC clients
From: lihuisong (C) @ 2026-05-21 12:26 UTC (permalink / raw)
To: Sudeep Holla
Cc: Adam Young, Jassi Brar, linux-kernel, linux-hwmon,
Rafael J . Wysocki, Len Brown, linux-acpi, Andi Shyti,
Guenter Roeck, MyungJoo Ham, Kyungmin Park, Chanwoo Choi,
linux-arm-kernel
In-Reply-To: <20260520-optimal-nightingale-of-champagne-0bbdfe@sudeepholla>
On 5/20/2026 9:32 PM, Sudeep Holla wrote:
> On Wed, May 20, 2026 at 07:53:45PM +0800, lihuisong (C) wrote:
>> On 5/20/2026 12:25 AM, Sudeep Holla wrote:
>>> On Tue, May 19, 2026 at 09:54:47PM +0800, lihuisong (C) wrote:
> [...]
>
>>>> @Sudeep, I have always had doubts about the addition of this line of code in
>>>> the
>>>> commit 9c753f7c953c (mailbox: pcc: Mark Tx as complete in PCC IRQ handler).
>>>> The patch seems to avoid the timeouts in the mailbox core according to its
>>>> commit log.
>>>> Regardless of whether the command succeeds or fails, each mbox client
>>>> driver, like cppc_acpi/acpi_pcc,kunpeng_hccs and so on, is responsible to
>>>> call mbox_chan_txdone() to tell mailbox core.
>>> Few controller drivers do have mbox_chan_txdone(), so Tx complete is detected
>> Which controller driver?
> git grep mbox_chan_txdone drivers/mailbox/
Ok
>
>>> by PCC, so not sure why you think this is not the right place to do. The irq
>> Because many mbox client drivers call mbox_chan_txdone() after running
>> rx_callback() in mbox_chan_received_data().
> OK, but why can't the controller hide that for the clients ? What am I missing?
Now I know what you want to do.
It's ok for me to do that in controller on irq scene.
But we also need to fix the mbox_chan_txdone() code in all client drivers.
>
>> These drivers doesn't set chan->cl->tx_block to true.
>> It seems that the client driver having tx_block need to set
>> chan->tx_complete in tx_tick().
>> Do you add this code for them?
> I don't quite follow you.
please ship this.
>
>>> is to indicate the completion. I am confused as why you think otherwise.
>>> It is defined in include/linux/mailbox_controller.h for the same reason.
>>>
>>> The client drivers can you mbox_client_txdone() if they wish to as defined
>>> in include/linux/mailbox_client.h
>> mbox_client_txdone() is used in the case that txdone_method is
>> MBOX_TXDONE_BY_ACK.
> Yes and agreed.
>
>> And mbox clinte driver using IRQ method need to use mbox_chan_txdone().
> Client doesn't handle IRQ its always controller driver and client must have
> no business to do that IMO.
Ack
mbox_chan_txdone should be used by controller as this function comment
said.
>
>> It seems that all the current client drivers are used in this way.
>> These interface internal would verify chan->txdone_method.
>>
> Yes, sounds wrong to me.
>
> drivers/acpi/acpi_pcc.c
> drivers/acpi/cppc_acpi.c
> drivers/hwmon/xgene-hwmon.c
> drivers/i2c/busses/i2c-xgene-slimpro.c
> drivers/soc/hisilicon/kunpeng_hccs.c
>
> It is very clear from the code in mailbox.c, mbox_client_txdone() is for
> the client drivers and mbox_chan_txdone() is for the controller. We need
> to fix the above list but I need to check if there is anything I am missing
> to understand first. Please let me know.
Agreed.
>
>> In addition, I find that you also modify the txdone_irq/poll in the commit
>> 3349f800609e (mailbox: pcc: Set txdone_irq/txdone_poll based on PCCT flags).
>> The txdone_method will change from MBOX_TXDONE_BY_ACK to MBOX_TXDONE_BY_POLL
>> on the platform using poll mode.
>> This may lead to the original mbox client driver printing exceptions in
>> mbox_client_txdone.
>> I haven't observed it based on the latest code yet, it's just code analysis.
> Right, I do remember seeing something and wonder if I moved to
> mbox_chan_txdone() in drivers/acpi/acpi_pcc.c for that reason. But if the
> expectations I have mentioned are correct, then we need to fix the framework
> to avoid throwing that warnings.
Yeah, we also need to do something for your another commit
3349f800609e (mailbox: pcc: Set txdone_irq/txdone_poll based on PCCT
flags).
>
^ permalink raw reply
* Re: [PATCH v14 03/44] arm64: RME: Handle Granule Protection Faults (GPFs)
From: Marc Zyngier @ 2026-05-21 12:25 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-4-steven.price@arm.com>
On Wed, 13 May 2026 14:17:11 +0100,
Steven Price <steven.price@arm.com> wrote:
>
> If the host attempts to access granules that have been delegated for use
> in a realm these accesses will be caught and will trigger a Granule
> Protection Fault (GPF).
>
> A fault during a page walk signals a bug in the kernel and is handled by
> oopsing the kernel. A non-page walk fault could be caused by user space
> having access to a page which has been delegated to the kernel and will
> trigger a SIGBUS to allow debugging why user space is trying to access a
> delegated page.
>
> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> Reviewed-by: Gavin Shan <gshan@redhat.com>
> Signed-off-by: Steven Price <steven.price@arm.com>
> ---
> Changes since v10:
> * Don't call arm64_notify_die() in do_gpf() but simply return 1.
> Changes since v2:
> * Include missing "Granule Protection Fault at level -1"
> ---
> arch/arm64/mm/fault.c | 28 ++++++++++++++++++++++------
> 1 file changed, 22 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 0f3c5c7ca054..6358ea4787ba 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -905,6 +905,22 @@ static int do_tag_check_fault(unsigned long far, unsigned long esr,
> return 0;
> }
>
> +static int do_gpf_ptw(unsigned long far, unsigned long esr, struct pt_regs *regs)
> +{
> + const struct fault_info *inf = esr_to_fault_info(esr);
> +
> + die_kernel_fault(inf->name, far, esr, regs);
> + return 0;
> +}
> +
> +static int do_gpf(unsigned long far, unsigned long esr, struct pt_regs *regs)
> +{
> + if (!is_el1_instruction_abort(esr) && fixup_exception(regs, esr))
> + return 0;
> +
> + return 1;
> +}
> +
> static const struct fault_info fault_info[] = {
> { do_bad, SIGKILL, SI_KERNEL, "ttbr address size fault" },
> { do_bad, SIGKILL, SI_KERNEL, "level 1 address size fault" },
> @@ -941,12 +957,12 @@ static const struct fault_info fault_info[] = {
> { do_bad, SIGKILL, SI_KERNEL, "unknown 32" },
> { do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" },
> { do_bad, SIGKILL, SI_KERNEL, "unknown 34" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 35" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 36" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 37" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 38" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 39" },
> - { do_bad, SIGKILL, SI_KERNEL, "unknown 40" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "Granule Protection Fault at level -1" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "Granule Protection Fault at level 0" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "Granule Protection Fault at level 1" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "Granule Protection Fault at level 2" },
> + { do_gpf_ptw, SIGKILL, SI_KERNEL, "Granule Protection Fault at level 3" },
> + { do_gpf, SIGBUS, SI_KERNEL, "Granule Protection Fault not on table walk" },
It wouldn't hurt to align the textual description with what we have
for other fault syndromes:
"level X granule protection fault (translation table walk)"
for the PTW-trigger faults, and
"granule protection fault"
for the non PTW case.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* [PATCH v9 4/4] coresight: cti: expose banked sysfs registers for Qualcomm extended CTI
From: Yingchao Deng @ 2026-05-21 12:16 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
jinlong.mao, quic_yingdeng, tingwei.zhang, jie.gan, Yingchao Deng
In-Reply-To: <20260521-extended_cti-v9-0-d21f4f92c51e@oss.qualcomm.com>
Qualcomm extended CTI implements banked trigger status and integration
registers, where each bank covers 32 triggers. Multiple instances of
these registers are required to expose the full trigger space.
Add coresight_cti_reg_index(), coresight_cti_reg_rw_index(), and
coresight_cti_reg_wo_index() macros that carry the bank index in the
cs_off_attribute.index field, keeping the base offset and index
separate rather than encoding them together.
Add static sysfs entries for the banked CTI registers and control
their visibility based on the underlying hardware configuration.
Visibility is determined by comparing the attribute's index against
the number of banks implied by nr_trig_max (32 triggers per bank).
Registers beyond the hardware capacity are hidden, preserving the
existing ABI on standard ARM CTIs while exposing the full register
set on Qualcomm CTIs.
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 58 +++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 7191a478b2da..feecc9d6563f 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -207,6 +207,15 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
} \
})[0].attr.attr)
+#define coresight_cti_reg_index(name, offset, idx) \
+ (&((struct cs_off_attribute[]) { \
+ { \
+ __ATTR(name, 0444, coresight_cti_reg_show, NULL), \
+ offset, \
+ idx \
+ } \
+ })[0].attr.attr)
+
#define coresight_cti_reg_rw(name, offset) \
(&((struct cs_off_attribute[]) { \
{ \
@@ -217,6 +226,16 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
} \
})[0].attr.attr)
+#define coresight_cti_reg_rw_index(name, offset, idx) \
+ (&((struct cs_off_attribute[]) { \
+ { \
+ __ATTR(name, 0644, coresight_cti_reg_show, \
+ coresight_cti_reg_store), \
+ offset, \
+ idx \
+ } \
+ })[0].attr.attr)
+
#define coresight_cti_reg_wo(name, offset) \
(&((struct cs_off_attribute[]) { \
{ \
@@ -226,6 +245,15 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
} \
})[0].attr.attr)
+#define coresight_cti_reg_wo_index(name, offset, idx) \
+ (&((struct cs_off_attribute[]) { \
+ { \
+ __ATTR(name, 0200, NULL, coresight_cti_reg_store), \
+ offset, \
+ idx \
+ } \
+ })[0].attr.attr)
+
/* coresight management registers */
static struct attribute *coresight_cti_mgmt_attrs[] = {
coresight_cti_reg(devaff0, CTIDEVAFF0),
@@ -515,18 +543,36 @@ static struct attribute *coresight_cti_regs_attrs[] = {
&dev_attr_appclear.attr,
&dev_attr_apppulse.attr,
coresight_cti_reg(triginstatus, CTITRIGINSTATUS),
+ coresight_cti_reg_index(triginstatus1, CTITRIGINSTATUS, 1),
+ coresight_cti_reg_index(triginstatus2, CTITRIGINSTATUS, 2),
+ coresight_cti_reg_index(triginstatus3, CTITRIGINSTATUS, 3),
coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS),
+ coresight_cti_reg_index(trigoutstatus1, CTITRIGOUTSTATUS, 1),
+ coresight_cti_reg_index(trigoutstatus2, CTITRIGOUTSTATUS, 2),
+ coresight_cti_reg_index(trigoutstatus3, CTITRIGOUTSTATUS, 3),
coresight_cti_reg(chinstatus, CTICHINSTATUS),
coresight_cti_reg(choutstatus, CTICHOUTSTATUS),
#ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS
coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL),
coresight_cti_reg(ittrigin, ITTRIGIN),
+ coresight_cti_reg_index(ittrigin1, ITTRIGIN, 1),
+ coresight_cti_reg_index(ittrigin2, ITTRIGIN, 2),
+ coresight_cti_reg_index(ittrigin3, ITTRIGIN, 3),
coresight_cti_reg(itchin, ITCHIN),
coresight_cti_reg_rw(ittrigout, ITTRIGOUT),
+ coresight_cti_reg_rw_index(ittrigout1, ITTRIGOUT, 1),
+ coresight_cti_reg_rw_index(ittrigout2, ITTRIGOUT, 2),
+ coresight_cti_reg_rw_index(ittrigout3, ITTRIGOUT, 3),
coresight_cti_reg_rw(itchout, ITCHOUT),
coresight_cti_reg(itchoutack, ITCHOUTACK),
coresight_cti_reg(ittrigoutack, ITTRIGOUTACK),
+ coresight_cti_reg_index(ittrigoutack1, ITTRIGOUTACK, 1),
+ coresight_cti_reg_index(ittrigoutack2, ITTRIGOUTACK, 2),
+ coresight_cti_reg_index(ittrigoutack3, ITTRIGOUTACK, 3),
coresight_cti_reg_wo(ittriginack, ITTRIGINACK),
+ coresight_cti_reg_wo_index(ittriginack1, ITTRIGINACK, 1),
+ coresight_cti_reg_wo_index(ittriginack2, ITTRIGINACK, 2),
+ coresight_cti_reg_wo_index(ittriginack3, ITTRIGINACK, 3),
coresight_cti_reg_wo(itchinack, ITCHINACK),
#endif
NULL,
@@ -537,10 +583,22 @@ static umode_t coresight_cti_regs_is_visible(struct kobject *kobj,
{
struct device *dev = kobj_to_dev(kobj);
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ struct device_attribute *dev_attr;
+ struct cs_off_attribute *cti_attr;
+ int max_bank;
if (attr == &dev_attr_asicctl.attr && !drvdata->config.asicctl_impl)
return 0;
+ dev_attr = container_of(attr, struct device_attribute, attr);
+ if (dev_attr->show == coresight_cti_reg_show ||
+ dev_attr->store == coresight_cti_reg_store) {
+ cti_attr = container_of(dev_attr, struct cs_off_attribute, attr);
+ max_bank = DIV_ROUND_UP(drvdata->config.nr_trig_max, 32);
+ if (cti_attr->index >= max_bank)
+ return 0;
+ }
+
return attr->mode;
}
--
2.43.0
^ permalink raw reply related
* [PATCH v9 3/4] coresight: cti: add Qualcomm extended CTI identification and quirks
From: Yingchao Deng @ 2026-05-21 12:16 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
jinlong.mao, quic_yingdeng, tingwei.zhang, jie.gan, Yingchao Deng
In-Reply-To: <20260521-extended_cti-v9-0-d21f4f92c51e@oss.qualcomm.com>
Qualcomm implements an extended variant of the ARM CoreSight CTI with a
different register layout and vendor-specific behavior. While the
programming model remains largely compatible, the register offsets differ
from the standard ARM CTI and require explicit handling.
Detect Qualcomm CTIs via the DEVARCH register and record this in the CTI
driver data. Introduce a small mapping layer to translate standard CTI
register offsets to Qualcomm-specific offsets, allowing the rest of the
driver to use a common register access path.
Additionally, handle a Qualcomm-specific quirk where the CLAIMSET
register is incorrectly initialized to a non-zero value, which can cause
tools or drivers to assume the component is already claimed. Clear the
register during probe to reflect the actual unclaimed state.
No functional change is intended for standard ARM CTI devices.
Co-developed-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-cti-core.c | 27 +++++++++-
drivers/hwtracing/coresight/coresight-cti.h | 7 ++-
drivers/hwtracing/coresight/qcom-cti.h | 65 ++++++++++++++++++++++++
3 files changed, 97 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index c5cc2706e241..2dac5eb4ecca 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -21,6 +21,7 @@
#include "coresight-priv.h"
#include "coresight-cti.h"
+#include "qcom-cti.h"
/*
* CTI devices can be associated with a PE, or be connected to CoreSight
@@ -45,6 +46,9 @@ static DEFINE_MUTEX(ect_mutex);
static void __iomem *__reg_addr(struct cti_drvdata *drvdata, u32 off,
u32 index)
{
+ if (unlikely(rvdata->is_qcom_cti))
+ off = cti_qcom_reg_off(off);
+
return drvdata->base + off + sizeof(u32) * index;
}
@@ -172,6 +176,9 @@ void cti_write_intack(struct device *dev, u32 ackval)
/* DEVID[19:16] - number of CTM channels */
#define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19))
+/* DEVARCH[31:21] - ARCHITECT */
+#define CTI_DEVARCH_ARCHITECT(devarch_val) ((int)BMVAL(devarch_val, 21, 31))
+
static int cti_set_default_config(struct device *dev,
struct cti_drvdata *drvdata)
{
@@ -702,6 +709,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
struct coresight_desc cti_desc;
struct coresight_platform_data *pdata = NULL;
struct resource *res = &adev->res;
+ u32 devarch;
/* driver data*/
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
@@ -726,6 +734,22 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
raw_spin_lock_init(&drvdata->spinlock);
+ devarch = readl_relaxed(drvdata->base + CORESIGHT_DEVARCH);
+ if (CTI_DEVARCH_ARCHITECT(devarch) == ARCHITECT_QCOM) {
+ drvdata->is_qcom_cti = true;
+ /*
+ * QCOM CTI does not implement Claimtag functionality as
+ * per CoreSight specification, but its CLAIMSET register
+ * is incorrectly initialized to 0xF. This can mislead
+ * tools or drivers into thinking the component is claimed.
+ *
+ * Reset CLAIMSET to 0 to reflect that no claims are active.
+ */
+ CS_UNLOCK(drvdata->base);
+ writel_relaxed(0, drvdata->base + CORESIGHT_CLAIMSET);
+ CS_LOCK(drvdata->base);
+ }
+
/* initialise CTI driver config values */
ret = cti_set_default_config(dev, drvdata);
if (ret)
@@ -782,7 +806,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
/* all done - dec pm refcount */
pm_runtime_put(&adev->dev);
- dev_info(&drvdata->csdev->dev, "CTI initialized\n");
+ dev_info(&drvdata->csdev->dev,
+ "%sCTI initialized\n", drvdata->is_qcom_cti ? "QCOM " : "");
return 0;
}
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index 98b8de8a3687..08ea6daf5b3c 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -54,10 +54,11 @@ struct fwnode_handle;
/*
* CTI CSSoc 600 has a max of 32 trigger signals per direction.
* CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def.
+ * QCOM CTI supports up to 128 trigger signals per direction.
* Max of in and out defined in the DEVID register.
* - pick up actual number used from .dts parameters if present.
*/
-#define CTIINOUTEN_MAX 32
+#define CTIINOUTEN_MAX 128
/**
* Group of related trigger signals
@@ -168,6 +169,9 @@ struct cti_config {
* @spinlock: Control data access to one at a time.
* @config: Configuration data for this CTI device.
* @node: List entry of this device in the list of CTI devices.
+ * @is_qcom_cti: True if this CTI is a Qualcomm vendor-specific
+ * variant that requires register offset translation
+ * via cti_qcom_reg_off().
*/
struct cti_drvdata {
void __iomem *base;
@@ -176,6 +180,7 @@ struct cti_drvdata {
raw_spinlock_t spinlock;
struct cti_config config;
struct list_head node;
+ bool is_qcom_cti;
};
/*
diff --git a/drivers/hwtracing/coresight/qcom-cti.h b/drivers/hwtracing/coresight/qcom-cti.h
new file mode 100644
index 000000000000..d3846613a0de
--- /dev/null
+++ b/drivers/hwtracing/coresight/qcom-cti.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef _CORESIGHT_QCOM_CTI_H
+#define _CORESIGHT_QCOM_CTI_H
+
+#include "coresight-cti.h"
+
+#define ARCHITECT_QCOM 0x477
+
+/* CTI programming registers */
+#define QCOM_CTIINTACK 0x020
+#define QCOM_CTIAPPSET 0x004
+#define QCOM_CTIAPPCLEAR 0x008
+#define QCOM_CTIAPPPULSE 0x00C
+#define QCOM_CTIINEN 0x400
+#define QCOM_CTIOUTEN 0x800
+#define QCOM_CTITRIGINSTATUS 0x040
+#define QCOM_CTITRIGOUTSTATUS 0x060
+#define QCOM_CTICHINSTATUS 0x080
+#define QCOM_CTICHOUTSTATUS 0x084
+#define QCOM_CTIGATE 0x088
+#define QCOM_ASICCTL 0x08C
+/* Integration test registers */
+#define QCOM_ITCHINACK 0xE70
+#define QCOM_ITTRIGINACK 0xE80
+#define QCOM_ITCHOUT 0xE74
+#define QCOM_ITTRIGOUT 0xEA0
+#define QCOM_ITCHOUTACK 0xE78
+#define QCOM_ITTRIGOUTACK 0xEC0
+#define QCOM_ITCHIN 0xE7C
+#define QCOM_ITTRIGIN 0xEE0
+
+static inline u32 cti_qcom_reg_off(u32 offset)
+{
+ switch (offset) {
+ case CTIINTACK: return QCOM_CTIINTACK;
+ case CTIAPPSET: return QCOM_CTIAPPSET;
+ case CTIAPPCLEAR: return QCOM_CTIAPPCLEAR;
+ case CTIAPPPULSE: return QCOM_CTIAPPPULSE;
+ case CTIINEN: return QCOM_CTIINEN;
+ case CTIOUTEN: return QCOM_CTIOUTEN;
+ case CTITRIGINSTATUS: return QCOM_CTITRIGINSTATUS;
+ case CTITRIGOUTSTATUS: return QCOM_CTITRIGOUTSTATUS;
+ case CTICHINSTATUS: return QCOM_CTICHINSTATUS;
+ case CTICHOUTSTATUS: return QCOM_CTICHOUTSTATUS;
+ case CTIGATE: return QCOM_CTIGATE;
+ case ASICCTL: return QCOM_ASICCTL;
+ case ITCHINACK: return QCOM_ITCHINACK;
+ case ITTRIGINACK: return QCOM_ITTRIGINACK;
+ case ITCHOUT: return QCOM_ITCHOUT;
+ case ITTRIGOUT: return QCOM_ITTRIGOUT;
+ case ITCHOUTACK: return QCOM_ITCHOUTACK;
+ case ITTRIGOUTACK: return QCOM_ITTRIGOUTACK;
+ case ITCHIN: return QCOM_ITCHIN;
+ case ITTRIGIN: return QCOM_ITTRIGIN;
+
+ default:
+ return offset;
+ }
+}
+
+#endif /* _CORESIGHT_QCOM_CTI_H */
--
2.43.0
^ permalink raw reply related
* [PATCH v9 2/4] coresight: cti: use __reg_addr() helper for register access
From: Yingchao Deng @ 2026-05-21 12:16 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
jinlong.mao, quic_yingdeng, tingwei.zhang, jie.gan, Yingchao Deng
In-Reply-To: <20260521-extended_cti-v9-0-d21f4f92c51e@oss.qualcomm.com>
Introduce __reg_addr(drvdata, off, index) to compute MMIO addresses
from a base offset and a per-trigger index, replacing the function-like
CTIINEN(n)/CTIOUTEN(n) macros with base offsets and explicit index
arithmetic. Add reg_addr and reg_index_addr convenience macros for
zero-index and indexed access respectively.
Extend cs_off_attribute with a u32 index field and update
cti_read_single_reg() and cti_write_single_reg() to accept separate
offset and index parameters, allowing sysfs show/store handlers to
use the attribute's index field directly.
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-cti-core.c | 45 ++++++++++++++---------
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 25 +++++++------
drivers/hwtracing/coresight/coresight-cti.h | 9 +++--
drivers/hwtracing/coresight/coresight-priv.h | 4 +-
4 files changed, 50 insertions(+), 33 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 4e7d12bd2d3e..c5cc2706e241 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -42,6 +42,15 @@ static DEFINE_MUTEX(ect_mutex);
#define csdev_to_cti_drvdata(csdev) \
dev_get_drvdata(csdev->dev.parent)
+static void __iomem *__reg_addr(struct cti_drvdata *drvdata, u32 off,
+ u32 index)
+{
+ return drvdata->base + off + sizeof(u32) * index;
+}
+
+#define reg_addr(drvdata, off) __reg_addr((drvdata), (off), 0)
+#define reg_index_addr(drvdata, off, i) __reg_addr((drvdata), (off), (i))
+
/* write set of regs to hardware - call with spinlock claimed */
void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
{
@@ -55,16 +64,17 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
/* write the CTI trigger registers */
for (i = 0; i < config->nr_trig_max; i++) {
- writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i));
+ writel_relaxed(config->ctiinen[i],
+ reg_index_addr(drvdata, CTIINEN, i));
writel_relaxed(config->ctiouten[i],
- drvdata->base + CTIOUTEN(i));
+ reg_index_addr(drvdata, CTIOUTEN, i));
}
/* other regs */
- writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
+ writel_relaxed(config->ctigate, reg_addr(drvdata, CTIGATE));
if (config->asicctl_impl)
- writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
- writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
+ writel_relaxed(config->asicctl, reg_addr(drvdata, ASICCTL));
+ writel_relaxed(config->ctiappset, reg_addr(drvdata, CTIAPPSET));
/* re-enable CTI */
writel_relaxed(1, drvdata->base + CTICONTROL);
@@ -122,21 +132,22 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
return 0;
}
-u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset)
+u32 cti_read_single_reg(struct cti_drvdata *drvdata, u32 off, u32 index)
{
- int val;
+ u32 val;
CS_UNLOCK(drvdata->base);
- val = readl_relaxed(drvdata->base + offset);
+ val = readl_relaxed(reg_index_addr(drvdata, off, index));
CS_LOCK(drvdata->base);
return val;
}
-void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value)
+void cti_write_single_reg(struct cti_drvdata *drvdata, u32 off, u32 index,
+ u32 value)
{
CS_UNLOCK(drvdata->base);
- writel_relaxed(value, drvdata->base + offset);
+ writel_relaxed(value, reg_index_addr(drvdata, off, index));
CS_LOCK(drvdata->base);
}
@@ -149,7 +160,7 @@ void cti_write_intack(struct device *dev, u32 ackval)
/* write if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, CTIINTACK, ackval);
+ cti_write_single_reg(drvdata, CTIINTACK, 0, ackval);
}
/*
@@ -322,7 +333,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
struct cti_config *config = &drvdata->config;
u32 chan_bitmask;
u32 reg_value;
- int reg_offset;
+ u32 reg_offset;
/* ensure indexes in range */
if ((channel_idx >= config->nr_ctm_channels) ||
@@ -344,8 +355,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
/* update the local register values */
chan_bitmask = BIT(channel_idx);
- reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
- CTIOUTEN(trigger_idx));
+ reg_offset = (direction == CTI_TRIG_IN ? CTIINEN : CTIOUTEN);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
@@ -365,7 +375,8 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
/* write through if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, reg_offset, reg_value);
+ cti_write_single_reg(drvdata, reg_offset, trigger_idx,
+ reg_value);
return 0;
}
@@ -403,7 +414,7 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
if (err == 0) {
config->ctigate = reg_value;
if (cti_is_active(config))
- cti_write_single_reg(drvdata, CTIGATE, reg_value);
+ cti_write_single_reg(drvdata, CTIGATE, 0, reg_value);
}
return err;
@@ -452,7 +463,7 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
}
if ((err == 0) && cti_is_active(config))
- cti_write_single_reg(drvdata, reg_offset, reg_value);
+ cti_write_single_reg(drvdata, reg_offset, 0, reg_value);
return err;
}
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 2bbfa405cb6b..7191a478b2da 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -171,7 +171,7 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
pm_runtime_get_sync(dev->parent);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
- val = cti_read_single_reg(drvdata, cti_attr->off);
+ val = cti_read_single_reg(drvdata, cti_attr->off, cti_attr->index);
pm_runtime_put_sync(dev->parent);
return sysfs_emit(buf, "0x%x\n", val);
@@ -192,7 +192,7 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
pm_runtime_get_sync(dev->parent);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
- cti_write_single_reg(drvdata, cti_attr->off, val);
+ cti_write_single_reg(drvdata, cti_attr->off, cti_attr->index, val);
pm_runtime_put_sync(dev->parent);
return size;
@@ -202,7 +202,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
(&((struct cs_off_attribute[]) { \
{ \
__ATTR(name, 0444, coresight_cti_reg_show, NULL), \
- offset \
+ offset, \
+ 0 \
} \
})[0].attr.attr)
@@ -211,7 +212,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
{ \
__ATTR(name, 0644, coresight_cti_reg_show, \
coresight_cti_reg_store), \
- offset \
+ offset, \
+ 0 \
} \
})[0].attr.attr)
@@ -219,7 +221,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
(&((struct cs_off_attribute[]) { \
{ \
__ATTR(name, 0200, NULL, coresight_cti_reg_store), \
- offset \
+ offset, \
+ 0 \
} \
})[0].attr.attr)
@@ -257,7 +260,7 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
if (cti_is_active(config)) {
- val = cti_read_single_reg(drvdata, reg_offset);
+ val = cti_read_single_reg(drvdata, reg_offset, 0);
if (pcached_val)
*pcached_val = val;
} else if (pcached_val) {
@@ -293,7 +296,7 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
/* write through if offset and enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, reg_offset, val);
+ cti_write_single_reg(drvdata, reg_offset, 0, val);
}
return size;
@@ -386,7 +389,7 @@ static ssize_t inen_store(struct device *dev,
/* write through if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, CTIINEN(index), val);
+ cti_write_single_reg(drvdata, CTIINEN, index, val);
return size;
}
@@ -427,7 +430,7 @@ static ssize_t outen_store(struct device *dev,
/* write through if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, CTIOUTEN(index), val);
+ cti_write_single_reg(drvdata, CTIOUTEN, index, val);
return size;
}
@@ -469,7 +472,7 @@ static ssize_t appclear_store(struct device *dev,
/* write through if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
+ cti_write_single_reg(drvdata, CTIAPPCLEAR, 0, val);
return size;
}
@@ -490,7 +493,7 @@ static ssize_t apppulse_store(struct device *dev,
/* write through if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, CTIAPPPULSE, val);
+ cti_write_single_reg(drvdata, CTIAPPPULSE, 0, val);
return size;
}
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index ef079fc18b72..98b8de8a3687 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -30,8 +30,8 @@ struct fwnode_handle;
#define CTIAPPSET 0x014
#define CTIAPPCLEAR 0x018
#define CTIAPPPULSE 0x01C
-#define CTIINEN(n) (0x020 + (4 * n))
-#define CTIOUTEN(n) (0x0A0 + (4 * n))
+#define CTIINEN 0x020
+#define CTIOUTEN 0x0A0
#define CTITRIGINSTATUS 0x130
#define CTITRIGOUTSTATUS 0x134
#define CTICHINSTATUS 0x138
@@ -217,8 +217,9 @@ int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
int cti_disable(struct coresight_device *csdev, struct coresight_path *path);
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
void cti_write_intack(struct device *dev, u32 ackval);
-void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
-u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset);
+void cti_write_single_reg(struct cti_drvdata *drvdata, u32 off, u32 index,
+ u32 value);
+u32 cti_read_single_reg(struct cti_drvdata *drvdata, u32 off, u32 index);
int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
enum cti_trig_dir direction, u32 channel_idx,
u32 trigger_idx);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 770a8dc881b3..4aa25dda856c 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -68,6 +68,7 @@ struct cs_pair_attribute {
struct cs_off_attribute {
struct device_attribute attr;
u32 off;
+ u32 index;
};
ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf);
@@ -77,7 +78,8 @@ ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute
(&((struct cs_off_attribute[]) { \
{ \
__ATTR(name, 0444, coresight_simple_show32, NULL), \
- offset \
+ offset, \
+ 0 \
} \
})[0].attr.attr)
--
2.43.0
^ permalink raw reply related
* [PATCH v9 1/4] coresight: cti: Convert trigger usage fields to dynamic
From: Yingchao Deng @ 2026-05-21 12:16 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
jinlong.mao, quic_yingdeng, tingwei.zhang, jie.gan, Yingchao Deng
In-Reply-To: <20260521-extended_cti-v9-0-d21f4f92c51e@oss.qualcomm.com>
Replace the fixed-size u32 fields in the cti_config and cti_trig_grp
structure with dynamically allocated bitmaps and arrays. This allows
memory to be allocated based on the actual number of triggers during probe
time, reducing memory footprint and improving scalability for platforms
with varying trigger counts.
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-cti-core.c | 59 +++++++++++++++++-----
.../hwtracing/coresight/coresight-cti-platform.c | 26 +++++++---
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 14 ++---
drivers/hwtracing/coresight/coresight-cti.h | 12 ++---
4 files changed, 76 insertions(+), 35 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 2f4c9362709a..4e7d12bd2d3e 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -161,8 +161,8 @@ void cti_write_intack(struct device *dev, u32 ackval)
/* DEVID[19:16] - number of CTM channels */
#define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19))
-static void cti_set_default_config(struct device *dev,
- struct cti_drvdata *drvdata)
+static int cti_set_default_config(struct device *dev,
+ struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
u32 devid;
@@ -181,6 +181,26 @@ static void cti_set_default_config(struct device *dev,
config->nr_trig_max = CTIINOUTEN_MAX;
}
+ config->trig_in_use = devm_bitmap_zalloc(dev, config->nr_trig_max, GFP_KERNEL);
+ if (!config->trig_in_use)
+ return -ENOMEM;
+
+ config->trig_out_use = devm_bitmap_zalloc(dev, config->nr_trig_max, GFP_KERNEL);
+ if (!config->trig_out_use)
+ return -ENOMEM;
+
+ config->trig_out_filter = devm_bitmap_zalloc(dev, config->nr_trig_max, GFP_KERNEL);
+ if (!config->trig_out_filter)
+ return -ENOMEM;
+
+ config->ctiinen = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32), GFP_KERNEL);
+ if (!config->ctiinen)
+ return -ENOMEM;
+
+ config->ctiouten = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32), GFP_KERNEL);
+ if (!config->ctiouten)
+ return -ENOMEM;
+
config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);
/* Most regs default to 0 as zalloc'ed except...*/
@@ -189,6 +209,7 @@ static void cti_set_default_config(struct device *dev,
config->enable_req_count = 0;
config->asicctl_impl = !!FIELD_GET(GENMASK(4, 0), devid);
+ return 0;
}
/*
@@ -219,8 +240,10 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
cti_dev->nr_trig_con++;
/* add connection usage bit info to overall info */
- drvdata->config.trig_in_use |= tc->con_in->used_mask;
- drvdata->config.trig_out_use |= tc->con_out->used_mask;
+ bitmap_or(drvdata->config.trig_in_use, drvdata->config.trig_in_use,
+ tc->con_in->used_mask, drvdata->config.nr_trig_max);
+ bitmap_or(drvdata->config.trig_out_use, drvdata->config.trig_out_use,
+ tc->con_out->used_mask, drvdata->config.nr_trig_max);
return 0;
}
@@ -231,6 +254,8 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
{
struct cti_trig_con *tc = NULL;
struct cti_trig_grp *in = NULL, *out = NULL;
+ struct cti_drvdata *drvdata = dev_get_drvdata(dev);
+ int n_trigs = drvdata->config.nr_trig_max;
tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL);
if (!tc)
@@ -242,12 +267,20 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
if (!in)
return NULL;
+ in->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL);
+ if (!in->used_mask)
+ return NULL;
+
out = devm_kzalloc(dev,
offsetof(struct cti_trig_grp, sig_types[out_sigs]),
GFP_KERNEL);
if (!out)
return NULL;
+ out->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL);
+ if (!out->used_mask)
+ return NULL;
+
tc->con_in = in;
tc->con_out = out;
tc->con_in->nr_sigs = in_sigs;
@@ -263,7 +296,6 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
{
int ret = 0;
int n_trigs = drvdata->config.nr_trig_max;
- u32 n_trig_mask = GENMASK(n_trigs - 1, 0);
struct cti_trig_con *tc = NULL;
/*
@@ -274,8 +306,8 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
if (!tc)
return -ENOMEM;
- tc->con_in->used_mask = n_trig_mask;
- tc->con_out->used_mask = n_trig_mask;
+ bitmap_fill(tc->con_in->used_mask, n_trigs);
+ bitmap_fill(tc->con_out->used_mask, n_trigs);
ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default");
return ret;
}
@@ -288,7 +320,6 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
{
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
- u32 trig_bitmask;
u32 chan_bitmask;
u32 reg_value;
int reg_offset;
@@ -298,18 +329,16 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
(trigger_idx >= config->nr_trig_max))
return -EINVAL;
- trig_bitmask = BIT(trigger_idx);
-
/* ensure registered triggers and not out filtered */
if (direction == CTI_TRIG_IN) {
- if (!(trig_bitmask & config->trig_in_use))
+ if (!(test_bit(trigger_idx, config->trig_in_use)))
return -EINVAL;
} else {
- if (!(trig_bitmask & config->trig_out_use))
+ if (!(test_bit(trigger_idx, config->trig_out_use)))
return -EINVAL;
if ((config->trig_filter_enable) &&
- (config->trig_out_filter & trig_bitmask))
+ test_bit(trigger_idx, config->trig_out_filter))
return -EINVAL;
}
@@ -687,7 +716,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
raw_spin_lock_init(&drvdata->spinlock);
/* initialise CTI driver config values */
- cti_set_default_config(dev, drvdata);
+ ret = cti_set_default_config(dev, drvdata);
+ if (ret)
+ return ret;
pdata = coresight_cti_get_platform_data(dev);
if (IS_ERR(pdata)) {
diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
index d6d5388705c3..ba5a7e4b6bff 100644
--- a/drivers/hwtracing/coresight/coresight-cti-platform.c
+++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
@@ -136,8 +136,8 @@ static int cti_plat_create_v8_etm_connection(struct device *dev,
goto create_v8_etm_out;
/* build connection data */
- tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */
- tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */
+ bitmap_set(tc->con_in->used_mask, 4, 4); /* sigs <4,5,6,7> */
+ bitmap_set(tc->con_out->used_mask, 4, 4); /* sigs <4,5,6,7> */
/*
* The EXTOUT type signals from the ETM are connected to a set of input
@@ -194,10 +194,10 @@ static int cti_plat_create_v8_connections(struct device *dev,
goto of_create_v8_out;
/* Set the v8 PE CTI connection data */
- tc->con_in->used_mask = 0x3; /* sigs <0 1> */
+ bitmap_set(tc->con_in->used_mask, 0, 2); /* sigs <0 1> */
tc->con_in->sig_types[0] = PE_DBGTRIGGER;
tc->con_in->sig_types[1] = PE_PMUIRQ;
- tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */
+ bitmap_set(tc->con_out->used_mask, 0, 3); /* sigs <0 1 2 > */
tc->con_out->sig_types[0] = PE_EDBGREQ;
tc->con_out->sig_types[1] = PE_DBGRESTART;
tc->con_out->sig_types[2] = PE_CTIIRQ;
@@ -213,7 +213,7 @@ static int cti_plat_create_v8_connections(struct device *dev,
goto of_create_v8_out;
/* filter pe_edbgreq - PE trigout sig <0> */
- drvdata->config.trig_out_filter |= 0x1;
+ set_bit(0, drvdata->config.trig_out_filter);
of_create_v8_out:
return ret;
@@ -257,7 +257,7 @@ static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp,
if (!err) {
/* set the signal usage mask */
for (idx = 0; idx < tgrp->nr_sigs; idx++)
- tgrp->used_mask |= BIT(values[idx]);
+ set_bit(values[idx], tgrp->used_mask);
}
kfree(values);
@@ -316,24 +316,34 @@ static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata,
{
struct cti_trig_grp *tg = NULL;
int err = 0, nr_filter_sigs;
+ int nr_trigs = drvdata->config.nr_trig_max;
nr_filter_sigs = cti_plat_count_sig_elements(fwnode,
CTI_DT_FILTER_OUT_SIGS);
if (nr_filter_sigs == 0)
return 0;
- if (nr_filter_sigs > drvdata->config.nr_trig_max)
+ if (nr_filter_sigs > nr_trigs)
return -EINVAL;
tg = kzalloc_obj(*tg);
if (!tg)
return -ENOMEM;
+ tg->used_mask = bitmap_zalloc(nr_trigs, GFP_KERNEL);
+ if (!tg->used_mask) {
+ kfree(tg);
+ return -ENOMEM;
+ }
+
tg->nr_sigs = nr_filter_sigs;
err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS);
if (!err)
- drvdata->config.trig_out_filter |= tg->used_mask;
+ bitmap_or(drvdata->config.trig_out_filter,
+ drvdata->config.trig_out_filter,
+ tg->used_mask, nr_trigs);
+ bitmap_free(tg->used_mask);
kfree(tg);
return err;
}
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 3fe2c916d228..2bbfa405cb6b 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -719,12 +719,12 @@ static ssize_t trigout_filtered_show(struct device *dev,
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *cfg = &drvdata->config;
int nr_trig_max = cfg->nr_trig_max;
- unsigned long mask = cfg->trig_out_filter;
+ unsigned long *mask = cfg->trig_out_filter;
- if (mask == 0)
+ if (bitmap_empty(mask, nr_trig_max))
return 0;
- return sysfs_emit(buf, "%*pbl\n", nr_trig_max, &mask);
+ return sysfs_emit(buf, "%*pbl\n", nr_trig_max, mask);
}
static DEVICE_ATTR_RO(trigout_filtered);
@@ -931,9 +931,9 @@ static ssize_t trigin_sig_show(struct device *dev,
struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *cfg = &drvdata->config;
- unsigned long mask = con->con_in->used_mask;
+ unsigned long *mask = con->con_in->used_mask;
- return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask);
+ return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask);
}
static ssize_t trigout_sig_show(struct device *dev,
@@ -945,9 +945,9 @@ static ssize_t trigout_sig_show(struct device *dev,
struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *cfg = &drvdata->config;
- unsigned long mask = con->con_out->used_mask;
+ unsigned long *mask = con->con_out->used_mask;
- return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask);
+ return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask);
}
/* convert a sig type id to a name */
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index c5f9e79fabc6..ef079fc18b72 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -68,7 +68,7 @@ struct fwnode_handle;
*/
struct cti_trig_grp {
int nr_sigs;
- u32 used_mask;
+ unsigned long *used_mask;
int sig_types[];
};
@@ -145,17 +145,17 @@ struct cti_config {
int enable_req_count;
/* registered triggers and filtering */
- u32 trig_in_use;
- u32 trig_out_use;
- u32 trig_out_filter;
+ unsigned long *trig_in_use;
+ unsigned long *trig_out_use;
+ unsigned long *trig_out_filter;
bool trig_filter_enable;
u8 xtrig_rchan_sel;
/* cti cross trig programmable regs */
u32 ctiappset;
u8 ctiinout_sel;
- u32 ctiinen[CTIINOUTEN_MAX];
- u32 ctiouten[CTIINOUTEN_MAX];
+ u32 *ctiinen;
+ u32 *ctiouten;
u32 ctigate;
u32 asicctl;
};
--
2.43.0
^ permalink raw reply related
* [PATCH v9 0/4] Add Qualcomm extended CTI support
From: Yingchao Deng @ 2026-05-21 12:16 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, linux-arm-msm,
jinlong.mao, quic_yingdeng, tingwei.zhang, jie.gan, Yingchao Deng
The Qualcomm extended CTI is a heavily parameterized version of ARM’s
CSCTI. It allows a debugger to send to trigger events to a processor or to
send a trigger event to one or more processors when a trigger event occurs
on another processor on the same SoC, or even between SoCs.
Qualcomm extended CTI supports up to 128 triggers. And some of the register
offsets are changed.
The commands to configure CTI triggers are the same as ARM's CTI.
Prerequisites:
This series depends on the following CoreSight fix:
[PATCH v2 1/1] coresight: fix issue where coresight component has no claimtags
Link: https://lore.kernel.org/all/20251027223545.2801-2-mike.leach@linaro.org/
Changes in v9:
1. rebase on top of linux-next-20260518.
2. patch 2: Replace the "encode index into offset high bits" scheme with a cleaner
__reg_addr(drvdata, off, index) helper; update cti_read/write_single_reg() to
take separate off and index arguments; add u32 index field to cs_off_attribute
(moved to coresight-priv.h); drop CTI_REG_SET/GET/CLR_NR macros and
<linux/bitfield.h>; update commit subject accordingly.
3. patch 4: Add three index-aware sysfs macros (coresight_cti_reg_index,
_rw_index, _wo_index); replace string-matching visibility logic with
cs_off_attribute.index field check;
Link to v8 - https://lore.kernel.org/all/20260426-extended-cti-v8-0-23b900a4902f@oss.qualcomm.com/
Changes in v8:
1. Rebased on top of linux-next-20260424.
2. patch 1: Use devm_bitmap_zalloc() with nr_trig_max instead of per-connection
signal counts; add bitmap_zalloc() for filter trigger group.
3. patch 2: Add #include <linux/bitfield.h>; move CTIINOUTEN_MAX expansion
to patch3.
4. patch 3: wrap CLAIMSET clear with CS_UNLOCK/CS_LOCK; move CTIINOUTEN_MAX
to 128 here with comment; fix macro alignment in qcom-cti.h.
5. patch 4: Make qcom_suffix_registers[] static.
Link to v7 - https://lore.kernel.org/all/20260325-extended_cti-v7-0-bb406005089f@oss.qualcomm.com/
Changes in v7:
1. Split the extended CTI support into smaller, logically independent
patches to improve reviewability.
2. Removed the dual offset-array based register access used in v6 for
standard and Qualcomm CTIs. Register addressing is now unified through
a single code path by encoding the register index together with the base
offset and applying variant-specific translation at the final MMIO
access point.
3. Removed ext_reg_sel, extend the CTI sysfs interface to expose banked
register instances on Qualcomm CTIs only. Numbered sysfs nodes are
hidden on standard ARM CTIs, and on Qualcomm CTIs their visibility is
derived from nr_trig_max (32 triggers per bank), ensuring that only
registers backed by hardware are exposed.
Link to v6 - https://lore.kernel.org/all/20251202-extended_cti-v6-0-ab68bb15c4f5@oss.qualcomm.com/
Changes in v6:
1. Rename regs_idx to ext_reg_sel and add information in documentation
file.
2. Reset CLAIMSET to zero for qcom-cti during probe.
3. Retrieve idx value under spinlock.
4. Use yearless copyright for qcom-cti.h.
Link to v5 - https://lore.kernel.org/all/20251020-extended_cti-v5-0-6f193da2d467@oss.qualcomm.com/
Changes in v5:
1. Move common part in qcom-cti.h to coresight-cti.h.
2. Convert trigger usage fields to dynamic bitmaps and arrays.
3. Fix holes in struct cti_config to save some space.
4. Revert the previous changes related to the claim tag in
cti_enable/disable_hw.
Link to v4 - https://lore.kernel.org/linux-arm-msm/20250902-extended_cti-v4-1-7677de04b416@oss.qualcomm.com/
Changes in v4:
1. Read the DEVARCH registers to identify Qualcomm CTI.
2. Add a reg_idx node, and refactor the coresight_cti_reg_show() and
coresight_cti_reg_store() functions accordingly.
3. The register offsets specific to Qualcomm CTI are moved to qcom_cti.h.
Link to v3 - https://lore.kernel.org/linux-arm-msm/20250722081405.2947294-1-quic_jinlmao@quicinc.com/
Changes in v3:
1. Rename is_extended_cti() to of_is_extended_cti().
2. Add the missing 'i' when write the CTI trigger registers.
3. Convert the multi-line output in sysfs to single line.
4. Initialize offset arrays using designated initializer.
Link to V2 - https://lore.kernel.org/all/20250429071841.1158315-3-quic_jinlmao@quicinc.com/
Changes in V2:
1. Add enum for compatible items.
2. Move offset arrays to coresight-cti-core
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
Yingchao Deng (4):
coresight: cti: Convert trigger usage fields to dynamic
coresight: cti: use __reg_addr() helper for register access
coresight: cti: add Qualcomm extended CTI identification and quirks
coresight: cti: expose banked sysfs registers for Qualcomm extended CTI
drivers/hwtracing/coresight/coresight-cti-core.c | 131 ++++++++++++++++-----
.../hwtracing/coresight/coresight-cti-platform.c | 26 ++--
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 97 ++++++++++++---
drivers/hwtracing/coresight/coresight-cti.h | 28 +++--
drivers/hwtracing/coresight/coresight-priv.h | 4 +-
drivers/hwtracing/coresight/qcom-cti.h | 65 ++++++++++
6 files changed, 281 insertions(+), 70 deletions(-)
---
base-commit: f0d051a4a0ad6d37c1a88fee7f6a611f2e3dfa77
change-id: 20260520-extended_cti-305ed12f0348
Best regards,
--
Yingchao Deng <yingchao.deng@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2 11/11] iio: dac: add mcf54415 DAC
From: Angelo Dureghello @ 2026-05-21 12:14 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Angelo Dureghello, Greg Ungerer, Geert Uytterhoeven, Steven King,
Arnd Bergmann, Maxime Coquelin, Alexandre Torgue,
Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Greg Ungerer, linux-m68k, linux-kernel, linux-stm32,
linux-arm-kernel, linux-iio
In-Reply-To: <agTe7vZ94DnmD4Ed@ashevche-desk.local>
Hi Andy,
just few points below, the rest has been fixed:
On Wed, May 13, 2026 at 11:28:30PM +0300, Andy Shevchenko wrote:
> On Wed, May 13, 2026 at 11:14:35AM +0200, Angelo Dureghello wrote:
> >
> > Add basic version of mcf54415 DAC driver. DAC is embedded in the cpu and
> > DAC configuration registers are mapped in the internal IO address space.
> >
> > The DAC accepts a 12-bit digital signal and creates a monotonic 12-bit
> > analog output varying from DAC_VREFL to DAC_VREFH. The DAC module
> > consists of a conversion unit, an output amplifier, and the associated
> > digital control blocks. Default register values for DAC_VREFL and DAC_VREFH
> > are respectively 0 and 0xfff, left untouched in this initial version.
> >
> > This initial version of the driver is minimalistic, "output raw" only, to
> > be extended in the future. DMA and external sync are disabled, default mode
> > is high speed, default format is right-justified 12bit on 16bit word.
>
> ...
>
> > +#include <linux/array_size.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bits.h>
> > +#include <linux/clk.h>
> > +#include <linux/compiler_types.h>
> > +#include <linux/delay.h>
>
> + err.h
>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/mutex.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
>
> ...
>
> > +struct mcf54415_dac {
> > + struct clk *clk;
> > + struct regmap *map;
>
> I believe that regmap pointer is used more often, can you check with
> bloat-o-meter that swapping these two (by the order) gives any benefit in
> object size?
>
checking size in ColdFire arch with last kernel.org gcc had no benefit,
anyway put regmap before
> > +};
>
> ...
>
> > + .max_register = 0x1F,
>
> No definition? What datasheet says about this? Perhaps define the MAX as per
> last defined register in the datasheet?
>
> > +};
>
> ...
>
> > +static void mcf54415_dac_init(struct mcf54415_dac *info)
> > +{
> > + /* Keeping defaults and enable DAC (bit 0 set to 0) */
> > + regmap_write(info->map, MCF54415_DAC_CR, MCF54415_DAC_CR_FILT |
> > + FIELD_PREP(MCF54415_DAC_CR_WMLVL, 1));
>
> Seems the whole driver ignores IO errors, why?
>
> > + /* DAC is ready after 12us, from RM table 40-3 */
> > + fsleep(12);
> > +}
>
> ...
>
> > +static void mcf54415_dac_exit(void *data)
> > +{
> > + struct mcf54415_dac *info = data;
> > +
> > + regmap_update_bits(info->map, MCF54415_DAC_CR, MCF54415_DAC_CR_PDN,
> > + MCF54415_DAC_CR_PDN);
>
> regmap_set_bits()
>
> > +}
>
> ...
>
> > +static int mcf54415_write_raw(struct iio_dev *indio_dev,
> > + struct iio_chan_spec const *chan,
> > + int val, int val2, long mask)
> > +{
> > + struct mcf54415_dac *info = iio_priv(indio_dev);
> > +
> > + switch (mask) {
> > + case IIO_CHAN_INFO_RAW:
> > + if (val < 0 || val > 4095)
>
> Do we have a definition for the resolution? I'm fine with the plain numbers,
> but it's better to add a short comment to say that this is "based on the
> resolution of XXX register per datasheet".
>
> > + return -EINVAL;
> > + regmap_write(info->map, MCF54415_DAC_DATA, val);
> > + return 0;
> > + default:
> > + return -EINVAL;
> > + }
> > +}
>
> ...
>
> > +static int mcf54415_dac_probe(struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + struct iio_dev *indio_dev;
> > + struct mcf54415_dac *info;
> > + void __iomem *regs;
> > + int ret;
> > +
> > + indio_dev = devm_iio_device_alloc(dev, sizeof(*info));
> > + if (!indio_dev)
> > + return -ENOMEM;
> > +
> > + info = iio_priv(indio_dev);
> > +
> > + regs = devm_platform_ioremap_resource(pdev, 0);
> > + if (IS_ERR(regs))
> > + return dev_err_probe(dev, PTR_ERR(regs),
> > + "failed to get io regs\n");
>
> One line.
>
i decided to stay inside 80 in all the file, is it ok ?
> > +
> > + info->map = devm_regmap_init_mmio(dev, regs,
> > + &mcf54415_dac_regmap_config);
> > + if (IS_ERR(info->map))
> > + return PTR_ERR(info->map);
> > +
> > + info->clk = devm_clk_get_enabled(dev, "dac");
> > + if (IS_ERR(info->clk))
> > + return dev_err_probe(dev, PTR_ERR(info->clk),
> > + "failed getting clock\n");
>
> Also can be a single line, but this one a bit longer than above, gives
> 88 characters.
same as above
>
> > + platform_set_drvdata(pdev, indio_dev);
> > +
> > + indio_dev->name = "mcf54415";
> > + indio_dev->info = &mcf54415_dac_iio_info;
> > + indio_dev->modes = INDIO_DIRECT_MODE;
> > + indio_dev->channels = mcf54415_dac_iio_channels;
> > + indio_dev->num_channels = ARRAY_SIZE(mcf54415_dac_iio_channels);
> > +
> > + mcf54415_dac_init(info);
> > +
> > + ret = devm_add_action_or_reset(dev, mcf54415_dac_exit, info);
> > + if (ret)
> > + return ret;
> > +
> > + return devm_iio_device_register(dev, indio_dev);
> > +}
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
Regards,
angelo
^ permalink raw reply
* Re: [PATCH v4 4/5] KVM: arm64: Fix bounds checking in do_ffa_mem_reclaim()
From: Marc Zyngier @ 2026-05-21 12:12 UTC (permalink / raw)
To: Mostafa Saleh
Cc: op-tee, linux-kernel, kvmarm, linux-arm-kernel, oupton,
joey.gouly, suzuki.poulose, catalin.marinas, jens.wiklander,
sumit.garg, sebastianene, vdonnefort, sudeep.holla
In-Reply-To: <CAFgf54qpNVvzSiV89g12-4jWeacm=06LMjCooeU1Mt+3sqWDLQ@mail.gmail.com>
On Thu, 21 May 2026 11:43:58 +0100,
Mostafa Saleh <smostafa@google.com> wrote:
>
> On Thu, May 21, 2026 at 11:30 AM Mostafa Saleh <smostafa@google.com> wrote:
> >
> > Hi Marc,
> >
> > On Thu, May 21, 2026 at 09:28:46AM +0100, Marc Zyngier wrote:
> > > On Wed, 20 May 2026 21:49:47 +0100,
> > > Mostafa Saleh <smostafa@google.com> wrote:
> > > >
> > > > Sashiko (locally) reports out of bound write possiblity if SPMD
> > > > returns an invalid data.
> > > >
> > > > While SPMD is considered trusted, pKVM does some basic checks,
> > > > for offset to be less than or equal len.
> > > >
> > > > However, that is incorrect as even if the offset is smaller than
> > > > len pKVM can still access out of bound memory in the next
> > > > ffa_host_unshare_ranges().
> > > >
> > > > Split this check into 2:
> > > > 1- Check that the fixed portion of the descriptor fits.
> > > > 2- After getting reg, check the variable array size addr_range_cnt
> > > > fits.
> > > >
> > > > Signed-off-by: Mostafa Saleh <smostafa@google.com>
> > > > ---
> > > > arch/arm64/kvm/hyp/nvhe/ffa.c | 7 ++++++-
> > > > 1 file changed, 6 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> > > > index 1af722771178..e6aa2bfa63b1 100644
> > > > --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> > > > +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> > > > @@ -607,7 +607,7 @@ static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *res,
> > > > * check that we end up with something that doesn't look _completely_
> > > > * bogus.
> > > > */
> > > > - if (WARN_ON(offset > len ||
> > > > + if (WARN_ON(offset + CONSTITUENTS_OFFSET(0) > len ||
> > > > fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) {
> > >
> > > Do you really want to keep this a WARN_ON(), given that this results
> > > in a panic in most pKVM configurations?
> >
> > Which kind of configuration will that check fail on?
> > Does that mean at the moment pKVM does out-of-bound access for
> > the header?
> >
> I might have misunderstood the point. I thought you meant the new
> change would cause a panic on most configurations, or were you
> suggesting just removing the WARN_ON?
Just dropping the WARN_ON(), because for most users, that means just
killing the machine (only configurations with debug will give you a
stack trace).
> I can do that, I just updated the current faulty check and left the
> WARN_ON as is.
I'd be all for that.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH] clocksource/drivers/owl: fix refcount leak
From: Markus Elfring @ 2026-05-21 12:10 UTC (permalink / raw)
To: Alexander A. Klimov, linux-actions, linux-arm-kernel,
Andreas Färber, Daniel Lezcano, Manivannan Sadhasivam,
Thomas Gleixner
Cc: LKML
In-Reply-To: <20260521041901.542964-1-grandmaster@al2klimov.de>
> Every value returned from of_clk_get() is supposed to be cleaned up
> via clk_put() once not needed anymore.
How do you think about to add a wording like “Thus add a missing function call.”?
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v7.1-rc4#n94
Would the application of another guard become helpful?
How will chances evolve to adjust variable scopes accordingly?
https://elixir.bootlin.com/linux/v7.1-rc4/source/drivers/clocksource/timer-owl.c#L116-L173
Regards,
Markus
^ 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