Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH bpf-next v14 1/5] bpf: Move constants blinding out of arch-specific JITs
From: Hengqi Chen @ 2026-04-15  1:55 UTC (permalink / raw)
  To: Xu Kuohai
  Cc: bpf, linux-kernel, linux-arm-kernel, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Yonghong Song,
	Puranjay Mohan, Anton Protopopov, Alexis Lothoré,
	Shahab Vahedi, Russell King, Tiezhu Yang, Johan Almbladh,
	Paul Burton, Hari Bathini, Christophe Leroy, Naveen N Rao,
	Luke Nelson, Xi Wang, Björn Töpel, Pu Lehui,
	Ilya Leoshkevich, Heiko Carstens, Vasily Gorbik, David S . Miller,
	Wang YanQing
In-Reply-To: <7d88904b4028cbe124bbaba5739c525663bedc64.1776062885.git.xukuohai@hotmail.com>

On Mon, Apr 13, 2026 at 9:07 PM Xu Kuohai <xukuohai@huaweicloud.com> wrote:
>
> From: Xu Kuohai <xukuohai@huawei.com>
>
> During the JIT stage, constants blinding rewrites instructions but only
> rewrites the private instruction copy of the JITed subprog, leaving the
> global env->prog->insnsi and env->insn_aux_data untouched. This causes a
> mismatch between subprog instructions and the global state, making it
> difficult to use the global data in the JIT.
>
> To avoid this mismatch, and given that all arch-specific JITs already
> support constants blinding, move it to the generic verifier code, and
> switch to rewrite the global env->prog->insnsi with the global states
> adjusted, as other rewrites in the verifier do.
>
> This removes the constants blinding calls in each JIT, which are largely
> duplicated code across architectures.
>
> Since constants blinding is only required for JIT, and there are two
> JIT entry functions, jit_subprogs() for BPF programs with multiple
> subprogs and bpf_prog_select_runtime() for programs with no subprogs,
> move the constants blinding invocation into these two functions.
>
> In the verifier path, bpf_patch_insn_data() is used to keep global
> verifier auxiliary data in sync with patched instructions. A key
> question is whether this global auxiliary data should be restored
> on the failure path.
>
> Besides instructions, bpf_patch_insn_data() adjusts:
>   - prog->aux->poke_tab
>   - env->insn_array_maps
>   - env->subprog_info
>   - env->insn_aux_data
>
> For prog->aux->poke_tab, it is only used by JIT or only meaningful after
> JIT succeeds, so it does not need to be restored on the failure path.
>
> For env->insn_array_maps, when JIT fails, programs using insn arrays
> are rejected by bpf_insn_array_ready() due to missing JIT addresses.
> Hence, env->insn_array_maps is only meaningful for JIT and does not need
> to be restored.
>
> For subprog_info, if jit_subprogs fails and CONFIG_BPF_JIT_ALWAYS_ON
> is not enabled, kernel falls back to interpreter. In this case,
> env->subprog_info is used to determine subprogram stack depth. So it
> must be restored on failure.
>
> For env->insn_aux_data, it is freed by clear_insn_aux_data() at the
> end of bpf_check(). Before freeing, clear_insn_aux_data() loops over
> env->insn_aux_data to release jump targets recorded in it. The loop
> uses env->prog->len as the array length, but this length no longer
> matches the actual size of the adjusted env->insn_aux_data array after
> constants blinding.
>
> To address it, a simple approach is to keep insn_aux_data as adjusted
> after failure, since it will be freed shortly, and record its actual size
> for the loop in clear_insn_aux_data(). But since clear_insn_aux_data()
> uses the same index to loop over both env->prog->insnsi and env->insn_aux_data,
> this approach results in incorrect index for the insnsi array. So an
> alternative approach is adopted: clone the original env->insn_aux_data
> before blinding and restore it after failure, similar to env->prog.
>
> For classic BPF programs, constants blinding works as before since it
> is still invoked from bpf_prog_select_runtime().
>
> Reviewed-by: Anton Protopopov <a.s.protopopov@gmail.com> # v8
> Reviewed-by: Hari Bathini <hbathini@linux.ibm.com> # powerpc jit
> Reviewed-by: Pu Lehui <pulehui@huawei.com> # riscv jit
> Signed-off-by: Xu Kuohai <xukuohai@huawei.com>
> ---

Acked-by: Hengqi Chen <hengqi.chen@gmail.com> # loongarch jit

>  arch/arc/net/bpf_jit_core.c      |  39 +++------
>  arch/arm/net/bpf_jit_32.c        |  41 ++-------
>  arch/arm64/net/bpf_jit_comp.c    |  72 +++++-----------
>  arch/loongarch/net/bpf_jit.c     |  59 ++++---------
>  arch/mips/net/bpf_jit_comp.c     |  20 +----
>  arch/parisc/net/bpf_jit_core.c   |  73 +++++++---------
>  arch/powerpc/net/bpf_jit_comp.c  |  68 ++++++---------
>  arch/riscv/net/bpf_jit_core.c    |  61 +++++--------
>  arch/s390/net/bpf_jit_comp.c     |  59 +++++--------
>  arch/sparc/net/bpf_jit_comp_64.c |  61 +++++--------
>  arch/x86/net/bpf_jit_comp.c      |  43 ++-------
>  arch/x86/net/bpf_jit_comp32.c    |  33 +------
>  include/linux/filter.h           |  33 ++++++-
>  kernel/bpf/core.c                |  69 +++++++++++++--
>  kernel/bpf/fixups.c              | 144 ++++++++++++++++++++++++++-----
>  15 files changed, 400 insertions(+), 475 deletions(-)
>
> diff --git a/arch/arc/net/bpf_jit_core.c b/arch/arc/net/bpf_jit_core.c
> index 1421eeced0f5..973ceae48675 100644
> --- a/arch/arc/net/bpf_jit_core.c
> +++ b/arch/arc/net/bpf_jit_core.c
> @@ -79,7 +79,6 @@ struct arc_jit_data {
>   * The JIT pertinent context that is used by different functions.
>   *
>   * prog:               The current eBPF program being handled.
> - * orig_prog:          The original eBPF program before any possible change.
>   * jit:                        The JIT buffer and its length.
>   * bpf_header:         The JITed program header. "jit.buf" points inside it.
>   * emit:               If set, opcodes are written to memory; else, a dry-run.
> @@ -94,12 +93,10 @@ struct arc_jit_data {
>   * need_extra_pass:    A forecast if an "extra_pass" will occur.
>   * is_extra_pass:      Indicates if the current pass is an extra pass.
>   * user_bpf_prog:      True, if VM opcodes come from a real program.
> - * blinded:            True if "constant blinding" step returned a new "prog".
>   * success:            Indicates if the whole JIT went OK.
>   */
>  struct jit_context {
>         struct bpf_prog                 *prog;
> -       struct bpf_prog                 *orig_prog;
>         struct jit_buffer               jit;
>         struct bpf_binary_header        *bpf_header;
>         bool                            emit;
> @@ -114,7 +111,6 @@ struct jit_context {
>         bool                            need_extra_pass;
>         bool                            is_extra_pass;
>         bool                            user_bpf_prog;
> -       bool                            blinded;
>         bool                            success;
>  };
>
> @@ -161,13 +157,7 @@ static int jit_ctx_init(struct jit_context *ctx, struct bpf_prog *prog)
>  {
>         memset(ctx, 0, sizeof(*ctx));
>
> -       ctx->orig_prog = prog;
> -
> -       /* If constant blinding was requested but failed, scram. */
> -       ctx->prog = bpf_jit_blind_constants(prog);
> -       if (IS_ERR(ctx->prog))
> -               return PTR_ERR(ctx->prog);
> -       ctx->blinded = (ctx->prog != ctx->orig_prog);
> +       ctx->prog = prog;
>
>         /* If the verifier doesn't zero-extend, then we have to do it. */
>         ctx->do_zext = !ctx->prog->aux->verifier_zext;
> @@ -214,14 +204,6 @@ static inline void maybe_free(struct jit_context *ctx, void **mem)
>   */
>  static void jit_ctx_cleanup(struct jit_context *ctx)
>  {
> -       if (ctx->blinded) {
> -               /* if all went well, release the orig_prog. */
> -               if (ctx->success)
> -                       bpf_jit_prog_release_other(ctx->prog, ctx->orig_prog);
> -               else
> -                       bpf_jit_prog_release_other(ctx->orig_prog, ctx->prog);
> -       }
> -
>         maybe_free(ctx, (void **)&ctx->bpf2insn);
>         maybe_free(ctx, (void **)&ctx->jit_data);
>
> @@ -229,12 +211,19 @@ static void jit_ctx_cleanup(struct jit_context *ctx)
>                 ctx->bpf2insn_valid = false;
>
>         /* Freeing "bpf_header" is enough. "jit.buf" is a sub-array of it. */
> -       if (!ctx->success && ctx->bpf_header) {
> -               bpf_jit_binary_free(ctx->bpf_header);
> -               ctx->bpf_header = NULL;
> -               ctx->jit.buf    = NULL;
> -               ctx->jit.index  = 0;
> -               ctx->jit.len    = 0;
> +       if (!ctx->success) {
> +               if (ctx->bpf_header) {
> +                       bpf_jit_binary_free(ctx->bpf_header);
> +                       ctx->bpf_header = NULL;
> +                       ctx->jit.buf    = NULL;
> +                       ctx->jit.index  = 0;
> +                       ctx->jit.len    = 0;
> +               }
> +               if (ctx->is_extra_pass) {
> +                       ctx->prog->bpf_func = NULL;
> +                       ctx->prog->jited = 0;
> +                       ctx->prog->jited_len = 0;
> +               }
>         }
>
>         ctx->emit = false;
> diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
> index deeb8f292454..e6b1bb2de627 100644
> --- a/arch/arm/net/bpf_jit_32.c
> +++ b/arch/arm/net/bpf_jit_32.c
> @@ -2144,9 +2144,7 @@ bool bpf_jit_needs_zext(void)
>
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
> -       struct bpf_prog *tmp, *orig_prog = prog;
>         struct bpf_binary_header *header;
> -       bool tmp_blinded = false;
>         struct jit_ctx ctx;
>         unsigned int tmp_idx;
>         unsigned int image_size;
> @@ -2156,20 +2154,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>          * the interpreter.
>          */
>         if (!prog->jit_requested)
> -               return orig_prog;
> -
> -       /* If constant blinding was enabled and we failed during blinding
> -        * then we must fall back to the interpreter. Otherwise, we save
> -        * the new JITed code.
> -        */
> -       tmp = bpf_jit_blind_constants(prog);
> -
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         memset(&ctx, 0, sizeof(ctx));
>         ctx.prog = prog;
> @@ -2179,10 +2164,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>          * we must fall back to the interpreter
>          */
>         ctx.offsets = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
> -       if (ctx.offsets == NULL) {
> -               prog = orig_prog;
> -               goto out;
> -       }
> +       if (ctx.offsets == NULL)
> +               return prog;
>
>         /* 1) fake pass to find in the length of the JITed code,
>          * to compute ctx->offsets and other context variables
> @@ -2194,10 +2177,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>          * being successful in the second pass, so just fall back
>          * to the interpreter.
>          */
> -       if (build_body(&ctx)) {
> -               prog = orig_prog;
> +       if (build_body(&ctx))
>                 goto out_off;
> -       }
>
>         tmp_idx = ctx.idx;
>         build_prologue(&ctx);
> @@ -2213,10 +2194,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         ctx.idx += ctx.imm_count;
>         if (ctx.imm_count) {
>                 ctx.imms = kcalloc(ctx.imm_count, sizeof(u32), GFP_KERNEL);
> -               if (ctx.imms == NULL) {
> -                       prog = orig_prog;
> +               if (ctx.imms == NULL)
>                         goto out_off;
> -               }
>         }
>  #else
>         /* there's nothing about the epilogue on ARMv7 */
> @@ -2238,10 +2217,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         /* Not able to allocate memory for the structure then
>          * we must fall back to the interpretation
>          */
> -       if (header == NULL) {
> -               prog = orig_prog;
> +       if (header == NULL)
>                 goto out_imms;
> -       }
>
>         /* 2.) Actual pass to generate final JIT code */
>         ctx.target = (u32 *) image_ptr;
> @@ -2278,16 +2255,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  #endif
>  out_off:
>         kfree(ctx.offsets);
> -out:
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -                                          tmp : orig_prog);
> +
>         return prog;
>
>  out_free:
>         image_ptr = NULL;
>         bpf_jit_binary_free(header);
> -       prog = orig_prog;
>         goto out_imms;
>  }
>
> diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
> index adf84962d579..cd5a72fff500 100644
> --- a/arch/arm64/net/bpf_jit_comp.c
> +++ b/arch/arm64/net/bpf_jit_comp.c
> @@ -2009,14 +2009,12 @@ struct arm64_jit_data {
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>         int image_size, prog_size, extable_size, extable_align, extable_offset;
> -       struct bpf_prog *tmp, *orig_prog = prog;
>         struct bpf_binary_header *header;
>         struct bpf_binary_header *ro_header = NULL;
>         struct arm64_jit_data *jit_data;
>         void __percpu *priv_stack_ptr = NULL;
>         bool was_classic = bpf_prog_was_classic(prog);
>         int priv_stack_alloc_sz;
> -       bool tmp_blinded = false;
>         bool extra_pass = false;
>         struct jit_ctx ctx;
>         u8 *image_ptr;
> @@ -2025,26 +2023,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         int exentry_idx;
>
>         if (!prog->jit_requested)
> -               return orig_prog;
> -
> -       tmp = bpf_jit_blind_constants(prog);
> -       /* If blinding was requested and we failed during blinding,
> -        * we must fall back to the interpreter.
> -        */
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         jit_data = prog->aux->jit_data;
>         if (!jit_data) {
>                 jit_data = kzalloc_obj(*jit_data);
> -               if (!jit_data) {
> -                       prog = orig_prog;
> -                       goto out;
> -               }
> +               if (!jit_data)
> +                       return prog;
>                 prog->aux->jit_data = jit_data;
>         }
>         priv_stack_ptr = prog->aux->priv_stack_ptr;
> @@ -2056,10 +2041,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 priv_stack_alloc_sz = round_up(prog->aux->stack_depth, 16) +
>                                       2 * PRIV_STACK_GUARD_SZ;
>                 priv_stack_ptr = __alloc_percpu_gfp(priv_stack_alloc_sz, 16, GFP_KERNEL);
> -               if (!priv_stack_ptr) {
> -                       prog = orig_prog;
> +               if (!priv_stack_ptr)
>                         goto out_priv_stack;
> -               }
>
>                 priv_stack_init_guard(priv_stack_ptr, priv_stack_alloc_sz);
>                 prog->aux->priv_stack_ptr = priv_stack_ptr;
> @@ -2079,10 +2062,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         ctx.prog = prog;
>
>         ctx.offset = kvzalloc_objs(int, prog->len + 1);
> -       if (ctx.offset == NULL) {
> -               prog = orig_prog;
> +       if (ctx.offset == NULL)
>                 goto out_off;
> -       }
>
>         ctx.user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
>         ctx.arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena);
> @@ -2095,15 +2076,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>          * BPF line info needs ctx->offset[i] to be the offset of
>          * instruction[i] in jited image, so build prologue first.
>          */
> -       if (build_prologue(&ctx, was_classic)) {
> -               prog = orig_prog;
> +       if (build_prologue(&ctx, was_classic))
>                 goto out_off;
> -       }
>
> -       if (build_body(&ctx, extra_pass)) {
> -               prog = orig_prog;
> +       if (build_body(&ctx, extra_pass))
>                 goto out_off;
> -       }
>
>         ctx.epilogue_offset = ctx.idx;
>         build_epilogue(&ctx, was_classic);
> @@ -2121,10 +2098,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         ro_header = bpf_jit_binary_pack_alloc(image_size, &ro_image_ptr,
>                                               sizeof(u64), &header, &image_ptr,
>                                               jit_fill_hole);
> -       if (!ro_header) {
> -               prog = orig_prog;
> +       if (!ro_header)
>                 goto out_off;
> -       }
>
>         /* Pass 2: Determine jited position and result for each instruction */
>
> @@ -2152,10 +2127,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         /* Dont write body instructions to memory for now */
>         ctx.write = false;
>
> -       if (build_body(&ctx, extra_pass)) {
> -               prog = orig_prog;
> +       if (build_body(&ctx, extra_pass))
>                 goto out_free_hdr;
> -       }
>
>         ctx.epilogue_offset = ctx.idx;
>         ctx.exentry_idx = exentry_idx;
> @@ -2164,19 +2137,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>
>         /* Pass 3: Adjust jump offset and write final image */
>         if (build_body(&ctx, extra_pass) ||
> -               WARN_ON_ONCE(ctx.idx != ctx.epilogue_offset)) {
> -               prog = orig_prog;
> +               WARN_ON_ONCE(ctx.idx != ctx.epilogue_offset))
>                 goto out_free_hdr;
> -       }
>
>         build_epilogue(&ctx, was_classic);
>         build_plt(&ctx);
>
>         /* Extra pass to validate JITed code. */
> -       if (validate_ctx(&ctx)) {
> -               prog = orig_prog;
> +       if (validate_ctx(&ctx))
>                 goto out_free_hdr;
> -       }
>
>         /* update the real prog size */
>         prog_size = sizeof(u32) * ctx.idx;
> @@ -2193,16 +2162,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 if (extra_pass && ctx.idx > jit_data->ctx.idx) {
>                         pr_err_once("multi-func JIT bug %d > %d\n",
>                                     ctx.idx, jit_data->ctx.idx);
> -                       prog->bpf_func = NULL;
> -                       prog->jited = 0;
> -                       prog->jited_len = 0;
>                         goto out_free_hdr;
>                 }
>                 if (WARN_ON(bpf_jit_binary_pack_finalize(ro_header, header))) {
> -                       /* ro_header has been freed */
> +                       /* ro_header and header has been freed */
>                         ro_header = NULL;
> -                       prog = orig_prog;
> -                       goto out_off;
> +                       header = NULL;
> +                       goto out_free_hdr;
>                 }
>                 /*
>                  * The instructions have now been copied to the ROX region from
> @@ -2245,13 +2211,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 kfree(jit_data);
>                 prog->aux->jit_data = NULL;
>         }
> -out:
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -                                          tmp : orig_prog);
> +
>         return prog;
>
>  out_free_hdr:
> +       if (extra_pass) {
> +               prog->bpf_func = NULL;
> +               prog->jited = 0;
> +               prog->jited_len = 0;
> +       }
>         if (header) {
>                 bpf_arch_text_copy(&ro_header->size, &header->size,
>                                    sizeof(header->size));
> diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
> index 9cb796e16379..fcc8c0c29fb0 100644
> --- a/arch/loongarch/net/bpf_jit.c
> +++ b/arch/loongarch/net/bpf_jit.c
> @@ -1922,43 +1922,26 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
>
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
> -       bool tmp_blinded = false, extra_pass = false;
> +       bool extra_pass = false;
>         u8 *image_ptr, *ro_image_ptr;
>         int image_size, prog_size, extable_size;
>         struct jit_ctx ctx;
>         struct jit_data *jit_data;
>         struct bpf_binary_header *header;
>         struct bpf_binary_header *ro_header;
> -       struct bpf_prog *tmp, *orig_prog = prog;
>
>         /*
>          * If BPF JIT was not enabled then we must fall back to
>          * the interpreter.
>          */
>         if (!prog->jit_requested)
> -               return orig_prog;
> -
> -       tmp = bpf_jit_blind_constants(prog);
> -       /*
> -        * If blinding was requested and we failed during blinding,
> -        * we must fall back to the interpreter. Otherwise, we save
> -        * the new JITed code.
> -        */
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         jit_data = prog->aux->jit_data;
>         if (!jit_data) {
>                 jit_data = kzalloc_obj(*jit_data);
> -               if (!jit_data) {
> -                       prog = orig_prog;
> -                       goto out;
> -               }
> +               if (!jit_data)
> +                       return prog;
>                 prog->aux->jit_data = jit_data;
>         }
>         if (jit_data->ctx.offset) {
> @@ -1978,17 +1961,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         ctx.user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
>
>         ctx.offset = kvcalloc(prog->len + 1, sizeof(u32), GFP_KERNEL);
> -       if (ctx.offset == NULL) {
> -               prog = orig_prog;
> +       if (ctx.offset == NULL)
>                 goto out_offset;
> -       }
>
>         /* 1. Initial fake pass to compute ctx->idx and set ctx->flags */
>         build_prologue(&ctx);
> -       if (build_body(&ctx, extra_pass)) {
> -               prog = orig_prog;
> +       if (build_body(&ctx, extra_pass))
>                 goto out_offset;
> -       }
>         ctx.epilogue_offset = ctx.idx;
>         build_epilogue(&ctx);
>
> @@ -2004,10 +1983,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         /* Now we know the size of the structure to make */
>         ro_header = bpf_jit_binary_pack_alloc(image_size, &ro_image_ptr, sizeof(u32),
>                                               &header, &image_ptr, jit_fill_hole);
> -       if (!ro_header) {
> -               prog = orig_prog;
> +       if (!ro_header)
>                 goto out_offset;
> -       }
>
>         /* 2. Now, the actual pass to generate final JIT code */
>         /*
> @@ -2027,17 +2004,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         ctx.num_exentries = 0;
>
>         build_prologue(&ctx);
> -       if (build_body(&ctx, extra_pass)) {
> -               prog = orig_prog;
> +       if (build_body(&ctx, extra_pass))
>                 goto out_free;
> -       }
>         build_epilogue(&ctx);
>
>         /* 3. Extra pass to validate JITed code */
> -       if (validate_ctx(&ctx)) {
> -               prog = orig_prog;
> +       if (validate_ctx(&ctx))
>                 goto out_free;
> -       }
>
>         /* And we're done */
>         if (bpf_jit_enable > 1)
> @@ -2050,9 +2023,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                         goto out_free;
>                 }
>                 if (WARN_ON(bpf_jit_binary_pack_finalize(ro_header, header))) {
> -                       /* ro_header has been freed */
> +                       /* ro_header and header have been freed */
>                         ro_header = NULL;
> -                       prog = orig_prog;
> +                       header = NULL;
>                         goto out_free;
>                 }
>                 /*
> @@ -2084,13 +2057,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 prog->aux->jit_data = NULL;
>         }
>
> -out:
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ? tmp : orig_prog);
> -
>         return prog;
>
>  out_free:
> +       if (extra_pass) {
> +               prog->bpf_func = NULL;
> +               prog->jited = 0;
> +               prog->jited_len = 0;
> +       }
> +
>         if (header) {
>                 bpf_arch_text_copy(&ro_header->size, &header->size, sizeof(header->size));
>                 bpf_jit_binary_pack_free(ro_header, header);
> diff --git a/arch/mips/net/bpf_jit_comp.c b/arch/mips/net/bpf_jit_comp.c
> index e355dfca4400..d2b6c955f18e 100644
> --- a/arch/mips/net/bpf_jit_comp.c
> +++ b/arch/mips/net/bpf_jit_comp.c
> @@ -911,10 +911,8 @@ bool bpf_jit_needs_zext(void)
>
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
> -       struct bpf_prog *tmp, *orig_prog = prog;
>         struct bpf_binary_header *header = NULL;
>         struct jit_context ctx;
> -       bool tmp_blinded = false;
>         unsigned int tmp_idx;
>         unsigned int image_size;
>         u8 *image_ptr;
> @@ -925,19 +923,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>          * the interpreter.
>          */
>         if (!prog->jit_requested)
> -               return orig_prog;
> -       /*
> -        * If constant blinding was enabled and we failed during blinding
> -        * then we must fall back to the interpreter. Otherwise, we save
> -        * the new JITed code.
> -        */
> -       tmp = bpf_jit_blind_constants(prog);
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         memset(&ctx, 0, sizeof(ctx));
>         ctx.program = prog;
> @@ -1025,14 +1011,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         prog->jited_len = image_size;
>
>  out:
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -                                          tmp : orig_prog);
>         kfree(ctx.descriptors);
>         return prog;
>
>  out_err:
> -       prog = orig_prog;
>         if (header)
>                 bpf_jit_binary_free(header);
>         goto out;
> diff --git a/arch/parisc/net/bpf_jit_core.c b/arch/parisc/net/bpf_jit_core.c
> index a5eb6b51e27a..35dca372b5df 100644
> --- a/arch/parisc/net/bpf_jit_core.c
> +++ b/arch/parisc/net/bpf_jit_core.c
> @@ -44,30 +44,19 @@ bool bpf_jit_needs_zext(void)
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>         unsigned int prog_size = 0, extable_size = 0;
> -       bool tmp_blinded = false, extra_pass = false;
> -       struct bpf_prog *tmp, *orig_prog = prog;
> +       bool extra_pass = false;
>         int pass = 0, prev_ninsns = 0, prologue_len, i;
>         struct hppa_jit_data *jit_data;
>         struct hppa_jit_context *ctx;
>
>         if (!prog->jit_requested)
> -               return orig_prog;
> -
> -       tmp = bpf_jit_blind_constants(prog);
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         jit_data = prog->aux->jit_data;
>         if (!jit_data) {
>                 jit_data = kzalloc_obj(*jit_data);
> -               if (!jit_data) {
> -                       prog = orig_prog;
> -                       goto out;
> -               }
> +               if (!jit_data)
> +                       return prog;
>                 prog->aux->jit_data = jit_data;
>         }
>
> @@ -81,10 +70,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>
>         ctx->prog = prog;
>         ctx->offset = kzalloc_objs(int, prog->len);
> -       if (!ctx->offset) {
> -               prog = orig_prog;
> -               goto out_offset;
> -       }
> +       if (!ctx->offset)
> +               goto out_err;
>         for (i = 0; i < prog->len; i++) {
>                 prev_ninsns += 20;
>                 ctx->offset[i] = prev_ninsns;
> @@ -93,10 +80,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         for (i = 0; i < NR_JIT_ITERATIONS; i++) {
>                 pass++;
>                 ctx->ninsns = 0;
> -               if (build_body(ctx, extra_pass, ctx->offset)) {
> -                       prog = orig_prog;
> -                       goto out_offset;
> -               }
> +               if (build_body(ctx, extra_pass, ctx->offset))
> +                       goto out_err;
>                 ctx->body_len = ctx->ninsns;
>                 bpf_jit_build_prologue(ctx);
>                 ctx->prologue_len = ctx->ninsns - ctx->body_len;
> @@ -116,10 +101,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                                                      &jit_data->image,
>                                                      sizeof(long),
>                                                      bpf_fill_ill_insns);
> -                       if (!jit_data->header) {
> -                               prog = orig_prog;
> -                               goto out_offset;
> -                       }
> +                       if (!jit_data->header)
> +                               goto out_err;
>
>                         ctx->insns = (u32 *)jit_data->image;
>                         /*
> @@ -134,8 +117,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
>                 if (jit_data->header)
>                         bpf_jit_binary_free(jit_data->header);
> -               prog = orig_prog;
> -               goto out_offset;
> +               goto out_err;
>         }
>
>         if (extable_size)
> @@ -148,8 +130,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         bpf_jit_build_prologue(ctx);
>         if (build_body(ctx, extra_pass, NULL)) {
>                 bpf_jit_binary_free(jit_data->header);
> -               prog = orig_prog;
> -               goto out_offset;
> +               goto out_err;
>         }
>         bpf_jit_build_epilogue(ctx);
>
> @@ -160,20 +141,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                         { extern int machine_restart(char *); machine_restart(""); }
>         }
>
> +       if (!prog->is_func || extra_pass) {
> +               if (bpf_jit_binary_lock_ro(jit_data->header)) {
> +                       bpf_jit_binary_free(jit_data->header);
> +                       goto out_err;
> +               }
> +               bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
> +       }
> +
>         prog->bpf_func = (void *)ctx->insns;
>         prog->jited = 1;
>         prog->jited_len = prog_size;
>
> -       bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
> -
>         if (!prog->is_func || extra_pass) {
> -               if (bpf_jit_binary_lock_ro(jit_data->header)) {
> -                       bpf_jit_binary_free(jit_data->header);
> -                       prog->bpf_func = NULL;
> -                       prog->jited = 0;
> -                       prog->jited_len = 0;
> -                       goto out_offset;
> -               }
>                 prologue_len = ctx->epilogue_offset - ctx->body_len;
>                 for (i = 0; i < prog->len; i++)
>                         ctx->offset[i] += prologue_len;
> @@ -183,14 +163,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 kfree(jit_data);
>                 prog->aux->jit_data = NULL;
>         }
> -out:
> +
>         if (HPPA_JIT_REBOOT)
>                 { extern int machine_restart(char *); machine_restart(""); }
>
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -                                          tmp : orig_prog);
>         return prog;
> +
> +out_err:
> +       if (extra_pass) {
> +               prog->bpf_func = NULL;
> +               prog->jited = 0;
> +               prog->jited_len = 0;
> +       }
> +       goto out_offset;
>  }
>
>  u64 hppa_div64(u64 div, u64 divisor)
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index a62a9a92b7b5..711028bebea3 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -142,9 +142,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>         int flen;
>         struct bpf_binary_header *fhdr = NULL;
>         struct bpf_binary_header *hdr = NULL;
> -       struct bpf_prog *org_fp = fp;
> -       struct bpf_prog *tmp_fp;
> -       bool bpf_blinded = false;
>         bool extra_pass = false;
>         u8 *fimage = NULL;
>         u32 *fcode_base;
> @@ -152,24 +149,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>         u32 fixup_len;
>
>         if (!fp->jit_requested)
> -               return org_fp;
> -
> -       tmp_fp = bpf_jit_blind_constants(org_fp);
> -       if (IS_ERR(tmp_fp))
> -               return org_fp;
> -
> -       if (tmp_fp != org_fp) {
> -               bpf_blinded = true;
> -               fp = tmp_fp;
> -       }
> +               return fp;
>
>         jit_data = fp->aux->jit_data;
>         if (!jit_data) {
>                 jit_data = kzalloc_obj(*jit_data);
> -               if (!jit_data) {
> -                       fp = org_fp;
> -                       goto out;
> -               }
> +               if (!jit_data)
> +                       return fp;
>                 fp->aux->jit_data = jit_data;
>         }
>
> @@ -194,10 +180,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>         }
>
>         addrs = kcalloc(flen + 1, sizeof(*addrs), GFP_KERNEL);
> -       if (addrs == NULL) {
> -               fp = org_fp;
> -               goto out_addrs;
> -       }
> +       if (addrs == NULL)
> +               goto out_err;
>
>         memset(&cgctx, 0, sizeof(struct codegen_context));
>         bpf_jit_init_reg_mapping(&cgctx);
> @@ -211,11 +195,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>         cgctx.exception_cb = fp->aux->exception_cb;
>
>         /* Scouting faux-generate pass 0 */
> -       if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
> +       if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false))
>                 /* We hit something illegal or unsupported. */
> -               fp = org_fp;
> -               goto out_addrs;
> -       }
> +               goto out_err;
>
>         /*
>          * If we have seen a tail call, we need a second pass.
> @@ -226,10 +208,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>          */
>         if (cgctx.seen & SEEN_TAILCALL || !is_offset_in_branch_range((long)cgctx.idx * 4)) {
>                 cgctx.idx = 0;
> -               if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
> -                       fp = org_fp;
> -                       goto out_addrs;
> -               }
> +               if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false))
> +                       goto out_err;
>         }
>
>         bpf_jit_realloc_regs(&cgctx);
> @@ -250,10 +230,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>
>         fhdr = bpf_jit_binary_pack_alloc(alloclen, &fimage, 4, &hdr, &image,
>                                               bpf_jit_fill_ill_insns);
> -       if (!fhdr) {
> -               fp = org_fp;
> -               goto out_addrs;
> -       }
> +       if (!fhdr)
> +               goto out_err;
>
>         if (extable_len)
>                 fp->aux->extable = (void *)fimage + FUNCTION_DESCR_SIZE + proglen + fixup_len;
> @@ -272,8 +250,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>                                        extra_pass)) {
>                         bpf_arch_text_copy(&fhdr->size, &hdr->size, sizeof(hdr->size));
>                         bpf_jit_binary_pack_free(fhdr, hdr);
> -                       fp = org_fp;
> -                       goto out_addrs;
> +                       goto out_err;
>                 }
>                 bpf_jit_build_epilogue(code_base, &cgctx);
>
> @@ -295,15 +272,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>         ((u64 *)image)[1] = local_paca->kernel_toc;
>  #endif
>
> +       if (!fp->is_func || extra_pass) {
> +               if (bpf_jit_binary_pack_finalize(fhdr, hdr))
> +                       goto out_err;
> +       }
> +
>         fp->bpf_func = (void *)fimage;
>         fp->jited = 1;
>         fp->jited_len = cgctx.idx * 4 + FUNCTION_DESCR_SIZE;
>
>         if (!fp->is_func || extra_pass) {
> -               if (bpf_jit_binary_pack_finalize(fhdr, hdr)) {
> -                       fp = org_fp;
> -                       goto out_addrs;
> -               }
>                 bpf_prog_fill_jited_linfo(fp, addrs);
>  out_addrs:
>                 kfree(addrs);
> @@ -318,11 +296,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>                 jit_data->hdr = hdr;
>         }
>
> -out:
> -       if (bpf_blinded)
> -               bpf_jit_prog_release_other(fp, fp == org_fp ? tmp_fp : org_fp);
> -
>         return fp;
> +
> +out_err:
> +       if (extra_pass) {
> +               fp->bpf_func = NULL;
> +               fp->jited = 0;
> +               fp->jited_len = 0;
> +       }
> +       goto out_addrs;
>  }
>
>  /*
> diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
> index b3581e926436..527baa50dc68 100644
> --- a/arch/riscv/net/bpf_jit_core.c
> +++ b/arch/riscv/net/bpf_jit_core.c
> @@ -44,29 +44,19 @@ bool bpf_jit_needs_zext(void)
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>         unsigned int prog_size = 0, extable_size = 0;
> -       bool tmp_blinded = false, extra_pass = false;
> -       struct bpf_prog *tmp, *orig_prog = prog;
> +       bool extra_pass = false;
>         int pass = 0, prev_ninsns = 0, i;
>         struct rv_jit_data *jit_data;
>         struct rv_jit_context *ctx;
>
>         if (!prog->jit_requested)
> -               return orig_prog;
> -
> -       tmp = bpf_jit_blind_constants(prog);
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         jit_data = prog->aux->jit_data;
>         if (!jit_data) {
>                 jit_data = kzalloc_obj(*jit_data);
>                 if (!jit_data) {
> -                       prog = orig_prog;
> -                       goto out;
> +                       return prog;
>                 }
>                 prog->aux->jit_data = jit_data;
>         }
> @@ -83,15 +73,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         ctx->user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
>         ctx->prog = prog;
>         ctx->offset = kzalloc_objs(int, prog->len);
> -       if (!ctx->offset) {
> -               prog = orig_prog;
> +       if (!ctx->offset)
>                 goto out_offset;
> -       }
>
> -       if (build_body(ctx, extra_pass, NULL)) {
> -               prog = orig_prog;
> +       if (build_body(ctx, extra_pass, NULL))
>                 goto out_offset;
> -       }
>
>         for (i = 0; i < prog->len; i++) {
>                 prev_ninsns += 32;
> @@ -105,10 +91,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 bpf_jit_build_prologue(ctx, bpf_is_subprog(prog));
>                 ctx->prologue_len = ctx->ninsns;
>
> -               if (build_body(ctx, extra_pass, ctx->offset)) {
> -                       prog = orig_prog;
> +               if (build_body(ctx, extra_pass, ctx->offset))
>                         goto out_offset;
> -               }
>
>                 ctx->epilogue_offset = ctx->ninsns;
>                 bpf_jit_build_epilogue(ctx);
> @@ -126,10 +110,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                                                           &jit_data->ro_image, sizeof(u32),
>                                                           &jit_data->header, &jit_data->image,
>                                                           bpf_fill_ill_insns);
> -                       if (!jit_data->ro_header) {
> -                               prog = orig_prog;
> +                       if (!jit_data->ro_header)
>                                 goto out_offset;
> -                       }
>
>                         /*
>                          * Use the image(RW) for writing the JITed instructions. But also save
> @@ -150,7 +132,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>
>         if (i == NR_JIT_ITERATIONS) {
>                 pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
> -               prog = orig_prog;
>                 goto out_free_hdr;
>         }
>
> @@ -163,26 +144,27 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         ctx->nexentries = 0;
>
>         bpf_jit_build_prologue(ctx, bpf_is_subprog(prog));
> -       if (build_body(ctx, extra_pass, NULL)) {
> -               prog = orig_prog;
> +       if (build_body(ctx, extra_pass, NULL))
>                 goto out_free_hdr;
> -       }
>         bpf_jit_build_epilogue(ctx);
>
>         if (bpf_jit_enable > 1)
>                 bpf_jit_dump(prog->len, prog_size, pass, ctx->insns);
>
> -       prog->bpf_func = (void *)ctx->ro_insns + cfi_get_offset();
> -       prog->jited = 1;
> -       prog->jited_len = prog_size - cfi_get_offset();
> -
>         if (!prog->is_func || extra_pass) {
>                 if (WARN_ON(bpf_jit_binary_pack_finalize(jit_data->ro_header, jit_data->header))) {
>                         /* ro_header has been freed */
>                         jit_data->ro_header = NULL;
> -                       prog = orig_prog;
> -                       goto out_offset;
> +                       jit_data->header = NULL;
> +                       goto out_free_hdr;
>                 }
> +       }
> +
> +       prog->bpf_func = (void *)ctx->ro_insns + cfi_get_offset();
> +       prog->jited = 1;
> +       prog->jited_len = prog_size - cfi_get_offset();
> +
> +       if (!prog->is_func || extra_pass) {
>                 /*
>                  * The instructions have now been copied to the ROX region from
>                  * where they will execute.
> @@ -198,14 +180,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 kfree(jit_data);
>                 prog->aux->jit_data = NULL;
>         }
> -out:
>
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -                                          tmp : orig_prog);
>         return prog;
>
>  out_free_hdr:
> +       if (extra_pass) {
> +               prog->bpf_func = NULL;
> +               prog->jited = 0;
> +               prog->jited_len = 0;
> +       }
>         if (jit_data->header) {
>                 bpf_arch_text_copy(&jit_data->ro_header->size, &jit_data->header->size,
>                                    sizeof(jit_data->header->size));
> diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
> index d08d159b6319..2dfc279b1be2 100644
> --- a/arch/s390/net/bpf_jit_comp.c
> +++ b/arch/s390/net/bpf_jit_comp.c
> @@ -2314,36 +2314,20 @@ static struct bpf_binary_header *bpf_jit_alloc(struct bpf_jit *jit,
>   */
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  {
> -       struct bpf_prog *tmp, *orig_fp = fp;
>         struct bpf_binary_header *header;
>         struct s390_jit_data *jit_data;
> -       bool tmp_blinded = false;
>         bool extra_pass = false;
>         struct bpf_jit jit;
>         int pass;
>
>         if (!fp->jit_requested)
> -               return orig_fp;
> -
> -       tmp = bpf_jit_blind_constants(fp);
> -       /*
> -        * If blinding was requested and we failed during blinding,
> -        * we must fall back to the interpreter.
> -        */
> -       if (IS_ERR(tmp))
> -               return orig_fp;
> -       if (tmp != fp) {
> -               tmp_blinded = true;
> -               fp = tmp;
> -       }
> +               return fp;
>
>         jit_data = fp->aux->jit_data;
>         if (!jit_data) {
>                 jit_data = kzalloc_obj(*jit_data);
> -               if (!jit_data) {
> -                       fp = orig_fp;
> -                       goto out;
> -               }
> +               if (!jit_data)
> +                       return fp;
>                 fp->aux->jit_data = jit_data;
>         }
>         if (jit_data->ctx.addrs) {
> @@ -2356,34 +2340,27 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>
>         memset(&jit, 0, sizeof(jit));
>         jit.addrs = kvcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL);
> -       if (jit.addrs == NULL) {
> -               fp = orig_fp;
> -               goto free_addrs;
> -       }
> +       if (jit.addrs == NULL)
> +               goto out_err;
>         /*
>          * Three initial passes:
>          *   - 1/2: Determine clobbered registers
>          *   - 3:   Calculate program size and addrs array
>          */
>         for (pass = 1; pass <= 3; pass++) {
> -               if (bpf_jit_prog(&jit, fp, extra_pass)) {
> -                       fp = orig_fp;
> -                       goto free_addrs;
> -               }
> +               if (bpf_jit_prog(&jit, fp, extra_pass))
> +                       goto out_err;
>         }
>         /*
>          * Final pass: Allocate and generate program
>          */
>         header = bpf_jit_alloc(&jit, fp);
> -       if (!header) {
> -               fp = orig_fp;
> -               goto free_addrs;
> -       }
> +       if (!header)
> +               goto out_err;
>  skip_init_ctx:
>         if (bpf_jit_prog(&jit, fp, extra_pass)) {
>                 bpf_jit_binary_free(header);
> -               fp = orig_fp;
> -               goto free_addrs;
> +               goto out_err;
>         }
>         if (bpf_jit_enable > 1) {
>                 bpf_jit_dump(fp->len, jit.size, pass, jit.prg_buf);
> @@ -2392,8 +2369,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>         if (!fp->is_func || extra_pass) {
>                 if (bpf_jit_binary_lock_ro(header)) {
>                         bpf_jit_binary_free(header);
> -                       fp = orig_fp;
> -                       goto free_addrs;
> +                       goto out_err;
>                 }
>         } else {
>                 jit_data->header = header;
> @@ -2411,11 +2387,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>                 kfree(jit_data);
>                 fp->aux->jit_data = NULL;
>         }
> -out:
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(fp, fp == orig_fp ?
> -                                          tmp : orig_fp);
> +
>         return fp;
> +
> +out_err:
> +       if (extra_pass) {
> +               fp->bpf_func = NULL;
> +               fp->jited = 0;
> +               fp->jited_len = 0;
> +       }
> +       goto free_addrs;
>  }
>
>  bool bpf_jit_supports_kfunc_call(void)
> diff --git a/arch/sparc/net/bpf_jit_comp_64.c b/arch/sparc/net/bpf_jit_comp_64.c
> index b23d1c645ae5..e83e29137566 100644
> --- a/arch/sparc/net/bpf_jit_comp_64.c
> +++ b/arch/sparc/net/bpf_jit_comp_64.c
> @@ -1479,37 +1479,22 @@ struct sparc64_jit_data {
>
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
> -       struct bpf_prog *tmp, *orig_prog = prog;
>         struct sparc64_jit_data *jit_data;
>         struct bpf_binary_header *header;
>         u32 prev_image_size, image_size;
> -       bool tmp_blinded = false;
>         bool extra_pass = false;
>         struct jit_ctx ctx;
>         u8 *image_ptr;
>         int pass, i;
>
>         if (!prog->jit_requested)
> -               return orig_prog;
> -
> -       tmp = bpf_jit_blind_constants(prog);
> -       /* If blinding was requested and we failed during blinding,
> -        * we must fall back to the interpreter.
> -        */
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         jit_data = prog->aux->jit_data;
>         if (!jit_data) {
>                 jit_data = kzalloc_obj(*jit_data);
> -               if (!jit_data) {
> -                       prog = orig_prog;
> -                       goto out;
> -               }
> +               if (!jit_data)
> +                       return prog;
>                 prog->aux->jit_data = jit_data;
>         }
>         if (jit_data->ctx.offset) {
> @@ -1527,10 +1512,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         ctx.prog = prog;
>
>         ctx.offset = kmalloc_array(prog->len, sizeof(unsigned int), GFP_KERNEL);
> -       if (ctx.offset == NULL) {
> -               prog = orig_prog;
> -               goto out_off;
> -       }
> +       if (ctx.offset == NULL)
> +               goto out_err;
>
>         /* Longest sequence emitted is for bswap32, 12 instructions.  Pre-cook
>          * the offset array so that we converge faster.
> @@ -1543,10 +1526,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 ctx.idx = 0;
>
>                 build_prologue(&ctx);
> -               if (build_body(&ctx)) {
> -                       prog = orig_prog;
> -                       goto out_off;
> -               }
> +               if (build_body(&ctx))
> +                       goto out_err;
>                 build_epilogue(&ctx);
>
>                 if (bpf_jit_enable > 1)
> @@ -1569,10 +1550,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         image_size = sizeof(u32) * ctx.idx;
>         header = bpf_jit_binary_alloc(image_size, &image_ptr,
>                                       sizeof(u32), jit_fill_hole);
> -       if (header == NULL) {
> -               prog = orig_prog;
> -               goto out_off;
> -       }
> +       if (header == NULL)
> +               goto out_err;
>
>         ctx.image = (u32 *)image_ptr;
>  skip_init_ctx:
> @@ -1582,8 +1561,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>
>         if (build_body(&ctx)) {
>                 bpf_jit_binary_free(header);
> -               prog = orig_prog;
> -               goto out_off;
> +               goto out_err;
>         }
>
>         build_epilogue(&ctx);
> @@ -1592,8 +1570,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 pr_err("bpf_jit: Failed to converge, prev_size=%u size=%d\n",
>                        prev_image_size, ctx.idx * 4);
>                 bpf_jit_binary_free(header);
> -               prog = orig_prog;
> -               goto out_off;
> +               goto out_err;
>         }
>
>         if (bpf_jit_enable > 1)
> @@ -1604,8 +1581,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         if (!prog->is_func || extra_pass) {
>                 if (bpf_jit_binary_lock_ro(header)) {
>                         bpf_jit_binary_free(header);
> -                       prog = orig_prog;
> -                       goto out_off;
> +                       goto out_err;
>                 }
>         } else {
>                 jit_data->ctx = ctx;
> @@ -1624,9 +1600,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 kfree(jit_data);
>                 prog->aux->jit_data = NULL;
>         }
> -out:
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -                                          tmp : orig_prog);
> +
>         return prog;
> +
> +out_err:
> +       if (extra_pass) {
> +               prog->bpf_func = NULL;
> +               prog->jited = 0;
> +               prog->jited_len = 0;
> +       }
> +       goto out_off;
>  }
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index e9b78040d703..77d00a8dec87 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -3717,13 +3717,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>         struct bpf_binary_header *rw_header = NULL;
>         struct bpf_binary_header *header = NULL;
> -       struct bpf_prog *tmp, *orig_prog = prog;
>         void __percpu *priv_stack_ptr = NULL;
>         struct x64_jit_data *jit_data;
>         int priv_stack_alloc_sz;
>         int proglen, oldproglen = 0;
>         struct jit_context ctx = {};
> -       bool tmp_blinded = false;
>         bool extra_pass = false;
>         bool padding = false;
>         u8 *rw_image = NULL;
> @@ -3733,27 +3731,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>         int i;
>
>         if (!prog->jit_requested)
> -               return orig_prog;
> -
> -       tmp = bpf_jit_blind_constants(prog);
> -       /*
> -        * If blinding was requested and we failed during blinding,
> -        * we must fall back to the interpreter.
> -        */
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         jit_data = prog->aux->jit_data;
>         if (!jit_data) {
>                 jit_data = kzalloc_obj(*jit_data);
> -               if (!jit_data) {
> -                       prog = orig_prog;
> -                       goto out;
> -               }
> +               if (!jit_data)
> +                       return prog;
>                 prog->aux->jit_data = jit_data;
>         }
>         priv_stack_ptr = prog->aux->priv_stack_ptr;
> @@ -3765,10 +3749,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 priv_stack_alloc_sz = round_up(prog->aux->stack_depth, 8) +
>                                       2 * PRIV_STACK_GUARD_SZ;
>                 priv_stack_ptr = __alloc_percpu_gfp(priv_stack_alloc_sz, 8, GFP_KERNEL);
> -               if (!priv_stack_ptr) {
> -                       prog = orig_prog;
> +               if (!priv_stack_ptr)
>                         goto out_priv_stack;
> -               }
>
>                 priv_stack_init_guard(priv_stack_ptr, priv_stack_alloc_sz);
>                 prog->aux->priv_stack_ptr = priv_stack_ptr;
> @@ -3786,10 +3768,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 goto skip_init_addrs;
>         }
>         addrs = kvmalloc_objs(*addrs, prog->len + 1);
> -       if (!addrs) {
> -               prog = orig_prog;
> +       if (!addrs)
>                 goto out_addrs;
> -       }
>
>         /*
>          * Before first pass, make a rough estimation of addrs[]
> @@ -3820,8 +3800,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                                                    sizeof(rw_header->size));
>                                 bpf_jit_binary_pack_free(header, rw_header);
>                         }
> -                       /* Fall back to interpreter mode */
> -                       prog = orig_prog;
>                         if (extra_pass) {
>                                 prog->bpf_func = NULL;
>                                 prog->jited = 0;
> @@ -3852,10 +3830,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                         header = bpf_jit_binary_pack_alloc(roundup(proglen, align) + extable_size,
>                                                            &image, align, &rw_header, &rw_image,
>                                                            jit_fill_hole);
> -                       if (!header) {
> -                               prog = orig_prog;
> +                       if (!header)
>                                 goto out_addrs;
> -                       }
>                         prog->aux->extable = (void *) image + roundup(proglen, align);
>                 }
>                 oldproglen = proglen;
> @@ -3908,8 +3884,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 prog->bpf_func = (void *)image + cfi_get_offset();
>                 prog->jited = 1;
>                 prog->jited_len = proglen - cfi_get_offset();
> -       } else {
> -               prog = orig_prog;
>         }
>
>         if (!image || !prog->is_func || extra_pass) {
> @@ -3925,10 +3899,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 kfree(jit_data);
>                 prog->aux->jit_data = NULL;
>         }
> -out:
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -                                          tmp : orig_prog);
> +
>         return prog;
>  }
>
> diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
> index dda423025c3d..5f259577614a 100644
> --- a/arch/x86/net/bpf_jit_comp32.c
> +++ b/arch/x86/net/bpf_jit_comp32.c
> @@ -2521,35 +2521,19 @@ bool bpf_jit_needs_zext(void)
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>         struct bpf_binary_header *header = NULL;
> -       struct bpf_prog *tmp, *orig_prog = prog;
>         int proglen, oldproglen = 0;
>         struct jit_context ctx = {};
> -       bool tmp_blinded = false;
>         u8 *image = NULL;
>         int *addrs;
>         int pass;
>         int i;
>
>         if (!prog->jit_requested)
> -               return orig_prog;
> -
> -       tmp = bpf_jit_blind_constants(prog);
> -       /*
> -        * If blinding was requested and we failed during blinding,
> -        * we must fall back to the interpreter.
> -        */
> -       if (IS_ERR(tmp))
> -               return orig_prog;
> -       if (tmp != prog) {
> -               tmp_blinded = true;
> -               prog = tmp;
> -       }
> +               return prog;
>
>         addrs = kmalloc_objs(*addrs, prog->len);
> -       if (!addrs) {
> -               prog = orig_prog;
> -               goto out;
> -       }
> +       if (!addrs)
> +               return prog;
>
>         /*
>          * Before first pass, make a rough estimation of addrs[]
> @@ -2574,7 +2558,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                         image = NULL;
>                         if (header)
>                                 bpf_jit_binary_free(header);
> -                       prog = orig_prog;
>                         goto out_addrs;
>                 }
>                 if (image) {
> @@ -2588,10 +2571,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 if (proglen == oldproglen) {
>                         header = bpf_jit_binary_alloc(proglen, &image,
>                                                       1, jit_fill_hole);
> -                       if (!header) {
> -                               prog = orig_prog;
> +                       if (!header)
>                                 goto out_addrs;
> -                       }
>                 }
>                 oldproglen = proglen;
>                 cond_resched();
> @@ -2604,16 +2585,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>                 prog->bpf_func = (void *)image;
>                 prog->jited = 1;
>                 prog->jited_len = proglen;
> -       } else {
> -               prog = orig_prog;
>         }
>
>  out_addrs:
>         kfree(addrs);
> -out:
> -       if (tmp_blinded)
> -               bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -                                          tmp : orig_prog);
>         return prog;
>  }
>
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index e40d4071a345..d396e55c9a1d 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -1183,6 +1183,18 @@ static inline bool bpf_dump_raw_ok(const struct cred *cred)
>
>  struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
>                                        const struct bpf_insn *patch, u32 len);
> +
> +#ifdef CONFIG_BPF_SYSCALL
> +struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
> +                                    const struct bpf_insn *patch, u32 len);
> +#else
> +static inline struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
> +                                                  const struct bpf_insn *patch, u32 len)
> +{
> +       return ERR_PTR(-ENOTSUPP);
> +}
> +#endif /* CONFIG_BPF_SYSCALL */
> +
>  int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt);
>
>  static inline bool xdp_return_frame_no_direct(void)
> @@ -1309,9 +1321,14 @@ int bpf_jit_get_func_addr(const struct bpf_prog *prog,
>
>  const char *bpf_jit_get_prog_name(struct bpf_prog *prog);
>
> -struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *fp);
> +struct bpf_prog *bpf_jit_blind_constants(struct bpf_verifier_env *env, struct bpf_prog *prog);
>  void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other);
>
> +static inline bool bpf_prog_need_blind(const struct bpf_prog *prog)
> +{
> +       return prog->blinding_requested && !prog->blinded;
> +}
> +
>  static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
>                                 u32 pass, void *image)
>  {
> @@ -1450,6 +1467,20 @@ static inline void bpf_prog_kallsyms_del(struct bpf_prog *fp)
>  {
>  }
>
> +static inline bool bpf_prog_need_blind(const struct bpf_prog *prog)
> +{
> +       return false;
> +}
> +
> +static inline
> +struct bpf_prog *bpf_jit_blind_constants(struct bpf_verifier_env *env, struct bpf_prog *prog)
> +{
> +       return prog;
> +}
> +
> +static inline void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other)
> +{
> +}
>  #endif /* CONFIG_BPF_JIT */
>
>  void bpf_prog_kallsyms_del_all(struct bpf_prog *fp);
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index 066b86e7233c..fc9fb3c07866 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -1508,7 +1508,11 @@ static void adjust_insn_arrays(struct bpf_prog *prog, u32 off, u32 len)
>  #endif
>  }
>
> -struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
> +/*
> + * Now this function is used only to blind the main prog and must be invoked only when
> + * bpf_prog_need_blind() returns true.
> + */
> +struct bpf_prog *bpf_jit_blind_constants(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>         struct bpf_insn insn_buff[16], aux[2];
>         struct bpf_prog *clone, *tmp;
> @@ -1516,13 +1520,17 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
>         struct bpf_insn *insn;
>         int i, rewritten;
>
> -       if (!prog->blinding_requested || prog->blinded)
> -               return prog;
> +       if (WARN_ON_ONCE(env && env->prog != prog))
> +               return ERR_PTR(-EINVAL);
>
>         clone = bpf_prog_clone_create(prog, GFP_USER);
>         if (!clone)
>                 return ERR_PTR(-ENOMEM);
>
> +       /* make sure bpf_patch_insn_data() patches the correct prog */
> +       if (env)
> +               env->prog = clone;
> +
>         insn_cnt = clone->len;
>         insn = clone->insnsi;
>
> @@ -1550,21 +1558,35 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
>                 if (!rewritten)
>                         continue;
>
> -               tmp = bpf_patch_insn_single(clone, i, insn_buff, rewritten);
> -               if (IS_ERR(tmp)) {
> +               if (env)
> +                       tmp = bpf_patch_insn_data(env, i, insn_buff, rewritten);
> +               else
> +                       tmp = bpf_patch_insn_single(clone, i, insn_buff, rewritten);
> +
> +               if (IS_ERR_OR_NULL(tmp)) {
> +                       if (env)
> +                               /* restore the original prog */
> +                               env->prog = prog;
>                         /* Patching may have repointed aux->prog during
>                          * realloc from the original one, so we need to
>                          * fix it up here on error.
>                          */
>                         bpf_jit_prog_release_other(prog, clone);
> -                       return tmp;
> +                       return IS_ERR(tmp) ? tmp : ERR_PTR(-ENOMEM);
>                 }
>
>                 clone = tmp;
>                 insn_delta = rewritten - 1;
>
> -               /* Instructions arrays must be updated using absolute xlated offsets */
> -               adjust_insn_arrays(clone, prog->aux->subprog_start + i, rewritten);
> +               if (env)
> +                       env->prog = clone;
> +               else
> +                       /*
> +                        * Instructions arrays must be updated using absolute xlated offsets.
> +                        * The arrays have already been adjusted by bpf_patch_insn_data() when
> +                        * env is not NULL.
> +                        */
> +                       adjust_insn_arrays(clone, i, rewritten);
>
>                 /* Walk new program and skip insns we just inserted. */
>                 insn = clone->insnsi + i + insn_delta;
> @@ -2533,6 +2555,35 @@ static bool bpf_prog_select_interpreter(struct bpf_prog *fp)
>         return select_interpreter;
>  }
>
> +static struct bpf_prog *bpf_prog_jit_compile(struct bpf_prog *prog)
> +{
> +#ifdef CONFIG_BPF_JIT
> +       struct bpf_prog *orig_prog;
> +
> +       if (!bpf_prog_need_blind(prog))
> +               return bpf_int_jit_compile(prog);
> +
> +       orig_prog = prog;
> +       prog = bpf_jit_blind_constants(NULL, prog);
> +       /*
> +        * If blinding was requested and we failed during blinding, we must fall
> +        * back to the interpreter.
> +        */
> +       if (IS_ERR(prog))
> +               return orig_prog;
> +
> +       prog = bpf_int_jit_compile(prog);
> +       if (prog->jited) {
> +               bpf_jit_prog_release_other(prog, orig_prog);
> +               return prog;
> +       }
> +
> +       bpf_jit_prog_release_other(orig_prog, prog);
> +       prog = orig_prog;
> +#endif
> +       return prog;
> +}
> +
>  /**
>   *     bpf_prog_select_runtime - select exec runtime for BPF program
>   *     @fp: bpf_prog populated with BPF program
> @@ -2572,7 +2623,7 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
>                 if (*err)
>                         return fp;
>
> -               fp = bpf_int_jit_compile(fp);
> +               fp = bpf_prog_jit_compile(fp);
>                 bpf_prog_jit_attempt_done(fp);
>                 if (!fp->jited && jit_needed) {
>                         *err = -ENOTSUPP;
> diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
> index 67c9b28767e1..ec8afd6a9369 100644
> --- a/kernel/bpf/fixups.c
> +++ b/kernel/bpf/fixups.c
> @@ -232,8 +232,8 @@ static void adjust_poke_descs(struct bpf_prog *prog, u32 off, u32 len)
>         }
>  }
>
> -static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
> -                                           const struct bpf_insn *patch, u32 len)
> +struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
> +                                    const struct bpf_insn *patch, u32 len)
>  {
>         struct bpf_prog *new_prog;
>         struct bpf_insn_aux_data *new_data = NULL;
> @@ -973,7 +973,45 @@ int bpf_convert_ctx_accesses(struct bpf_verifier_env *env)
>         return 0;
>  }
>
> -int bpf_jit_subprogs(struct bpf_verifier_env *env)
> +static u32 *bpf_dup_subprog_starts(struct bpf_verifier_env *env)
> +{
> +       u32 *starts = NULL;
> +
> +       starts = kvmalloc_objs(u32, env->subprog_cnt, GFP_KERNEL_ACCOUNT);
> +       if (starts) {
> +               for (int i = 0; i < env->subprog_cnt; i++)
> +                       starts[i] = env->subprog_info[i].start;
> +       }
> +       return starts;
> +}
> +
> +static void bpf_restore_subprog_starts(struct bpf_verifier_env *env, u32 *orig_starts)
> +{
> +       for (int i = 0; i < env->subprog_cnt; i++)
> +               env->subprog_info[i].start = orig_starts[i];
> +}
> +
> +static struct bpf_insn_aux_data *bpf_dup_insn_aux_data(struct bpf_verifier_env *env)
> +{
> +       size_t size;
> +       void *new_aux;
> +
> +       size = array_size(sizeof(struct bpf_insn_aux_data), env->prog->len);
> +       new_aux = __vmalloc(size, GFP_KERNEL_ACCOUNT);
> +       if (new_aux)
> +               memcpy(new_aux, env->insn_aux_data, size);
> +       return new_aux;
> +}
> +
> +static void bpf_restore_insn_aux_data(struct bpf_verifier_env *env,
> +                                     struct bpf_insn_aux_data *orig_insn_aux)
> +{
> +       /* the expanded elements are zero-filled, so no special handling is required */
> +       vfree(env->insn_aux_data);
> +       env->insn_aux_data = orig_insn_aux;
> +}
> +
> +static int jit_subprogs(struct bpf_verifier_env *env)
>  {
>         struct bpf_prog *prog = env->prog, **func, *tmp;
>         int i, j, subprog_start, subprog_end = 0, len, subprog;
> @@ -981,10 +1019,6 @@ int bpf_jit_subprogs(struct bpf_verifier_env *env)
>         struct bpf_insn *insn;
>         void *old_bpf_func;
>         int err, num_exentries;
> -       int old_len, subprog_start_adjustment = 0;
> -
> -       if (env->subprog_cnt <= 1)
> -               return 0;
>
>         for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
>                 if (!bpf_pseudo_func(insn) && !bpf_pseudo_call(insn))
> @@ -1053,10 +1087,11 @@ int bpf_jit_subprogs(struct bpf_verifier_env *env)
>                         goto out_free;
>                 func[i]->is_func = 1;
>                 func[i]->sleepable = prog->sleepable;
> +               func[i]->blinded = prog->blinded;
>                 func[i]->aux->func_idx = i;
>                 /* Below members will be freed only at prog->aux */
>                 func[i]->aux->btf = prog->aux->btf;
> -               func[i]->aux->subprog_start = subprog_start + subprog_start_adjustment;
> +               func[i]->aux->subprog_start = subprog_start;
>                 func[i]->aux->func_info = prog->aux->func_info;
>                 func[i]->aux->func_info_cnt = prog->aux->func_info_cnt;
>                 func[i]->aux->poke_tab = prog->aux->poke_tab;
> @@ -1112,15 +1147,7 @@ int bpf_jit_subprogs(struct bpf_verifier_env *env)
>                 func[i]->aux->might_sleep = env->subprog_info[i].might_sleep;
>                 if (!i)
>                         func[i]->aux->exception_boundary = env->seen_exception;
> -
> -               /*
> -                * To properly pass the absolute subprog start to jit
> -                * all instruction adjustments should be accumulated
> -                */
> -               old_len = func[i]->len;
>                 func[i] = bpf_int_jit_compile(func[i]);
> -               subprog_start_adjustment += func[i]->len - old_len;
> -
>                 if (!func[i]->jited) {
>                         err = -ENOTSUPP;
>                         goto out_free;
> @@ -1246,16 +1273,87 @@ int bpf_jit_subprogs(struct bpf_verifier_env *env)
>         }
>         kfree(func);
>  out_undo_insn:
> +       bpf_prog_jit_attempt_done(prog);
> +       return err;
> +}
> +
> +int bpf_jit_subprogs(struct bpf_verifier_env *env)
> +{
> +       int err, i;
> +       bool blinded = false;
> +       struct bpf_insn *insn;
> +       struct bpf_prog *prog, *orig_prog;
> +       struct bpf_insn_aux_data *orig_insn_aux;
> +       u32 *orig_subprog_starts;
> +
> +       if (env->subprog_cnt <= 1)
> +               return 0;
> +
> +       prog = orig_prog = env->prog;
> +       if (bpf_prog_need_blind(prog)) {
> +               orig_insn_aux = bpf_dup_insn_aux_data(env);
> +               if (!orig_insn_aux) {
> +                       err = -ENOMEM;
> +                       goto out_cleanup;
> +               }
> +               orig_subprog_starts = bpf_dup_subprog_starts(env);
> +               if (!orig_subprog_starts) {
> +                       vfree(orig_insn_aux);
> +                       err = -ENOMEM;
> +                       goto out_cleanup;
> +               }
> +               prog = bpf_jit_blind_constants(env, prog);
> +               if (IS_ERR(prog)) {
> +                       err = -ENOMEM;
> +                       prog = orig_prog;
> +                       goto out_restore;
> +               }
> +               blinded = true;
> +       }
> +
> +       err = jit_subprogs(env);
> +       if (err)
> +               goto out_jit_err;
> +
> +       if (blinded) {
> +               bpf_jit_prog_release_other(prog, orig_prog);
> +               kvfree(orig_subprog_starts);
> +               vfree(orig_insn_aux);
> +       }
> +
> +       return 0;
> +
> +out_jit_err:
> +       if (blinded) {
> +               bpf_jit_prog_release_other(orig_prog, prog);
> +               /* roll back to the clean original prog */
> +               prog = env->prog = orig_prog;
> +               goto out_restore;
> +       } else {
> +               if (err != -EFAULT) {
> +                       /*
> +                        * We will fall back to interpreter mode when err is not -EFAULT, before
> +                        * that, insn->off and insn->imm should be restored to their original
> +                        * values since they were modified by __jit_subprogs.
> +                        */
> +                       for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
> +                               if (!bpf_pseudo_call(insn))
> +                                       continue;
> +                               insn->off = 0;
> +                               insn->imm = env->insn_aux_data[i].call_imm;
> +                       }
> +               }
> +               goto out_cleanup;
> +       }
> +
> +out_restore:
> +       bpf_restore_subprog_starts(env, orig_subprog_starts);
> +       bpf_restore_insn_aux_data(env, orig_insn_aux);
> +       kvfree(orig_subprog_starts);
> +out_cleanup:
>         /* cleanup main prog to be interpreted */
>         prog->jit_requested = 0;
>         prog->blinding_requested = 0;
> -       for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
> -               if (!bpf_pseudo_call(insn))
> -                       continue;
> -               insn->off = 0;
> -               insn->imm = env->insn_aux_data[i].call_imm;
> -       }
> -       bpf_prog_jit_attempt_done(prog);
>         return err;
>  }
>
> --
> 2.47.3
>


^ permalink raw reply

* Re: [PATCH RFC] ACPI: processor: idle: Do not propagate acpi_processor_ffh_lpi_probe() -ENODEV
From: lihuisong (C) @ 2026-04-15  1:32 UTC (permalink / raw)
  To: Sudeep Holla, Rafael J. Wysocki
  Cc: Breno Leitao, Len Brown, lpieralisi, catalin.marinas, will,
	Rafael J. Wysocki, linux-acpi, linux-kernel, pjaroszynski,
	guohanjun, linux-arm-kernel, rmikey, kernel-team, lihuisong
In-Reply-To: <20260414-cute-shapeless-dolphin-c5b2fc@sudeepholla>


On 4/14/2026 8:25 PM, Sudeep Holla wrote:
> On Tue, Apr 14, 2026 at 07:31:29PM +0800, lihuisong (C) wrote:
>> On 4/14/2026 6:21 PM, Breno Leitao wrote:
>>> Hello Huisong,
>>>
>>> On Tue, Apr 14, 2026 at 05:43:51PM +0800, lihuisong (C) wrote:
>>>> But it is a real issue. Thanks for your report.
>>>> I think the best way to fix your issue is that remove this verification in
>>>> psci_acpi_cpu_init_idle().
>>>> Because it is legal for platform to report one LPI state.
>>>> This function just needs to verify the LPI states which are FFH.
>>> Thank you for the prompt feedback.
>>>
>>> Would this approach work?
>>>
>>> commit 6c9d52840a4f778cc989838ba76ee51416e85de3
>>> Author: Breno Leitao <leitao@debian.org>
>>> Date:   Tue Apr 14 03:16:08 2026 -0700
>>>
>>>       ACPI: processor: idle: Allow platforms with only one LPI state
>>>       psci_acpi_cpu_init_idle() rejects platforms where power.count - 1 <= 0
>>>       by returning -ENODEV. However, having a single LPI state (WFI) is a
>>>       valid configuration. The function's purpose is to verify FFH idle states,
>>>       and when count is zero, there are simply no FFH states to validate —
>>>       this is not an error.
>>>       On NVIDIA Grace (aarch64) systems with PSCIv1.1, power.count is 1 for
>>>       all 72 CPUs, so the probe fails with -ENODEV. After commit cac173bea57d
>>>       ("ACPI: processor: idle: Rework the handling of
>>>       acpi_processor_ffh_lpi_probe()"), this failure propagates up and prevents
>>>       cpuidle registration entirely.
>>>       Change the check from (count <= 0) to (count < 0) so that platforms
>>>       with only WFI are accepted. The for loop naturally handles count == 0
>>>       by not iterating.
>>>       Fixes: cac173bea57d ("ACPI: processor: idle: Rework the handling of acpi_processor_ffh_lpi_probe()")
>>>       Signed-off-by: Breno Leitao <leitao@debian.org>
>>>
>>> diff --git a/drivers/acpi/arm64/cpuidle.c b/drivers/acpi/arm64/cpuidle.c
>>> index 801f9c4501425..7791b751042ce 100644
>>> --- a/drivers/acpi/arm64/cpuidle.c
>>> +++ b/drivers/acpi/arm64/cpuidle.c
>>> @@ -31,7 +31,7 @@ static int psci_acpi_cpu_init_idle(unsigned int cpu)
>>>    		return -EOPNOTSUPP;
>>>    	count = pr->power.count - 1;
>>> -	if (count <= 0)
>>> +	if (count < 0)
>>>    		return -ENODEV;
>>>    	for (i = 0; i < count; i++) {
>> This count already verified in acpi_processor_get_lpi_info.
>>
>> I suggest modifing it as below:
>>
>> -->
>>
>> git diff
>> diff --git a/drivers/acpi/arm64/cpuidle.c b/drivers/acpi/arm64/cpuidle.c
>> index 801f9c450142..c68a5db8ebba 100644
>> --- a/drivers/acpi/arm64/cpuidle.c
>> +++ b/drivers/acpi/arm64/cpuidle.c
>> @@ -16,7 +16,7 @@
>>
>>   static int psci_acpi_cpu_init_idle(unsigned int cpu)
>>   {
>> -       int i, count;
>> +       int i;
>>          struct acpi_lpi_state *lpi;
>>          struct acpi_processor *pr = per_cpu(processors, cpu);
>>
>> @@ -30,14 +30,10 @@ static int psci_acpi_cpu_init_idle(unsigned int cpu)
>>          if (!psci_ops.cpu_suspend)
>>                  return -EOPNOTSUPP;
>>
>> -       count = pr->power.count - 1;
>> -       if (count <= 0)
>> -               return -ENODEV;
>> -
> It was intentionally designed this way, as there is little value in defining
> only WFI in the _LPI tables. In the absence of a cpuidle driver/LPI entry,
> arch_cpu_idle() is invoked, which is sufficient and avoids unnecessary
> complexity, only to ultimately execute wfi() anyway.
Yeah, it's correct. The code flow will be more simple and high-efficiency.
This looks good to me.


But cpuidle sysfs under per CPU is created when firmware just reports 
WFI state before
my commit cac173bea57d ("ACPI: processor: idle: Rework the handling of 
acpi_processor_ffh_lpi_probe()").
However, these platforms will no longer be created now and some 
statistics for state0 are also missing.
This change in behavor is visiable to user space.I'm not sure if it is 
acceptable.
What do you think, Rafael?
> So while I understand that the kernel did not report an error previously, that
> does not mean the _LPI table is merely moot on this platform when it contains
> only a WFI state.
>
>


^ permalink raw reply

* Re: [Question mpam mpam/snapshot+extras/v6.18-rc1] Question with Configuring iommu_group in 'task'
From: Zeng Heng @ 2026-04-15  1:27 UTC (permalink / raw)
  To: Ben Horgan, James Morse
  Cc: Qinxin Xia, amitsinght, baisheng.gao, baolin.wang, carl,
	dave.martin, david, dfustini, fenghuay, gshan, james.morse,
	jonathan.cameron, kobak, lcherian, linux-arm-kernel, linux-kernel,
	peternewman, punit.agrawal, quic_jiles, reinette.chatre,
	rohit.mathew, scott, sdonthineni, xhao, Linuxarm
In-Reply-To: <0d578c61-1341-4149-9e8c-936ea0ce0c50@arm.com>

Hi Ben,

On 2026/4/13 23:02, Ben Horgan wrote:
> Hi Qinxin,
> 
> On 4/3/26 03:44, Qinxin Xia wrote:
>>
>>
>> On 2026/3/27 18:47:49, Ben Horgan <ben.horgan@arm.com> wrote:
>>> Hi Qinxin,
>>>
>>> On 3/27/26 10:21, Qinxin Xia wrote:
>>>>
>>>> Hello everyone!
>>>>
>>>> In earlier versions, mpam supports the configuration of iommu_groups.
>>>>
>>>>    823 static ssize_t rdtgroup_tasks_write(struct kernfs_open_file *of,
>>>>    824                                     char *buf, size_t nbytes,
>>>> loff_t off)
>>>>    825 {
>>>>    826         struct rdtgroup *rdtgrp;
>>>>    827         int iommu_group_id;
>>>>    828         bool is_iommu;
>>>>    829         char *pid_str;
>>>>    830         int ret = 0;
>>>>    831         pid_t pid;
>>>>    832
>>>>    833         rdtgrp = rdtgroup_kn_lock_live(of->kn);
>>>>    834         if (!rdtgrp) {
>>>>    835                 rdtgroup_kn_unlock(of->kn);
>>>>    836                 return -ENOENT;
>>>>    837         }
>>>>    838         rdt_last_cmd_clear();
>>>>    839
>>>>    840         if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED ||
>>>>    841             rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
>>>>    842                 ret = -EINVAL;
>>>>    843                 rdt_last_cmd_puts("Pseudo-locking in progress\n");
>>>>    844                 goto unlock;
>>>>    845         }
>>>>    846
>>>>    847         while (buf && buf[0] != '\0' && buf[0] != '\n') {
>>>>    848                 pid_str = strim(strsep(&buf, ","));
>>>>    849
>>>>    850                 is_iommu = string_is_iommu_group(pid_str, &iommu_group_id);
>>>>
>>>> What puzzles me is why we would put it under 'task'—this seems a little
>>>>    strange to users.It seems they are not related.Why don't we add a new
>>>> interface like 'iommu'?
>>>
>>> I think it is likely that this interface would change if upstream support is added.
>>>
>>
>> I have done some work in this direction before, and I will release an
>> RFC later for further discussion.:-)
> 
> Looking forward to seeing it.
> 
> Ben
> 

Following the current SMMU approach, I've submitted several bugfix
patches for the MPAM driver, but haven't received any review feedback
yet.

To avoid these being overlooked, I'd like to kindly remind to take a
look:
v2: 
https://lore.kernel.org/all/20260414032610.1523958-1-zengheng4@huawei.com/
v1: 
https://lore.kernel.org/all/20251107063300.1580046-1-zengheng4@huawei.com/

Additionally, I'd like to check on the status of this branch — is it
still actively maintained? It would be helpful to understand the future
plans for MPAM development.


Thanks for your time,
Zeng Heng


^ permalink raw reply

* Re: [RFC PATCH 00/12] Add Linux RISC-V trace support via CoreSight
From: Zane Leung @ 2026-04-15  1:23 UTC (permalink / raw)
  To: Bo Gan, Anup Patel
  Cc: robh, krzk+dt, conor+dt, palmer, pjw, gregkh, alexander.shishkin,
	irogers, coresight, peterz, mingo, namhyung, mark.rutland, jolsa,
	adrian.hunter, mchitale, atish.patra, andrew.jones, sunilvl,
	linux-riscv, linux-kernel, anup.patel, mayuresh.chitale,
	zhuangqiubin, suzuki.poulose, mike.leach, james.clark,
	linux-arm-kernel
In-Reply-To: <1ced8f98-6ac5-4ffc-ac29-cef25937a920@gmail.com>

Hi Bo,

On 4/15/2026 8:10 AM, Bo Gan wrote:
> Hi Zane, Anup,
>
> On 4/14/26 02:04, Zane Leung wrote:
>>
>> On 4/14/2026 3:23 PM, Anup Patel wrote:
>>> On Tue, Apr 14, 2026 at 9:12 AM Zane Leung <liangzhen@linux.spacemit.com> wrote:
>>>> From: liangzhen <zhen.liang@spacemit.com>
>>>>
>>>> This series adds Linux RISC-V trace support via CoreSight, implementing RISC-V
>>>> trace drivers within the CoreSight framework and integrating them with perf tools.
>>>> The K3 SoC contains RISC-V Encoder, Funnel, ATB, CoreSight Funnel, and CoreSight TMC
>>>> components, which can be directly leveraged through the existing CoreSight infrastructure.
>>>>
>>>> Linux RISC-V trace support form Anup Patel:
>>>> (https://patchwork.kernel.org/project/linux-riscv/cover/20260225062448.4027948-1-anup.patel@oss.qualcomm.com/)
>>>> which currently lacks ATB component support and guidance on reusing CoreSight components.
>>> What stops you from adding RISC-V trace funnel and ATB bridge drivers
>>> on top of this series ?
>>>
>> Firstly, my works started much earlier than this series. Secondly, it is difficult to add the coresight funnel and coresight tmc components to this series. Based on the coresight framework, I can directly reuse them.
>>
>>>
>>>> The series includes:
>>>> - RISC-V trace driver implementation within the CoreSight framework
>>> The RISC-V trace very different from the CoreSight framework in many ways:
>>> 1) Types of components supported
>>> 2) Trace packet formats
>>> 3) The way MMIO based components are discoverd
>>> 4) ... and more ...
>> 1) I believe that RISC-V tracing is coresight-alike, where have encoders/funnel/sink/bridge that are described through DT and controlled by MMIO.
>> 2) I think the difference in package format is nothing more than the coresight frame generated by the ATB component to distinguish the trace source. After removing it, it becomes riscv trace data.
>> 3) The current CoreSight framework code does not introduce this mechanism, it is described through DT.
>>>> - RISC-V Trace Encoder, Funnel, and ATB Bridge drivers as CoreSight devices
>>>> - RISC-V trace PMU record capabilities and parsing events in perf.
>>>> - RISC-V Nexus Trace decoder for perf tools
>>>>
>>>> Any comments or suggestions are welcome.
>>>>
>>>> Verification on K3 SoC:
>>>> To verify this patch series on K3 hardware, the following device tree are required:
>>>> 1. RISC-V Trace Encoder node (8)
>>>> 2. RISC-V ATB Bridge node (8)
>>>> 3. RISC-V Trace Funnel node (2)
>>>> 3. CoreSight Funnel configuration for RISC-V (1)
>>>> 4. CoreSight TMC configuration for trace buffer (1)
>>>>
>>>> /{
>>>>          dummy_clk: apb-pclk {
>>>>                  compatible = "fixed-clock";
>>>>                  #clock-cells = <0x0>;
>>>>                  clock-output-names = "clk14mhz";
>>>>                  clock-frequency = <14000000>;
>>>>          };
>>>>
>>>>
>>>>          soc: soc {
>>>>                  #address-cells = <2>;
>>>>                  #size-cells = <2>;
>>>>
>>>>                  encoder0: encoder@d9002000 {
>>>>                          compatible = "riscv,trace-encoder";
>>>>                          reg = <0x0 0xd9002000 0x0 0x1000>;
>>>>                          cpus = <&cpu_0>;
>>>>                          out-ports {
>>>>                                  port {
>>>>                                          cluster0_encoder0_out_port: endpoint {
>>>>                                                  remote-endpoint = <&cluster0_bridge0_in_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                  };
>>>>
>>>>                  bridge0: bridge@d9003000 {
>>>>                          compatible = "riscv,trace-atbbridge";
>>>>                          reg = <0x0 0xd9003000 0x0 0x1000>;
>>>>                          cpus = <&cpu_0>;
>>>>                          out-ports {
>>>>                                  port {
>>>>                                          cluster0_bridge0_out_port: endpoint {
>>>>                                                  remote-endpoint = <&cluster0_funnel_in_port0>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                          in-ports {
>>>>                                  port {
>>>>                                          cluster0_bridge0_in_port: endpoint {
>>>>                                                  remote-endpoint = <&cluster0_encoder0_out_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                  };
>>>>
>>>> ...
>>>>
>>>>                  cluster0_funnel: funnel@d9000000 {
>>>>                          compatible = "riscv,trace-funnel";
>>>>                          reg = <0x0 0xd9000000 0x0 0x1000>;
>>>>                          cpus = <&cpu_0>, <&cpu_1>, <&cpu_2>, <&cpu_3>;
>>>>                          riscv,timestamp-present;
>>>>                          out-ports {
>>>>                                  port {
>>>>                                          cluster0_funnel_out_port: endpoint {
>>>>                                                  remote-endpoint = <&main_funnel_in_port0>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                          in-ports {
>>>>                                  #address-cells = <1>;
>>>>                                  #size-cells = <0>;
>>>>
>>>>                                  port@0 {
>>>>                                          reg = <0>;
>>>>                                          cluster0_funnel_in_port0: endpoint {
>>>>                                                  remote-endpoint = <&cluster0_bridge0_out_port>;
>>>>                                          };
>>>>                                  };
>>>>
>>>>                                  port@1 {
>>>>                                          reg = <1>;
>>>>                                          cluster0_funnel_in_port1: endpoint {
>>>>                                                  remote-endpoint = <&cluster0_bridge1_out_port>;
>>>>                                          };
>>>>                                  };
>>>>
>>>>                                  port@2 {
>>>>                                          reg = <2>;
>>>>                                          cluster0_funnel_in_port2: endpoint {
>>>>                                                  remote-endpoint = <&cluster0_bridge2_out_port>;
>>>>                                          };
>>>>                                  };
>>>>
>>>>                                  port@3 {
>>>>                                          reg = <3>;
>>>>                                          cluster0_funnel_in_port3: endpoint {
>>>>                                                  remote-endpoint = <&cluster0_bridge3_out_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                  };
>>>>
>>>>                  cluster1_funnel: funnel@d9010000 {
>>>>                          compatible = "riscv,trace-funnel";
>>>>                          reg = <0x0 0xd9010000 0x0 0x1000>;
>>>>                          cpus = <&cpu_4>, <&cpu_5>, <&cpu_6>, <&cpu_7>;
>>>>                          riscv,timestamp-present;
>>>>                          out-ports {
>>>>                                  port {
>>>>                                          cluster1_funnel_out_port: endpoint {
>>>>                                                  remote-endpoint = <&main_funnel_in_port1>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                          in-ports {
>>>>                                  #address-cells = <1>;
>>>>                                  #size-cells = <0>;
>>>>
>>>>                                  port@0 {
>>>>                                          reg = <0>;
>>>>                                          cluster1_funnel_in_port0: endpoint {
>>>>                                                  remote-endpoint = <&cluster1_bridge0_out_port>;
>>>>                                          };
>>>>                                  };
>>>>
>>>>                                  port@1 {
>>>>                                          reg = <1>;
>>>>                                          cluster1_funnel_in_port1: endpoint {
>>>>                                                  remote-endpoint = <&cluster1_bridge1_out_port>;
>>>>                                          };
>>>>                                  };
>>>>
>>>>                                  port@2 {
>>>>                                          reg = <2>;
>>>>                                          cluster1_funnel_in_port2: endpoint {
>>>>                                                  remote-endpoint = <&cluster1_bridge2_out_port>;
>>>>                                          };
>>>>                                  };
>>>>
>>>>                                  port@3 {
>>>>                                          reg = <3>;
>>>>                                          cluster1_funnel_in_port3: endpoint {
>>>>                                                  remote-endpoint = <&cluster1_bridge3_out_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                  };
>>>>
>>>>                  main_funnel: funnel@d9042000 {
>>>>                          compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
>>> Is it legally allowed to mix and match ARM coresight IPs with
>>> RISC-V trace components at hardware level ?
>> The ATB Bridge allows sending RISC-V trace to Arm CoreSight infrastructure (instead of RISC-V compliant sink defined in this document) as an ATB initiator.  see:
>> https://github.com/riscv-non-isa/riscv-nexus-trace/blob/105dc1c349556622e4d202d22b584a887ded462f/docs/RISC-V-Trace-Control-Interface.adoc#L184
>> For ATB Bridge, read trace using Coresight components (ETB/TMC/TPIU). see:
>> https://github.com/riscv-non-isa/riscv-nexus-trace/blob/105dc1c349556622e4d202d22b584a887ded462f/docs/RISC-V-Trace-Control-Interface.adoc#L1684
>>>
>>>>                          reg = <0x0 0xd9042000 0x0 0x1000>;
>>>>                          clocks = <&dummy_clk>;
>>>>                          clock-names = "apb_pclk";
>>>>                          out-ports {
>>>>                                  port {
>>>>                                          main_funnel_out_port: endpoint {
>>>>                                                  remote-endpoint = <&etf_in_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                          in-ports {
>>>>                                  #address-cells = <1>;
>>>>                                  #size-cells = <0>;
>>>>
>>>>                                  port@0 {
>>>>                                          reg = <0>;
>>>>                                          main_funnel_in_port0: endpoint {
>>>>                                                  remote-endpoint = <&cluster0_funnel_out_port>;
>>>>                                          };
>>>>                                  };
>>>>
>>>>                                  port@1 {
>>>>                                          reg = <1>;
>>>>                                          main_funnel_in_port1: endpoint {
>>>>                                                  remote-endpoint = <&cluster1_funnel_out_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                  };
>>>>
>>>>                  etf: etf@d9043000 {
>>>>                          compatible = "arm,coresight-tmc", "arm,primecell";
>>>>                          reg = <0x0 0xd9043000 0x0 0x1000>;
>>>>                          clocks = <&dummy_clk>;
>>>>                          clock-names = "apb_pclk";
>>>>                          out-ports {
>>>>                                  port {
>>>>                                          etf_out_port: endpoint {
>>>>                                                  remote-endpoint = <&etr_in_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                          in-ports {
>>>>                                  port {
>>>>                                          etf_in_port: endpoint {
>>>>                                                  remote-endpoint = <&main_funnel_out_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                  };
>>>>
>>>>                  etr: etr@d9044000 {
>>>>                          compatible = "arm,coresight-tmc", "arm,primecell";
>>>>                          reg = <0x0 0xd9044000 0x0 0x1000>;
>>>>                          clocks = <&dummy_clk>;
>>>>                          clock-names = "apb_pclk";
>>>>                          arm,scatter-gather;
>>>>                          in-ports {
>>>>                                  port {
>>>>                                          etr_in_port: endpoint {
>>>>                                                  remote-endpoint = <&etf_out_port>;
>>>>                                          };
>>>>                                  };
>>>>                          };
>>>>                  };
>>>>          };
>>>> };
>>>>
>>>> Verification case:
>>>>
>>>> ~ # perf list pmu
>>>>    rvtrace//                                          [Kernel PMU event]
>>>>
>>>> ~ # perf record -e rvtrace/@tmc_etr0/ --per-thread uname
>>>> Linux
>>>> [ perf record: Woken up 1 times to write data ]
>>>> [ perf record: Captured and wrote 0.191 MB perf.data ]
>>>> ~ # perf script
>>>>             uname     137 [003]          1           branches:  ffffffff80931470 rvtrace_poll_bit+0x38 ([kernel.kallsyms]) => ffffffff80931492 rvtrace_poll_bit+0x5a ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff809328a6 encoder_enable_hw+0x252 ([kernel.kallsyms]) => ffffffff809328ba encoder_enable_hw+0x266 ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff80932c4a encoder_enable+0x82 ([kernel.kallsyms]) => ffffffff80932c36 encoder_enable+0x6e ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff80928198 etm_event_start+0xf0 ([kernel.kallsyms]) => ffffffff809281aa etm_event_start+0x102 ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff809281e6 etm_event_start+0x13e ([kernel.kallsyms]) => ffffffff8092755e coresight_get_sink_id+0x16 ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff8092820e etm_event_start+0x166 ([kernel.kallsyms]) => ffffffff80928226 etm_event_start+0x17e ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff801c3bb4 perf_report_aux_output_id+0x0 ([kernel.kallsyms]) => ffffffff801c3bd6 perf_report_aux_output_id+0x22 ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff801c3c5a perf_report_aux_output_id+0xa6 ([kernel.kallsyms]) => ffffffff801c3bf0 perf_report_aux_output_id+0x3c ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff801c3c40 perf_report_aux_output_id+0x8c ([kernel.kallsyms]) => ffffffff801c3aea __perf_event_header__init_id+0x2a ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff801c3b42 __perf_event_header__init_id+0x82 ([kernel.kallsyms]) => ffffffff801c3b4a __perf_event_header__init_id+0x8a ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff801c3bb0 __perf_event_header__init_id+0xf0 ([kernel.kallsyms]) => ffffffff801c3b58 __perf_event_header__init_id+0x98 ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff8004c658 __task_pid_nr_ns+0x0 ([kernel.kallsyms]) => ffffffff8004c696 __task_pid_nr_ns+0x3e ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff8004c71e __task_pid_nr_ns+0xc6 ([kernel.kallsyms]) => ffffffff8004c6a4 __task_pid_nr_ns+0x4c ([kernel.kallsyms])
>>>>             uname     137 [003]          1           branches:  ffffffff8004c6e4 __task_pid_nr_ns+0x8c ([kernel.kallsyms]) => ffffffff8004c6e4 __task_pid_nr_ns+0x8c ([kernel.kallsyms])
>>>> ...
>>>>
>>>> liangzhen (12):
>>>>    coresight: Add RISC-V support to CoreSight tracing
>>>>    coresight: Initial implementation of RISC-V trace driver
>>>>    coresight: Add RISC-V Trace Encoder driver
>>>>    coresight: Add RISC-V Trace Funnel driver
>>>>    coresight: Add RISC-V Trace ATB Bridge driver
>>>>    coresight rvtrace: Add timestamp component support for encoder and
>>>>      funnel
>>>>    coresight: Add RISC-V PMU name support
>>>>    perf tools: riscv: making rvtrace PMU listable
>>>>    perf tools: Add RISC-V trace PMU record capabilities
>>>>    perf tools: Add Nexus RISC-V Trace decoder
>>>>    perf symbols: Add RISC-V PLT entry sizes
>>>>    perf tools: Integrate RISC-V trace decoder into auxtrace
>>>>
>>>>   drivers/hwtracing/Kconfig                     |    2 +
>>>>   drivers/hwtracing/coresight/Kconfig           |   46 +-
>>>>   drivers/hwtracing/coresight/Makefile          |    6 +
>>>>   drivers/hwtracing/coresight/coresight-core.c  |    8 +
>>>>   .../hwtracing/coresight/coresight-etm-perf.c  |    1 -
>>>>   .../hwtracing/coresight/coresight-etm-perf.h  |   21 +
>>>>   .../hwtracing/coresight/coresight-platform.c  |    1 -
>>>>   .../hwtracing/coresight/coresight-tmc-etf.c   |    4 +
>>>>   .../hwtracing/coresight/coresight-tmc-etr.c   |    4 +
>>>>   .../hwtracing/coresight/rvtrace-atbbridge.c   |  239 +++
>>>>   drivers/hwtracing/coresight/rvtrace-core.c    |  135 ++
>>>>   .../coresight/rvtrace-encoder-core.c          |  562 +++++++
>>>>   .../coresight/rvtrace-encoder-sysfs.c         |  363 +++++
>>>>   drivers/hwtracing/coresight/rvtrace-encoder.h |  151 ++
>>>>   drivers/hwtracing/coresight/rvtrace-funnel.c  |  337 ++++
>>>>   drivers/hwtracing/coresight/rvtrace-funnel.h  |   39 +
>>>>   .../hwtracing/coresight/rvtrace-timestamp.c   |  278 ++++
>>>>   .../hwtracing/coresight/rvtrace-timestamp.h   |   64 +
>>>>   include/linux/coresight-pmu.h                 |    4 +
>>>>   include/linux/rvtrace.h                       |  116 ++
>>>>   tools/arch/riscv/include/asm/insn.h           |  645 ++++++++
>>>>   tools/perf/arch/riscv/util/Build              |    2 +
>>>>   tools/perf/arch/riscv/util/auxtrace.c         |  490 ++++++
>>>>   tools/perf/arch/riscv/util/pmu.c              |   20 +
>>>>   tools/perf/util/Build                         |    3 +
>>>>   tools/perf/util/auxtrace.c                    |    4 +
>>>>   tools/perf/util/auxtrace.h                    |    1 +
>>>>   tools/perf/util/nexus-rv-decoder/Build        |    1 +
>>>>   .../util/nexus-rv-decoder/nexus-rv-decoder.c  | 1364 +++++++++++++++++
>>>>   .../util/nexus-rv-decoder/nexus-rv-decoder.h  |  139 ++
>>>>   .../perf/util/nexus-rv-decoder/nexus-rv-msg.h |  190 +++
>>>>   tools/perf/util/rvtrace-decoder.c             | 1039 +++++++++++++
>>>>   tools/perf/util/rvtrace.h                     |   40 +
>>>>   tools/perf/util/symbol-elf.c                  |    4 +
>>>>   34 files changed, 6320 insertions(+), 3 deletions(-)
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-atbbridge.c
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-core.c
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder-core.c
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder-sysfs.c
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder.h
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.c
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.h
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-timestamp.c
>>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-timestamp.h
>>>>   create mode 100644 include/linux/rvtrace.h
>>>>   create mode 100644 tools/arch/riscv/include/asm/insn.h
>>>>   create mode 100644 tools/perf/arch/riscv/util/auxtrace.c
>>>>   create mode 100644 tools/perf/arch/riscv/util/pmu.c
>>>>   create mode 100644 tools/perf/util/nexus-rv-decoder/Build
>>>>   create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-decoder.c
>>>>   create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-decoder.h
>>>>   create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-msg.h
>>>>   create mode 100644 tools/perf/util/rvtrace-decoder.c
>>>>   create mode 100644 tools/perf/util/rvtrace.h
>>>>
>>>> -- 
>>>> 2.34.1
>>>>
>>> NACK to this approach of retrofitting RISC-V trace into ARM coresight.
>> I agree that integrating RISC-V trace directly into CoreSight is not a good approach, so I think we should abstract some of the logic of coresight and reuse it in RISC-V Trace.
>
> I think we should indeed abstract out some coresight logic so it can be
> reused by both coresight/rvtrace, especially the way of handling trace
> component topology. The generic logic of building a path from source ->
> sink should be common among coresight/rvtrace and for future architecture.
> To support ATB use case like the K3, I think the best way to approach this
> is to model the atb driver as a separate rvtrace-atb drive and let it
> drive the ARM coresight components. Don't treat risc-v trace as another
> type of coresight.
>
> @Zane, can you also clarify that only the 2 X100 clusters have trace
> encoders, and the A100 clusters do not? I don't see the 2 A100 clusters
> listed in your sample devicetree. If that's the case, then we'll be faced
> with heterogeneous trace setup, making it even more complicated.
>
The A100 clusters also have trace encoders, just like the X100 clusters. The reason I didn't include the two A100 clusters in the sample devicetree is to maintain consistency with the upstream k3.dtsi.


>>>
>>> Regards,
>>> Anup
>>
>> Thanks,
>> Zane
>
> Bo
>

Thanks,

Zane


^ permalink raw reply

* Re: [PATCH v4 3/9] coresight: etm4x: fix leaked trace id
From: Jie Gan @ 2026-04-15  1:21 UTC (permalink / raw)
  To: Yeoreum Yun, Leo Yan
  Cc: coresight, linux-arm-kernel, linux-kernel, suzuki.poulose,
	mike.leach, james.clark, alexander.shishkin
In-Reply-To: <ad5wVVnUw1jnkCdn@e129823.arm.com>



On 4/15/2026 12:50 AM, Yeoreum Yun wrote:
> Hi,
> 
>> On Mon, Apr 13, 2026 at 03:19:56PM +0100, Yeoreum Yun wrote:
>>> If etm4_enable_sysfs() fails in cscfg_csdev_enable_active_config(),
>>> the trace ID may be leaked because it is not released.
>>>
>>> To address this, call etm4_release_trace_id() when etm4_enable_sysfs()
>>> fails in cscfg_csdev_enable_active_config().
>>>
>>> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
>>> ---
>>>   drivers/hwtracing/coresight/coresight-etm4x-core.c | 4 +++-
>>>   1 file changed, 3 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> index 8ebfd3924143..1bc9f13e33f7 100644
>>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> @@ -918,8 +918,10 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
>>>   	cscfg_config_sysfs_get_active_cfg(&cfg_hash, &preset);
>>>   	if (cfg_hash) {
>>>   		ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
>>> -		if (ret)
>>> +		if (ret) {
>>> +			etm4_release_trace_id(drvdata);
>>
>> I am not familiar with the trace ID, seems to me, it just allocate a ID
>> for each tracer from the ID map and then always use this cached ID for
>> the tracers.
>>
>> If so, even an ID is reserved for failures, and the ID map is big enough
>> for each CPU, we don't need to worry memory leak or ID used out issue ?
>>
> 
> Agree. Practically, this is not a big issue and I don't think
> because of this new id couldn't be allocated in 128
> although the one id is occupied by cpu while source is disabled.
> 
> However, in theory, this could lead to an ID leak,
> so it would be better to release it in error cases.

Actually, the 128 Trace ID is not enough for allocating. That's why the 
TPDM devices share the trace ID of the connected TPDA devices.

For the QCOM platform, we may got plenty of ETM devices (SoC with more 
than 20 Cores), lots of TPDM devices for each subsystem(CDSP, ADSP, GPU, 
GCC, MODEM, etc ...), and lots of dummy sources...

What I am thinking is as SoCs continue to grow more complex with an 
increasing number of subsystems, trace IDs may be exhausted in the near 
future. (that's why we have dynamic trace ID allocation/release).

Thanks,
Jie

> 
> [...]
> 
> --
> Sincerely,
> Yeoreum Yun



^ permalink raw reply

* Re: [PATCH net-next] net: stmmac: enable RPS and RBU interrupts
From: Russell King (Oracle) @ 2026-04-15  1:19 UTC (permalink / raw)
  To: Sam Edwards
  Cc: Jakub Kicinski, Andrew Lunn, Alexandre Torgue, Andrew Lunn,
	David S. Miller, Eric Dumazet,
	moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	linux-stm32, Linux Network Development Mailing List, Paolo Abeni
In-Reply-To: <ad5LlXzeQ8j14Mjg@shell.armlinux.org.uk>

Okay, just a quick note to say that nvidia's 5.10.216-tegra kernel
survives iperf3 -c -R to the imx6.

Dumping the registers and comparing, and then forcing the RQS and TQS
values to 0x23 (+1 = 36, *256 = 9216 bytes) and 0x8f (+1 = 144,
*256 = 36864 ytes) respectively seems to solve the problem. Under
net-next, these both end up being 0xff (+1 = 256, *256 = 65536 bytes.)
Suspiciously, 36 * 4 = 144, and I also see that this kernel programs
all four of the MTL receive operation mode registers, but only the
first MTL transmit operation mode register. However, DMA channels 1-3
aren't initialised.

net-next derives them from:

        unsigned int tqs = fifosz / 256 - 1;

where fifosz is passed in to dwmac4_dma_tx_chan_op_mode() and

        unsigned int rqs = fifosz / 256 - 1;

where fifosz is passed in to dwmac4_dma_rx_chan_op_mode().

Now, according to the DMA capabilities:

        Number of Additional RX channel: 4
        Number of Additional TX channel: 4
        Number of Additional RX queues: 4
        Number of Additional TX queues: 4
        TX Fifo Size: 65536
        RX Fifo Size: 65536

However:

# ethtool -l eth0
Channel parameters for eth0:
Pre-set maximums:
RX:             4
TX:             4
Other:          0
Combined:       0
Current hardware settings:
RX:             1
TX:             1
Other:          0
Combined:       0

So, we end up allocating the entire 64K of the tx and rx FIFO to one
queue in net-next.

Looking back at 5.10, I don't see any code that would account for these
values being programmed for TQS and RQS, it looks like the calculations
are basically the same as we have today.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


^ permalink raw reply

* Re: [PATCH v3 2/4] phy: axiado: add Axiado eMMC PHY driver
From: Tzu-Hao Wei @ 2026-04-15  0:55 UTC (permalink / raw)
  To: SriNavmani A, Prasad Bolisetty, Vinod Koul, Neil Armstrong,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-phy, devicetree, linux-arm-kernel, linux-kernel, openbmc
In-Reply-To: <20260317-axiado-ax3000-add-emmc-phy-driver-support-v3-2-fbf790f3f711@axiado.com>

On 3/18/2026 3:52 AM, Tzu-Hao Wei wrote:
> From: SriNavmani A <srinavmani@axiado.com>
> 
> It provides the required configurations for Axiado eMMC PHY driver for
> HS200 mode.
> 
> Signed-off-by: SriNavmani A <srinavmani@axiado.com>
> Co-developed-by: Prasad Bolisetty <pbolisetty@axiado.com>
> Signed-off-by: Prasad Bolisetty <pbolisetty@axiado.com>
> Signed-off-by: Tzu-Hao Wei <twei@axiado.com>
> ---
>  drivers/phy/Kconfig                  |   1 +
>  drivers/phy/Makefile                 |   1 +
>  drivers/phy/axiado/Kconfig           |  11 ++
>  drivers/phy/axiado/Makefile          |   1 +
>  drivers/phy/axiado/phy-axiado-emmc.c | 217 +++++++++++++++++++++++++++++++++++
>  5 files changed, 231 insertions(+)
> 

Hi Vinod,

Just a gentle ping on this patch series.

Since you reviewed the previous version, I wanted to check if you might have
a chance to take a look at this one when time permits.

Any feedback would be appreciated.

Best regards,
TH



^ permalink raw reply

* Re: [RFC PATCH 00/12] Add Linux RISC-V trace support via CoreSight
From: Bo Gan @ 2026-04-15  0:10 UTC (permalink / raw)
  To: Zane Leung, Anup Patel
  Cc: robh, krzk+dt, conor+dt, palmer, pjw, gregkh, alexander.shishkin,
	irogers, coresight, peterz, mingo, namhyung, mark.rutland, jolsa,
	adrian.hunter, mchitale, atish.patra, andrew.jones, sunilvl,
	linux-riscv, linux-kernel, anup.patel, mayuresh.chitale,
	zhuangqiubin, suzuki.poulose, mike.leach, james.clark,
	linux-arm-kernel
In-Reply-To: <7EFD9F2504326BD1+26395797-fbe8-491b-b651-701286fb5751@linux.spacemit.com>

Hi Zane, Anup,

On 4/14/26 02:04, Zane Leung wrote:
> 
> On 4/14/2026 3:23 PM, Anup Patel wrote:
>> On Tue, Apr 14, 2026 at 9:12 AM Zane Leung <liangzhen@linux.spacemit.com> wrote:
>>> From: liangzhen <zhen.liang@spacemit.com>
>>>
>>> This series adds Linux RISC-V trace support via CoreSight, implementing RISC-V
>>> trace drivers within the CoreSight framework and integrating them with perf tools.
>>> The K3 SoC contains RISC-V Encoder, Funnel, ATB, CoreSight Funnel, and CoreSight TMC
>>> components, which can be directly leveraged through the existing CoreSight infrastructure.
>>>
>>> Linux RISC-V trace support form Anup Patel:
>>> (https://patchwork.kernel.org/project/linux-riscv/cover/20260225062448.4027948-1-anup.patel@oss.qualcomm.com/)
>>> which currently lacks ATB component support and guidance on reusing CoreSight components.
>> What stops you from adding RISC-V trace funnel and ATB bridge drivers
>> on top of this series ?
>>
> Firstly, my works started much earlier than this series. Secondly, it is difficult to add the coresight funnel and coresight tmc components to this series. Based on the coresight framework, I can directly reuse them.
> 
>>
>>> The series includes:
>>> - RISC-V trace driver implementation within the CoreSight framework
>> The RISC-V trace very different from the CoreSight framework in many ways:
>> 1) Types of components supported
>> 2) Trace packet formats
>> 3) The way MMIO based components are discoverd
>> 4) ... and more ...
> 1) I believe that RISC-V tracing is coresight-alike, where have encoders/funnel/sink/bridge that are described through DT and controlled by MMIO.
> 2) I think the difference in package format is nothing more than the coresight frame generated by the ATB component to distinguish the trace source. After removing it, it becomes riscv trace data.
> 3) The current CoreSight framework code does not introduce this mechanism, it is described through DT.
>>> - RISC-V Trace Encoder, Funnel, and ATB Bridge drivers as CoreSight devices
>>> - RISC-V trace PMU record capabilities and parsing events in perf.
>>> - RISC-V Nexus Trace decoder for perf tools
>>>
>>> Any comments or suggestions are welcome.
>>>
>>> Verification on K3 SoC:
>>> To verify this patch series on K3 hardware, the following device tree are required:
>>> 1. RISC-V Trace Encoder node (8)
>>> 2. RISC-V ATB Bridge node (8)
>>> 3. RISC-V Trace Funnel node (2)
>>> 3. CoreSight Funnel configuration for RISC-V (1)
>>> 4. CoreSight TMC configuration for trace buffer (1)
>>>
>>> /{
>>>          dummy_clk: apb-pclk {
>>>                  compatible = "fixed-clock";
>>>                  #clock-cells = <0x0>;
>>>                  clock-output-names = "clk14mhz";
>>>                  clock-frequency = <14000000>;
>>>          };
>>>
>>>
>>>          soc: soc {
>>>                  #address-cells = <2>;
>>>                  #size-cells = <2>;
>>>
>>>                  encoder0: encoder@d9002000 {
>>>                          compatible = "riscv,trace-encoder";
>>>                          reg = <0x0 0xd9002000 0x0 0x1000>;
>>>                          cpus = <&cpu_0>;
>>>                          out-ports {
>>>                                  port {
>>>                                          cluster0_encoder0_out_port: endpoint {
>>>                                                  remote-endpoint = <&cluster0_bridge0_in_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                  };
>>>
>>>                  bridge0: bridge@d9003000 {
>>>                          compatible = "riscv,trace-atbbridge";
>>>                          reg = <0x0 0xd9003000 0x0 0x1000>;
>>>                          cpus = <&cpu_0>;
>>>                          out-ports {
>>>                                  port {
>>>                                          cluster0_bridge0_out_port: endpoint {
>>>                                                  remote-endpoint = <&cluster0_funnel_in_port0>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                          in-ports {
>>>                                  port {
>>>                                          cluster0_bridge0_in_port: endpoint {
>>>                                                  remote-endpoint = <&cluster0_encoder0_out_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                  };
>>>
>>> ...
>>>
>>>                  cluster0_funnel: funnel@d9000000 {
>>>                          compatible = "riscv,trace-funnel";
>>>                          reg = <0x0 0xd9000000 0x0 0x1000>;
>>>                          cpus = <&cpu_0>, <&cpu_1>, <&cpu_2>, <&cpu_3>;
>>>                          riscv,timestamp-present;
>>>                          out-ports {
>>>                                  port {
>>>                                          cluster0_funnel_out_port: endpoint {
>>>                                                  remote-endpoint = <&main_funnel_in_port0>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                          in-ports {
>>>                                  #address-cells = <1>;
>>>                                  #size-cells = <0>;
>>>
>>>                                  port@0 {
>>>                                          reg = <0>;
>>>                                          cluster0_funnel_in_port0: endpoint {
>>>                                                  remote-endpoint = <&cluster0_bridge0_out_port>;
>>>                                          };
>>>                                  };
>>>
>>>                                  port@1 {
>>>                                          reg = <1>;
>>>                                          cluster0_funnel_in_port1: endpoint {
>>>                                                  remote-endpoint = <&cluster0_bridge1_out_port>;
>>>                                          };
>>>                                  };
>>>
>>>                                  port@2 {
>>>                                          reg = <2>;
>>>                                          cluster0_funnel_in_port2: endpoint {
>>>                                                  remote-endpoint = <&cluster0_bridge2_out_port>;
>>>                                          };
>>>                                  };
>>>
>>>                                  port@3 {
>>>                                          reg = <3>;
>>>                                          cluster0_funnel_in_port3: endpoint {
>>>                                                  remote-endpoint = <&cluster0_bridge3_out_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                  };
>>>
>>>                  cluster1_funnel: funnel@d9010000 {
>>>                          compatible = "riscv,trace-funnel";
>>>                          reg = <0x0 0xd9010000 0x0 0x1000>;
>>>                          cpus = <&cpu_4>, <&cpu_5>, <&cpu_6>, <&cpu_7>;
>>>                          riscv,timestamp-present;
>>>                          out-ports {
>>>                                  port {
>>>                                          cluster1_funnel_out_port: endpoint {
>>>                                                  remote-endpoint = <&main_funnel_in_port1>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                          in-ports {
>>>                                  #address-cells = <1>;
>>>                                  #size-cells = <0>;
>>>
>>>                                  port@0 {
>>>                                          reg = <0>;
>>>                                          cluster1_funnel_in_port0: endpoint {
>>>                                                  remote-endpoint = <&cluster1_bridge0_out_port>;
>>>                                          };
>>>                                  };
>>>
>>>                                  port@1 {
>>>                                          reg = <1>;
>>>                                          cluster1_funnel_in_port1: endpoint {
>>>                                                  remote-endpoint = <&cluster1_bridge1_out_port>;
>>>                                          };
>>>                                  };
>>>
>>>                                  port@2 {
>>>                                          reg = <2>;
>>>                                          cluster1_funnel_in_port2: endpoint {
>>>                                                  remote-endpoint = <&cluster1_bridge2_out_port>;
>>>                                          };
>>>                                  };
>>>
>>>                                  port@3 {
>>>                                          reg = <3>;
>>>                                          cluster1_funnel_in_port3: endpoint {
>>>                                                  remote-endpoint = <&cluster1_bridge3_out_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                  };
>>>
>>>                  main_funnel: funnel@d9042000 {
>>>                          compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
>> Is it legally allowed to mix and match ARM coresight IPs with
>> RISC-V trace components at hardware level ?
> The ATB Bridge allows sending RISC-V trace to Arm CoreSight infrastructure (instead of RISC-V compliant sink defined in this document) as an ATB initiator.  see:
> https://github.com/riscv-non-isa/riscv-nexus-trace/blob/105dc1c349556622e4d202d22b584a887ded462f/docs/RISC-V-Trace-Control-Interface.adoc#L184
> For ATB Bridge, read trace using Coresight components (ETB/TMC/TPIU). see:
> https://github.com/riscv-non-isa/riscv-nexus-trace/blob/105dc1c349556622e4d202d22b584a887ded462f/docs/RISC-V-Trace-Control-Interface.adoc#L1684
>>
>>>                          reg = <0x0 0xd9042000 0x0 0x1000>;
>>>                          clocks = <&dummy_clk>;
>>>                          clock-names = "apb_pclk";
>>>                          out-ports {
>>>                                  port {
>>>                                          main_funnel_out_port: endpoint {
>>>                                                  remote-endpoint = <&etf_in_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                          in-ports {
>>>                                  #address-cells = <1>;
>>>                                  #size-cells = <0>;
>>>
>>>                                  port@0 {
>>>                                          reg = <0>;
>>>                                          main_funnel_in_port0: endpoint {
>>>                                                  remote-endpoint = <&cluster0_funnel_out_port>;
>>>                                          };
>>>                                  };
>>>
>>>                                  port@1 {
>>>                                          reg = <1>;
>>>                                          main_funnel_in_port1: endpoint {
>>>                                                  remote-endpoint = <&cluster1_funnel_out_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                  };
>>>
>>>                  etf: etf@d9043000 {
>>>                          compatible = "arm,coresight-tmc", "arm,primecell";
>>>                          reg = <0x0 0xd9043000 0x0 0x1000>;
>>>                          clocks = <&dummy_clk>;
>>>                          clock-names = "apb_pclk";
>>>                          out-ports {
>>>                                  port {
>>>                                          etf_out_port: endpoint {
>>>                                                  remote-endpoint = <&etr_in_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                          in-ports {
>>>                                  port {
>>>                                          etf_in_port: endpoint {
>>>                                                  remote-endpoint = <&main_funnel_out_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                  };
>>>
>>>                  etr: etr@d9044000 {
>>>                          compatible = "arm,coresight-tmc", "arm,primecell";
>>>                          reg = <0x0 0xd9044000 0x0 0x1000>;
>>>                          clocks = <&dummy_clk>;
>>>                          clock-names = "apb_pclk";
>>>                          arm,scatter-gather;
>>>                          in-ports {
>>>                                  port {
>>>                                          etr_in_port: endpoint {
>>>                                                  remote-endpoint = <&etf_out_port>;
>>>                                          };
>>>                                  };
>>>                          };
>>>                  };
>>>          };
>>> };
>>>
>>> Verification case:
>>>
>>> ~ # perf list pmu
>>>    rvtrace//                                          [Kernel PMU event]
>>>
>>> ~ # perf record -e rvtrace/@tmc_etr0/ --per-thread uname
>>> Linux
>>> [ perf record: Woken up 1 times to write data ]
>>> [ perf record: Captured and wrote 0.191 MB perf.data ]
>>> ~ # perf script
>>>             uname     137 [003]          1           branches:  ffffffff80931470 rvtrace_poll_bit+0x38 ([kernel.kallsyms]) => ffffffff80931492 rvtrace_poll_bit+0x5a ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff809328a6 encoder_enable_hw+0x252 ([kernel.kallsyms]) => ffffffff809328ba encoder_enable_hw+0x266 ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff80932c4a encoder_enable+0x82 ([kernel.kallsyms]) => ffffffff80932c36 encoder_enable+0x6e ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff80928198 etm_event_start+0xf0 ([kernel.kallsyms]) => ffffffff809281aa etm_event_start+0x102 ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff809281e6 etm_event_start+0x13e ([kernel.kallsyms]) => ffffffff8092755e coresight_get_sink_id+0x16 ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff8092820e etm_event_start+0x166 ([kernel.kallsyms]) => ffffffff80928226 etm_event_start+0x17e ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff801c3bb4 perf_report_aux_output_id+0x0 ([kernel.kallsyms]) => ffffffff801c3bd6 perf_report_aux_output_id+0x22 ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff801c3c5a perf_report_aux_output_id+0xa6 ([kernel.kallsyms]) => ffffffff801c3bf0 perf_report_aux_output_id+0x3c ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff801c3c40 perf_report_aux_output_id+0x8c ([kernel.kallsyms]) => ffffffff801c3aea __perf_event_header__init_id+0x2a ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff801c3b42 __perf_event_header__init_id+0x82 ([kernel.kallsyms]) => ffffffff801c3b4a __perf_event_header__init_id+0x8a ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff801c3bb0 __perf_event_header__init_id+0xf0 ([kernel.kallsyms]) => ffffffff801c3b58 __perf_event_header__init_id+0x98 ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff8004c658 __task_pid_nr_ns+0x0 ([kernel.kallsyms]) => ffffffff8004c696 __task_pid_nr_ns+0x3e ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff8004c71e __task_pid_nr_ns+0xc6 ([kernel.kallsyms]) => ffffffff8004c6a4 __task_pid_nr_ns+0x4c ([kernel.kallsyms])
>>>             uname     137 [003]          1           branches:  ffffffff8004c6e4 __task_pid_nr_ns+0x8c ([kernel.kallsyms]) => ffffffff8004c6e4 __task_pid_nr_ns+0x8c ([kernel.kallsyms])
>>> ...
>>>
>>> liangzhen (12):
>>>    coresight: Add RISC-V support to CoreSight tracing
>>>    coresight: Initial implementation of RISC-V trace driver
>>>    coresight: Add RISC-V Trace Encoder driver
>>>    coresight: Add RISC-V Trace Funnel driver
>>>    coresight: Add RISC-V Trace ATB Bridge driver
>>>    coresight rvtrace: Add timestamp component support for encoder and
>>>      funnel
>>>    coresight: Add RISC-V PMU name support
>>>    perf tools: riscv: making rvtrace PMU listable
>>>    perf tools: Add RISC-V trace PMU record capabilities
>>>    perf tools: Add Nexus RISC-V Trace decoder
>>>    perf symbols: Add RISC-V PLT entry sizes
>>>    perf tools: Integrate RISC-V trace decoder into auxtrace
>>>
>>>   drivers/hwtracing/Kconfig                     |    2 +
>>>   drivers/hwtracing/coresight/Kconfig           |   46 +-
>>>   drivers/hwtracing/coresight/Makefile          |    6 +
>>>   drivers/hwtracing/coresight/coresight-core.c  |    8 +
>>>   .../hwtracing/coresight/coresight-etm-perf.c  |    1 -
>>>   .../hwtracing/coresight/coresight-etm-perf.h  |   21 +
>>>   .../hwtracing/coresight/coresight-platform.c  |    1 -
>>>   .../hwtracing/coresight/coresight-tmc-etf.c   |    4 +
>>>   .../hwtracing/coresight/coresight-tmc-etr.c   |    4 +
>>>   .../hwtracing/coresight/rvtrace-atbbridge.c   |  239 +++
>>>   drivers/hwtracing/coresight/rvtrace-core.c    |  135 ++
>>>   .../coresight/rvtrace-encoder-core.c          |  562 +++++++
>>>   .../coresight/rvtrace-encoder-sysfs.c         |  363 +++++
>>>   drivers/hwtracing/coresight/rvtrace-encoder.h |  151 ++
>>>   drivers/hwtracing/coresight/rvtrace-funnel.c  |  337 ++++
>>>   drivers/hwtracing/coresight/rvtrace-funnel.h  |   39 +
>>>   .../hwtracing/coresight/rvtrace-timestamp.c   |  278 ++++
>>>   .../hwtracing/coresight/rvtrace-timestamp.h   |   64 +
>>>   include/linux/coresight-pmu.h                 |    4 +
>>>   include/linux/rvtrace.h                       |  116 ++
>>>   tools/arch/riscv/include/asm/insn.h           |  645 ++++++++
>>>   tools/perf/arch/riscv/util/Build              |    2 +
>>>   tools/perf/arch/riscv/util/auxtrace.c         |  490 ++++++
>>>   tools/perf/arch/riscv/util/pmu.c              |   20 +
>>>   tools/perf/util/Build                         |    3 +
>>>   tools/perf/util/auxtrace.c                    |    4 +
>>>   tools/perf/util/auxtrace.h                    |    1 +
>>>   tools/perf/util/nexus-rv-decoder/Build        |    1 +
>>>   .../util/nexus-rv-decoder/nexus-rv-decoder.c  | 1364 +++++++++++++++++
>>>   .../util/nexus-rv-decoder/nexus-rv-decoder.h  |  139 ++
>>>   .../perf/util/nexus-rv-decoder/nexus-rv-msg.h |  190 +++
>>>   tools/perf/util/rvtrace-decoder.c             | 1039 +++++++++++++
>>>   tools/perf/util/rvtrace.h                     |   40 +
>>>   tools/perf/util/symbol-elf.c                  |    4 +
>>>   34 files changed, 6320 insertions(+), 3 deletions(-)
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-atbbridge.c
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-core.c
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder-core.c
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder-sysfs.c
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-encoder.h
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.c
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.h
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-timestamp.c
>>>   create mode 100644 drivers/hwtracing/coresight/rvtrace-timestamp.h
>>>   create mode 100644 include/linux/rvtrace.h
>>>   create mode 100644 tools/arch/riscv/include/asm/insn.h
>>>   create mode 100644 tools/perf/arch/riscv/util/auxtrace.c
>>>   create mode 100644 tools/perf/arch/riscv/util/pmu.c
>>>   create mode 100644 tools/perf/util/nexus-rv-decoder/Build
>>>   create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-decoder.c
>>>   create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-decoder.h
>>>   create mode 100644 tools/perf/util/nexus-rv-decoder/nexus-rv-msg.h
>>>   create mode 100644 tools/perf/util/rvtrace-decoder.c
>>>   create mode 100644 tools/perf/util/rvtrace.h
>>>
>>> --
>>> 2.34.1
>>>
>> NACK to this approach of retrofitting RISC-V trace into ARM coresight.
> I agree that integrating RISC-V trace directly into CoreSight is not a good approach, so I think we should abstract some of the logic of coresight and reuse it in RISC-V Trace.

I think we should indeed abstract out some coresight logic so it can be
reused by both coresight/rvtrace, especially the way of handling trace
component topology. The generic logic of building a path from source ->
sink should be common among coresight/rvtrace and for future architecture.
To support ATB use case like the K3, I think the best way to approach this
is to model the atb driver as a separate rvtrace-atb drive and let it
drive the ARM coresight components. Don't treat risc-v trace as another
type of coresight.

@Zane, can you also clarify that only the 2 X100 clusters have trace
encoders, and the A100 clusters do not? I don't see the 2 A100 clusters
listed in your sample devicetree. If that's the case, then we'll be faced
with heterogeneous trace setup, making it even more complicated.

>>
>> Regards,
>> Anup
> 
> Thanks,
> Zane

Bo


^ permalink raw reply

* Re: [GIT PULL] arm64 updates for 7.1
From: pr-tracker-bot @ 2026-04-15  0:03 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Linus Torvalds, Will Deacon, Thomas Gleixner, James Morse,
	Ben Horgan, linux-arm-kernel, linux-kernel
In-Reply-To: <ad5Fh5JUqptcYkrp@arm.com>

The pull request you sent on Tue, 14 Apr 2026 14:47:51 +0100:

> git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux tags/arm64-upstream

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/c43267e6794a36013fd495a4d81bf7f748fe4615

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html


^ permalink raw reply

* Re: [GIT PULL] arm64 updates for 7.1
From: Linus Torvalds @ 2026-04-15  0:02 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Will Deacon, Thomas Gleixner, James Morse, Ben Horgan,
	linux-arm-kernel, linux-kernel, Peter Zijlstra
In-Reply-To: <ad5Fh5JUqptcYkrp@arm.com>

On Tue, 14 Apr 2026 at 06:47, Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> The generic entry patches touch include/linux/*entry* and kernel/entry/*
> as they are based on a tag from tip. Not sure when Thomas will send them
> your way, so sending the arm64 pull request in the meantime.

Ok, so the conflict with the irq changes is something that I want
Thomas and PeterZ to take a look at, because it involved two calls to
hrtimer_rearm_deferred() that got added in the meantime - while in
this pull the call site then got split up and moved from
kernel/entry/common.c to include/linux/irq-entry-common.h.

In my initial resolution I placed the two hrtimer_rearm_deferred()
calls very similarly to how they were placed before (just in the moved
location).

So my initial resolution was the fairly direct "that's what the code
movement would do".

But then I double-checked what linux-next did, and it did something
quite different. The linux-next resolution isn't the naive direct code
movement, and seems to be a smarter semantic resolution with just one
call-site.

So after having stared at it for a long time, and convinced myself it
was the better resolution I went back and fixed up mine too.

It all makes me go "PeterZ and Thomas should double-check me that I
didn't miss something else".

I did the builds on both x86-64 and arm64, but I feel it should still
be checked by people involved with that hrtimer code.

               Linus


^ permalink raw reply

* ✅ PASS (MISSED 51 of 56): Test report for for-kernelci (7.0.0-0, upstream-arm-next, 986cb454)
From: cki-project @ 2026-04-15  0:02 UTC (permalink / raw)
  To: linux-arm-kernel, catalin.marinas, will

Hi, we tested your kernel and here are the results:

    Overall result: PASSED
             Merge: OK
           Compile: OK
              Test: OK

Tested-by: CKI Project <cki-project@redhat.com>

Kernel information:
    Commit message: Merge branch 'for-next/core' into for-kernelci

You can find all the details about the test run at
    https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:2453129617

Tests that were not ran because of internal issues:
    /distribution/check-install [aarch64]
    /distribution/command [aarch64]
    /test/misc/machineinfo [aarch64]
    Boot test [aarch64]
    CKI/restraint [aarch64]
    Hardware - Firmware test suite [aarch64]
    Reboot test [aarch64]
    SELinux Custom Module Setup [aarch64]
    selinux-policy: serge-testsuite [aarch64]
    Storage - blktests - throtl [aarch64]
    Storage - blktests - ublk [aarch64]
    stress: stress-ng - cpu-cache [aarch64]
    stress: stress-ng - memory [aarch64]
    xfstests - btrfs [aarch64]
    xfstests - ext4 [aarch64]
    xfstests - xfs [aarch64]


If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.

Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.

        ,-.   ,-.
       ( C ) ( K )  Continuous
        `-',-.`-'   Kernel
          ( I )     Integration
           `-'
______________________________________________________________________________



^ permalink raw reply

* Re: [PATCH v1 2/2] arm_mpam: resctrl: Make resctrl_mon_ctx_waiters static
From: Gavin Shan @ 2026-04-14 23:09 UTC (permalink / raw)
  To: Ben Horgan
  Cc: Dan Carpenter, Dan Carpenter, James Morse, Reinette Chatre,
	Fenghua Yu, lkml, linux-arm-kernel, kernel test robot
In-Reply-To: <20260414132758.196874-4-ben.horgan@arm.com>

On 4/14/26 11:27 PM, Ben Horgan wrote:
> resctrl_mon_ctx_waiters is not used outside of this file, so make it
> static. This fixes the sparse warning:
> 
> drivers/resctrl/mpam_resctrl.c:25:1: warning: symbol 'resctrl_mon_ctx_waiters' was not declared. Should it be static?
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202603281842.c2K96tJA-lkp@intel.com/
> Fixes: 2a3c79c61539 ("arm_mpam: resctrl: Allow resctrl to allocate monitors")
> Signed-off-by: Ben Horgan <ben.horgan@arm.com>
> ---
>   drivers/resctrl/mpam_resctrl.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
Reviewed-by: Gavin Shan <gshan@redhat.com>



^ permalink raw reply

* Re: [PATCH v1 1/2] arm_mpam: resctrl: Fix the check for no monitor components found
From: Gavin Shan @ 2026-04-14 23:08 UTC (permalink / raw)
  To: Ben Horgan
  Cc: Dan Carpenter, Dan Carpenter, James Morse, Reinette Chatre,
	Fenghua Yu, lkml, linux-arm-kernel
In-Reply-To: <20260414132758.196874-3-ben.horgan@arm.com>

On 4/14/26 11:27 PM, Ben Horgan wrote:
> Dan Carpenter reports that, in mpam_resctrl_alloc_domain(), any_mon_comp is
> used in an 'if' condition when it may be uninitialized. Initialize it to
> NULL so that the check behaves correctly when no monitor components are
> found.
> 
> Reported-by: Dan Carpenter <error27@gmail.com>
> Fixes: 264c285999fc ("arm_mpam: resctrl: Add monitor initialisation and domain boilerplate")
> Signed-off-by: Ben Horgan <ben.horgan@arm.com>
> ---
>   drivers/resctrl/mpam_resctrl.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
Reviewed-by: Gavin Shan <gshan@redhat.com>



^ permalink raw reply

* Re: [v1,PATCH 1/1] i2c: mediatek: add bus regulator control for power saving
From: Andi Shyti @ 2026-04-14 23:03 UTC (permalink / raw)
  To: adlavinitha reddy
  Cc: Qii Wang, Matthias Brugger, AngeloGioacchino Del Regno, linux-i2c,
	linux-kernel, linux-arm-kernel, linux-mediatek,
	Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260318084621.4127757-2-adlavinitha.reddy@mediatek.com>

Hi Adlavinitha,

On Wed, Mar 18, 2026 at 04:46:16PM +0800, adlavinitha reddy wrote:
> Add conditional bus regulator enable/disable in mtk_i2c_transfer()
> to support I2C bus power gating for platforms that require it.
> 
> This implementation:
> - Enables bus_regulator before clk_bulk_enable() if vbus-supply is defined
> - Disables bus_regulator after clk_bulk_disable()
> - Only activates when vbus-supply is provided in device tree
> - Has no impact on platforms without vbus-supply defined
> 
> This approach provides power savinggs for platforms with an extra I2C bus

I changed /savinggs/savings/.

> regulator, while avoiding runtime PM complexity.
> 
> TEST= Build and boot on MT8188

'"TEST=..." is a tag. There is no need to save characters in the
commit log. I changed it to "Tested on MT8188.".'

> Signed-off-by: adlavinitha reddy <adlavinitha.reddy@mediatek.com>

Please use capital letters for your name and for the committer's
name as well. I fixed it.

Now you have to explain me why you sent three times this same
patch.

Next time, please use the format '[PATCH v1 1/1]' instead of
'[v1,PATCH 1/1]'. Normally for the first version you can omit v1.

For single patches you don't need the 0/1 cover letter. Just send
as [PATCH].

Please read Documentation/SubmittingPatches.

For now I merged this patch in i2c/i2c-host-2.

Thanks,
Andi


^ permalink raw reply

* [PATCH v3 3/3] iio: adc: xilinx-ams: refactor alarm mapping to table-driven approach
From: Guilherme Ivo Bozi @ 2026-04-14 22:40 UTC (permalink / raw)
  To: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel, Guilherme Ivo Bozi
In-Reply-To: <20260414224245.8493-1-guilherme.bozi@usp.br>

Replace multiple open-coded switch statements that map between
scan_index, alarm bits, and register offsets with a centralized
table-driven approach.

Introduce a struct-based alarm_map to describe the relationship
between scan indices and alarm offsets, and add a helper to
translate scan_index to event IDs. This removes duplicated logic
across ams_get_alarm_offset(), ams_event_to_channel(), and
ams_get_alarm_mask().

The new approach improves maintainability, reduces code size,
and makes it easier to extend or modify alarm mappings in the
future, while preserving existing behavior.

Signed-off-by: Guilherme Ivo Bozi <guilherme.bozi@usp.br>
---
 drivers/iio/adc/xilinx-ams.c | 161 +++++++++++++----------------------
 1 file changed, 58 insertions(+), 103 deletions(-)

diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index 70a1f97f6dad..2ce78883cead 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -102,6 +102,7 @@
 #define AMS_PS_SEQ_MASK			GENMASK(21, 0)
 #define AMS_PL_SEQ_MASK			GENMASK_ULL(59, 22)
 
+#define AMS_ALARM_NONE			0x000 /* not a real offset */
 #define AMS_ALARM_TEMP			0x140
 #define AMS_ALARM_SUPPLY1		0x144
 #define AMS_ALARM_SUPPLY2		0x148
@@ -763,9 +764,49 @@ static int ams_read_raw(struct iio_dev *indio_dev,
 	}
 }
 
+struct ams_alarm_map {
+	enum ams_ps_pl_seq scan_index;
+	unsigned int base_offset;
+};
+
+/*
+ * Array index matches enum ams_alarm_bit.
+ * Entries with base_offset == AMS_ALARM_NONE are unused/invalid
+ * (e.g. RESERVED) and must be skipped.
+ */
+static const struct ams_alarm_map alarm_map[] = {
+	[AMS_ALARM_BIT_TEMP] = { AMS_SEQ_TEMP, AMS_ALARM_TEMP },
+	[AMS_ALARM_BIT_SUPPLY1] = { AMS_SEQ_SUPPLY1, AMS_ALARM_SUPPLY1 },
+	[AMS_ALARM_BIT_SUPPLY2] = { AMS_SEQ_SUPPLY2, AMS_ALARM_SUPPLY2 },
+	[AMS_ALARM_BIT_SUPPLY3] = { AMS_SEQ_SUPPLY3, AMS_ALARM_SUPPLY3 },
+	[AMS_ALARM_BIT_SUPPLY4] = { AMS_SEQ_SUPPLY4, AMS_ALARM_SUPPLY4 },
+	[AMS_ALARM_BIT_SUPPLY5] = { AMS_SEQ_SUPPLY5, AMS_ALARM_SUPPLY5 },
+	[AMS_ALARM_BIT_SUPPLY6] = { AMS_SEQ_SUPPLY6, AMS_ALARM_SUPPLY6 },
+	[AMS_ALARM_BIT_RESERVED] = { 0, AMS_ALARM_NONE },
+	[AMS_ALARM_BIT_SUPPLY7] = { AMS_SEQ_SUPPLY7, AMS_ALARM_SUPPLY7 },
+	[AMS_ALARM_BIT_SUPPLY8] = { AMS_SEQ_SUPPLY8, AMS_ALARM_SUPPLY8 },
+	[AMS_ALARM_BIT_SUPPLY9] = { AMS_SEQ_SUPPLY9, AMS_ALARM_SUPPLY9 },
+	[AMS_ALARM_BIT_SUPPLY10] = { AMS_SEQ_SUPPLY10, AMS_ALARM_SUPPLY10 },
+	[AMS_ALARM_BIT_VCCAMS] = { AMS_SEQ_VCCAMS, AMS_ALARM_VCCAMS },
+	[AMS_ALARM_BIT_TEMP_REMOTE] = { AMS_SEQ_TEMP_REMOTE, AMS_ALARM_TEMP_REMOTE },
+};
+
+static int ams_scan_index_to_event(int scan_index)
+{
+	for (unsigned int i = 0; i < ARRAY_SIZE(alarm_map); i++) {
+		if (alarm_map[i].base_offset == AMS_ALARM_NONE)
+			continue;
+
+		if (alarm_map[i].scan_index == scan_index)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
 static int ams_get_alarm_offset(int scan_index, enum iio_event_direction dir)
 {
-	int offset;
+	int offset, event;
 
 	if (scan_index >= AMS_PS_SEQ_MAX)
 		scan_index -= AMS_PS_SEQ_MAX;
@@ -779,36 +820,11 @@ static int ams_get_alarm_offset(int scan_index, enum iio_event_direction dir)
 		offset = 0;
 	}
 
-	switch (scan_index) {
-	case AMS_SEQ_TEMP:
-		return AMS_ALARM_TEMP + offset;
-	case AMS_SEQ_SUPPLY1:
-		return AMS_ALARM_SUPPLY1 + offset;
-	case AMS_SEQ_SUPPLY2:
-		return AMS_ALARM_SUPPLY2 + offset;
-	case AMS_SEQ_SUPPLY3:
-		return AMS_ALARM_SUPPLY3 + offset;
-	case AMS_SEQ_SUPPLY4:
-		return AMS_ALARM_SUPPLY4 + offset;
-	case AMS_SEQ_SUPPLY5:
-		return AMS_ALARM_SUPPLY5 + offset;
-	case AMS_SEQ_SUPPLY6:
-		return AMS_ALARM_SUPPLY6 + offset;
-	case AMS_SEQ_SUPPLY7:
-		return AMS_ALARM_SUPPLY7 + offset;
-	case AMS_SEQ_SUPPLY8:
-		return AMS_ALARM_SUPPLY8 + offset;
-	case AMS_SEQ_SUPPLY9:
-		return AMS_ALARM_SUPPLY9 + offset;
-	case AMS_SEQ_SUPPLY10:
-		return AMS_ALARM_SUPPLY10 + offset;
-	case AMS_SEQ_VCCAMS:
-		return AMS_ALARM_VCCAMS + offset;
-	case AMS_SEQ_TEMP_REMOTE:
-		return AMS_ALARM_TEMP_REMOTE + offset;
-	default:
+	event = ams_scan_index_to_event(scan_index);
+	if (event < 0 || alarm_map[event].base_offset == AMS_ALARM_NONE)
 		return 0;
-	}
+
+	return alarm_map[event].base_offset + offset;
 }
 
 static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
@@ -821,49 +837,13 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
 		scan_index = AMS_PS_SEQ_MAX;
 	}
 
-	switch (event) {
-	case AMS_ALARM_BIT_TEMP:
-		scan_index += AMS_SEQ_TEMP;
-		break;
-	case AMS_ALARM_BIT_SUPPLY1:
-		scan_index += AMS_SEQ_SUPPLY1;
-		break;
-	case AMS_ALARM_BIT_SUPPLY2:
-		scan_index += AMS_SEQ_SUPPLY2;
-		break;
-	case AMS_ALARM_BIT_SUPPLY3:
-		scan_index += AMS_SEQ_SUPPLY3;
-		break;
-	case AMS_ALARM_BIT_SUPPLY4:
-		scan_index += AMS_SEQ_SUPPLY4;
-		break;
-	case AMS_ALARM_BIT_SUPPLY5:
-		scan_index += AMS_SEQ_SUPPLY5;
-		break;
-	case AMS_ALARM_BIT_SUPPLY6:
-		scan_index += AMS_SEQ_SUPPLY6;
-		break;
-	case AMS_ALARM_BIT_SUPPLY7:
-		scan_index += AMS_SEQ_SUPPLY7;
-		break;
-	case AMS_ALARM_BIT_SUPPLY8:
-		scan_index += AMS_SEQ_SUPPLY8;
-		break;
-	case AMS_ALARM_BIT_SUPPLY9:
-		scan_index += AMS_SEQ_SUPPLY9;
-		break;
-	case AMS_ALARM_BIT_SUPPLY10:
-		scan_index += AMS_SEQ_SUPPLY10;
-		break;
-	case AMS_ALARM_BIT_VCCAMS:
-		scan_index += AMS_SEQ_VCCAMS;
-		break;
-	case AMS_ALARM_BIT_TEMP_REMOTE:
-		scan_index += AMS_SEQ_TEMP_REMOTE;
-		break;
-	default:
-		break;
-	}
+	if (event < 0 || event >= ARRAY_SIZE(alarm_map))
+		return NULL;
+
+	if (alarm_map[event].base_offset == AMS_ALARM_NONE)
+		return NULL;
+
+	scan_index += alarm_map[event].scan_index;
 
 	for (i = 0; i < dev->num_channels; i++)
 		if (dev->channels[i].scan_index == scan_index)
@@ -877,43 +857,18 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
 
 static int ams_get_alarm_mask(int scan_index)
 {
-	int bit = 0;
+	int bit = 0, event;
 
 	if (scan_index >= AMS_PS_SEQ_MAX) {
 		bit = AMS_PL_ALARM_START;
 		scan_index -= AMS_PS_SEQ_MAX;
 	}
 
-	switch (scan_index) {
-	case AMS_SEQ_TEMP:
-		return BIT(AMS_ALARM_BIT_TEMP + bit);
-	case AMS_SEQ_SUPPLY1:
-		return BIT(AMS_ALARM_BIT_SUPPLY1 + bit);
-	case AMS_SEQ_SUPPLY2:
-		return BIT(AMS_ALARM_BIT_SUPPLY2 + bit);
-	case AMS_SEQ_SUPPLY3:
-		return BIT(AMS_ALARM_BIT_SUPPLY3 + bit);
-	case AMS_SEQ_SUPPLY4:
-		return BIT(AMS_ALARM_BIT_SUPPLY4 + bit);
-	case AMS_SEQ_SUPPLY5:
-		return BIT(AMS_ALARM_BIT_SUPPLY5 + bit);
-	case AMS_SEQ_SUPPLY6:
-		return BIT(AMS_ALARM_BIT_SUPPLY6 + bit);
-	case AMS_SEQ_SUPPLY7:
-		return BIT(AMS_ALARM_BIT_SUPPLY7 + bit);
-	case AMS_SEQ_SUPPLY8:
-		return BIT(AMS_ALARM_BIT_SUPPLY8 + bit);
-	case AMS_SEQ_SUPPLY9:
-		return BIT(AMS_ALARM_BIT_SUPPLY9 + bit);
-	case AMS_SEQ_SUPPLY10:
-		return BIT(AMS_ALARM_BIT_SUPPLY10 + bit);
-	case AMS_SEQ_VCCAMS:
-		return BIT(AMS_ALARM_BIT_VCCAMS + bit);
-	case AMS_SEQ_TEMP_REMOTE:
-		return BIT(AMS_ALARM_BIT_TEMP_REMOTE + bit);
-	default:
+	event = ams_scan_index_to_event(scan_index);
+	if (event < 0)
 		return 0;
-	}
+
+	return BIT(event + bit);
 }
 
 static int ams_read_event_config(struct iio_dev *indio_dev,
-- 
2.47.3



^ permalink raw reply related

* [PATCH v3 2/3] iio: adc: xilinx-ams: use guard(mutex) for automatic locking
From: Guilherme Ivo Bozi @ 2026-04-14 22:40 UTC (permalink / raw)
  To: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel, Guilherme Ivo Bozi,
	Andy Shevchenko
In-Reply-To: <20260414224245.8493-1-guilherme.bozi@usp.br>

Replace open-coded mutex_lock()/mutex_unlock() pairs with
guard(mutex) to simplify locking and ensure proper unlock on
all control flow paths.

This removes explicit unlock handling, reduces boilerplate,
and avoids potential mistakes in error paths while keeping
the behavior unchanged.

Signed-off-by: Guilherme Ivo Bozi <guilherme.bozi@usp.br>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
---
 drivers/iio/adc/xilinx-ams.c | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index 6191cd1b29a5..70a1f97f6dad 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -720,22 +720,20 @@ static int ams_read_raw(struct iio_dev *indio_dev,
 	int ret;
 
 	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&ams->lock);
+	case IIO_CHAN_INFO_RAW: {
+		guard(mutex)(&ams->lock);
 		if (chan->scan_index >= AMS_CTRL_SEQ_BASE) {
 			ret = ams_read_vcc_reg(ams, chan->address, val);
 			if (ret)
-				goto unlock_mutex;
+				return ret;
 			ams_enable_channel_sequence(indio_dev);
 		} else if (chan->scan_index >= AMS_PS_SEQ_MAX)
 			*val = readl(ams->pl_base + chan->address);
 		else
 			*val = readl(ams->ps_base + chan->address);
 
-		ret = IIO_VAL_INT;
-unlock_mutex:
-		mutex_unlock(&ams->lock);
-		return ret;
+		return IIO_VAL_INT;
+	}
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_VOLTAGE:
@@ -939,7 +937,7 @@ static int ams_write_event_config(struct iio_dev *indio_dev,
 
 	alarm = ams_get_alarm_mask(chan->scan_index);
 
-	mutex_lock(&ams->lock);
+	guard(mutex)(&ams->lock);
 
 	if (state)
 		ams->alarm_mask |= alarm;
@@ -948,8 +946,6 @@ static int ams_write_event_config(struct iio_dev *indio_dev,
 
 	ams_update_alarm(ams, ams->alarm_mask);
 
-	mutex_unlock(&ams->lock);
-
 	return 0;
 }
 
@@ -962,15 +958,13 @@ static int ams_read_event_value(struct iio_dev *indio_dev,
 	struct ams *ams = iio_priv(indio_dev);
 	unsigned int offset = ams_get_alarm_offset(chan->scan_index, dir);
 
-	mutex_lock(&ams->lock);
+	guard(mutex)(&ams->lock);
 
 	if (chan->scan_index >= AMS_PS_SEQ_MAX)
 		*val = readl(ams->pl_base + offset);
 	else
 		*val = readl(ams->ps_base + offset);
 
-	mutex_unlock(&ams->lock);
-
 	return IIO_VAL_INT;
 }
 
@@ -983,7 +977,7 @@ static int ams_write_event_value(struct iio_dev *indio_dev,
 	struct ams *ams = iio_priv(indio_dev);
 	unsigned int offset;
 
-	mutex_lock(&ams->lock);
+	guard(mutex)(&ams->lock);
 
 	/* Set temperature channel threshold to direct threshold */
 	if (chan->type == IIO_TEMP) {
@@ -1005,8 +999,6 @@ static int ams_write_event_value(struct iio_dev *indio_dev,
 	else
 		writel(val, ams->ps_base + offset);
 
-	mutex_unlock(&ams->lock);
-
 	return 0;
 }
 
-- 
2.47.3



^ permalink raw reply related

* [PATCH v3 1/3] iio: adc: xilinx-ams: fix out-of-bounds channel lookup in event handling
From: Guilherme Ivo Bozi @ 2026-04-14 22:40 UTC (permalink / raw)
  To: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel, Guilherme Ivo Bozi
In-Reply-To: <20260414224245.8493-1-guilherme.bozi@usp.br>

ams_event_to_channel() may return a pointer past the end of
dev->channels when no matching scan_index is found. This can lead
to invalid memory access in ams_handle_event().

Add a bounds check in ams_event_to_channel() and return NULL when
no channel is found. Also guard the caller to safely handle this
case.

Fixes: d5c70627a794 ("iio: adc: Add Xilinx AMS driver")
Signed-off-by: Guilherme Ivo Bozi <guilherme.bozi@usp.br>
---
 drivers/iio/adc/xilinx-ams.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index 124470c92529..6191cd1b29a5 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -871,6 +871,9 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
 		if (dev->channels[i].scan_index == scan_index)
 			break;
 
+	if (i == dev->num_channels)
+		return NULL;
+
 	return &dev->channels[i];
 }
 
@@ -1012,6 +1015,8 @@ static void ams_handle_event(struct iio_dev *indio_dev, u32 event)
 	const struct iio_chan_spec *chan;
 
 	chan = ams_event_to_channel(indio_dev, event);
+	if (!chan)
+		return;
 
 	if (chan->type == IIO_TEMP) {
 		/*
-- 
2.47.3



^ permalink raw reply related

* [PATCH v3 0/3] iio: adc: xilinx-ams: refactor alarm handling to table-driven design
From: Guilherme Ivo Bozi @ 2026-04-14 22:40 UTC (permalink / raw)
  To: Salih Erim, Conall O'Griofa, Jonathan Cameron, Michal Simek
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	linux-arm-kernel, linux-kernel, Guilherme Ivo Bozi

This series addresses significant code duplication in alarm handling
logic across the Xilinx AMS IIO driver.

To address this, the series introduces a centralized table-driven
mapping (alarm_map) that replaces multiple switch statements spread
across the driver.

This improves:
- maintainability (single source of truth for mappings)
- readability (removes repeated switch logic)
- extensibility (new alarms require only table updates)

No functional changes are intended.

Series overview:
- Patch 1: fix out-of-bounds channel lookup 
- Patch 2: convert mutex handling to guard(mutex) 
- Patch 3: introduce table-driven alarm mapping

v1 -> v2:
- Fixed Fixes tag format
- Replaced AMS_ALARM_INVALID with AMS_ALARM_NONE
- Changed alarm_map base_offset type

v2 -> v3:
- Replace 'i >= num_channels' with 'i == num_channels'
- Add missing trailing comma in alarm_map array initializer

Guilherme Ivo Bozi (3):
  iio: adc: xilinx-ams: fix out-of-bounds channel lookup in event
    handling
  iio: adc: xilinx-ams: use guard(mutex) for automatic locking
  iio: adc: xilinx-ams: refactor alarm mapping to table-driven approach

 drivers/iio/adc/xilinx-ams.c | 190 +++++++++++++----------------------
 1 file changed, 71 insertions(+), 119 deletions(-)

-- 
2.47.3



^ permalink raw reply

* Re: [PATCH v2 2/4] KVM: arm64: sefltests: Add helpers for guest hypervisors
From: Itaru Kitayama @ 2026-04-14 22:14 UTC (permalink / raw)
  To: Wei-Lin Chang
  Cc: linux-arm-kernel, kvmarm, kvm, linux-kselftest, linux-kernel,
	Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
	Zenghui Yu, Catalin Marinas, Will Deacon, Paolo Bonzini,
	Shuah Khan
In-Reply-To: <20260412142216.3806482-3-weilin.chang@arm.com>

On Sun, Apr 12, 2026 at 03:22:14PM +0100, Wei-Lin Chang wrote:
> Add helpers so that guest hypervisors can run nested guests. SP_EL1
> save/restore is added to allow nested guests to use a stack.
> 
> Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> ---
>  .../selftests/kvm/include/arm64/nested.h      | 17 +++++++
>  tools/testing/selftests/kvm/lib/arm64/entry.S |  5 ++
>  .../testing/selftests/kvm/lib/arm64/nested.c  | 46 +++++++++++++++++++
>  3 files changed, 68 insertions(+)
> 
> diff --git a/tools/testing/selftests/kvm/include/arm64/nested.h b/tools/testing/selftests/kvm/include/arm64/nested.h
> index 86d931facacb..7928ef89494a 100644
> --- a/tools/testing/selftests/kvm/include/arm64/nested.h
> +++ b/tools/testing/selftests/kvm/include/arm64/nested.h
> @@ -21,8 +21,17 @@
>  
>  extern char hyp_vectors[];
>  
> +enum vcpu_sysreg {
> +	__INVALID_SYSREG__,   /* 0 is reserved as an invalid value */
> +
> +	SP_EL1,
> +
> +	NR_SYS_REGS
> +};
> +
>  struct cpu_context {
>  	struct user_pt_regs regs;	/* sp = sp_el0 */
> +	u64 sys_regs[NR_SYS_REGS];
>  };
>  
>  struct vcpu {
> @@ -37,9 +46,17 @@ struct hyp_data {
>  	struct cpu_context hyp_context;
>  };

I am not sure of these structs you introduced only for nested guest feature
testing, as the KVM arm64 code they are quite complex and involved, 
extracring part of those and add members as hello_nested or simliar
tests evolve, then add test cases to me seems fragile. 
But if you have strong reason to add these would you mind explaining a bit?

Thanks,
Itaru.

>  
> +void prepare_hyp(void);
> +void init_vcpu(struct vcpu *vcpu, vm_paddr_t l2_pc, vm_paddr_t l2_stack_top);
> +int run_l2(struct vcpu *vcpu, struct hyp_data *hyp_data);
> +
> +void do_hvc(void);
>  u64 __guest_enter(struct vcpu *vcpu, struct cpu_context *hyp_context);
>  void __hyp_exception(u64 type);
>  
> +void __sysreg_save_el1_state(struct cpu_context *ctxt);
> +void __sysreg_restore_el1_state(struct cpu_context *ctxt);
> +
>  #endif /* !__ASSEMBLER__ */
>  
>  #endif /* SELFTEST_KVM_NESTED_H */
> diff --git a/tools/testing/selftests/kvm/lib/arm64/entry.S b/tools/testing/selftests/kvm/lib/arm64/entry.S
> index 33bedf5e7fb2..df3af3463c6c 100644
> --- a/tools/testing/selftests/kvm/lib/arm64/entry.S
> +++ b/tools/testing/selftests/kvm/lib/arm64/entry.S
> @@ -3,6 +3,11 @@
>   * adapted from arch/arm64/kvm/hyp/entry.S
>   */
>  
> + .globl do_hvc
> + do_hvc:
> +	hvc	#0
> +	ret
> +
>  /*
>   * Manually define these for now
>   */
> diff --git a/tools/testing/selftests/kvm/lib/arm64/nested.c b/tools/testing/selftests/kvm/lib/arm64/nested.c
> index 06ddaab2436f..b30d20b101c4 100644
> --- a/tools/testing/selftests/kvm/lib/arm64/nested.c
> +++ b/tools/testing/selftests/kvm/lib/arm64/nested.c
> @@ -4,7 +4,53 @@
>   */
>  
>  #include "nested.h"
> +#include "processor.h"
>  #include "test_util.h"
> +#include <asm/sysreg.h>
> +
> +void prepare_hyp(void)
> +{
> +	write_sysreg(HCR_EL2_E2H | HCR_EL2_RW, hcr_el2);
> +	write_sysreg(hyp_vectors, vbar_el2);
> +	isb();
> +}
> +
> +void init_vcpu(struct vcpu *vcpu, vm_paddr_t l2_pc, vm_paddr_t l2_stack_top)
> +{
> +	memset(vcpu, 0, sizeof(*vcpu));
> +	vcpu->context.regs.pc = l2_pc;
> +	vcpu->context.regs.pstate = PSR_MODE_EL1h | PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT;
> +	vcpu->context.sys_regs[SP_EL1] = l2_stack_top;
> +}
> +
> +void __sysreg_save_el1_state(struct cpu_context *ctxt)
> +{
> +	ctxt->sys_regs[SP_EL1] = read_sysreg(sp_el1);
> +}
> +
> +void __sysreg_restore_el1_state(struct cpu_context *ctxt)
> +{
> +	write_sysreg(ctxt->sys_regs[SP_EL1], sp_el1);
> +}
> +
> +int run_l2(struct vcpu *vcpu, struct hyp_data *hyp_data)
> +{
> +	u64 ret;
> +
> +	__sysreg_restore_el1_state(&vcpu->context);
> +
> +	write_sysreg(vcpu->context.regs.pstate, spsr_el2);
> +	write_sysreg(vcpu->context.regs.pc, elr_el2);
> +
> +	ret =  __guest_enter(vcpu, &hyp_data->hyp_context);
> +
> +	vcpu->context.regs.pc = read_sysreg(elr_el2);
> +	vcpu->context.regs.pstate = read_sysreg(spsr_el2);
> +
> +	__sysreg_save_el1_state(&vcpu->context);
> +
> +	return ret;
> +}
>  
>  void __hyp_exception(u64 type)
>  {
> -- 
> 2.43.0
> 


^ permalink raw reply

* Re: [PATCH v2 3/4] KVM: arm64: sefltests: Add basic NV selftest
From: Itaru Kitayama @ 2026-04-14 22:05 UTC (permalink / raw)
  To: Wei-Lin Chang
  Cc: linux-arm-kernel, kvmarm, kvm, linux-kselftest, linux-kernel,
	Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
	Zenghui Yu, Catalin Marinas, Will Deacon, Paolo Bonzini,
	Shuah Khan
In-Reply-To: <xsdf2k2u4g6n7nmxcgwhiraqodwtteuxqqtnj2dx5sxgu74a7j@yjijkyohkq4i>

On Tue, Apr 14, 2026 at 11:16:47AM +0100, Wei-Lin Chang wrote:
> On Tue, Apr 14, 2026 at 06:31:22AM +0900, Itaru Kitayama wrote:
> > On Mon, Apr 13, 2026 at 10:18:42AM +0100, Wei-Lin Chang wrote:
> > > Hi Itaru,
> > > 
> > > On Mon, Apr 13, 2026 at 08:19:25AM +0900, Itaru Kitayama wrote:
> > > > On Sun, Apr 12, 2026 at 03:22:15PM +0100, Wei-Lin Chang wrote:
> > > > > This selftest simply starts an L1, which starts its own guest (L2). L2
> > > > > runs without stage-1 and 2 translations, it calls an HVC to jump back
> > > > > to L1.
> > > > 
> > > > How do you disable both the nested guest (L2)'s MMU and stage 2
> > > > translations?
> > > 
> > > Guest stage-2 is disabled by not setting HCR_EL2.VM in prepare_hyp(),
> > > and stage-1 is disabled by not writing to SCTLR_EL12 in init_vcpu(),
> > > effectively using the default value set by L0. However since SCTLR_EL1
> > > has many architecturally UNKNOWN bits (including SCTLR_EL1.M), it should
> > > be better to write a value before running L2 I suppose...
> > 
> > Thanks. What do you think of using copy_el2_to_el1() macro in at.c, so we
> > can prepare in guest_code() to manipulate the SCTLR_EL12 System register 
> > with the sensible programmed values?
> 
> Yes, using copy_el2_to_el1() can give us an L2 stage-1 that is identical
> to the L1's stage-1. But what I was considering was if guest stage-2 is
> enabled (which we plan to implement), then those stage-1 page tables
> will have to be mapped for L2, and its base address translated to L2IPA.
> It's doable but seems like extra complexity when stage-1 is not so
> interesting for KVM (except for AT?), it lets the guest do whatever it
> likes and let the hardware do the translation.
> 
> Let me know if you have reasons to want stage-1 for L2, there could be
> something I should consider but did not.

By keeping nested guest's MMU enabled, we can exercise the shadow stage
2 on the host. But I am fine with you starting nested guest's IPA and I
hope Marc and Oliver approve this seris and merge upstream.

Thanks,
Itaru.

> 
> Thanks,
> Wei-Lin Chang
> 
> > 
> > Itaru.
> > 
> > > 
> > > Thanks,
> > > Wei-Lin Chang
> > > 
> > > > 
> > > > Itaru.
> > > > 
> > > > > 
> > > > > Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> > > > > ---
> > > > >  tools/testing/selftests/kvm/Makefile.kvm      |   1 +
> > > > >  .../selftests/kvm/arm64/hello_nested.c        | 103 ++++++++++++++++++
> > > > >  2 files changed, 104 insertions(+)
> > > > >  create mode 100644 tools/testing/selftests/kvm/arm64/hello_nested.c
> > > > > 
> > > > > diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
> > > > > index 3dc3e39f7025..e8c108e0c487 100644
> > > > > --- a/tools/testing/selftests/kvm/Makefile.kvm
> > > > > +++ b/tools/testing/selftests/kvm/Makefile.kvm
> > > > > @@ -168,6 +168,7 @@ TEST_GEN_PROGS_arm64 += arm64/arch_timer_edge_cases
> > > > >  TEST_GEN_PROGS_arm64 += arm64/at
> > > > >  TEST_GEN_PROGS_arm64 += arm64/debug-exceptions
> > > > >  TEST_GEN_PROGS_arm64 += arm64/hello_el2
> > > > > +TEST_GEN_PROGS_arm64 += arm64/hello_nested
> > > > >  TEST_GEN_PROGS_arm64 += arm64/host_sve
> > > > >  TEST_GEN_PROGS_arm64 += arm64/hypercalls
> > > > >  TEST_GEN_PROGS_arm64 += arm64/external_aborts
> > > > > diff --git a/tools/testing/selftests/kvm/arm64/hello_nested.c b/tools/testing/selftests/kvm/arm64/hello_nested.c
> > > > > new file mode 100644
> > > > > index 000000000000..97387e4697b3
> > > > > --- /dev/null
> > > > > +++ b/tools/testing/selftests/kvm/arm64/hello_nested.c
> > > > > @@ -0,0 +1,103 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0-only
> > > > > +/*
> > > > > + * hello_nested - Go from vEL2 to EL1 then back
> > > > > + */
> > > > > +
> > > > > +#include "nested.h"
> > > > > +#include "processor.h"
> > > > > +#include "test_util.h"
> > > > > +#include "ucall.h"
> > > > > +
> > > > > +#define XLATE2GPA	(0xABCD)
> > > > > +#define L2STACKSZ	(0x100)
> > > > > +
> > > > > +/*
> > > > > + * TPIDR_EL2 is used to store vcpu id, so save and restore it.
> > > > > + */
> > > > > +static vm_paddr_t ucall_translate_to_gpa(void *gva)
> > > > > +{
> > > > > +	vm_paddr_t gpa;
> > > > > +	u64 vcpu_id = read_sysreg(tpidr_el2);
> > > > > +
> > > > > +	GUEST_SYNC2(XLATE2GPA, gva);
> > > > > +
> > > > > +	/* get the result from userspace */
> > > > > +	gpa = read_sysreg(tpidr_el2);
> > > > > +
> > > > > +	write_sysreg(vcpu_id, tpidr_el2);
> > > > > +
> > > > > +	return gpa;
> > > > > +}
> > > > > +
> > > > > +static void l2_guest_code(void)
> > > > > +{
> > > > > +	do_hvc();
> > > > > +}
> > > > > +
> > > > > +static void guest_code(void)
> > > > > +{
> > > > > +	struct vcpu vcpu;
> > > > > +	struct hyp_data hyp_data;
> > > > > +	int ret;
> > > > > +	vm_paddr_t l2_pc, l2_stack_top;
> > > > > +	/* force 16-byte alignment for the stack pointer */
> > > > > +	u8 l2_stack[L2STACKSZ] __attribute__((aligned(16)));
> > > > > +
> > > > > +	GUEST_ASSERT_EQ(get_current_el(), 2);
> > > > > +	GUEST_PRINTF("vEL2 entry\n");
> > > > > +
> > > > > +	l2_pc = ucall_translate_to_gpa(l2_guest_code);
> > > > > +	l2_stack_top = ucall_translate_to_gpa(&l2_stack[L2STACKSZ]);
> > > > > +
> > > > > +	init_vcpu(&vcpu, l2_pc, l2_stack_top);
> > > > > +	prepare_hyp();
> > > > > +
> > > > > +	ret = run_l2(&vcpu, &hyp_data);
> > > > > +	GUEST_ASSERT_EQ(ret, ARM_EXCEPTION_TRAP);
> > > > > +	GUEST_DONE();
> > > > > +}
> > > > > +
> > > > > +int main(void)
> > > > > +{
> > > > > +	struct kvm_vcpu_init init;
> > > > > +	struct kvm_vcpu *vcpu;
> > > > > +	struct kvm_vm *vm;
> > > > > +	struct ucall uc;
> > > > > +	vm_paddr_t gpa;
> > > > > +
> > > > > +	TEST_REQUIRE(kvm_check_cap(KVM_CAP_ARM_EL2));
> > > > > +	vm = vm_create(1);
> > > > > +
> > > > > +	kvm_get_default_vcpu_target(vm, &init);
> > > > > +	init.features[0] |= BIT(KVM_ARM_VCPU_HAS_EL2);
> > > > > +	vcpu = aarch64_vcpu_add(vm, 0, &init, guest_code);
> > > > > +	kvm_arch_vm_finalize_vcpus(vm);
> > > > > +
> > > > > +	while (true) {
> > > > > +		vcpu_run(vcpu);
> > > > > +
> > > > > +		switch (get_ucall(vcpu, &uc)) {
> > > > > +		case UCALL_SYNC:
> > > > > +			if (uc.args[0] == XLATE2GPA) {
> > > > > +				gpa = addr_gva2gpa(vm, (vm_vaddr_t)uc.args[1]);
> > > > > +				vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TPIDR_EL2), gpa);
> > > > > +			}
> > > > > +			break;
> > > > > +		case UCALL_PRINTF:
> > > > > +			pr_info("%s", uc.buffer);
> > > > > +			break;
> > > > > +		case UCALL_DONE:
> > > > > +			pr_info("DONE!\n");
> > > > > +			goto end;
> > > > > +		case UCALL_ABORT:
> > > > > +			REPORT_GUEST_ASSERT(uc);
> > > > > +			fallthrough;
> > > > > +		default:
> > > > > +			TEST_FAIL("Unhandled ucall: %ld\n", uc.cmd);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +end:
> > > > > +	kvm_vm_free(vm);
> > > > > +	return 0;
> > > > > +}
> > > > > -- 
> > > > > 2.43.0
> > > > > 


^ permalink raw reply

* [PATCH v7 6/6] arm64: dts: rockchip: Add Orange Pi 5 Pro board support
From: Dennis Gilmore @ 2026-04-14 21:40 UTC (permalink / raw)
  Cc: Alexey Charkov, Andrew Lunn, Andrzej Hajda, Chaoyi Chen,
	Conor Dooley, David Airlie, Dennis Gilmore, devicetree, dri-devel,
	FUKAUMI Naoki, Heiko Stuebner, Hsun Lai, Jernej Skrabec,
	Jimmy Hon, John Clark, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, linux-arm-kernel, linux-kernel, linux-rockchip,
	Maarten Lankhorst, Maxime Ripard, Michael Opdenacker,
	Michael Riesch, Mykola Kvach, Neil Armstrong, Peter Robinson,
	Quentin Schulz, Robert Foss, Rob Herring, Simona Vetter,
	Thomas Zimmermann
In-Reply-To: <20260414214104.1363987-1-dennis@ausil.us>

Add device tree for the Xunlong Orange Pi 5 Pro (RK3588S).

- eMMC module, you can optionally solder a SPI NOR in place and turn
 off the eMMC
- PCIe-attached NIC (pcie2x1l1)
- PCIe NVMe slot (pcie2x1l2)
- AP6256 WiFi (BCM43456) via SDIO with mmc-pwrseq
- BCM4345C5 Bluetooth
- es8388 audio
- USB 2.0 and USB 3.0
- Two HDMI ports, the second is connected to the SoC's DP controller
  driven through a Lontium LT8711UXD bridge.

Vendors schematics are available at:
https://drive.google.com/file/d/1qs1DratHuh7C6J6MEtQIwUsiSrg8qgTi/view

Signed-off-by: Dennis Gilmore <dennis@ausil.us>
---
 arch/arm64/boot/dts/rockchip/Makefile         |   1 +
 .../dts/rockchip/rk3588s-orangepi-5-pro.dts   | 442 ++++++++++++++++++
 2 files changed, 443 insertions(+)
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts

diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index 4d384f153c13..c99dca2ae9e7 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -214,6 +214,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6c.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-odroid-m2.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5b.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5-pro.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-cm5-base.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-radxa-cm5-io.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-roc-pc.dtb
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
new file mode 100644
index 000000000000..61462c66753d
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3588s-orangepi-5.dtsi"
+
+/ {
+	model = "Xunlong Orange Pi 5 Pro";
+	compatible = "xunlong,orangepi-5-pro", "rockchip,rk3588s";
+
+	aliases {
+		mmc0 = &sdhci;
+		mmc1 = &sdmmc;
+		mmc2 = &sdio;
+	};
+
+	hdmi1-con {
+		compatible = "hdmi-connector";
+		label = "HDMI1 OUT";
+		type = "a";
+
+		port {
+			hdmi1_con_in: endpoint {
+				remote-endpoint = <&lt8711uxd_out>;
+			};
+		};
+	};
+
+	lt8711uxd {
+		compatible = "lontium,lt8711uxd";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				lt8711uxd_in: endpoint {
+					remote-endpoint = <&dp0_out_con>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				lt8711uxd_out: endpoint {
+					remote-endpoint = <&hdmi1_con_in>;
+				};
+			};
+		};
+	};
+
+	analog-sound {
+		compatible = "simple-audio-card";
+		pinctrl-names = "default";
+		pinctrl-0 = <&hp_detect>;
+		simple-audio-card,format = "i2s";
+		simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
+		simple-audio-card,mclk-fs = <256>;
+		simple-audio-card,name = "rockchip,es8388";
+		simple-audio-card,routing =
+			"Headphones", "LOUT1",
+			"Headphones", "ROUT1",
+			"LINPUT1", "Microphone Jack",
+			"RINPUT1", "Microphone Jack",
+			"LINPUT2", "Onboard Microphone",
+			"RINPUT2", "Onboard Microphone";
+		simple-audio-card,widgets =
+			"Microphone", "Microphone Jack",
+			"Microphone", "Onboard Microphone",
+			"Headphone", "Headphones";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s2_2ch>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&es8388>;
+			system-clock-frequency = <12288000>;
+		};
+	};
+
+	pwm-leds {
+		compatible = "pwm-leds";
+
+		led-0 {
+			color = <LED_COLOR_ID_BLUE>;
+			function = LED_FUNCTION_STATUS;
+			linux,default-trigger = "heartbeat";
+			max-brightness = <255>;
+			pwms = <&pwm15 0 1000000 0>;
+		};
+
+		led-1 {
+			color = <LED_COLOR_ID_GREEN>;
+			function = LED_FUNCTION_ACTIVITY;
+			linux,default-trigger = "heartbeat";
+			max-brightness = <255>;
+			pwms = <&pwm3 0 1000000 0>;
+		};
+	};
+
+	fan: pwm-fan {
+		compatible = "pwm-fan";
+		#cooling-cells = <2>;
+		cooling-levels = <0 50 100 150 200 255>;
+		fan-supply = <&vcc5v0_sys>;
+		pwms = <&pwm2 0 20000000 0>;
+	};
+
+	vcc3v3_dp: regulator-vcc3v3-dp {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&dp_bridge_en>;
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		regulator-name = "vcc3v3_dp";
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_3v3_s3>;
+	};
+
+	vcc3v3_phy1: regulator-vcc3v3-phy1 {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&vcc3v3_phy1_en>;
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		regulator-name = "vcc3v3_phy1";
+		startup-delay-us = <50000>;
+		vin-supply = <&vcc_3v3_s3>;
+	};
+
+	vcc5v0_otg: regulator-vcc5v0-otg {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&vcc5v0_otg_en>;
+		regulator-max-microvolt = <5000000>;
+		regulator-min-microvolt = <5000000>;
+		regulator-name = "vcc5v0_otg";
+		vin-supply = <&vcc5v0_sys>;
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&hym8563>;
+		clock-names = "ext_clock";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_enable_h>;
+		post-power-on-delay-ms = <200>;
+		reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_LOW>;
+	};
+
+	typea_con: usb-a-connector {
+		compatible = "usb-a-connector";
+		data-role = "host";
+		label = "USB3 Type-A";
+		power-role = "source";
+		vbus-supply = <&vcc5v0_otg>;
+	};
+};
+
+&dp0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&dp0m0_pins>;
+	status = "okay";
+};
+
+&dp0_in {
+	dp0_in_vp1: endpoint {
+		remote-endpoint = <&vp1_out_dp0>;
+	};
+};
+
+&dp0_out {
+	dp0_out_con: endpoint {
+		remote-endpoint = <&lt8711uxd_in>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1m4_xfer>;
+	status = "okay";
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3m0_xfer>;
+	status = "okay";
+
+	es8388: audio-codec@11 {
+		compatible = "everest,es8388", "everest,es8328";
+		reg = <0x11>;
+		#sound-dai-cells = <0>;
+		AVDD-supply = <&vcca_3v3_s0>;
+		DVDD-supply = <&vcca_1v8_s0>;
+		HPVDD-supply = <&vcca_3v3_s0>;
+		PVDD-supply = <&vcca_1v8_s0>;
+		assigned-clock-rates = <12288000>;
+		assigned-clocks = <&cru I2S2_2CH_MCLKOUT>;
+		clocks = <&cru I2S2_2CH_MCLKOUT>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s2m1_mclk>;
+	};
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4m3_xfer>;
+	status = "okay";
+};
+
+&i2s2_2ch {
+	pinctrl-0 = <&i2s2m1_lrck &i2s2m1_sclk
+		     &i2s2m1_sdi &i2s2m1_sdo>;
+	status = "okay";
+};
+
+&package_thermal {
+	polling-delay = <1000>;
+
+	cooling-maps {
+		map0 {
+			trip = <&package_fan0>;
+			cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+		};
+
+		map1 {
+			trip = <&package_fan1>;
+			cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+		};
+	};
+
+	trips {
+		package_fan0: package-fan0 {
+			hysteresis = <2000>;
+			temperature = <55000>;
+			type = "active";
+		};
+
+		package_fan1: package-fan1 {
+			hysteresis = <2000>;
+			temperature = <65000>;
+			type = "active";
+		};
+	};
+};
+
+/* NVMe */
+&pcie2x1l1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2x1l1_rst &pcie30x1m1_1_clkreqn &pcie30x1m1_1_waken>;
+	reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
+	supports-clkreq;
+	vpcie3v3-supply = <&vcc_3v3_s3>;
+	status = "okay";
+};
+
+/* NIC */
+&pcie2x1l2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie2x1l2_rst>;
+	reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
+	vpcie3v3-supply = <&vcc3v3_phy1>;
+	status = "okay";
+};
+
+&pinctrl {
+	bluetooth {
+		bt_wake_gpio: bt-wake-pin {
+			rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_wake_host_irq: bt-wake-host-irq {
+			rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+	};
+
+	dp {
+		dp_bridge_en: dp-bridge-en {
+			rockchip,pins = <3 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pcie {
+		pcie2x1l1_rst: pcie2x1l1-rst {
+			rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		pcie2x1l2_rst: pcie2x1l2-rst {
+			rockchip,pins = <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		vcc3v3_phy1_en: vcc3v3-phy1-en {
+			rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb {
+		vcc5v0_otg_en: vcc5v0-otg-en {
+			rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	wlan {
+		wifi_enable_h: wifi-enable-h {
+			rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		wifi_host_wake_irq: wifi-host-wake-irq {
+			rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+	};
+};
+
+&pwm15 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm15m2_pins>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm2m1_pins>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm3m2_pins>;
+	status = "okay";
+};
+
+&rk806_single {
+	regulators {
+		vcca_1v8_s0: pldo-reg1 {
+			regulator-name = "vcca_1v8_s0";
+			regulator-always-on;
+			regulator-boot-on;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+
+			regulator-state-mem {
+				regulator-off-in-suspend;
+				regulator-suspend-microvolt = <1800000>;
+			};
+		};
+
+		vcc_1v8_s0: pldo-reg2 {
+			regulator-name = "vcc_1v8_s0";
+			regulator-always-on;
+			regulator-boot-on;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+
+			regulator-state-mem {
+				regulator-off-in-suspend;
+			};
+		};
+	};
+};
+
+&sdhci {
+	status = "okay";
+};
+
+&sdio {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	bus-width = <4>;
+	cap-sd-highspeed;
+	cap-sdio-irq;
+	keep-power-in-suspend;
+	max-frequency = <150000000>;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	no-mmc;
+	no-sd;
+	non-removable;
+	sd-uhs-sdr104;
+	status = "okay";
+
+	ap6256: wifi@1 {
+		compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
+		reg = <1>;
+		interrupt-names = "host-wake";
+		interrupt-parent = <&gpio0>;
+		interrupts = <RK_PA0 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_host_wake_irq>;
+	};
+};
+
+&uart9 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart9m2_xfer &uart9m2_ctsn &uart9m2_rtsn>;
+	uart-has-rtscts;
+	status = "okay";
+
+	bluetooth {
+		compatible = "brcm,bcm4345c5";
+		clocks = <&hym8563>;
+		clock-names = "lpo";
+		device-wakeup-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
+		interrupt-names = "host-wakeup";
+		interrupt-parent = <&gpio0>;
+		interrupts = <RK_PC5 IRQ_TYPE_LEVEL_HIGH>;
+		max-speed = <1500000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&bt_wake_host_irq &bt_wake_gpio>;
+		shutdown-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
+		vbat-supply = <&vcc_3v3_s3>;
+		vddio-supply = <&vcc_1v8_s3>;
+	};
+};
+
+&usb_host0_xhci {
+	dr_mode = "host";
+};
+
+&usbdp_phy0 {
+	/*
+	 * USBDP PHY0 is wired to a USB3 Type-A host connector via lanes 2/3.
+	 * Additionally lanes 0/1 and the aux channel are wired to the
+	 * Lontium LT8711UXD DP-to-HDMI bridge feeding the HDMI1 connector.
+	 */
+	rockchip,dp-lane-mux = <0 1>;
+};
+
+&vp1 {
+	vp1_out_dp0: endpoint@a {
+		reg = <ROCKCHIP_VOP2_EP_DP0>;
+		remote-endpoint = <&dp0_in_vp1>;
+	};
+};
-- 
2.53.0



^ permalink raw reply related

* [PATCH v7 5/6] arm64: dts: rockchip: refactor items from Orange Pi 5/b to prep for Pro
From: Dennis Gilmore @ 2026-04-14 21:40 UTC (permalink / raw)
  Cc: Alexey Charkov, Andrew Lunn, Andrzej Hajda, Chaoyi Chen,
	Conor Dooley, David Airlie, Dennis Gilmore, devicetree, dri-devel,
	FUKAUMI Naoki, Heiko Stuebner, Hsun Lai, Jernej Skrabec,
	Jimmy Hon, John Clark, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, linux-arm-kernel, linux-kernel, linux-rockchip,
	Maarten Lankhorst, Maxime Ripard, Michael Opdenacker,
	Michael Riesch, Mykola Kvach, Neil Armstrong, Peter Robinson,
	Quentin Schulz, Robert Foss, Rob Herring, Simona Vetter,
	Thomas Zimmermann
In-Reply-To: <20260414214104.1363987-1-dennis@ausil.us>

The Orange Pi 5 Pro uses the same SoC and base as the Orange Pi 5 and
Orange Pi 5B but has had sound, USB, and leds wired up differently. The
5 and 5B boards use gmac for ethernet where the Pro has a PCIe attached
NIC.

Move the 5/5B-specific bits (analog-sound/es8388, FUSB302 Type-C,
gmac1, pwm-leds, i2s1_8ch routing, USB role-switch plumbing) out of
rk3588s-orangepi-5.dtsi into a new rk3588s-orangepi-5-5b.dtsi that is
included by both 5 and 5B.

The RK806 PLDO1 and PLDO2 outputs are wired differently between the
5/5B and the Pro (PLDO1/PLDO2 are swapped), so label the PMIC node
rk806_single in the base dtsi, drop pldo-reg1/pldo-reg2 from it, and
define them via a &rk806_single regulators augmentation in
rk3588s-orangepi-5-5b.dtsi. The Pro will supply its own mapping.

Signed-off-by: Dennis Gilmore <dennis@ausil.us>
---
 .../dts/rockchip/rk3588s-orangepi-5-5b.dtsi   | 222 +++++++++++++++++
 .../boot/dts/rockchip/rk3588s-orangepi-5.dts  |   6 +-
 .../boot/dts/rockchip/rk3588s-orangepi-5.dtsi | 225 +-----------------
 .../boot/dts/rockchip/rk3588s-orangepi-5b.dts |   2 +-
 4 files changed, 240 insertions(+), 215 deletions(-)
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-5b.dtsi

diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-5b.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-5b.dtsi
new file mode 100644
index 000000000000..9e987ffa6241
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-5b.dtsi
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device tree definitions shared by the Orange Pi 5 and Orange Pi 5B
+ * but not the Orange Pi 5 Pro.
+ */
+
+#include <dt-bindings/usb/pd.h>
+#include "rk3588s-orangepi-5.dtsi"
+
+/ {
+	aliases {
+		ethernet0 = &gmac1;
+	};
+
+	analog-sound {
+		compatible = "simple-audio-card";
+		pinctrl-names = "default";
+		pinctrl-0 = <&hp_detect>;
+		simple-audio-card,name = "rockchip,es8388";
+		simple-audio-card,bitclock-master = <&masterdai>;
+		simple-audio-card,format = "i2s";
+		simple-audio-card,frame-master = <&masterdai>;
+		simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
+		simple-audio-card,mclk-fs = <256>;
+		simple-audio-card,routing =
+			"Headphones", "LOUT1",
+			"Headphones", "ROUT1",
+			"LINPUT1", "Microphone Jack",
+			"RINPUT1", "Microphone Jack",
+			"LINPUT2", "Onboard Microphone",
+			"RINPUT2", "Onboard Microphone";
+		simple-audio-card,widgets =
+			"Microphone", "Microphone Jack",
+			"Microphone", "Onboard Microphone",
+			"Headphone", "Headphones";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s1_8ch>;
+		};
+
+		masterdai: simple-audio-card,codec {
+			sound-dai = <&es8388>;
+			system-clock-frequency = <12288000>;
+		};
+	};
+
+	pwm-leds {
+		compatible = "pwm-leds";
+
+		led {
+			color = <LED_COLOR_ID_GREEN>;
+			function = LED_FUNCTION_STATUS;
+			linux,default-trigger = "heartbeat";
+			max-brightness = <255>;
+			pwms = <&pwm0 0 25000 0>;
+		};
+	};
+};
+
+&gmac1 {
+	clock_in_out = "output";
+	phy-handle = <&rgmii_phy1>;
+	phy-mode = "rgmii-rxid";
+	pinctrl-0 = <&gmac1_miim
+			&gmac1_tx_bus2
+			&gmac1_rx_bus2
+			&gmac1_rgmii_clk
+			&gmac1_rgmii_bus>;
+	pinctrl-names = "default";
+	tx_delay = <0x42>;
+	status = "okay";
+};
+
+&i2c6 {
+	es8388: audio-codec@10 {
+		compatible = "everest,es8388", "everest,es8328";
+		reg = <0x10>;
+		clocks = <&cru I2S1_8CH_MCLKOUT>;
+		AVDD-supply = <&vcca_3v3_s0>;
+		DVDD-supply = <&vcca_1v8_s0>;
+		HPVDD-supply = <&vcca_3v3_s0>;
+		PVDD-supply = <&vcca_3v3_s0>;
+		assigned-clocks = <&cru I2S1_8CH_MCLKOUT>;
+		assigned-clock-rates = <12288000>;
+		#sound-dai-cells = <0>;
+	};
+
+	usbc0: usb-typec@22 {
+		compatible = "fcs,fusb302";
+		reg = <0x22>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usbc0_int>;
+		vbus-supply = <&vbus_typec>;
+		status = "okay";
+
+		usb_con: connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			data-role = "dual";
+			op-sink-microwatt = <1000000>;
+			power-role = "dual";
+			sink-pdos =
+				<PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
+			source-pdos =
+				<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+			try-power-role = "source";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					usbc0_hs: endpoint {
+						remote-endpoint = <&usb_host0_xhci_drd_sw>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					usbc0_ss: endpoint {
+						remote-endpoint = <&usbdp_phy0_typec_ss>;
+					};
+				};
+
+				port@2 {
+					reg = <2>;
+					usbc0_sbu: endpoint {
+						remote-endpoint = <&usbdp_phy0_typec_sbu>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&i2s1_8ch {
+	rockchip,i2s-tx-route = <3 2 1 0>;
+	rockchip,i2s-rx-route = <1 3 2 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2s1m0_sclk
+			   &i2s1m0_mclk
+			   &i2s1m0_lrck
+			   &i2s1m0_sdi1
+			   &i2s1m0_sdo3>;
+	status = "okay";
+};
+
+&pwm0 {
+	pinctrl-0 = <&pwm0m2_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&rk806_single {
+	regulators {
+		vcc_1v8_s0: pldo-reg1 {
+			regulator-name = "vcc_1v8_s0";
+			regulator-always-on;
+			regulator-boot-on;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+
+			regulator-state-mem {
+				regulator-off-in-suspend;
+			};
+		};
+
+		vcca_1v8_s0: pldo-reg2 {
+			regulator-name = "vcca_1v8_s0";
+			regulator-always-on;
+			regulator-boot-on;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+
+			regulator-state-mem {
+				regulator-off-in-suspend;
+				regulator-suspend-microvolt = <1800000>;
+			};
+		};
+	};
+};
+
+
+&usb_host0_xhci {
+	dr_mode = "otg";
+	usb-role-switch;
+
+	port {
+		usb_host0_xhci_drd_sw: endpoint {
+			remote-endpoint = <&usbc0_hs>;
+		};
+	};
+};
+
+&usb_host2_xhci {
+	status = "okay";
+};
+
+&usbdp_phy0 {
+	mode-switch;
+	orientation-switch;
+	sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
+	sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		usbdp_phy0_typec_ss: endpoint@0 {
+			reg = <0>;
+			remote-endpoint = <&usbc0_ss>;
+		};
+
+		usbdp_phy0_typec_sbu: endpoint@1 {
+			reg = <1>;
+			remote-endpoint = <&usbc0_sbu>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
index 83b9b6645a1e..d76bdf1b5e90 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts
@@ -2,12 +2,16 @@
 
 /dts-v1/;
 
-#include "rk3588s-orangepi-5.dtsi"
+#include "rk3588s-orangepi-5-5b.dtsi"
 
 / {
 	model = "Xunlong Orange Pi 5";
 	compatible = "xunlong,orangepi-5", "rockchip,rk3588s";
 
+	aliases {
+		mmc0 = &sdmmc;
+	};
+
 	vcc3v3_pcie20: regulator-vcc3v3-pcie20 {
 		compatible = "regulator-fixed";
 		enable-active-high;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
index fd5c6a025cd1..2b605e5fc35a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
@@ -3,19 +3,13 @@
 /dts-v1/;
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/leds/common.h>
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
 #include <dt-bindings/pinctrl/rockchip.h>
 #include <dt-bindings/soc/rockchip,vop2.h>
-#include <dt-bindings/usb/pd.h>
 #include "rk3588s.dtsi"
 
 / {
-	aliases {
-		ethernet0 = &gmac1;
-		mmc0 = &sdmmc;
-	};
-
 	chosen {
 		stdout-path = "serial2:1500000n8";
 	};
@@ -34,38 +28,6 @@ button-recovery {
 		};
 	};
 
-	analog-sound {
-		compatible = "simple-audio-card";
-		pinctrl-names = "default";
-		pinctrl-0 = <&hp_detect>;
-		simple-audio-card,name = "rockchip,es8388";
-		simple-audio-card,bitclock-master = <&masterdai>;
-		simple-audio-card,format = "i2s";
-		simple-audio-card,frame-master = <&masterdai>;
-		simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
-		simple-audio-card,mclk-fs = <256>;
-		simple-audio-card,routing =
-			"Headphones", "LOUT1",
-			"Headphones", "ROUT1",
-			"LINPUT1", "Microphone Jack",
-			"RINPUT1", "Microphone Jack",
-			"LINPUT2", "Onboard Microphone",
-			"RINPUT2", "Onboard Microphone";
-		simple-audio-card,widgets =
-			"Microphone", "Microphone Jack",
-			"Microphone", "Onboard Microphone",
-			"Headphone", "Headphones";
-
-		simple-audio-card,cpu {
-			sound-dai = <&i2s1_8ch>;
-		};
-
-		masterdai: simple-audio-card,codec {
-			sound-dai = <&es8388>;
-			system-clock-frequency = <12288000>;
-		};
-	};
-
 	hdmi0-con {
 		compatible = "hdmi-connector";
 		type = "a";
@@ -77,18 +39,6 @@ hdmi0_con_in: endpoint {
 		};
 	};
 
-	pwm-leds {
-		compatible = "pwm-leds";
-
-		led {
-			color = <LED_COLOR_ID_GREEN>;
-			function = LED_FUNCTION_STATUS;
-			linux,default-trigger = "heartbeat";
-			max-brightness = <255>;
-			pwms = <&pwm0 0 25000 0>;
-		};
-	};
-
 	vbus_typec: regulator-vbus-typec {
 		compatible = "regulator-fixed";
 		enable-active-high;
@@ -101,15 +51,6 @@ vbus_typec: regulator-vbus-typec {
 		vin-supply = <&vcc5v0_sys>;
 	};
 
-	vcc5v0_sys: regulator-vcc5v0-sys {
-		compatible = "regulator-fixed";
-		regulator-name = "vcc5v0_sys";
-		regulator-always-on;
-		regulator-boot-on;
-		regulator-min-microvolt = <5000000>;
-		regulator-max-microvolt = <5000000>;
-	};
-
 	vcc_3v3_sd_s0: regulator-vcc-3v3-sd-s0 {
 		compatible = "regulator-fixed";
 		gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>;
@@ -119,6 +60,15 @@ vcc_3v3_sd_s0: regulator-vcc-3v3-sd-s0 {
 		regulator-max-microvolt = <3300000>;
 		vin-supply = <&vcc_3v3_s3>;
 	};
+
+	vcc5v0_sys: regulator-vcc5v0-sys {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc5v0_sys";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
 };
 
 &combphy0_ps {
@@ -161,20 +111,6 @@ &cpu_l3 {
 	cpu-supply = <&vdd_cpu_lit_s0>;
 };
 
-&gmac1 {
-	clock_in_out = "output";
-	phy-handle = <&rgmii_phy1>;
-	phy-mode = "rgmii-rxid";
-	pinctrl-0 = <&gmac1_miim
-		     &gmac1_tx_bus2
-		     &gmac1_rx_bus2
-		     &gmac1_rgmii_clk
-		     &gmac1_rgmii_bus>;
-	pinctrl-names = "default";
-	tx_delay = <0x42>;
-	status = "okay";
-};
-
 &gpu {
 	mali-supply = <&vdd_gpu_s0>;
 	status = "okay";
@@ -270,69 +206,6 @@ &i2c6 {
 	pinctrl-0 = <&i2c6m3_xfer>;
 	status = "okay";
 
-	es8388: audio-codec@10 {
-		compatible = "everest,es8388", "everest,es8328";
-		reg = <0x10>;
-		clocks = <&cru I2S1_8CH_MCLKOUT>;
-		AVDD-supply = <&vcca_3v3_s0>;
-		DVDD-supply = <&vcca_1v8_s0>;
-		HPVDD-supply = <&vcca_3v3_s0>;
-		PVDD-supply = <&vcca_3v3_s0>;
-		assigned-clocks = <&cru I2S1_8CH_MCLKOUT>;
-		assigned-clock-rates = <12288000>;
-		#sound-dai-cells = <0>;
-	};
-
-	usbc0: usb-typec@22 {
-		compatible = "fcs,fusb302";
-		reg = <0x22>;
-		interrupt-parent = <&gpio0>;
-		interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&usbc0_int>;
-		vbus-supply = <&vbus_typec>;
-		status = "okay";
-
-		usb_con: connector {
-			compatible = "usb-c-connector";
-			label = "USB-C";
-			data-role = "dual";
-			op-sink-microwatt = <1000000>;
-			power-role = "dual";
-			sink-pdos =
-				<PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
-			source-pdos =
-				<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
-			try-power-role = "source";
-
-			ports {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				port@0 {
-					reg = <0>;
-					usbc0_hs: endpoint {
-						remote-endpoint = <&usb_host0_xhci_drd_sw>;
-					};
-				};
-
-				port@1 {
-					reg = <1>;
-					usbc0_ss: endpoint {
-						remote-endpoint = <&usbdp_phy0_typec_ss>;
-					};
-				};
-
-				port@2 {
-					reg = <2>;
-					usbc0_sbu: endpoint {
-						remote-endpoint = <&usbdp_phy0_typec_sbu>;
-					};
-				};
-			};
-		};
-	};
-
 	hym8563: rtc@51 {
 		compatible = "haoyu,hym8563";
 		reg = <0x51>;
@@ -346,18 +219,6 @@ hym8563: rtc@51 {
 	};
 };
 
-&i2s1_8ch {
-	rockchip,i2s-tx-route = <3 2 1 0>;
-	rockchip,i2s-rx-route = <1 3 2 0>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2s1m0_sclk
-	             &i2s1m0_mclk
-	             &i2s1m0_lrck
-	             &i2s1m0_sdi1
-	             &i2s1m0_sdo3>;
-	status = "okay";
-};
-
 &i2s5_8ch {
 	status = "okay";
 };
@@ -404,12 +265,6 @@ typec5v_pwren: typec5v-pwren {
 	};
 };
 
-&pwm0 {
-	pinctrl-0 = <&pwm0m2_pins>;
-	pinctrl-names = "default";
-	status = "okay";
-};
-
 &rknn_core_0 {
 	npu-supply = <&vdd_npu_s0>;
 	sram-supply = <&vdd_npu_s0>;
@@ -491,7 +346,7 @@ &spi2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>;
 
-	pmic@0 {
+	rk806_single: pmic@0 {
 		compatible = "rockchip,rk806";
 		reg = <0x0>;
 		interrupt-parent = <&gpio0>;
@@ -666,31 +521,6 @@ regulator-state-mem {
 				};
 			};
 
-			vcc_1v8_s0: pldo-reg1 {
-				regulator-name = "vcc_1v8_s0";
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-
-				regulator-state-mem {
-					regulator-off-in-suspend;
-				};
-			};
-
-			vcca_1v8_s0: pldo-reg2 {
-				regulator-name = "vcca_1v8_s0";
-				regulator-always-on;
-				regulator-boot-on;
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
-
-				regulator-state-mem {
-					regulator-off-in-suspend;
-					regulator-suspend-microvolt = <1800000>;
-				};
-			};
-
 			vdda_1v2_s0: pldo-reg3 {
 				regulator-name = "vdda_1v2_s0";
 				regulator-always-on;
@@ -841,26 +671,7 @@ &uart2 {
 };
 
 &usbdp_phy0 {
-	mode-switch;
-	orientation-switch;
-	sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>;
-	sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
 	status = "okay";
-
-	port {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		usbdp_phy0_typec_ss: endpoint@0 {
-			reg = <0>;
-			remote-endpoint = <&usbc0_ss>;
-		};
-
-		usbdp_phy0_typec_sbu: endpoint@1 {
-			reg = <1>;
-			remote-endpoint = <&usbc0_sbu>;
-		};
-	};
 };
 
 &usb_host0_ehci {
@@ -872,15 +683,7 @@ &usb_host0_ohci {
 };
 
 &usb_host0_xhci {
-	dr_mode = "otg";
-	usb-role-switch;
 	status = "okay";
-
-	port {
-		usb_host0_xhci_drd_sw: endpoint {
-			remote-endpoint = <&usbc0_hs>;
-		};
-	};
 };
 
 &usb_host1_ehci {
@@ -891,7 +694,7 @@ &usb_host1_ohci {
 	status = "okay";
 };
 
-&usb_host2_xhci {
+&vop {
 	status = "okay";
 };
 
@@ -899,10 +702,6 @@ &vop_mmu {
 	status = "okay";
 };
 
-&vop {
-	status = "okay";
-};
-
 &vp0 {
 	vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
 		reg = <ROCKCHIP_VOP2_EP_HDMI0>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts
index d21ec320d295..8af174777809 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5b.dts
@@ -2,7 +2,7 @@
 
 /dts-v1/;
 
-#include "rk3588s-orangepi-5.dtsi"
+#include "rk3588s-orangepi-5-5b.dtsi"
 
 / {
 	model = "Xunlong Orange Pi 5B";
-- 
2.53.0



^ permalink raw reply related

* [PATCH v7 4/6] arm64: dts: rockchip: rk3588s-orangepi-5: rename PLDO regulator labels to match schematic
From: Dennis Gilmore @ 2026-04-14 21:40 UTC (permalink / raw)
  Cc: Alexey Charkov, Andrew Lunn, Andrzej Hajda, Chaoyi Chen,
	Conor Dooley, David Airlie, Dennis Gilmore, devicetree, dri-devel,
	FUKAUMI Naoki, Heiko Stuebner, Hsun Lai, Jernej Skrabec,
	Jimmy Hon, John Clark, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, linux-arm-kernel, linux-kernel, linux-rockchip,
	Maarten Lankhorst, Maxime Ripard, Michael Opdenacker,
	Michael Riesch, Mykola Kvach, Neil Armstrong, Peter Robinson,
	Quentin Schulz, Robert Foss, Rob Herring, Simona Vetter,
	Thomas Zimmermann
In-Reply-To: <20260414214104.1363987-1-dennis@ausil.us>

The Orange Pi 5, 5B and 5 Pro schematics label the RK806 PLDO outputs
using the pattern VCC_*_S0 / VCCA_*_S0 / VDDA_*_S0. Rename the base
dtsi regulator labels (and the es8388 supply references) to match:

  pldo-reg1: avcc_1v8_s0 -> vcc_1v8_s0
  pldo-reg2: vcc_1v8_s0  -> vcca_1v8_s0
  pldo-reg3: avdd_1v2_s0 -> vdda_1v2_s0
  pldo-reg4: vcc_3v3_s0  -> vcca_3v3_s0

Also update the saradc vref-supply reference to track the pldo-reg1
rename. No functional change.

Signed-off-by: Dennis Gilmore <dennis@ausil.us>
---
 .../boot/dts/rockchip/rk3588s-orangepi-5.dtsi | 26 +++++++++----------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
index dafad29f9854..fd5c6a025cd1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi
@@ -274,10 +274,10 @@ es8388: audio-codec@10 {
 		compatible = "everest,es8388", "everest,es8328";
 		reg = <0x10>;
 		clocks = <&cru I2S1_8CH_MCLKOUT>;
-		AVDD-supply = <&vcc_3v3_s0>;
-		DVDD-supply = <&vcc_1v8_s0>;
-		HPVDD-supply = <&vcc_3v3_s0>;
-		PVDD-supply = <&vcc_3v3_s0>;
+		AVDD-supply = <&vcca_3v3_s0>;
+		DVDD-supply = <&vcca_1v8_s0>;
+		HPVDD-supply = <&vcca_3v3_s0>;
+		PVDD-supply = <&vcca_3v3_s0>;
 		assigned-clocks = <&cru I2S1_8CH_MCLKOUT>;
 		assigned-clock-rates = <12288000>;
 		#sound-dai-cells = <0>;
@@ -441,7 +441,7 @@ &rknn_mmu_2 {
 };
 
 &saradc {
-	vref-supply = <&avcc_1v8_s0>;
+	vref-supply = <&vcc_1v8_s0>;
 	status = "okay";
 };
 
@@ -666,8 +666,8 @@ regulator-state-mem {
 				};
 			};
 
-			avcc_1v8_s0: pldo-reg1 {
-				regulator-name = "avcc_1v8_s0";
+			vcc_1v8_s0: pldo-reg1 {
+				regulator-name = "vcc_1v8_s0";
 				regulator-always-on;
 				regulator-boot-on;
 				regulator-min-microvolt = <1800000>;
@@ -678,8 +678,8 @@ regulator-state-mem {
 				};
 			};
 
-			vcc_1v8_s0: pldo-reg2 {
-				regulator-name = "vcc_1v8_s0";
+			vcca_1v8_s0: pldo-reg2 {
+				regulator-name = "vcca_1v8_s0";
 				regulator-always-on;
 				regulator-boot-on;
 				regulator-min-microvolt = <1800000>;
@@ -691,8 +691,8 @@ regulator-state-mem {
 				};
 			};
 
-			avdd_1v2_s0: pldo-reg3 {
-				regulator-name = "avdd_1v2_s0";
+			vdda_1v2_s0: pldo-reg3 {
+				regulator-name = "vdda_1v2_s0";
 				regulator-always-on;
 				regulator-boot-on;
 				regulator-min-microvolt = <1200000>;
@@ -703,8 +703,8 @@ regulator-state-mem {
 				};
 			};
 
-			vcc_3v3_s0: pldo-reg4 {
-				regulator-name = "vcc_3v3_s0";
+			vcca_3v3_s0: pldo-reg4 {
+				regulator-name = "vcca_3v3_s0";
 				regulator-always-on;
 				regulator-boot-on;
 				regulator-min-microvolt = <3300000>;
-- 
2.53.0



^ permalink raw reply related

* [PATCH v7 3/6] drm/bridge: simple: Add the Lontium LT8711UXD DP-to-HDMI bridge
From: Dennis Gilmore @ 2026-04-14 21:40 UTC (permalink / raw)
  Cc: Alexey Charkov, Andrew Lunn, Andrzej Hajda, Chaoyi Chen,
	Conor Dooley, David Airlie, Dennis Gilmore, devicetree, dri-devel,
	FUKAUMI Naoki, Heiko Stuebner, Hsun Lai, Jernej Skrabec,
	Jimmy Hon, John Clark, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, linux-arm-kernel, linux-kernel, linux-rockchip,
	Maarten Lankhorst, Maxime Ripard, Michael Opdenacker,
	Michael Riesch, Mykola Kvach, Neil Armstrong, Peter Robinson,
	Quentin Schulz, Robert Foss, Rob Herring, Simona Vetter,
	Thomas Zimmermann
In-Reply-To: <20260414214104.1363987-1-dennis@ausil.us>

The Lontium LT8711UXD is a high performance two lane Type-C/DP1.4
to HDMI2.0 converter, designed to connect a USB Type-C source or
a DP1.4 source to an HDMI2.0 sink.

Signed-off-by: Dennis Gilmore <dennis@ausil.us>
---
 drivers/gpu/drm/bridge/simple-bridge.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index 8aa31ca3c72d..42c1f3d5ba0c 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -270,6 +270,11 @@ static const struct of_device_id simple_bridge_match[] = {
 		.data = &(const struct simple_bridge_info) {
 			.connector_type = DRM_MODE_CONNECTOR_HDMIA,
 		},
+	}, {
+		.compatible = "lontium,lt8711uxd",
+		.data = &(const struct simple_bridge_info) {
+			.connector_type = DRM_MODE_CONNECTOR_HDMIA,
+		},
 	}, {
 		.compatible = "parade,ps185hdm",
 		.data = &(const struct simple_bridge_info) {
-- 
2.53.0



^ permalink raw reply related

* [PATCH v7 2/6] dt-bindings: display: bridge: simple: document the Lontium LT8711UXD DP-to-HDMI bridge
From: Dennis Gilmore @ 2026-04-14 21:40 UTC (permalink / raw)
  Cc: Alexey Charkov, Andrew Lunn, Andrzej Hajda, Chaoyi Chen,
	Conor Dooley, David Airlie, Dennis Gilmore, devicetree, dri-devel,
	FUKAUMI Naoki, Heiko Stuebner, Hsun Lai, Jernej Skrabec,
	Jimmy Hon, John Clark, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, linux-arm-kernel, linux-kernel, linux-rockchip,
	Maarten Lankhorst, Maxime Ripard, Michael Opdenacker,
	Michael Riesch, Mykola Kvach, Neil Armstrong, Peter Robinson,
	Quentin Schulz, Robert Foss, Rob Herring, Simona Vetter,
	Thomas Zimmermann
In-Reply-To: <20260414214104.1363987-1-dennis@ausil.us>

The Lontium LT8711UXD is a high performance two lane Type-C/DP1.4
to HDMI2.0 converter, designed to connect a USB Type-C source or
a DP1.4 source to an HDMI2.0 sink.

Signed-off-by: Dennis Gilmore <dennis@ausil.us>
---
 .../devicetree/bindings/display/bridge/simple-bridge.yaml        | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml b/Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml
index e6808419f625..752c736c8f85 100644
--- a/Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml
@@ -30,6 +30,7 @@ properties:
           - algoltek,ag6311
           - asl-tek,cs5263
           - dumb-vga-dac
+          - lontium,lt8711uxd
           - parade,ps185hdm
           - radxa,ra620
           - realtek,rtd2171
-- 
2.53.0



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox